1 /* src/prism2/driver/prism2mgmt.c
3 * Management request handler functions.
5 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
6 * --------------------------------------------------------------------
10 * The contents of this file are subject to the Mozilla Public
11 * License Version 1.1 (the "License"); you may not use this file
12 * except in compliance with the License. You may obtain a copy of
13 * the License at http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS
16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 * implied. See the License for the specific language governing
18 * rights and limitations under the License.
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU Public License version 2 (the "GPL"), in which
22 * case the provisions of the GPL are applicable instead of the
23 * above. If you wish to allow the use of your version of this file
24 * only under the terms of the GPL and not to allow others to use
25 * your version of this file under the MPL, indicate your decision
26 * by deleting the provisions above and replace them with the notice
27 * and other provisions required by the GPL. If you do not delete
28 * the provisions above, a recipient may use your version of this
29 * file under either the MPL or the GPL.
31 * --------------------------------------------------------------------
33 * Inquiries regarding the linux-wlan Open Source project can be
36 * AbsoluteValue Systems Inc.
38 * http://www.linux-wlan.com
40 * --------------------------------------------------------------------
42 * Portions of the development of this software were funded by
43 * Intersil Corporation as part of PRISM(R) chipset product development.
45 * --------------------------------------------------------------------
47 * The functions in this file handle management requests sent from
50 * Most of these functions have two separate blocks of code that are
51 * conditional on whether this is a station or an AP. This is used
52 * to separate out the STA and AP responses to these management primitives.
53 * It's a choice (good, bad, indifferent?) to have the code in the same
54 * place so it's clear that the same primitive is implemented in both
55 * cases but has different behavior.
57 * --------------------------------------------------------------------
60 /*================================================================*/
62 #define WLAN_DBVAR prism2_debug
65 #include <linux/if_arp.h>
66 #include <linux/module.h>
67 #include <linux/kernel.h>
68 #include <linux/wait.h>
69 #include <linux/sched.h>
70 #include <linux/types.h>
71 #include <linux/slab.h>
72 #include <linux/wireless.h>
73 #include <linux/netdevice.h>
74 #include <linux/delay.h>
76 #include <asm/byteorder.h>
77 #include <linux/random.h>
78 #include <linux/usb.h>
80 #include "wlan_compat.h"
82 /*================================================================*/
83 /* Project Includes */
85 #include "p80211types.h"
86 #include "p80211hdr.h"
87 #include "p80211mgmt.h"
88 #include "p80211conv.h"
89 #include "p80211msg.h"
90 #include "p80211netdev.h"
91 #include "p80211metadef.h"
92 #include "p80211metastruct.h"
94 #include "prism2mgmt.h"
96 /* Converts 802.11 format rate specifications to prism2 */
97 #define p80211rate_to_p2bit(n) ((((n)&~BIT7) == 2) ? BIT0 : \
98 (((n)&~BIT7) == 4) ? BIT1 : \
99 (((n)&~BIT7) == 11) ? BIT2 : \
100 (((n)&~BIT7) == 22) ? BIT3 : 0)
102 /*----------------------------------------------------------------
105 * Initiate a scan for BSSs.
107 * This function corresponds to MLME-scan.request and part of
108 * MLME-scan.confirm. As far as I can tell in the standard, there
109 * are no restrictions on when a scan.request may be issued. We have
110 * to handle in whatever state the driver/MAC happen to be.
113 * wlandev wlan device structure
114 * msgp ptr to msg buffer
118 * <0 success, but we're waiting for something to finish.
119 * >0 an error occurred while handling the message.
123 * process thread (usually)
125 ----------------------------------------------------------------*/
126 int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
129 hfa384x_t *hw = wlandev->priv;
130 p80211msg_dot11req_scan_t *msg = msgp;
131 u16 roamingmode, word;
135 hfa384x_HostScanRequest_data_t scanreq;
139 /* gatekeeper check */
140 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
141 hw->ident_sta_fw.minor,
142 hw->ident_sta_fw.variant) <
143 HFA384x_FIRMWARE_VERSION(1,3,2)) {
144 WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n");
146 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
150 memset(&scanreq, 0, sizeof(scanreq));
152 /* save current roaming mode */
153 result = hfa384x_drvr_getconfig16(hw,
154 HFA384x_RID_CNFROAMINGMODE, &roamingmode);
156 WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n",
158 msg->resultcode.data =
159 P80211ENUM_resultcode_implementation_failure;
163 /* drop into mode 3 for the scan */
164 result = hfa384x_drvr_setconfig16(hw,
165 HFA384x_RID_CNFROAMINGMODE,
166 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
168 WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n",
170 msg->resultcode.data =
171 P80211ENUM_resultcode_implementation_failure;
175 /* active or passive? */
176 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
177 hw->ident_sta_fw.minor,
178 hw->ident_sta_fw.variant) >
179 HFA384x_FIRMWARE_VERSION(1,5,0)) {
180 if (msg->scantype.data != P80211ENUM_scantype_active) {
181 word = host2hfa384x_16(msg->maxchanneltime.data);
185 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word);
187 WLAN_LOG_WARNING("Passive scan not supported with "
188 "current firmware. (<1.5.1)\n");
192 /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
193 word = HFA384x_RATEBIT_2;
194 scanreq.txRate = host2hfa384x_16(word);
196 /* set up the channel list */
198 for (i = 0; i < msg->channellist.data.len; i++) {
199 u8 channel = msg->channellist.data.data[i];
200 if (channel > 14) continue;
201 /* channel 1 is BIT0 ... channel 14 is BIT13 */
202 word |= (1 << (channel-1));
204 scanreq.channelList = host2hfa384x_16(word);
206 /* set up the ssid, if present. */
207 scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
208 memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
210 /* Enable the MAC port if it's not already enabled */
211 result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
213 WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. "
214 "result=%d\n", result);
215 msg->resultcode.data =
216 P80211ENUM_resultcode_implementation_failure;
219 if (word == HFA384x_PORTSTATUS_DISABLED) {
222 result = hfa384x_drvr_setconfig16(hw,
223 HFA384x_RID_CNFROAMINGMODE,
224 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
226 WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result);
227 msg->resultcode.data =
228 P80211ENUM_resultcode_implementation_failure;
231 /* Construct a bogus SSID and assign it to OwnSSID and
234 wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN);
235 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
236 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
237 wordbuf, HFA384x_RID_CNFOWNSSID_LEN);
239 WLAN_LOG_ERROR("Failed to set OwnSSID.\n");
240 msg->resultcode.data =
241 P80211ENUM_resultcode_implementation_failure;
244 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
245 wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN);
247 WLAN_LOG_ERROR("Failed to set DesiredSSID.\n");
248 msg->resultcode.data =
249 P80211ENUM_resultcode_implementation_failure;
253 result = hfa384x_drvr_setconfig16(hw,
254 HFA384x_RID_CNFPORTTYPE,
255 HFA384x_PORTTYPE_IBSS);
257 WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n");
258 msg->resultcode.data =
259 P80211ENUM_resultcode_implementation_failure;
263 result = hfa384x_drvr_setconfig16(hw,
264 HFA384x_RID_CREATEIBSS,
265 HFA384x_CREATEIBSS_JOINCREATEIBSS);
267 WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n");
268 msg->resultcode.data =
269 P80211ENUM_resultcode_implementation_failure;
272 result = hfa384x_drvr_enable(hw, 0);
274 WLAN_LOG_ERROR("drvr_enable(0) failed. "
275 "result=%d\n", result);
276 msg->resultcode.data =
277 P80211ENUM_resultcode_implementation_failure;
283 /* Figure out our timeout first Kus, then HZ */
284 timeout = msg->channellist.data.len * msg->maxchanneltime.data;
285 timeout = (timeout * HZ)/1000;
287 /* Issue the scan request */
290 WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq));
292 result = hfa384x_drvr_setconfig( hw,
293 HFA384x_RID_HOSTSCAN, &scanreq,
294 sizeof(hfa384x_HostScanRequest_data_t));
296 WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n",
298 msg->resultcode.data =
299 P80211ENUM_resultcode_implementation_failure;
303 /* sleep until info frame arrives */
304 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
306 msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
307 if (hw->scanflag == -1)
310 msg->numbss.data = hw->scanflag;
314 /* Disable port if we temporarily enabled it. */
316 result = hfa384x_drvr_disable(hw, 0);
318 WLAN_LOG_ERROR("drvr_disable(0) failed. "
319 "result=%d\n", result);
320 msg->resultcode.data =
321 P80211ENUM_resultcode_implementation_failure;
326 /* restore original roaming mode */
327 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
330 WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n",
332 msg->resultcode.data =
333 P80211ENUM_resultcode_implementation_failure;
338 msg->resultcode.data = P80211ENUM_resultcode_success;
341 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
348 /*----------------------------------------------------------------
349 * prism2mgmt_scan_results
351 * Retrieve the BSS description for one of the BSSs identified in
355 * wlandev wlan device structure
356 * msgp ptr to msg buffer
360 * <0 success, but we're waiting for something to finish.
361 * >0 an error occurred while handling the message.
365 * process thread (usually)
367 ----------------------------------------------------------------*/
368 int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
371 p80211msg_dot11req_scan_results_t *req;
372 hfa384x_t *hw = wlandev->priv;
373 hfa384x_HScanResultSub_t *item = NULL;
379 req = (p80211msg_dot11req_scan_results_t *) msgp;
381 req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
383 if (! hw->scanresults) {
384 WLAN_LOG_ERROR("dot11req_scan_results can only be used after a successful dot11req_scan.\n");
386 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
390 count = (hw->scanresults->framelen - 3) / 32;
391 if (count > 32) count = 32;
393 if (req->bssindex.data >= count) {
394 WLAN_LOG_DEBUG(0, "requested index (%d) out of range (%d)\n",
395 req->bssindex.data, count);
397 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
401 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
402 /* signal and noise */
403 req->signal.status = P80211ENUM_msgitem_status_data_ok;
404 req->noise.status = P80211ENUM_msgitem_status_data_ok;
405 req->signal.data = hfa384x2host_16(item->sl);
406 req->noise.data = hfa384x2host_16(item->anl);
409 req->bssid.status = P80211ENUM_msgitem_status_data_ok;
410 req->bssid.data.len = WLAN_BSSID_LEN;
411 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
414 req->ssid.status = P80211ENUM_msgitem_status_data_ok;
415 req->ssid.data.len = hfa384x2host_16(item->ssid.len);
416 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
418 /* supported rates */
419 for (count = 0; count < 10 ; count++)
420 if (item->supprates[count] == 0)
423 #define REQBASICRATE(N) \
424 if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
425 req->basicrate ## N .data = item->supprates[(N)-1]; \
426 req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \
438 #define REQSUPPRATE(N) \
440 req->supprate ## N .data = item->supprates[(N)-1]; \
441 req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \
454 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
455 req->beaconperiod.data = hfa384x2host_16(item->bcnint);
458 req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
459 req->timestamp.data = jiffies;
460 req->localtime.status = P80211ENUM_msgitem_status_data_ok;
461 req->localtime.data = jiffies;
464 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
465 req->ibssatimwindow.data = hfa384x2host_16(item->atim);
468 req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
469 req->dschannel.data = hfa384x2host_16(item->chid);
472 count = hfa384x2host_16(item->capinfo);
475 req->privacy.status = P80211ENUM_msgitem_status_data_ok;
476 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
479 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
480 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
483 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
484 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
487 req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
488 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
489 P80211ENUM_bsstype_infrastructure :
490 P80211ENUM_bsstype_independent;
492 // item->proberesp_rate
502 req->resultcode.data = P80211ENUM_resultcode_success;
509 /*----------------------------------------------------------------
512 * Start a BSS. Any station can do this for IBSS, only AP for ESS.
515 * wlandev wlan device structure
516 * msgp ptr to msg buffer
520 * <0 success, but we're waiting for something to finish.
521 * >0 an error occurred while handling the message.
525 * process thread (usually)
527 ----------------------------------------------------------------*/
528 int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
531 hfa384x_t *hw = wlandev->priv;
532 p80211msg_dot11req_start_t *msg = msgp;
536 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
540 wlandev->macmode = WLAN_MACMODE_NONE;
543 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
546 /* see if current f/w is less than 8c3 */
547 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
548 hw->ident_sta_fw.minor,
549 hw->ident_sta_fw.variant) <
550 HFA384x_FIRMWARE_VERSION(0,8,3)) {
551 /* Ad-Hoc not quite supported on Prism2 */
552 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
553 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
557 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
560 /* Set the REQUIRED config items */
562 pstr = (p80211pstrd_t*)&(msg->ssid.data);
563 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
564 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
565 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
567 WLAN_LOG_ERROR("Failed to set CnfOwnSSID\n");
570 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
571 bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
573 WLAN_LOG_ERROR("Failed to set CnfDesiredSSID\n");
577 /* bsstype - we use the default in the ap firmware */
579 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
582 word = msg->beaconperiod.data;
583 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
585 WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word);
590 word = msg->dschannel.data;
591 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
593 WLAN_LOG_ERROR("Failed to set channel=%d.\n", word);
597 word = p80211rate_to_p2bit(msg->basicrate1.data);
598 if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
599 word |= p80211rate_to_p2bit(msg->basicrate2.data);
601 if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
602 word |= p80211rate_to_p2bit(msg->basicrate3.data);
604 if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
605 word |= p80211rate_to_p2bit(msg->basicrate4.data);
607 if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
608 word |= p80211rate_to_p2bit(msg->basicrate5.data);
610 if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
611 word |= p80211rate_to_p2bit(msg->basicrate6.data);
613 if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
614 word |= p80211rate_to_p2bit(msg->basicrate7.data);
616 if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
617 word |= p80211rate_to_p2bit(msg->basicrate8.data);
619 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
621 WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word);
625 /* Operational rates (supprates and txratecontrol) */
626 word = p80211rate_to_p2bit(msg->operationalrate1.data);
627 if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
628 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
630 if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
631 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
633 if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
634 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
636 if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
637 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
639 if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
640 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
642 if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
643 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
645 if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
646 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
648 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
650 WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word);
654 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
656 WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word);
660 /* Set the macmode so the frame setup code knows what to do */
661 if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) {
662 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
663 /* lets extend the data length a bit */
664 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
667 /* Enable the Port */
668 result = hfa384x_drvr_enable(hw, 0);
670 WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
674 msg->resultcode.data = P80211ENUM_resultcode_success;
678 WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result);
679 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
688 /*----------------------------------------------------------------
691 * Collect the PDA data and put it in the message.
694 * wlandev wlan device structure
695 * msgp ptr to msg buffer
699 * <0 success, but we're waiting for something to finish.
700 * >0 an error occurred while handling the message.
704 * process thread (usually)
705 ----------------------------------------------------------------*/
706 int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
708 hfa384x_t *hw = wlandev->priv;
709 p80211msg_p2req_readpda_t *msg = msgp;
713 /* We only support collecting the PDA when in the FWLOAD
716 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
718 "PDA may only be read "
719 "in the fwload state.\n");
720 msg->resultcode.data =
721 P80211ENUM_resultcode_implementation_failure;
722 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
724 /* Call drvr_readpda(), it handles the auxport enable
725 * and validating the returned PDA.
727 result = hfa384x_drvr_readpda(
730 HFA384x_PDA_LEN_MAX);
733 "hfa384x_drvr_readpda() failed, "
737 msg->resultcode.data =
738 P80211ENUM_resultcode_implementation_failure;
739 msg->resultcode.status =
740 P80211ENUM_msgitem_status_data_ok;
744 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
745 msg->resultcode.data = P80211ENUM_resultcode_success;
746 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
753 /*----------------------------------------------------------------
754 * prism2mgmt_ramdl_state
756 * Establishes the beginning/end of a card RAM download session.
758 * It is expected that the ramdl_write() function will be called
759 * one or more times between the 'enable' and 'disable' calls to
762 * Note: This function should not be called when a mac comm port
766 * wlandev wlan device structure
767 * msgp ptr to msg buffer
771 * <0 success, but we're waiting for something to finish.
772 * >0 an error occurred while handling the message.
776 * process thread (usually)
777 ----------------------------------------------------------------*/
778 int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
780 hfa384x_t *hw = wlandev->priv;
781 p80211msg_p2req_ramdl_state_t *msg = msgp;
784 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
786 "ramdl_state(): may only be called "
787 "in the fwload state.\n");
788 msg->resultcode.data =
789 P80211ENUM_resultcode_implementation_failure;
790 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
796 ** Note: Interrupts are locked out if this is an AP and are NOT
797 ** locked out if this is a station.
800 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
801 if ( msg->enable.data == P80211ENUM_truth_true ) {
802 if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) {
803 msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
805 msg->resultcode.data = P80211ENUM_resultcode_success;
808 hfa384x_drvr_ramdl_disable(hw);
809 msg->resultcode.data = P80211ENUM_resultcode_success;
817 /*----------------------------------------------------------------
818 * prism2mgmt_ramdl_write
820 * Writes a buffer to the card RAM using the download state. This
821 * is for writing code to card RAM. To just read or write raw data
822 * use the aux functions.
825 * wlandev wlan device structure
826 * msgp ptr to msg buffer
830 * <0 success, but we're waiting for something to finish.
831 * >0 an error occurred while handling the message.
835 * process thread (usually)
836 ----------------------------------------------------------------*/
837 int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
839 hfa384x_t *hw = wlandev->priv;
840 p80211msg_p2req_ramdl_write_t *msg = msgp;
846 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
848 "ramdl_write(): may only be called "
849 "in the fwload state.\n");
850 msg->resultcode.data =
851 P80211ENUM_resultcode_implementation_failure;
852 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
857 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
858 /* first validate the length */
859 if ( msg->len.data > sizeof(msg->data.data) ) {
860 msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters;
863 /* call the hfa384x function to do the write */
864 addr = msg->addr.data;
866 buf = msg->data.data;
867 if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) {
868 msg->resultcode.data = P80211ENUM_resultcode_refused;
871 msg->resultcode.data = P80211ENUM_resultcode_success;
878 /*----------------------------------------------------------------
879 * prism2mgmt_flashdl_state
881 * Establishes the beginning/end of a card Flash download session.
883 * It is expected that the flashdl_write() function will be called
884 * one or more times between the 'enable' and 'disable' calls to
887 * Note: This function should not be called when a mac comm port
891 * wlandev wlan device structure
892 * msgp ptr to msg buffer
896 * <0 success, but we're waiting for something to finish.
897 * >0 an error occurred while handling the message.
901 * process thread (usually)
902 ----------------------------------------------------------------*/
903 int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
906 hfa384x_t *hw = wlandev->priv;
907 p80211msg_p2req_flashdl_state_t *msg = msgp;
910 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
912 "flashdl_state(): may only be called "
913 "in the fwload state.\n");
914 msg->resultcode.data =
915 P80211ENUM_resultcode_implementation_failure;
916 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
922 ** Note: Interrupts are locked out if this is an AP and are NOT
923 ** locked out if this is a station.
926 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
927 if ( msg->enable.data == P80211ENUM_truth_true ) {
928 if ( hfa384x_drvr_flashdl_enable(hw) ) {
929 msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
931 msg->resultcode.data = P80211ENUM_resultcode_success;
934 hfa384x_drvr_flashdl_disable(hw);
935 msg->resultcode.data = P80211ENUM_resultcode_success;
936 /* NOTE: At this point, the MAC is in the post-reset
937 * state and the driver is in the fwload state.
938 * We need to get the MAC back into the fwload
939 * state. To do this, we set the nsdstate to HWPRESENT
940 * and then call the ifstate function to redo everything
941 * that got us into the fwload state.
943 wlandev->msdstate = WLAN_MSD_HWPRESENT;
944 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
945 if (result != P80211ENUM_resultcode_success) {
946 WLAN_LOG_ERROR("prism2sta_ifstate(fwload) failed,"
947 "P80211ENUM_resultcode=%d\n", result);
948 msg->resultcode.data =
949 P80211ENUM_resultcode_implementation_failure;
959 /*----------------------------------------------------------------
960 * prism2mgmt_flashdl_write
965 * wlandev wlan device structure
966 * msgp ptr to msg buffer
970 * <0 success, but we're waiting for something to finish.
971 * >0 an error occurred while handling the message.
975 * process thread (usually)
976 ----------------------------------------------------------------*/
977 int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
979 hfa384x_t *hw = wlandev->priv;
980 p80211msg_p2req_flashdl_write_t *msg = msgp;
986 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
988 "flashdl_write(): may only be called "
989 "in the fwload state.\n");
990 msg->resultcode.data =
991 P80211ENUM_resultcode_implementation_failure;
992 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
998 ** Note: Interrupts are locked out if this is an AP and are NOT
999 ** locked out if this is a station.
1002 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1003 /* first validate the length */
1004 if ( msg->len.data > sizeof(msg->data.data) ) {
1005 msg->resultcode.status =
1006 P80211ENUM_resultcode_invalid_parameters;
1009 /* call the hfa384x function to do the write */
1010 addr = msg->addr.data;
1011 len = msg->len.data;
1012 buf = msg->data.data;
1013 if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) {
1014 msg->resultcode.data = P80211ENUM_resultcode_refused;
1017 msg->resultcode.data = P80211ENUM_resultcode_success;
1023 /*----------------------------------------------------------------
1024 * prism2mgmt_autojoin
1026 * Associate with an ESS.
1029 * wlandev wlan device structure
1030 * msgp ptr to msg buffer
1033 * 0 success and done
1034 * <0 success, but we're waiting for something to finish.
1035 * >0 an error occurred while handling the message.
1039 * process thread (usually)
1041 ----------------------------------------------------------------*/
1042 int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
1044 hfa384x_t *hw = wlandev->priv;
1048 p80211msg_lnxreq_autojoin_t *msg = msgp;
1049 p80211pstrd_t *pstr;
1051 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
1054 wlandev->macmode = WLAN_MACMODE_NONE;
1057 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1059 /* Disable the Port */
1060 hfa384x_drvr_disable(hw, 0);
1063 /* Set the TxRates */
1064 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1066 /* Set the auth type */
1067 if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
1068 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
1070 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
1072 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1075 memset(bytebuf, 0, 256);
1076 pstr = (p80211pstrd_t*)&(msg->ssid.data);
1077 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1078 result = hfa384x_drvr_setconfig(
1079 hw, HFA384x_RID_CNFDESIREDSSID,
1080 bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
1082 /* we can use the new-fangled auto-unknown mode if the firmware
1083 is 1.3.3 or newer */
1084 if (HFA384x_FIRMARE_VERSION(hw->ident_sta_fw.major,
1085 hw->ident_sta_fw.minor,
1086 hw->ident_sta_fw.variant) >=
1087 HFA384x_FIRMWARE_VERSION(1,3,3)) {
1088 /* Set up the IBSS options */
1089 reg = HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS;
1090 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CREATEIBSS, reg);
1092 /* Set the PortType */
1093 port_type = HFA384x_PORTTYPE_IBSS;
1095 port_type = HFA384x_PORTTYPE_BSS;
1098 port_type = HFA384x_PORTTYPE_BSS;
1100 /* Set the PortType */
1101 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1103 /* Enable the Port */
1104 hfa384x_drvr_enable(hw, 0);
1106 /* Set the resultcode */
1107 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1108 msg->resultcode.data = P80211ENUM_resultcode_success;
1115 /*----------------------------------------------------------------
1116 * prism2mgmt_wlansniff
1118 * Start or stop sniffing.
1121 * wlandev wlan device structure
1122 * msgp ptr to msg buffer
1125 * 0 success and done
1126 * <0 success, but we're waiting for something to finish.
1127 * >0 an error occurred while handling the message.
1131 * process thread (usually)
1133 ----------------------------------------------------------------*/
1134 int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
1137 p80211msg_lnxreq_wlansniff_t *msg = msgp;
1139 hfa384x_t *hw = wlandev->priv;
1144 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1145 switch (msg->enable.data)
1147 case P80211ENUM_truth_false:
1148 /* Confirm that we're in monitor mode */
1149 if ( wlandev->netdev->type == ARPHRD_ETHER ) {
1150 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1154 /* Disable monitor mode */
1155 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
1158 "failed to disable monitor mode, result=%d\n",
1162 /* Disable port 0 */
1163 result = hfa384x_drvr_disable(hw, 0);
1166 "failed to disable port 0 after sniffing, result=%d\n",
1170 /* Clear the driver state */
1171 wlandev->netdev->type = ARPHRD_ETHER;
1173 /* Restore the wepflags */
1174 result = hfa384x_drvr_setconfig16(hw,
1175 HFA384x_RID_CNFWEPFLAGS,
1176 hw->presniff_wepflags);
1179 "failed to restore wepflags=0x%04x, result=%d\n",
1180 hw->presniff_wepflags,
1185 /* Set the port to its prior type and enable (if necessary) */
1186 if (hw->presniff_port_type != 0 ) {
1187 word = hw->presniff_port_type;
1188 result = hfa384x_drvr_setconfig16(hw,
1189 HFA384x_RID_CNFPORTTYPE, word);
1192 "failed to restore porttype, result=%d\n",
1197 /* Enable the port */
1198 result = hfa384x_drvr_enable(hw, 0);
1200 WLAN_LOG_DEBUG(1, "failed to enable port to presniff setting, result=%d\n", result);
1204 result = hfa384x_drvr_disable(hw, 0);
1208 WLAN_LOG_INFO("monitor mode disabled\n");
1209 msg->resultcode.data = P80211ENUM_resultcode_success;
1213 case P80211ENUM_truth_true:
1214 /* Disable the port (if enabled), only check Port 0 */
1215 if ( hw->port_enabled[0]) {
1216 if (wlandev->netdev->type == ARPHRD_ETHER) {
1217 /* Save macport 0 state */
1218 result = hfa384x_drvr_getconfig16(hw,
1219 HFA384x_RID_CNFPORTTYPE,
1220 &(hw->presniff_port_type));
1222 WLAN_LOG_DEBUG(1,"failed to read porttype, result=%d\n", result);
1225 /* Save the wepflags state */
1226 result = hfa384x_drvr_getconfig16(hw,
1227 HFA384x_RID_CNFWEPFLAGS,
1228 &(hw->presniff_wepflags));
1230 WLAN_LOG_DEBUG(1,"failed to read wepflags, result=%d\n", result);
1233 hfa384x_drvr_stop(hw);
1234 result = hfa384x_drvr_start(hw);
1237 "failed to restart the card for sniffing, result=%d\n",
1242 /* Disable the port */
1243 result = hfa384x_drvr_disable(hw, 0);
1246 "failed to enable port for sniffing, result=%d\n",
1252 hw->presniff_port_type = 0;
1255 /* Set the channel we wish to sniff */
1256 word = msg->channel.data;
1257 result = hfa384x_drvr_setconfig16(hw,
1258 HFA384x_RID_CNFOWNCHANNEL, word);
1259 hw->sniff_channel=word;
1263 "failed to set channel %d, result=%d\n",
1269 /* Now if we're already sniffing, we can skip the rest */
1270 if (wlandev->netdev->type != ARPHRD_ETHER) {
1271 /* Set the port type to pIbss */
1272 word = HFA384x_PORTTYPE_PSUEDOIBSS;
1273 result = hfa384x_drvr_setconfig16(hw,
1274 HFA384x_RID_CNFPORTTYPE, word);
1277 "failed to set porttype %d, result=%d\n",
1282 if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) {
1283 /* Set the wepflags for no decryption */
1284 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
1285 HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1286 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word);
1291 "failed to set wepflags=0x%04x, result=%d\n",
1298 /* Do we want to strip the FCS in monitor mode? */
1299 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) {
1305 /* Do we want to truncate the packets? */
1306 if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) {
1307 hw->sniff_truncate = msg->packet_trunc.data;
1309 hw->sniff_truncate = 0;
1312 /* Enable the port */
1313 result = hfa384x_drvr_enable(hw, 0);
1316 "failed to enable port for sniffing, result=%d\n",
1320 /* Enable monitor mode */
1321 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
1324 "failed to enable monitor mode, result=%d\n",
1329 if (wlandev->netdev->type == ARPHRD_ETHER) {
1330 WLAN_LOG_INFO("monitor mode enabled\n");
1333 /* Set the driver state */
1334 /* Do we want the prism2 header? */
1335 if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) {
1337 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1338 } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) {
1340 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1342 wlandev->netdev->type = ARPHRD_IEEE80211;
1345 msg->resultcode.data = P80211ENUM_resultcode_success;
1350 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1357 msg->resultcode.data = P80211ENUM_resultcode_refused;