Root/drivers/staging/wlan-ng/cfg80211.c

1/* cfg80211 Interface for prism2_usb module */
2
3
4/* Prism2 channell/frequency/bitrate declarations */
5static const struct ieee80211_channel prism2_channels[] = {
6    { .center_freq = 2412 },
7    { .center_freq = 2417 },
8    { .center_freq = 2422 },
9    { .center_freq = 2427 },
10    { .center_freq = 2432 },
11    { .center_freq = 2437 },
12    { .center_freq = 2442 },
13    { .center_freq = 2447 },
14    { .center_freq = 2452 },
15    { .center_freq = 2457 },
16    { .center_freq = 2462 },
17    { .center_freq = 2467 },
18    { .center_freq = 2472 },
19    { .center_freq = 2484 },
20};
21
22static const struct ieee80211_rate prism2_rates[] = {
23    { .bitrate = 10 },
24    { .bitrate = 20 },
25    { .bitrate = 55 },
26    { .bitrate = 110 }
27};
28
29#define PRISM2_NUM_CIPHER_SUITES 2
30static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = {
31    WLAN_CIPHER_SUITE_WEP40,
32    WLAN_CIPHER_SUITE_WEP104
33};
34
35
36/* prism2 device private data */
37struct prism2_wiphy_private {
38    wlandevice_t *wlandev;
39
40    struct ieee80211_supported_band band;
41    struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)];
42    struct ieee80211_rate rates[ARRAY_SIZE(prism2_rates)];
43
44    struct cfg80211_scan_request *scan_request;
45};
46
47static const void * const prism2_wiphy_privid = &prism2_wiphy_privid;
48
49
50/* Helper Functions */
51static int prism2_result2err(int prism2_result)
52{
53    int err = 0;
54
55    switch (prism2_result) {
56    case P80211ENUM_resultcode_invalid_parameters:
57        err = -EINVAL;
58        break;
59    case P80211ENUM_resultcode_implementation_failure:
60        err = -EIO;
61        break;
62    case P80211ENUM_resultcode_not_supported:
63        err = -EOPNOTSUPP;
64        break;
65    default:
66        err = 0;
67        break;
68    }
69
70    return err;
71}
72
73static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data)
74{
75    struct p80211msg_dot11req_mibset msg;
76    p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data;
77
78    msg.msgcode = DIDmsg_dot11req_mibset;
79    mibitem->did = did;
80    mibitem->data = data;
81
82    return p80211req_dorequest(wlandev, (u8 *) &msg);
83}
84
85static int prism2_domibset_pstr32(wlandevice_t *wlandev,
86                  u32 did, u8 len, u8 *data)
87{
88    struct p80211msg_dot11req_mibset msg;
89    p80211item_pstr32_t *mibitem = (p80211item_pstr32_t *) &msg.mibattribute.data;
90
91    msg.msgcode = DIDmsg_dot11req_mibset;
92    mibitem->did = did;
93    mibitem->data.len = len;
94    memcpy(mibitem->data.data, data, len);
95
96    return p80211req_dorequest(wlandev, (u8 *) &msg);
97}
98
99
100/* The interface functions, called by the cfg80211 layer */
101int prism2_change_virtual_intf(struct wiphy *wiphy,
102                   struct net_device *dev,
103                   enum nl80211_iftype type, u32 *flags,
104                   struct vif_params *params)
105{
106    wlandevice_t *wlandev = dev->ml_priv;
107    u32 data;
108    int result;
109    int err = 0;
110
111    switch (type) {
112    case NL80211_IFTYPE_ADHOC:
113        if (wlandev->macmode == WLAN_MACMODE_IBSS_STA)
114            goto exit;
115        wlandev->macmode = WLAN_MACMODE_IBSS_STA;
116        data = 0;
117        break;
118    case NL80211_IFTYPE_STATION:
119        if (wlandev->macmode == WLAN_MACMODE_ESS_STA)
120            goto exit;
121        wlandev->macmode = WLAN_MACMODE_ESS_STA;
122        data = 1;
123        break;
124    default:
125        printk(KERN_WARNING "Operation mode: %d not support\n", type);
126        return -EOPNOTSUPP;
127    }
128
129    /* Set Operation mode to the PORT TYPE RID */
130    result = prism2_domibset_uint32(wlandev,
131                    DIDmib_p2_p2Static_p2CnfPortType,
132                    data);
133
134    if (result)
135        err = -EFAULT;
136
137    dev->ieee80211_ptr->iftype = type;
138
139exit:
140    return err;
141}
142
143int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
144           u8 key_index, bool pairwise, const u8 *mac_addr,
145           struct key_params *params)
146{
147    wlandevice_t *wlandev = dev->ml_priv;
148    u32 did;
149
150    int err = 0;
151    int result = 0;
152
153    switch (params->cipher) {
154    case WLAN_CIPHER_SUITE_WEP40:
155    case WLAN_CIPHER_SUITE_WEP104:
156        result = prism2_domibset_uint32(wlandev,
157                        DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
158                        key_index);
159        if (result)
160            goto exit;
161
162        /* send key to driver */
163        switch (key_index) {
164        case 0:
165            did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
166            break;
167
168        case 1:
169            did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
170            break;
171
172        case 2:
173            did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
174            break;
175
176        case 3:
177            did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
178            break;
179
180        default:
181            err = -EINVAL;
182            goto exit;
183        }
184
185        result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key);
186        if (result)
187            goto exit;
188        break;
189
190    default:
191        pr_debug("Unsupported cipher suite\n");
192        result = 1;
193    }
194
195exit:
196    if (result)
197        err = -EFAULT;
198
199    return err;
200}
201
202int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
203           u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie,
204           void (*callback)(void *cookie, struct key_params*))
205{
206    wlandevice_t *wlandev = dev->ml_priv;
207    struct key_params params;
208    int len;
209
210    if (key_index >= NUM_WEPKEYS)
211        return -EINVAL;
212
213    len = wlandev->wep_keylens[key_index];
214    memset(&params, 0, sizeof(params));
215
216    if (len == 13)
217        params.cipher = WLAN_CIPHER_SUITE_WEP104;
218    else if (len == 5)
219        params.cipher = WLAN_CIPHER_SUITE_WEP104;
220    else
221        return -ENOENT;
222    params.key_len = len;
223    params.key = wlandev->wep_keys[key_index];
224    params.seq_len = 0;
225
226    callback(cookie, &params);
227
228    return 0;
229}
230
231int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
232           u8 key_index, bool pairwise, const u8 *mac_addr)
233{
234    wlandevice_t *wlandev = dev->ml_priv;
235    u32 did;
236    int err = 0;
237    int result = 0;
238
239    /* There is no direct way in the hardware (AFAIK) of removing
240       a key, so we will cheat by setting the key to a bogus value */
241    /* send key to driver */
242    switch (key_index) {
243    case 0:
244        did =
245            DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
246        break;
247
248    case 1:
249        did =
250            DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
251        break;
252
253    case 2:
254        did =
255            DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
256        break;
257
258    case 3:
259        did =
260            DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
261        break;
262
263    default:
264        err = -EINVAL;
265        goto exit;
266    }
267
268    result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000");
269
270exit:
271    if (result)
272        err = -EFAULT;
273
274    return err;
275}
276
277int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
278               u8 key_index, bool unicast, bool multicast)
279{
280    wlandevice_t *wlandev = dev->ml_priv;
281
282    int err = 0;
283    int result = 0;
284
285    result = prism2_domibset_uint32(wlandev,
286        DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
287        key_index);
288
289    if (result)
290        err = -EFAULT;
291
292    return err;
293}
294
295
296int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
297               u8 *mac, struct station_info *sinfo)
298{
299    wlandevice_t *wlandev = dev->ml_priv;
300    struct p80211msg_lnxreq_commsquality quality;
301    int result;
302
303    memset(sinfo, 0, sizeof(*sinfo));
304
305    if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
306        return -EOPNOTSUPP;
307
308    /* build request message */
309    quality.msgcode = DIDmsg_lnxreq_commsquality;
310    quality.dbm.data = P80211ENUM_truth_true;
311    quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
312
313    /* send message to nsd */
314    if (wlandev->mlmerequest == NULL)
315        return -EOPNOTSUPP;
316
317    result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality);
318
319
320    if (result == 0) {
321        sinfo->txrate.legacy = quality.txrate.data;
322        sinfo->filled |= STATION_INFO_TX_BITRATE;
323        sinfo->signal = quality.level.data;
324        sinfo->filled |= STATION_INFO_SIGNAL;
325    }
326
327    return result;
328}
329
330int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
331{
332    struct net_device *dev = request->wdev->netdev;
333    struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
334    wlandevice_t *wlandev = dev->ml_priv;
335    struct p80211msg_dot11req_scan msg1;
336    struct p80211msg_dot11req_scan_results msg2;
337    struct cfg80211_bss *bss;
338    int result;
339    int err = 0;
340    int numbss = 0;
341    int i = 0;
342    u8 ie_buf[46];
343    int ie_len;
344
345    if (!request)
346        return -EINVAL;
347
348    if (priv->scan_request && priv->scan_request != request)
349        return -EBUSY;
350
351    if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
352        printk(KERN_ERR "Can't scan in AP mode\n");
353        return -EOPNOTSUPP;
354    }
355
356    priv->scan_request = request;
357
358    memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan));
359    msg1.msgcode = DIDmsg_dot11req_scan;
360    msg1.bsstype.data = P80211ENUM_bsstype_any;
361
362    memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data));
363    msg1.bssid.data.len = 6;
364
365    if (request->n_ssids > 0) {
366        msg1.scantype.data = P80211ENUM_scantype_active;
367        msg1.ssid.data.len = request->ssids->ssid_len;
368        memcpy(msg1.ssid.data.data,
369            request->ssids->ssid, request->ssids->ssid_len);
370    } else {
371        msg1.scantype.data = 0;
372    }
373    msg1.probedelay.data = 0;
374
375    for (i = 0;
376        (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
377        i++)
378        msg1.channellist.data.data[i] =
379            ieee80211_frequency_to_channel(request->channels[i]->center_freq);
380    msg1.channellist.data.len = request->n_channels;
381
382    msg1.maxchanneltime.data = 250;
383    msg1.minchanneltime.data = 200;
384
385    result = p80211req_dorequest(wlandev, (u8 *) &msg1);
386    if (result) {
387        err = prism2_result2err(msg1.resultcode.data);
388        goto exit;
389    }
390    /* Now retrieve scan results */
391    numbss = msg1.numbss.data;
392
393    for (i = 0; i < numbss; i++) {
394        memset(&msg2, 0, sizeof(msg2));
395        msg2.msgcode = DIDmsg_dot11req_scan_results;
396        msg2.bssindex.data = i;
397
398        result = p80211req_dorequest(wlandev, (u8 *) &msg2);
399        if ((result != 0) ||
400            (msg2.resultcode.data != P80211ENUM_resultcode_success)) {
401            break;
402        }
403
404        ie_buf[0] = WLAN_EID_SSID;
405        ie_buf[1] = msg2.ssid.data.len;
406        ie_len = ie_buf[1] + 2;
407        memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len);
408        bss = cfg80211_inform_bss(wiphy,
409            ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)),
410            (const u8 *) &(msg2.bssid.data.data),
411            msg2.timestamp.data, msg2.capinfo.data,
412            msg2.beaconperiod.data,
413            ie_buf,
414            ie_len,
415            (msg2.signal.data - 65536) * 100, /* Conversion to signed type */
416            GFP_KERNEL
417        );
418
419        if (!bss) {
420            err = -ENOMEM;
421            goto exit;
422        }
423
424        cfg80211_put_bss(bss);
425    }
426
427    if (result)
428        err = prism2_result2err(msg2.resultcode.data);
429
430exit:
431    cfg80211_scan_done(request, err ? 1 : 0);
432    priv->scan_request = NULL;
433    return err;
434}
435
436int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
437{
438    struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
439    wlandevice_t *wlandev = priv->wlandev;
440    u32 data;
441    int result;
442    int err = 0;
443
444    if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
445        if (wiphy->rts_threshold == -1)
446            data = 2347;
447        else
448            data = wiphy->rts_threshold;
449
450        result = prism2_domibset_uint32(wlandev,
451                        DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
452                        data);
453        if (result) {
454            err = -EFAULT;
455            goto exit;
456        }
457    }
458
459    if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
460        if (wiphy->frag_threshold == -1)
461            data = 2346;
462        else
463            data = wiphy->frag_threshold;
464
465        result = prism2_domibset_uint32(wlandev,
466                        DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
467                        data);
468        if (result) {
469            err = -EFAULT;
470            goto exit;
471        }
472    }
473
474exit:
475    return err;
476}
477
478int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
479           struct cfg80211_connect_params *sme)
480{
481    wlandevice_t *wlandev = dev->ml_priv;
482    struct ieee80211_channel *channel = sme->channel;
483    struct p80211msg_lnxreq_autojoin msg_join;
484    u32 did;
485    int length = sme->ssid_len;
486    int chan = -1;
487    int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
488        (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
489    int result;
490    int err = 0;
491
492    /* Set the channel */
493    if (channel) {
494        chan = ieee80211_frequency_to_channel(channel->center_freq);
495        result = prism2_domibset_uint32(wlandev,
496                        DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
497                        chan);
498        if (result)
499            goto exit;
500    }
501
502    /* Set the authorisation */
503    if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
504        ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
505            msg_join.authtype.data = P80211ENUM_authalg_opensystem;
506    else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
507        ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
508            msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
509    else
510        printk(KERN_WARNING
511            "Unhandled authorisation type for connect (%d)\n",
512            sme->auth_type);
513
514    /* Set the encryption - we only support wep */
515    if (is_wep) {
516        if (sme->key) {
517            result = prism2_domibset_uint32(wlandev,
518                DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
519                sme->key_idx);
520            if (result)
521                goto exit;
522
523            /* send key to driver */
524            switch (sme->key_idx) {
525            case 0:
526                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
527                break;
528
529            case 1:
530                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
531                break;
532
533            case 2:
534                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
535                break;
536
537            case 3:
538                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
539                break;
540
541            default:
542                err = -EINVAL;
543                goto exit;
544            }
545
546            result = prism2_domibset_pstr32(wlandev,
547                            did, sme->key_len,
548                            (u8 *)sme->key);
549            if (result)
550                goto exit;
551
552        }
553
554        /* Assume we should set privacy invoked and exclude unencrypted
555           We could possibly use sme->privacy here, but the assumption
556           seems reasonable anyway */
557        result = prism2_domibset_uint32(wlandev,
558                        DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
559                        P80211ENUM_truth_true);
560        if (result)
561            goto exit;
562
563        result = prism2_domibset_uint32(wlandev,
564                        DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
565                        P80211ENUM_truth_true);
566        if (result)
567            goto exit;
568
569    } else {
570        /* Assume we should unset privacy invoked
571           and exclude unencrypted */
572        result = prism2_domibset_uint32(wlandev,
573                        DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
574                        P80211ENUM_truth_false);
575        if (result)
576            goto exit;
577
578        result = prism2_domibset_uint32(wlandev,
579                        DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
580                        P80211ENUM_truth_false);
581        if (result)
582            goto exit;
583
584    }
585
586    /* Now do the actual join. Note there is no way that I can
587       see to request a specific bssid */
588    msg_join.msgcode = DIDmsg_lnxreq_autojoin;
589
590    memcpy(msg_join.ssid.data.data, sme->ssid, length);
591    msg_join.ssid.data.len = length;
592
593    result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
594
595exit:
596    if (result)
597        err = -EFAULT;
598
599    return err;
600}
601
602int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
603              u16 reason_code)
604{
605    wlandevice_t *wlandev = dev->ml_priv;
606    struct p80211msg_lnxreq_autojoin msg_join;
607    int result;
608    int err = 0;
609
610
611    /* Do a join, with a bogus ssid. Thats the only way I can think of */
612    msg_join.msgcode = DIDmsg_lnxreq_autojoin;
613
614    memcpy(msg_join.ssid.data.data, "---", 3);
615    msg_join.ssid.data.len = 3;
616
617    result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
618
619    if (result)
620        err = -EFAULT;
621
622    return err;
623}
624
625
626int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
627             struct cfg80211_ibss_params *params)
628{
629    return -EOPNOTSUPP;
630}
631
632int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
633{
634    return -EOPNOTSUPP;
635}
636
637
638int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
639            int mbm)
640{
641    struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
642    wlandevice_t *wlandev = priv->wlandev;
643    u32 data;
644    int result;
645    int err = 0;
646
647    if (type == NL80211_TX_POWER_AUTOMATIC)
648        data = 30;
649    else
650        data = MBM_TO_DBM(mbm);
651
652    result = prism2_domibset_uint32(wlandev,
653        DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
654        data);
655
656    if (result) {
657        err = -EFAULT;
658        goto exit;
659    }
660
661exit:
662    return err;
663}
664
665int prism2_get_tx_power(struct wiphy *wiphy, int *dbm)
666{
667    struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
668    wlandevice_t *wlandev = priv->wlandev;
669    struct p80211msg_dot11req_mibget msg;
670    p80211item_uint32_t *mibitem;
671    int result;
672    int err = 0;
673
674    mibitem = (p80211item_uint32_t *) &msg.mibattribute.data;
675    msg.msgcode = DIDmsg_dot11req_mibget;
676    mibitem->did =
677        DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
678
679    result = p80211req_dorequest(wlandev, (u8 *) &msg);
680
681    if (result) {
682        err = -EFAULT;
683        goto exit;
684    }
685
686    *dbm = mibitem->data;
687
688exit:
689    return err;
690}
691
692
693
694
695/* Interface callback functions, passing data back up to the cfg80211 layer */
696void prism2_connect_result(wlandevice_t *wlandev, u8 failed)
697{
698    u16 status = failed ?
699             WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS;
700
701    cfg80211_connect_result(wlandev->netdev, wlandev->bssid,
702                NULL, 0, NULL, 0, status, GFP_KERNEL);
703}
704
705void prism2_disconnected(wlandevice_t *wlandev)
706{
707    cfg80211_disconnected(wlandev->netdev, 0, NULL,
708        0, GFP_KERNEL);
709}
710
711void prism2_roamed(wlandevice_t *wlandev)
712{
713    cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid,
714        NULL, 0, NULL, 0, GFP_KERNEL);
715}
716
717
718/* Structures for declaring wiphy interface */
719static const struct cfg80211_ops prism2_usb_cfg_ops = {
720    .change_virtual_intf = prism2_change_virtual_intf,
721    .add_key = prism2_add_key,
722    .get_key = prism2_get_key,
723    .del_key = prism2_del_key,
724    .set_default_key = prism2_set_default_key,
725    .get_station = prism2_get_station,
726    .scan = prism2_scan,
727    .set_wiphy_params = prism2_set_wiphy_params,
728    .connect = prism2_connect,
729    .disconnect = prism2_disconnect,
730    .join_ibss = prism2_join_ibss,
731    .leave_ibss = prism2_leave_ibss,
732    .set_tx_power = prism2_set_tx_power,
733    .get_tx_power = prism2_get_tx_power,
734};
735
736
737/* Functions to create/free wiphy interface */
738struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev)
739{
740    struct wiphy *wiphy;
741    struct prism2_wiphy_private *priv;
742
743    wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv));
744    if (!wiphy)
745        return NULL;
746
747    priv = wiphy_priv(wiphy);
748    priv->wlandev = wlandev;
749    memcpy(priv->channels, prism2_channels, sizeof(prism2_channels));
750    memcpy(priv->rates, prism2_rates, sizeof(prism2_rates));
751    priv->band.channels = priv->channels;
752    priv->band.n_channels = ARRAY_SIZE(prism2_channels);
753    priv->band.bitrates = priv->rates;
754    priv->band.n_bitrates = ARRAY_SIZE(prism2_rates);
755    priv->band.band = IEEE80211_BAND_2GHZ;
756    priv->band.ht_cap.ht_supported = false;
757    wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
758
759    set_wiphy_dev(wiphy, dev);
760    wiphy->privid = prism2_wiphy_privid;
761    wiphy->max_scan_ssids = 1;
762    wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
763                 | BIT(NL80211_IFTYPE_ADHOC);
764    wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
765    wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES;
766    wiphy->cipher_suites = prism2_cipher_suites;
767
768    if (wiphy_register(wiphy) < 0)
769        return NULL;
770
771    return wiphy;
772}
773
774
775void wlan_free_wiphy(struct wiphy *wiphy)
776{
777    wiphy_unregister(wiphy);
778    wiphy_free(wiphy);
779}
780

Archive Download this file



interactive