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
;