prism2mgmt.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  1. // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
  2. /* src/prism2/driver/prism2mgmt.c
  3. *
  4. * Management request handler functions.
  5. *
  6. * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  7. * --------------------------------------------------------------------
  8. *
  9. * linux-wlan
  10. *
  11. * The contents of this file are subject to the Mozilla Public
  12. * License Version 1.1 (the "License"); you may not use this file
  13. * except in compliance with the License. You may obtain a copy of
  14. * the License at http://www.mozilla.org/MPL/
  15. *
  16. * Software distributed under the License is distributed on an "AS
  17. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  18. * implied. See the License for the specific language governing
  19. * rights and limitations under the License.
  20. *
  21. * Alternatively, the contents of this file may be used under the
  22. * terms of the GNU Public License version 2 (the "GPL"), in which
  23. * case the provisions of the GPL are applicable instead of the
  24. * above. If you wish to allow the use of your version of this file
  25. * only under the terms of the GPL and not to allow others to use
  26. * your version of this file under the MPL, indicate your decision
  27. * by deleting the provisions above and replace them with the notice
  28. * and other provisions required by the GPL. If you do not delete
  29. * the provisions above, a recipient may use your version of this
  30. * file under either the MPL or the GPL.
  31. *
  32. * --------------------------------------------------------------------
  33. *
  34. * Inquiries regarding the linux-wlan Open Source project can be
  35. * made directly to:
  36. *
  37. * AbsoluteValue Systems Inc.
  38. * info@linux-wlan.com
  39. * http://www.linux-wlan.com
  40. *
  41. * --------------------------------------------------------------------
  42. *
  43. * Portions of the development of this software were funded by
  44. * Intersil Corporation as part of PRISM(R) chipset product development.
  45. *
  46. * --------------------------------------------------------------------
  47. *
  48. * The functions in this file handle management requests sent from
  49. * user mode.
  50. *
  51. * Most of these functions have two separate blocks of code that are
  52. * conditional on whether this is a station or an AP. This is used
  53. * to separate out the STA and AP responses to these management primitives.
  54. * It's a choice (good, bad, indifferent?) to have the code in the same
  55. * place so it's clear that the same primitive is implemented in both
  56. * cases but has different behavior.
  57. *
  58. * --------------------------------------------------------------------
  59. */
  60. #include <linux/if_arp.h>
  61. #include <linux/module.h>
  62. #include <linux/kernel.h>
  63. #include <linux/wait.h>
  64. #include <linux/sched.h>
  65. #include <linux/types.h>
  66. #include <linux/wireless.h>
  67. #include <linux/netdevice.h>
  68. #include <linux/delay.h>
  69. #include <linux/io.h>
  70. #include <asm/byteorder.h>
  71. #include <linux/random.h>
  72. #include <linux/usb.h>
  73. #include <linux/bitops.h>
  74. #include "p80211types.h"
  75. #include "p80211hdr.h"
  76. #include "p80211mgmt.h"
  77. #include "p80211conv.h"
  78. #include "p80211msg.h"
  79. #include "p80211netdev.h"
  80. #include "p80211metadef.h"
  81. #include "p80211metastruct.h"
  82. #include "hfa384x.h"
  83. #include "prism2mgmt.h"
  84. /* Converts 802.11 format rate specifications to prism2 */
  85. static inline u16 p80211rate_to_p2bit(u32 rate)
  86. {
  87. switch (rate & ~BIT(7)) {
  88. case 2:
  89. return BIT(0);
  90. case 4:
  91. return BIT(1);
  92. case 11:
  93. return BIT(2);
  94. case 22:
  95. return BIT(3);
  96. default:
  97. return 0;
  98. }
  99. }
  100. /*----------------------------------------------------------------
  101. * prism2mgmt_scan
  102. *
  103. * Initiate a scan for BSSs.
  104. *
  105. * This function corresponds to MLME-scan.request and part of
  106. * MLME-scan.confirm. As far as I can tell in the standard, there
  107. * are no restrictions on when a scan.request may be issued. We have
  108. * to handle in whatever state the driver/MAC happen to be.
  109. *
  110. * Arguments:
  111. * wlandev wlan device structure
  112. * msgp ptr to msg buffer
  113. *
  114. * Returns:
  115. * 0 success and done
  116. * <0 success, but we're waiting for something to finish.
  117. * >0 an error occurred while handling the message.
  118. * Side effects:
  119. *
  120. * Call context:
  121. * process thread (usually)
  122. * interrupt
  123. *----------------------------------------------------------------
  124. */
  125. int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp)
  126. {
  127. int result = 0;
  128. struct hfa384x *hw = wlandev->priv;
  129. struct p80211msg_dot11req_scan *msg = msgp;
  130. u16 roamingmode, word;
  131. int i, timeout;
  132. int istmpenable = 0;
  133. struct hfa384x_host_scan_request_data scanreq;
  134. /* gatekeeper check */
  135. if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
  136. hw->ident_sta_fw.minor,
  137. hw->ident_sta_fw.variant) <
  138. HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
  139. netdev_err(wlandev->netdev,
  140. "HostScan not supported with current firmware (<1.3.2).\n");
  141. result = 1;
  142. msg->resultcode.data = P80211ENUM_resultcode_not_supported;
  143. goto exit;
  144. }
  145. memset(&scanreq, 0, sizeof(scanreq));
  146. /* save current roaming mode */
  147. result = hfa384x_drvr_getconfig16(hw,
  148. HFA384x_RID_CNFROAMINGMODE,
  149. &roamingmode);
  150. if (result) {
  151. netdev_err(wlandev->netdev,
  152. "getconfig(ROAMMODE) failed. result=%d\n", result);
  153. msg->resultcode.data =
  154. P80211ENUM_resultcode_implementation_failure;
  155. goto exit;
  156. }
  157. /* drop into mode 3 for the scan */
  158. result = hfa384x_drvr_setconfig16(hw,
  159. HFA384x_RID_CNFROAMINGMODE,
  160. HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
  161. if (result) {
  162. netdev_err(wlandev->netdev,
  163. "setconfig(ROAMINGMODE) failed. result=%d\n",
  164. result);
  165. msg->resultcode.data =
  166. P80211ENUM_resultcode_implementation_failure;
  167. goto exit;
  168. }
  169. /* active or passive? */
  170. if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
  171. hw->ident_sta_fw.minor,
  172. hw->ident_sta_fw.variant) >
  173. HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
  174. if (msg->scantype.data != P80211ENUM_scantype_active)
  175. word = msg->maxchanneltime.data;
  176. else
  177. word = 0;
  178. result =
  179. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
  180. word);
  181. if (result) {
  182. netdev_warn(wlandev->netdev,
  183. "Passive scan not supported with current firmware. (<1.5.1)\n");
  184. }
  185. }
  186. /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
  187. word = HFA384x_RATEBIT_2;
  188. scanreq.tx_rate = cpu_to_le16(word);
  189. /* set up the channel list */
  190. word = 0;
  191. for (i = 0; i < msg->channellist.data.len; i++) {
  192. u8 channel = msg->channellist.data.data[i];
  193. if (channel > 14)
  194. continue;
  195. /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
  196. word |= (1 << (channel - 1));
  197. }
  198. scanreq.channel_list = cpu_to_le16(word);
  199. /* set up the ssid, if present. */
  200. scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len);
  201. memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
  202. /* Enable the MAC port if it's not already enabled */
  203. result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
  204. if (result) {
  205. netdev_err(wlandev->netdev,
  206. "getconfig(PORTSTATUS) failed. result=%d\n", result);
  207. msg->resultcode.data =
  208. P80211ENUM_resultcode_implementation_failure;
  209. goto exit;
  210. }
  211. if (word == HFA384x_PORTSTATUS_DISABLED) {
  212. __le16 wordbuf[17];
  213. result = hfa384x_drvr_setconfig16(hw,
  214. HFA384x_RID_CNFROAMINGMODE,
  215. HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
  216. if (result) {
  217. netdev_err(wlandev->netdev,
  218. "setconfig(ROAMINGMODE) failed. result=%d\n",
  219. result);
  220. msg->resultcode.data =
  221. P80211ENUM_resultcode_implementation_failure;
  222. goto exit;
  223. }
  224. /* Construct a bogus SSID and assign it to OwnSSID and
  225. * DesiredSSID
  226. */
  227. wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN);
  228. get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
  229. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
  230. wordbuf,
  231. HFA384x_RID_CNFOWNSSID_LEN);
  232. if (result) {
  233. netdev_err(wlandev->netdev, "Failed to set OwnSSID.\n");
  234. msg->resultcode.data =
  235. P80211ENUM_resultcode_implementation_failure;
  236. goto exit;
  237. }
  238. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
  239. wordbuf,
  240. HFA384x_RID_CNFDESIREDSSID_LEN);
  241. if (result) {
  242. netdev_err(wlandev->netdev,
  243. "Failed to set DesiredSSID.\n");
  244. msg->resultcode.data =
  245. P80211ENUM_resultcode_implementation_failure;
  246. goto exit;
  247. }
  248. /* bsstype */
  249. result = hfa384x_drvr_setconfig16(hw,
  250. HFA384x_RID_CNFPORTTYPE,
  251. HFA384x_PORTTYPE_IBSS);
  252. if (result) {
  253. netdev_err(wlandev->netdev,
  254. "Failed to set CNFPORTTYPE.\n");
  255. msg->resultcode.data =
  256. P80211ENUM_resultcode_implementation_failure;
  257. goto exit;
  258. }
  259. /* ibss options */
  260. result = hfa384x_drvr_setconfig16(hw,
  261. HFA384x_RID_CREATEIBSS,
  262. HFA384x_CREATEIBSS_JOINCREATEIBSS);
  263. if (result) {
  264. netdev_err(wlandev->netdev,
  265. "Failed to set CREATEIBSS.\n");
  266. msg->resultcode.data =
  267. P80211ENUM_resultcode_implementation_failure;
  268. goto exit;
  269. }
  270. result = hfa384x_drvr_enable(hw, 0);
  271. if (result) {
  272. netdev_err(wlandev->netdev,
  273. "drvr_enable(0) failed. result=%d\n",
  274. result);
  275. msg->resultcode.data =
  276. P80211ENUM_resultcode_implementation_failure;
  277. goto exit;
  278. }
  279. istmpenable = 1;
  280. }
  281. /* Figure out our timeout first Kus, then HZ */
  282. timeout = msg->channellist.data.len * msg->maxchanneltime.data;
  283. timeout = (timeout * HZ) / 1000;
  284. /* Issue the scan request */
  285. hw->scanflag = 0;
  286. result = hfa384x_drvr_setconfig(hw,
  287. HFA384x_RID_HOSTSCAN, &scanreq,
  288. sizeof(scanreq));
  289. if (result) {
  290. netdev_err(wlandev->netdev,
  291. "setconfig(SCANREQUEST) failed. result=%d\n",
  292. result);
  293. msg->resultcode.data =
  294. P80211ENUM_resultcode_implementation_failure;
  295. goto exit;
  296. }
  297. /* sleep until info frame arrives */
  298. wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
  299. msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
  300. if (hw->scanflag == -1)
  301. hw->scanflag = 0;
  302. msg->numbss.data = hw->scanflag;
  303. hw->scanflag = 0;
  304. /* Disable port if we temporarily enabled it. */
  305. if (istmpenable) {
  306. result = hfa384x_drvr_disable(hw, 0);
  307. if (result) {
  308. netdev_err(wlandev->netdev,
  309. "drvr_disable(0) failed. result=%d\n",
  310. result);
  311. msg->resultcode.data =
  312. P80211ENUM_resultcode_implementation_failure;
  313. goto exit;
  314. }
  315. }
  316. /* restore original roaming mode */
  317. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
  318. roamingmode);
  319. if (result) {
  320. netdev_err(wlandev->netdev,
  321. "setconfig(ROAMMODE) failed. result=%d\n", result);
  322. msg->resultcode.data =
  323. P80211ENUM_resultcode_implementation_failure;
  324. goto exit;
  325. }
  326. result = 0;
  327. msg->resultcode.data = P80211ENUM_resultcode_success;
  328. exit:
  329. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  330. return result;
  331. }
  332. /*----------------------------------------------------------------
  333. * prism2mgmt_scan_results
  334. *
  335. * Retrieve the BSS description for one of the BSSs identified in
  336. * a scan.
  337. *
  338. * Arguments:
  339. * wlandev wlan device structure
  340. * msgp ptr to msg buffer
  341. *
  342. * Returns:
  343. * 0 success and done
  344. * <0 success, but we're waiting for something to finish.
  345. * >0 an error occurred while handling the message.
  346. * Side effects:
  347. *
  348. * Call context:
  349. * process thread (usually)
  350. * interrupt
  351. *----------------------------------------------------------------
  352. */
  353. int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp)
  354. {
  355. int result = 0;
  356. struct p80211msg_dot11req_scan_results *req;
  357. struct hfa384x *hw = wlandev->priv;
  358. struct hfa384x_hscan_result_sub *item = NULL;
  359. int count;
  360. req = msgp;
  361. req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  362. if (!hw->scanresults) {
  363. netdev_err(wlandev->netdev,
  364. "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
  365. result = 2;
  366. req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  367. goto exit;
  368. }
  369. count = (hw->scanresults->framelen - 3) / 32;
  370. if (count > HFA384x_SCANRESULT_MAX)
  371. count = HFA384x_SCANRESULT_MAX;
  372. if (req->bssindex.data >= count) {
  373. netdev_dbg(wlandev->netdev,
  374. "requested index (%d) out of range (%d)\n",
  375. req->bssindex.data, count);
  376. result = 2;
  377. req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  378. goto exit;
  379. }
  380. item = &hw->scanresults->info.hscanresult.result[req->bssindex.data];
  381. /* signal and noise */
  382. req->signal.status = P80211ENUM_msgitem_status_data_ok;
  383. req->noise.status = P80211ENUM_msgitem_status_data_ok;
  384. req->signal.data = le16_to_cpu(item->sl);
  385. req->noise.data = le16_to_cpu(item->anl);
  386. /* BSSID */
  387. req->bssid.status = P80211ENUM_msgitem_status_data_ok;
  388. req->bssid.data.len = WLAN_BSSID_LEN;
  389. memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
  390. /* SSID */
  391. req->ssid.status = P80211ENUM_msgitem_status_data_ok;
  392. req->ssid.data.len = le16_to_cpu(item->ssid.len);
  393. req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
  394. memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
  395. /* supported rates */
  396. for (count = 0; count < 10; count++)
  397. if (item->supprates[count] == 0)
  398. break;
  399. #define REQBASICRATE(N) \
  400. do { \
  401. if ((count >= (N)) && DOT11_RATE5_ISBASIC_GET( \
  402. item->supprates[(N) - 1])) { \
  403. req->basicrate ## N .data = item->supprates[(N) - 1]; \
  404. req->basicrate ## N .status = \
  405. P80211ENUM_msgitem_status_data_ok; \
  406. } \
  407. } while (0)
  408. REQBASICRATE(1);
  409. REQBASICRATE(2);
  410. REQBASICRATE(3);
  411. REQBASICRATE(4);
  412. REQBASICRATE(5);
  413. REQBASICRATE(6);
  414. REQBASICRATE(7);
  415. REQBASICRATE(8);
  416. #define REQSUPPRATE(N) \
  417. do { \
  418. if (count >= (N)) { \
  419. req->supprate ## N .data = item->supprates[(N) - 1]; \
  420. req->supprate ## N .status = \
  421. P80211ENUM_msgitem_status_data_ok; \
  422. } \
  423. } while (0)
  424. REQSUPPRATE(1);
  425. REQSUPPRATE(2);
  426. REQSUPPRATE(3);
  427. REQSUPPRATE(4);
  428. REQSUPPRATE(5);
  429. REQSUPPRATE(6);
  430. REQSUPPRATE(7);
  431. REQSUPPRATE(8);
  432. /* beacon period */
  433. req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
  434. req->beaconperiod.data = le16_to_cpu(item->bcnint);
  435. /* timestamps */
  436. req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
  437. req->timestamp.data = jiffies;
  438. req->localtime.status = P80211ENUM_msgitem_status_data_ok;
  439. req->localtime.data = jiffies;
  440. /* atim window */
  441. req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
  442. req->ibssatimwindow.data = le16_to_cpu(item->atim);
  443. /* Channel */
  444. req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
  445. req->dschannel.data = le16_to_cpu(item->chid);
  446. /* capinfo bits */
  447. count = le16_to_cpu(item->capinfo);
  448. req->capinfo.status = P80211ENUM_msgitem_status_data_ok;
  449. req->capinfo.data = count;
  450. /* privacy flag */
  451. req->privacy.status = P80211ENUM_msgitem_status_data_ok;
  452. req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
  453. /* cfpollable */
  454. req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
  455. req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
  456. /* cfpollreq */
  457. req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
  458. req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
  459. /* bsstype */
  460. req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
  461. req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
  462. P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent;
  463. result = 0;
  464. req->resultcode.data = P80211ENUM_resultcode_success;
  465. exit:
  466. return result;
  467. }
  468. /*----------------------------------------------------------------
  469. * prism2mgmt_start
  470. *
  471. * Start a BSS. Any station can do this for IBSS, only AP for ESS.
  472. *
  473. * Arguments:
  474. * wlandev wlan device structure
  475. * msgp ptr to msg buffer
  476. *
  477. * Returns:
  478. * 0 success and done
  479. * <0 success, but we're waiting for something to finish.
  480. * >0 an error occurred while handling the message.
  481. * Side effects:
  482. *
  483. * Call context:
  484. * process thread (usually)
  485. * interrupt
  486. *----------------------------------------------------------------
  487. */
  488. int prism2mgmt_start(struct wlandevice *wlandev, void *msgp)
  489. {
  490. int result = 0;
  491. struct hfa384x *hw = wlandev->priv;
  492. struct p80211msg_dot11req_start *msg = msgp;
  493. struct p80211pstrd *pstr;
  494. u8 bytebuf[80];
  495. struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf;
  496. u16 word;
  497. wlandev->macmode = WLAN_MACMODE_NONE;
  498. /* Set the SSID */
  499. memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
  500. /*** ADHOC IBSS ***/
  501. /* see if current f/w is less than 8c3 */
  502. if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
  503. hw->ident_sta_fw.minor,
  504. hw->ident_sta_fw.variant) <
  505. HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
  506. /* Ad-Hoc not quite supported on Prism2 */
  507. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  508. msg->resultcode.data = P80211ENUM_resultcode_not_supported;
  509. goto done;
  510. }
  511. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  512. /*** STATION ***/
  513. /* Set the REQUIRED config items */
  514. /* SSID */
  515. pstr = (struct p80211pstrd *)&msg->ssid.data;
  516. prism2mgmt_pstr2bytestr(p2bytestr, pstr);
  517. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
  518. bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
  519. if (result) {
  520. netdev_err(wlandev->netdev, "Failed to set CnfOwnSSID\n");
  521. goto failed;
  522. }
  523. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
  524. bytebuf,
  525. HFA384x_RID_CNFDESIREDSSID_LEN);
  526. if (result) {
  527. netdev_err(wlandev->netdev, "Failed to set CnfDesiredSSID\n");
  528. goto failed;
  529. }
  530. /* bsstype - we use the default in the ap firmware */
  531. /* IBSS port */
  532. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
  533. /* beacon period */
  534. word = msg->beaconperiod.data;
  535. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word);
  536. if (result) {
  537. netdev_err(wlandev->netdev,
  538. "Failed to set beacon period=%d.\n", word);
  539. goto failed;
  540. }
  541. /* dschannel */
  542. word = msg->dschannel.data;
  543. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
  544. if (result) {
  545. netdev_err(wlandev->netdev,
  546. "Failed to set channel=%d.\n", word);
  547. goto failed;
  548. }
  549. /* Basic rates */
  550. word = p80211rate_to_p2bit(msg->basicrate1.data);
  551. if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok)
  552. word |= p80211rate_to_p2bit(msg->basicrate2.data);
  553. if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok)
  554. word |= p80211rate_to_p2bit(msg->basicrate3.data);
  555. if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok)
  556. word |= p80211rate_to_p2bit(msg->basicrate4.data);
  557. if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok)
  558. word |= p80211rate_to_p2bit(msg->basicrate5.data);
  559. if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok)
  560. word |= p80211rate_to_p2bit(msg->basicrate6.data);
  561. if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok)
  562. word |= p80211rate_to_p2bit(msg->basicrate7.data);
  563. if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok)
  564. word |= p80211rate_to_p2bit(msg->basicrate8.data);
  565. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
  566. if (result) {
  567. netdev_err(wlandev->netdev,
  568. "Failed to set basicrates=%d.\n", word);
  569. goto failed;
  570. }
  571. /* Operational rates (supprates and txratecontrol) */
  572. word = p80211rate_to_p2bit(msg->operationalrate1.data);
  573. if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok)
  574. word |= p80211rate_to_p2bit(msg->operationalrate2.data);
  575. if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok)
  576. word |= p80211rate_to_p2bit(msg->operationalrate3.data);
  577. if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok)
  578. word |= p80211rate_to_p2bit(msg->operationalrate4.data);
  579. if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok)
  580. word |= p80211rate_to_p2bit(msg->operationalrate5.data);
  581. if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok)
  582. word |= p80211rate_to_p2bit(msg->operationalrate6.data);
  583. if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok)
  584. word |= p80211rate_to_p2bit(msg->operationalrate7.data);
  585. if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok)
  586. word |= p80211rate_to_p2bit(msg->operationalrate8.data);
  587. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
  588. if (result) {
  589. netdev_err(wlandev->netdev,
  590. "Failed to set supprates=%d.\n", word);
  591. goto failed;
  592. }
  593. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
  594. if (result) {
  595. netdev_err(wlandev->netdev, "Failed to set txrates=%d.\n",
  596. word);
  597. goto failed;
  598. }
  599. /* Set the macmode so the frame setup code knows what to do */
  600. if (msg->bsstype.data == P80211ENUM_bsstype_independent) {
  601. wlandev->macmode = WLAN_MACMODE_IBSS_STA;
  602. /* lets extend the data length a bit */
  603. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
  604. }
  605. /* Enable the Port */
  606. result = hfa384x_drvr_enable(hw, 0);
  607. if (result) {
  608. netdev_err(wlandev->netdev,
  609. "Enable macport failed, result=%d.\n", result);
  610. goto failed;
  611. }
  612. msg->resultcode.data = P80211ENUM_resultcode_success;
  613. goto done;
  614. failed:
  615. netdev_dbg(wlandev->netdev,
  616. "Failed to set a config option, result=%d\n", result);
  617. msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  618. done:
  619. return 0;
  620. }
  621. /*----------------------------------------------------------------
  622. * prism2mgmt_readpda
  623. *
  624. * Collect the PDA data and put it in the message.
  625. *
  626. * Arguments:
  627. * wlandev wlan device structure
  628. * msgp ptr to msg buffer
  629. *
  630. * Returns:
  631. * 0 success and done
  632. * <0 success, but we're waiting for something to finish.
  633. * >0 an error occurred while handling the message.
  634. * Side effects:
  635. *
  636. * Call context:
  637. * process thread (usually)
  638. *----------------------------------------------------------------
  639. */
  640. int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp)
  641. {
  642. struct hfa384x *hw = wlandev->priv;
  643. struct p80211msg_p2req_readpda *msg = msgp;
  644. int result;
  645. /* We only support collecting the PDA when in the FWLOAD
  646. * state.
  647. */
  648. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  649. netdev_err(wlandev->netdev,
  650. "PDA may only be read in the fwload state.\n");
  651. msg->resultcode.data =
  652. P80211ENUM_resultcode_implementation_failure;
  653. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  654. } else {
  655. /* Call drvr_readpda(), it handles the auxport enable
  656. * and validating the returned PDA.
  657. */
  658. result = hfa384x_drvr_readpda(hw,
  659. msg->pda.data,
  660. HFA384x_PDA_LEN_MAX);
  661. if (result) {
  662. netdev_err(wlandev->netdev,
  663. "hfa384x_drvr_readpda() failed, result=%d\n",
  664. result);
  665. msg->resultcode.data =
  666. P80211ENUM_resultcode_implementation_failure;
  667. msg->resultcode.status =
  668. P80211ENUM_msgitem_status_data_ok;
  669. return 0;
  670. }
  671. msg->pda.status = P80211ENUM_msgitem_status_data_ok;
  672. msg->resultcode.data = P80211ENUM_resultcode_success;
  673. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  674. }
  675. return 0;
  676. }
  677. /*----------------------------------------------------------------
  678. * prism2mgmt_ramdl_state
  679. *
  680. * Establishes the beginning/end of a card RAM download session.
  681. *
  682. * It is expected that the ramdl_write() function will be called
  683. * one or more times between the 'enable' and 'disable' calls to
  684. * this function.
  685. *
  686. * Note: This function should not be called when a mac comm port
  687. * is active.
  688. *
  689. * Arguments:
  690. * wlandev wlan device structure
  691. * msgp ptr to msg buffer
  692. *
  693. * Returns:
  694. * 0 success and done
  695. * <0 success, but we're waiting for something to finish.
  696. * >0 an error occurred while handling the message.
  697. * Side effects:
  698. *
  699. * Call context:
  700. * process thread (usually)
  701. *----------------------------------------------------------------
  702. */
  703. int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp)
  704. {
  705. struct hfa384x *hw = wlandev->priv;
  706. struct p80211msg_p2req_ramdl_state *msg = msgp;
  707. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  708. netdev_err(wlandev->netdev,
  709. "ramdl_state(): may only be called in the fwload state.\n");
  710. msg->resultcode.data =
  711. P80211ENUM_resultcode_implementation_failure;
  712. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  713. return 0;
  714. }
  715. /*
  716. ** Note: Interrupts are locked out if this is an AP and are NOT
  717. ** locked out if this is a station.
  718. */
  719. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  720. if (msg->enable.data == P80211ENUM_truth_true) {
  721. if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
  722. msg->resultcode.data =
  723. P80211ENUM_resultcode_implementation_failure;
  724. } else {
  725. msg->resultcode.data = P80211ENUM_resultcode_success;
  726. }
  727. } else {
  728. hfa384x_drvr_ramdl_disable(hw);
  729. msg->resultcode.data = P80211ENUM_resultcode_success;
  730. }
  731. return 0;
  732. }
  733. /*----------------------------------------------------------------
  734. * prism2mgmt_ramdl_write
  735. *
  736. * Writes a buffer to the card RAM using the download state. This
  737. * is for writing code to card RAM. To just read or write raw data
  738. * use the aux functions.
  739. *
  740. * Arguments:
  741. * wlandev wlan device structure
  742. * msgp ptr to msg buffer
  743. *
  744. * Returns:
  745. * 0 success and done
  746. * <0 success, but we're waiting for something to finish.
  747. * >0 an error occurred while handling the message.
  748. * Side effects:
  749. *
  750. * Call context:
  751. * process thread (usually)
  752. *----------------------------------------------------------------
  753. */
  754. int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp)
  755. {
  756. struct hfa384x *hw = wlandev->priv;
  757. struct p80211msg_p2req_ramdl_write *msg = msgp;
  758. u32 addr;
  759. u32 len;
  760. u8 *buf;
  761. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  762. netdev_err(wlandev->netdev,
  763. "ramdl_write(): may only be called in the fwload state.\n");
  764. msg->resultcode.data =
  765. P80211ENUM_resultcode_implementation_failure;
  766. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  767. return 0;
  768. }
  769. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  770. /* first validate the length */
  771. if (msg->len.data > sizeof(msg->data.data)) {
  772. msg->resultcode.status =
  773. P80211ENUM_resultcode_invalid_parameters;
  774. return 0;
  775. }
  776. /* call the hfa384x function to do the write */
  777. addr = msg->addr.data;
  778. len = msg->len.data;
  779. buf = msg->data.data;
  780. if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
  781. msg->resultcode.data = P80211ENUM_resultcode_refused;
  782. msg->resultcode.data = P80211ENUM_resultcode_success;
  783. return 0;
  784. }
  785. /*----------------------------------------------------------------
  786. * prism2mgmt_flashdl_state
  787. *
  788. * Establishes the beginning/end of a card Flash download session.
  789. *
  790. * It is expected that the flashdl_write() function will be called
  791. * one or more times between the 'enable' and 'disable' calls to
  792. * this function.
  793. *
  794. * Note: This function should not be called when a mac comm port
  795. * is active.
  796. *
  797. * Arguments:
  798. * wlandev wlan device structure
  799. * msgp ptr to msg buffer
  800. *
  801. * Returns:
  802. * 0 success and done
  803. * <0 success, but we're waiting for something to finish.
  804. * >0 an error occurred while handling the message.
  805. * Side effects:
  806. *
  807. * Call context:
  808. * process thread (usually)
  809. *----------------------------------------------------------------
  810. */
  811. int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp)
  812. {
  813. int result = 0;
  814. struct hfa384x *hw = wlandev->priv;
  815. struct p80211msg_p2req_flashdl_state *msg = msgp;
  816. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  817. netdev_err(wlandev->netdev,
  818. "flashdl_state(): may only be called in the fwload state.\n");
  819. msg->resultcode.data =
  820. P80211ENUM_resultcode_implementation_failure;
  821. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  822. return 0;
  823. }
  824. /*
  825. ** Note: Interrupts are locked out if this is an AP and are NOT
  826. ** locked out if this is a station.
  827. */
  828. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  829. if (msg->enable.data == P80211ENUM_truth_true) {
  830. if (hfa384x_drvr_flashdl_enable(hw)) {
  831. msg->resultcode.data =
  832. P80211ENUM_resultcode_implementation_failure;
  833. } else {
  834. msg->resultcode.data = P80211ENUM_resultcode_success;
  835. }
  836. } else {
  837. hfa384x_drvr_flashdl_disable(hw);
  838. msg->resultcode.data = P80211ENUM_resultcode_success;
  839. /* NOTE: At this point, the MAC is in the post-reset
  840. * state and the driver is in the fwload state.
  841. * We need to get the MAC back into the fwload
  842. * state. To do this, we set the nsdstate to HWPRESENT
  843. * and then call the ifstate function to redo everything
  844. * that got us into the fwload state.
  845. */
  846. wlandev->msdstate = WLAN_MSD_HWPRESENT;
  847. result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
  848. if (result != P80211ENUM_resultcode_success) {
  849. netdev_err(wlandev->netdev,
  850. "prism2sta_ifstate(fwload) failed, P80211ENUM_resultcode=%d\n",
  851. result);
  852. msg->resultcode.data =
  853. P80211ENUM_resultcode_implementation_failure;
  854. result = -1;
  855. }
  856. }
  857. return result;
  858. }
  859. /*----------------------------------------------------------------
  860. * prism2mgmt_flashdl_write
  861. *
  862. *
  863. *
  864. * Arguments:
  865. * wlandev wlan device structure
  866. * msgp ptr to msg buffer
  867. *
  868. * Returns:
  869. * 0 success and done
  870. * <0 success, but we're waiting for something to finish.
  871. * >0 an error occurred while handling the message.
  872. * Side effects:
  873. *
  874. * Call context:
  875. * process thread (usually)
  876. *----------------------------------------------------------------
  877. */
  878. int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp)
  879. {
  880. struct hfa384x *hw = wlandev->priv;
  881. struct p80211msg_p2req_flashdl_write *msg = msgp;
  882. u32 addr;
  883. u32 len;
  884. u8 *buf;
  885. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  886. netdev_err(wlandev->netdev,
  887. "flashdl_write(): may only be called in the fwload state.\n");
  888. msg->resultcode.data =
  889. P80211ENUM_resultcode_implementation_failure;
  890. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  891. return 0;
  892. }
  893. /*
  894. ** Note: Interrupts are locked out if this is an AP and are NOT
  895. ** locked out if this is a station.
  896. */
  897. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  898. /* first validate the length */
  899. if (msg->len.data > sizeof(msg->data.data)) {
  900. msg->resultcode.status =
  901. P80211ENUM_resultcode_invalid_parameters;
  902. return 0;
  903. }
  904. /* call the hfa384x function to do the write */
  905. addr = msg->addr.data;
  906. len = msg->len.data;
  907. buf = msg->data.data;
  908. if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
  909. msg->resultcode.data = P80211ENUM_resultcode_refused;
  910. msg->resultcode.data = P80211ENUM_resultcode_success;
  911. return 0;
  912. }
  913. /*----------------------------------------------------------------
  914. * prism2mgmt_autojoin
  915. *
  916. * Associate with an ESS.
  917. *
  918. * Arguments:
  919. * wlandev wlan device structure
  920. * msgp ptr to msg buffer
  921. *
  922. * Returns:
  923. * 0 success and done
  924. * <0 success, but we're waiting for something to finish.
  925. * >0 an error occurred while handling the message.
  926. * Side effects:
  927. *
  928. * Call context:
  929. * process thread (usually)
  930. * interrupt
  931. *----------------------------------------------------------------
  932. */
  933. int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp)
  934. {
  935. struct hfa384x *hw = wlandev->priv;
  936. int result = 0;
  937. u16 reg;
  938. u16 port_type;
  939. struct p80211msg_lnxreq_autojoin *msg = msgp;
  940. struct p80211pstrd *pstr;
  941. u8 bytebuf[256];
  942. struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf;
  943. wlandev->macmode = WLAN_MACMODE_NONE;
  944. /* Set the SSID */
  945. memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
  946. /* Disable the Port */
  947. hfa384x_drvr_disable(hw, 0);
  948. /*** STATION ***/
  949. /* Set the TxRates */
  950. hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
  951. /* Set the auth type */
  952. if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
  953. reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
  954. else
  955. reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
  956. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
  957. /* Set the ssid */
  958. memset(bytebuf, 0, 256);
  959. pstr = (struct p80211pstrd *)&msg->ssid.data;
  960. prism2mgmt_pstr2bytestr(p2bytestr, pstr);
  961. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
  962. bytebuf,
  963. HFA384x_RID_CNFDESIREDSSID_LEN);
  964. port_type = HFA384x_PORTTYPE_BSS;
  965. /* Set the PortType */
  966. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
  967. /* Enable the Port */
  968. hfa384x_drvr_enable(hw, 0);
  969. /* Set the resultcode */
  970. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  971. msg->resultcode.data = P80211ENUM_resultcode_success;
  972. return result;
  973. }
  974. /*----------------------------------------------------------------
  975. * prism2mgmt_wlansniff
  976. *
  977. * Start or stop sniffing.
  978. *
  979. * Arguments:
  980. * wlandev wlan device structure
  981. * msgp ptr to msg buffer
  982. *
  983. * Returns:
  984. * 0 success and done
  985. * <0 success, but we're waiting for something to finish.
  986. * >0 an error occurred while handling the message.
  987. * Side effects:
  988. *
  989. * Call context:
  990. * process thread (usually)
  991. * interrupt
  992. *----------------------------------------------------------------
  993. */
  994. int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp)
  995. {
  996. int result = 0;
  997. struct p80211msg_lnxreq_wlansniff *msg = msgp;
  998. struct hfa384x *hw = wlandev->priv;
  999. u16 word;
  1000. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  1001. switch (msg->enable.data) {
  1002. case P80211ENUM_truth_false:
  1003. /* Confirm that we're in monitor mode */
  1004. if (wlandev->netdev->type == ARPHRD_ETHER) {
  1005. msg->resultcode.data =
  1006. P80211ENUM_resultcode_invalid_parameters;
  1007. return 0;
  1008. }
  1009. /* Disable monitor mode */
  1010. result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
  1011. if (result) {
  1012. netdev_dbg(wlandev->netdev,
  1013. "failed to disable monitor mode, result=%d\n",
  1014. result);
  1015. goto failed;
  1016. }
  1017. /* Disable port 0 */
  1018. result = hfa384x_drvr_disable(hw, 0);
  1019. if (result) {
  1020. netdev_dbg
  1021. (wlandev->netdev,
  1022. "failed to disable port 0 after sniffing, result=%d\n",
  1023. result);
  1024. goto failed;
  1025. }
  1026. /* Clear the driver state */
  1027. wlandev->netdev->type = ARPHRD_ETHER;
  1028. /* Restore the wepflags */
  1029. result = hfa384x_drvr_setconfig16(hw,
  1030. HFA384x_RID_CNFWEPFLAGS,
  1031. hw->presniff_wepflags);
  1032. if (result) {
  1033. netdev_dbg
  1034. (wlandev->netdev,
  1035. "failed to restore wepflags=0x%04x, result=%d\n",
  1036. hw->presniff_wepflags, result);
  1037. goto failed;
  1038. }
  1039. /* Set the port to its prior type and enable (if necessary) */
  1040. if (hw->presniff_port_type != 0) {
  1041. word = hw->presniff_port_type;
  1042. result = hfa384x_drvr_setconfig16(hw,
  1043. HFA384x_RID_CNFPORTTYPE,
  1044. word);
  1045. if (result) {
  1046. netdev_dbg
  1047. (wlandev->netdev,
  1048. "failed to restore porttype, result=%d\n",
  1049. result);
  1050. goto failed;
  1051. }
  1052. /* Enable the port */
  1053. result = hfa384x_drvr_enable(hw, 0);
  1054. if (result) {
  1055. netdev_dbg(wlandev->netdev,
  1056. "failed to enable port to presniff setting, result=%d\n",
  1057. result);
  1058. goto failed;
  1059. }
  1060. } else {
  1061. result = hfa384x_drvr_disable(hw, 0);
  1062. }
  1063. netdev_info(wlandev->netdev, "monitor mode disabled\n");
  1064. msg->resultcode.data = P80211ENUM_resultcode_success;
  1065. return 0;
  1066. case P80211ENUM_truth_true:
  1067. /* Disable the port (if enabled), only check Port 0 */
  1068. if (hw->port_enabled[0]) {
  1069. if (wlandev->netdev->type == ARPHRD_ETHER) {
  1070. /* Save macport 0 state */
  1071. result = hfa384x_drvr_getconfig16(hw,
  1072. HFA384x_RID_CNFPORTTYPE,
  1073. &hw->presniff_port_type);
  1074. if (result) {
  1075. netdev_dbg
  1076. (wlandev->netdev,
  1077. "failed to read porttype, result=%d\n",
  1078. result);
  1079. goto failed;
  1080. }
  1081. /* Save the wepflags state */
  1082. result = hfa384x_drvr_getconfig16(hw,
  1083. HFA384x_RID_CNFWEPFLAGS,
  1084. &hw->presniff_wepflags);
  1085. if (result) {
  1086. netdev_dbg
  1087. (wlandev->netdev,
  1088. "failed to read wepflags, result=%d\n",
  1089. result);
  1090. goto failed;
  1091. }
  1092. hfa384x_drvr_stop(hw);
  1093. result = hfa384x_drvr_start(hw);
  1094. if (result) {
  1095. netdev_dbg(wlandev->netdev,
  1096. "failed to restart the card for sniffing, result=%d\n",
  1097. result);
  1098. goto failed;
  1099. }
  1100. } else {
  1101. /* Disable the port */
  1102. result = hfa384x_drvr_disable(hw, 0);
  1103. if (result) {
  1104. netdev_dbg(wlandev->netdev,
  1105. "failed to enable port for sniffing, result=%d\n",
  1106. result);
  1107. goto failed;
  1108. }
  1109. }
  1110. } else {
  1111. hw->presniff_port_type = 0;
  1112. }
  1113. /* Set the channel we wish to sniff */
  1114. word = msg->channel.data;
  1115. result = hfa384x_drvr_setconfig16(hw,
  1116. HFA384x_RID_CNFOWNCHANNEL,
  1117. word);
  1118. hw->sniff_channel = word;
  1119. if (result) {
  1120. netdev_dbg(wlandev->netdev,
  1121. "failed to set channel %d, result=%d\n",
  1122. word, result);
  1123. goto failed;
  1124. }
  1125. /* Now if we're already sniffing, we can skip the rest */
  1126. if (wlandev->netdev->type != ARPHRD_ETHER) {
  1127. /* Set the port type to pIbss */
  1128. word = HFA384x_PORTTYPE_PSUEDOIBSS;
  1129. result = hfa384x_drvr_setconfig16(hw,
  1130. HFA384x_RID_CNFPORTTYPE,
  1131. word);
  1132. if (result) {
  1133. netdev_dbg
  1134. (wlandev->netdev,
  1135. "failed to set porttype %d, result=%d\n",
  1136. word, result);
  1137. goto failed;
  1138. }
  1139. if ((msg->keepwepflags.status ==
  1140. P80211ENUM_msgitem_status_data_ok) &&
  1141. (msg->keepwepflags.data != P80211ENUM_truth_true)) {
  1142. /* Set the wepflags for no decryption */
  1143. word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
  1144. HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
  1145. result =
  1146. hfa384x_drvr_setconfig16(hw,
  1147. HFA384x_RID_CNFWEPFLAGS,
  1148. word);
  1149. }
  1150. if (result) {
  1151. netdev_dbg
  1152. (wlandev->netdev,
  1153. "failed to set wepflags=0x%04x, result=%d\n",
  1154. word, result);
  1155. goto failed;
  1156. }
  1157. }
  1158. /* Do we want to strip the FCS in monitor mode? */
  1159. if ((msg->stripfcs.status ==
  1160. P80211ENUM_msgitem_status_data_ok) &&
  1161. (msg->stripfcs.data == P80211ENUM_truth_true)) {
  1162. hw->sniff_fcs = 0;
  1163. } else {
  1164. hw->sniff_fcs = 1;
  1165. }
  1166. /* Do we want to truncate the packets? */
  1167. if (msg->packet_trunc.status ==
  1168. P80211ENUM_msgitem_status_data_ok) {
  1169. hw->sniff_truncate = msg->packet_trunc.data;
  1170. } else {
  1171. hw->sniff_truncate = 0;
  1172. }
  1173. /* Enable the port */
  1174. result = hfa384x_drvr_enable(hw, 0);
  1175. if (result) {
  1176. netdev_dbg
  1177. (wlandev->netdev,
  1178. "failed to enable port for sniffing, result=%d\n",
  1179. result);
  1180. goto failed;
  1181. }
  1182. /* Enable monitor mode */
  1183. result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
  1184. if (result) {
  1185. netdev_dbg(wlandev->netdev,
  1186. "failed to enable monitor mode, result=%d\n",
  1187. result);
  1188. goto failed;
  1189. }
  1190. if (wlandev->netdev->type == ARPHRD_ETHER)
  1191. netdev_info(wlandev->netdev, "monitor mode enabled\n");
  1192. /* Set the driver state */
  1193. /* Do we want the prism2 header? */
  1194. if ((msg->prismheader.status ==
  1195. P80211ENUM_msgitem_status_data_ok) &&
  1196. (msg->prismheader.data == P80211ENUM_truth_true)) {
  1197. hw->sniffhdr = 0;
  1198. wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
  1199. } else if ((msg->wlanheader.status ==
  1200. P80211ENUM_msgitem_status_data_ok) &&
  1201. (msg->wlanheader.data == P80211ENUM_truth_true)) {
  1202. hw->sniffhdr = 1;
  1203. wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
  1204. } else {
  1205. wlandev->netdev->type = ARPHRD_IEEE80211;
  1206. }
  1207. msg->resultcode.data = P80211ENUM_resultcode_success;
  1208. return 0;
  1209. default:
  1210. msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  1211. return 0;
  1212. }
  1213. failed:
  1214. msg->resultcode.data = P80211ENUM_resultcode_refused;
  1215. return 0;
  1216. }