cfg80211.c 18 KB

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