0001
0002
0003 #include "hfa384x.h"
0004 #include "prism2mgmt.h"
0005
0006
0007 static const struct ieee80211_channel prism2_channels[] = {
0008 { .center_freq = 2412 },
0009 { .center_freq = 2417 },
0010 { .center_freq = 2422 },
0011 { .center_freq = 2427 },
0012 { .center_freq = 2432 },
0013 { .center_freq = 2437 },
0014 { .center_freq = 2442 },
0015 { .center_freq = 2447 },
0016 { .center_freq = 2452 },
0017 { .center_freq = 2457 },
0018 { .center_freq = 2462 },
0019 { .center_freq = 2467 },
0020 { .center_freq = 2472 },
0021 { .center_freq = 2484 },
0022 };
0023
0024 static const struct ieee80211_rate prism2_rates[] = {
0025 { .bitrate = 10 },
0026 { .bitrate = 20 },
0027 { .bitrate = 55 },
0028 { .bitrate = 110 }
0029 };
0030
0031 #define PRISM2_NUM_CIPHER_SUITES 2
0032 static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = {
0033 WLAN_CIPHER_SUITE_WEP40,
0034 WLAN_CIPHER_SUITE_WEP104
0035 };
0036
0037
0038 struct prism2_wiphy_private {
0039 struct wlandevice *wlandev;
0040
0041 struct ieee80211_supported_band band;
0042 struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)];
0043 struct ieee80211_rate rates[ARRAY_SIZE(prism2_rates)];
0044
0045 struct cfg80211_scan_request *scan_request;
0046 };
0047
0048 static const void * const prism2_wiphy_privid = &prism2_wiphy_privid;
0049
0050
0051 static int prism2_result2err(int prism2_result)
0052 {
0053 int err = 0;
0054
0055 switch (prism2_result) {
0056 case P80211ENUM_resultcode_invalid_parameters:
0057 err = -EINVAL;
0058 break;
0059 case P80211ENUM_resultcode_implementation_failure:
0060 err = -EIO;
0061 break;
0062 case P80211ENUM_resultcode_not_supported:
0063 err = -EOPNOTSUPP;
0064 break;
0065 default:
0066 err = 0;
0067 break;
0068 }
0069
0070 return err;
0071 }
0072
0073 static int prism2_domibset_uint32(struct wlandevice *wlandev,
0074 u32 did, u32 data)
0075 {
0076 struct p80211msg_dot11req_mibset msg;
0077 struct p80211item_uint32 *mibitem =
0078 (struct p80211item_uint32 *)&msg.mibattribute.data;
0079
0080 msg.msgcode = DIDMSG_DOT11REQ_MIBSET;
0081 mibitem->did = did;
0082 mibitem->data = data;
0083
0084 return p80211req_dorequest(wlandev, (u8 *)&msg);
0085 }
0086
0087 static int prism2_domibset_pstr32(struct wlandevice *wlandev,
0088 u32 did, u8 len, const u8 *data)
0089 {
0090 struct p80211msg_dot11req_mibset msg;
0091 struct p80211item_pstr32 *mibitem =
0092 (struct p80211item_pstr32 *)&msg.mibattribute.data;
0093
0094 msg.msgcode = DIDMSG_DOT11REQ_MIBSET;
0095 mibitem->did = did;
0096 mibitem->data.len = len;
0097 memcpy(mibitem->data.data, data, len);
0098
0099 return p80211req_dorequest(wlandev, (u8 *)&msg);
0100 }
0101
0102
0103 static int prism2_change_virtual_intf(struct wiphy *wiphy,
0104 struct net_device *dev,
0105 enum nl80211_iftype type,
0106 struct vif_params *params)
0107 {
0108 struct wlandevice *wlandev = dev->ml_priv;
0109 u32 data;
0110 int result;
0111 int err = 0;
0112
0113 switch (type) {
0114 case NL80211_IFTYPE_ADHOC:
0115 if (wlandev->macmode == WLAN_MACMODE_IBSS_STA)
0116 goto exit;
0117 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
0118 data = 0;
0119 break;
0120 case NL80211_IFTYPE_STATION:
0121 if (wlandev->macmode == WLAN_MACMODE_ESS_STA)
0122 goto exit;
0123 wlandev->macmode = WLAN_MACMODE_ESS_STA;
0124 data = 1;
0125 break;
0126 default:
0127 netdev_warn(dev, "Operation mode: %d not support\n", type);
0128 return -EOPNOTSUPP;
0129 }
0130
0131
0132 result = prism2_domibset_uint32(wlandev,
0133 DIDMIB_P2_STATIC_CNFPORTTYPE,
0134 data);
0135
0136 if (result)
0137 err = -EFAULT;
0138
0139 dev->ieee80211_ptr->iftype = type;
0140
0141 exit:
0142 return err;
0143 }
0144
0145 static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
0146 u8 key_index, bool pairwise, const u8 *mac_addr,
0147 struct key_params *params)
0148 {
0149 struct wlandevice *wlandev = dev->ml_priv;
0150 u32 did;
0151
0152 if (key_index >= NUM_WEPKEYS)
0153 return -EINVAL;
0154
0155 if (params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
0156 params->cipher != WLAN_CIPHER_SUITE_WEP104) {
0157 pr_debug("Unsupported cipher suite\n");
0158 return -EFAULT;
0159 }
0160
0161 if (prism2_domibset_uint32(wlandev,
0162 DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID,
0163 key_index))
0164 return -EFAULT;
0165
0166
0167 did = didmib_dot11smt_wepdefaultkeystable_key(key_index + 1);
0168
0169 if (prism2_domibset_pstr32(wlandev, did, params->key_len, params->key))
0170 return -EFAULT;
0171 return 0;
0172 }
0173
0174 static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
0175 u8 key_index, bool pairwise,
0176 const u8 *mac_addr, void *cookie,
0177 void (*callback)(void *cookie, struct key_params*))
0178 {
0179 struct wlandevice *wlandev = dev->ml_priv;
0180 struct key_params params;
0181 int len;
0182
0183 if (key_index >= NUM_WEPKEYS)
0184 return -EINVAL;
0185
0186 len = wlandev->wep_keylens[key_index];
0187 memset(¶ms, 0, sizeof(params));
0188
0189 if (len == 13)
0190 params.cipher = WLAN_CIPHER_SUITE_WEP104;
0191 else if (len == 5)
0192 params.cipher = WLAN_CIPHER_SUITE_WEP104;
0193 else
0194 return -ENOENT;
0195 params.key_len = len;
0196 params.key = wlandev->wep_keys[key_index];
0197 params.seq_len = 0;
0198
0199 callback(cookie, ¶ms);
0200
0201 return 0;
0202 }
0203
0204 static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
0205 u8 key_index, bool pairwise, const u8 *mac_addr)
0206 {
0207 struct wlandevice *wlandev = dev->ml_priv;
0208 u32 did;
0209 int err = 0;
0210 int result = 0;
0211
0212
0213
0214
0215
0216 if (key_index >= NUM_WEPKEYS)
0217 return -EINVAL;
0218
0219
0220 did = didmib_dot11smt_wepdefaultkeystable_key(key_index + 1);
0221 result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000");
0222
0223 if (result)
0224 err = -EFAULT;
0225
0226 return err;
0227 }
0228
0229 static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
0230 u8 key_index, bool unicast, bool multicast)
0231 {
0232 struct wlandevice *wlandev = dev->ml_priv;
0233
0234 return prism2_domibset_uint32(wlandev,
0235 DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID,
0236 key_index);
0237 }
0238
0239 static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
0240 const u8 *mac, struct station_info *sinfo)
0241 {
0242 struct wlandevice *wlandev = dev->ml_priv;
0243 struct p80211msg_lnxreq_commsquality quality;
0244 int result;
0245
0246 memset(sinfo, 0, sizeof(*sinfo));
0247
0248 if (!wlandev || (wlandev->msdstate != WLAN_MSD_RUNNING))
0249 return -EOPNOTSUPP;
0250
0251
0252 quality.msgcode = DIDMSG_LNXREQ_COMMSQUALITY;
0253 quality.dbm.data = P80211ENUM_truth_true;
0254 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
0255
0256
0257 if (!wlandev->mlmerequest)
0258 return -EOPNOTSUPP;
0259
0260 result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality);
0261
0262 if (result == 0) {
0263 sinfo->txrate.legacy = quality.txrate.data;
0264 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
0265 sinfo->signal = quality.level.data;
0266 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
0267 }
0268
0269 return result;
0270 }
0271
0272 static int prism2_scan(struct wiphy *wiphy,
0273 struct cfg80211_scan_request *request)
0274 {
0275 struct net_device *dev;
0276 struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
0277 struct wlandevice *wlandev;
0278 struct p80211msg_dot11req_scan msg1;
0279 struct p80211msg_dot11req_scan_results *msg2;
0280 struct cfg80211_bss *bss;
0281 struct cfg80211_scan_info info = {};
0282
0283 int result;
0284 int err = 0;
0285 int numbss = 0;
0286 int i = 0;
0287 u8 ie_buf[46];
0288 int ie_len;
0289
0290 if (!request)
0291 return -EINVAL;
0292
0293 dev = request->wdev->netdev;
0294 wlandev = dev->ml_priv;
0295
0296 if (priv->scan_request && priv->scan_request != request)
0297 return -EBUSY;
0298
0299 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
0300 netdev_err(dev, "Can't scan in AP mode\n");
0301 return -EOPNOTSUPP;
0302 }
0303
0304 msg2 = kzalloc(sizeof(*msg2), GFP_KERNEL);
0305 if (!msg2)
0306 return -ENOMEM;
0307
0308 priv->scan_request = request;
0309
0310 memset(&msg1, 0x00, sizeof(msg1));
0311 msg1.msgcode = DIDMSG_DOT11REQ_SCAN;
0312 msg1.bsstype.data = P80211ENUM_bsstype_any;
0313
0314 memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data));
0315 msg1.bssid.data.len = 6;
0316
0317 if (request->n_ssids > 0) {
0318 msg1.scantype.data = P80211ENUM_scantype_active;
0319 msg1.ssid.data.len = request->ssids->ssid_len;
0320 memcpy(msg1.ssid.data.data,
0321 request->ssids->ssid, request->ssids->ssid_len);
0322 } else {
0323 msg1.scantype.data = 0;
0324 }
0325 msg1.probedelay.data = 0;
0326
0327 for (i = 0;
0328 (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
0329 i++)
0330 msg1.channellist.data.data[i] =
0331 ieee80211_frequency_to_channel(request->channels[i]->center_freq);
0332 msg1.channellist.data.len = request->n_channels;
0333
0334 msg1.maxchanneltime.data = 250;
0335 msg1.minchanneltime.data = 200;
0336
0337 result = p80211req_dorequest(wlandev, (u8 *)&msg1);
0338 if (result) {
0339 err = prism2_result2err(msg1.resultcode.data);
0340 goto exit;
0341 }
0342
0343 numbss = msg1.numbss.data;
0344
0345 for (i = 0; i < numbss; i++) {
0346 int freq;
0347
0348 msg2->msgcode = DIDMSG_DOT11REQ_SCAN_RESULTS;
0349 msg2->bssindex.data = i;
0350
0351 result = p80211req_dorequest(wlandev, (u8 *)&msg2);
0352 if ((result != 0) ||
0353 (msg2->resultcode.data != P80211ENUM_resultcode_success)) {
0354 break;
0355 }
0356
0357 ie_buf[0] = WLAN_EID_SSID;
0358 ie_buf[1] = msg2->ssid.data.len;
0359 ie_len = ie_buf[1] + 2;
0360 memcpy(&ie_buf[2], &msg2->ssid.data.data, msg2->ssid.data.len);
0361 freq = ieee80211_channel_to_frequency(msg2->dschannel.data,
0362 NL80211_BAND_2GHZ);
0363 bss = cfg80211_inform_bss(wiphy,
0364 ieee80211_get_channel(wiphy, freq),
0365 CFG80211_BSS_FTYPE_UNKNOWN,
0366 (const u8 *)&msg2->bssid.data.data,
0367 msg2->timestamp.data, msg2->capinfo.data,
0368 msg2->beaconperiod.data,
0369 ie_buf,
0370 ie_len,
0371 (msg2->signal.data - 65536) * 100,
0372 GFP_KERNEL);
0373
0374 if (!bss) {
0375 err = -ENOMEM;
0376 goto exit;
0377 }
0378
0379 cfg80211_put_bss(wiphy, bss);
0380 }
0381
0382 if (result)
0383 err = prism2_result2err(msg2->resultcode.data);
0384
0385 exit:
0386 info.aborted = !!(err);
0387 cfg80211_scan_done(request, &info);
0388 priv->scan_request = NULL;
0389 kfree(msg2);
0390 return err;
0391 }
0392
0393 static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
0394 {
0395 struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
0396 struct wlandevice *wlandev = priv->wlandev;
0397 u32 data;
0398 int result;
0399 int err = 0;
0400
0401 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
0402 if (wiphy->rts_threshold == -1)
0403 data = 2347;
0404 else
0405 data = wiphy->rts_threshold;
0406
0407 result = prism2_domibset_uint32(wlandev,
0408 DIDMIB_DOT11MAC_OPERATIONTABLE_RTSTHRESHOLD,
0409 data);
0410 if (result) {
0411 err = -EFAULT;
0412 goto exit;
0413 }
0414 }
0415
0416 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
0417 if (wiphy->frag_threshold == -1)
0418 data = 2346;
0419 else
0420 data = wiphy->frag_threshold;
0421
0422 result = prism2_domibset_uint32(wlandev,
0423 DIDMIB_DOT11MAC_OPERATIONTABLE_FRAGMENTATIONTHRESHOLD,
0424 data);
0425 if (result) {
0426 err = -EFAULT;
0427 goto exit;
0428 }
0429 }
0430
0431 exit:
0432 return err;
0433 }
0434
0435 static int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
0436 struct cfg80211_connect_params *sme)
0437 {
0438 struct wlandevice *wlandev = dev->ml_priv;
0439 struct ieee80211_channel *channel = sme->channel;
0440 struct p80211msg_lnxreq_autojoin msg_join;
0441 u32 did;
0442 int length = sme->ssid_len;
0443 int chan = -1;
0444 int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
0445 (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
0446 int result;
0447 int err = 0;
0448
0449
0450 if (channel) {
0451 chan = ieee80211_frequency_to_channel(channel->center_freq);
0452 result = prism2_domibset_uint32(wlandev,
0453 DIDMIB_DOT11PHY_DSSSTABLE_CURRENTCHANNEL,
0454 chan);
0455 if (result)
0456 goto exit;
0457 }
0458
0459
0460 if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
0461 ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
0462 msg_join.authtype.data = P80211ENUM_authalg_opensystem;
0463 else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
0464 ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
0465 msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
0466 else
0467 netdev_warn(dev,
0468 "Unhandled authorisation type for connect (%d)\n",
0469 sme->auth_type);
0470
0471
0472 if (is_wep) {
0473 if (sme->key) {
0474 if (sme->key_idx >= NUM_WEPKEYS)
0475 return -EINVAL;
0476
0477 result = prism2_domibset_uint32(wlandev,
0478 DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID,
0479 sme->key_idx);
0480 if (result)
0481 goto exit;
0482
0483
0484 did = didmib_dot11smt_wepdefaultkeystable_key(sme->key_idx + 1);
0485 result = prism2_domibset_pstr32(wlandev,
0486 did, sme->key_len,
0487 (u8 *)sme->key);
0488 if (result)
0489 goto exit;
0490 }
0491
0492
0493
0494
0495
0496 result = prism2_domibset_uint32(wlandev,
0497 DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED,
0498 P80211ENUM_truth_true);
0499 if (result)
0500 goto exit;
0501
0502 result = prism2_domibset_uint32(wlandev,
0503 DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED,
0504 P80211ENUM_truth_true);
0505 if (result)
0506 goto exit;
0507
0508 } else {
0509
0510
0511
0512 result = prism2_domibset_uint32(wlandev,
0513 DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED,
0514 P80211ENUM_truth_false);
0515 if (result)
0516 goto exit;
0517
0518 result = prism2_domibset_uint32(wlandev,
0519 DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED,
0520 P80211ENUM_truth_false);
0521 if (result)
0522 goto exit;
0523 }
0524
0525
0526
0527
0528 msg_join.msgcode = DIDMSG_LNXREQ_AUTOJOIN;
0529
0530 memcpy(msg_join.ssid.data.data, sme->ssid, length);
0531 msg_join.ssid.data.len = length;
0532
0533 result = p80211req_dorequest(wlandev, (u8 *)&msg_join);
0534
0535 exit:
0536 if (result)
0537 err = -EFAULT;
0538
0539 return err;
0540 }
0541
0542 static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
0543 u16 reason_code)
0544 {
0545 struct wlandevice *wlandev = dev->ml_priv;
0546 struct p80211msg_lnxreq_autojoin msg_join;
0547 int result;
0548 int err = 0;
0549
0550
0551 msg_join.msgcode = DIDMSG_LNXREQ_AUTOJOIN;
0552
0553 memcpy(msg_join.ssid.data.data, "---", 3);
0554 msg_join.ssid.data.len = 3;
0555
0556 result = p80211req_dorequest(wlandev, (u8 *)&msg_join);
0557
0558 if (result)
0559 err = -EFAULT;
0560
0561 return err;
0562 }
0563
0564 static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
0565 struct cfg80211_ibss_params *params)
0566 {
0567 return -EOPNOTSUPP;
0568 }
0569
0570 static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
0571 {
0572 return -EOPNOTSUPP;
0573 }
0574
0575 static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
0576 enum nl80211_tx_power_setting type, int mbm)
0577 {
0578 struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
0579 struct wlandevice *wlandev = priv->wlandev;
0580 u32 data;
0581 int result;
0582 int err = 0;
0583
0584 if (type == NL80211_TX_POWER_AUTOMATIC)
0585 data = 30;
0586 else
0587 data = MBM_TO_DBM(mbm);
0588
0589 result = prism2_domibset_uint32(wlandev,
0590 DIDMIB_DOT11PHY_TXPOWERTABLE_CURRENTTXPOWERLEVEL,
0591 data);
0592
0593 if (result) {
0594 err = -EFAULT;
0595 goto exit;
0596 }
0597
0598 exit:
0599 return err;
0600 }
0601
0602 static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
0603 int *dbm)
0604 {
0605 struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
0606 struct wlandevice *wlandev = priv->wlandev;
0607 struct p80211msg_dot11req_mibget msg;
0608 struct p80211item_uint32 *mibitem;
0609 int result;
0610 int err = 0;
0611
0612 mibitem = (struct p80211item_uint32 *)&msg.mibattribute.data;
0613 msg.msgcode = DIDMSG_DOT11REQ_MIBGET;
0614 mibitem->did = DIDMIB_DOT11PHY_TXPOWERTABLE_CURRENTTXPOWERLEVEL;
0615
0616 result = p80211req_dorequest(wlandev, (u8 *)&msg);
0617
0618 if (result) {
0619 err = -EFAULT;
0620 goto exit;
0621 }
0622
0623 *dbm = mibitem->data;
0624
0625 exit:
0626 return err;
0627 }
0628
0629
0630 void prism2_connect_result(struct wlandevice *wlandev, u8 failed)
0631 {
0632 u16 status = failed ?
0633 WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS;
0634
0635 cfg80211_connect_result(wlandev->netdev, wlandev->bssid,
0636 NULL, 0, NULL, 0, status, GFP_KERNEL);
0637 }
0638
0639 void prism2_disconnected(struct wlandevice *wlandev)
0640 {
0641 cfg80211_disconnected(wlandev->netdev, 0, NULL,
0642 0, false, GFP_KERNEL);
0643 }
0644
0645 void prism2_roamed(struct wlandevice *wlandev)
0646 {
0647 struct cfg80211_roam_info roam_info = {
0648 .links[0].bssid = wlandev->bssid,
0649 };
0650
0651 cfg80211_roamed(wlandev->netdev, &roam_info, GFP_KERNEL);
0652 }
0653
0654
0655 static const struct cfg80211_ops prism2_usb_cfg_ops = {
0656 .change_virtual_intf = prism2_change_virtual_intf,
0657 .add_key = prism2_add_key,
0658 .get_key = prism2_get_key,
0659 .del_key = prism2_del_key,
0660 .set_default_key = prism2_set_default_key,
0661 .get_station = prism2_get_station,
0662 .scan = prism2_scan,
0663 .set_wiphy_params = prism2_set_wiphy_params,
0664 .connect = prism2_connect,
0665 .disconnect = prism2_disconnect,
0666 .join_ibss = prism2_join_ibss,
0667 .leave_ibss = prism2_leave_ibss,
0668 .set_tx_power = prism2_set_tx_power,
0669 .get_tx_power = prism2_get_tx_power,
0670 };
0671
0672
0673 static struct wiphy *wlan_create_wiphy(struct device *dev,
0674 struct wlandevice *wlandev)
0675 {
0676 struct wiphy *wiphy;
0677 struct prism2_wiphy_private *priv;
0678
0679 wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv));
0680 if (!wiphy)
0681 return NULL;
0682
0683 priv = wiphy_priv(wiphy);
0684 priv->wlandev = wlandev;
0685 memcpy(priv->channels, prism2_channels, sizeof(prism2_channels));
0686 memcpy(priv->rates, prism2_rates, sizeof(prism2_rates));
0687 priv->band.channels = priv->channels;
0688 priv->band.n_channels = ARRAY_SIZE(prism2_channels);
0689 priv->band.bitrates = priv->rates;
0690 priv->band.n_bitrates = ARRAY_SIZE(prism2_rates);
0691 priv->band.band = NL80211_BAND_2GHZ;
0692 priv->band.ht_cap.ht_supported = false;
0693 wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
0694
0695 set_wiphy_dev(wiphy, dev);
0696 wiphy->privid = prism2_wiphy_privid;
0697 wiphy->max_scan_ssids = 1;
0698 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
0699 | BIT(NL80211_IFTYPE_ADHOC);
0700 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
0701 wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES;
0702 wiphy->cipher_suites = prism2_cipher_suites;
0703
0704 if (wiphy_register(wiphy) < 0) {
0705 wiphy_free(wiphy);
0706 return NULL;
0707 }
0708
0709 return wiphy;
0710 }
0711
0712 static void wlan_free_wiphy(struct wiphy *wiphy)
0713 {
0714 wiphy_unregister(wiphy);
0715 wiphy_free(wiphy);
0716 }