cfg80211.c 18 KB

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