cfg80211.c 18 KB

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