cfg80211.c 18 KB

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