1 // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
2 /* src/prism2/driver/prism2mgmt.c
4 * Management request handler functions.
6 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
7 * --------------------------------------------------------------------
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/
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.
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.
32 * --------------------------------------------------------------------
34 * Inquiries regarding the linux-wlan Open Source project can be
37 * AbsoluteValue Systems Inc.
39 * http://www.linux-wlan.com
41 * --------------------------------------------------------------------
43 * Portions of the development of this software were funded by
44 * Intersil Corporation as part of PRISM(R) chipset product development.
46 * --------------------------------------------------------------------
48 * The functions in this file handle management requests sent from
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.
58 * --------------------------------------------------------------------
61 #include <linux/if_arp.h>
62 #include <linux/module.h>
63 #include <linux/kernel.h>
64 #include <linux/wait.h>
65 #include <linux/sched.h>
66 #include <linux/types.h>
67 #include <linux/wireless.h>
68 #include <linux/netdevice.h>
69 #include <linux/delay.h>
71 #include <asm/byteorder.h>
72 #include <linux/random.h>
73 #include <linux/usb.h>
74 #include <linux/bitops.h>
76 #include "p80211types.h"
77 #include "p80211hdr.h"
78 #include "p80211mgmt.h"
79 #include "p80211conv.h"
80 #include "p80211msg.h"
81 #include "p80211netdev.h"
82 #include "p80211metadef.h"
83 #include "p80211metastruct.h"
85 #include "prism2mgmt.h"
87 /* Converts 802.11 format rate specifications to prism2 */
88 static inline u16
p80211rate_to_p2bit(u32 rate
)
90 switch (rate
& ~BIT(7)) {
104 /*----------------------------------------------------------------
107 * Initiate a scan for BSSs.
109 * This function corresponds to MLME-scan.request and part of
110 * MLME-scan.confirm. As far as I can tell in the standard, there
111 * are no restrictions on when a scan.request may be issued. We have
112 * to handle in whatever state the driver/MAC happen to be.
115 * wlandev wlan device structure
116 * msgp ptr to msg buffer
120 * <0 success, but we're waiting for something to finish.
121 * >0 an error occurred while handling the message.
125 * process thread (usually)
127 *----------------------------------------------------------------
129 int prism2mgmt_scan(struct wlandevice
*wlandev
, void *msgp
)
132 struct hfa384x
*hw
= wlandev
->priv
;
133 struct p80211msg_dot11req_scan
*msg
= msgp
;
134 u16 roamingmode
, word
;
138 struct hfa384x_host_scan_request_data scanreq
;
140 /* gatekeeper check */
141 if (HFA384x_FIRMWARE_VERSION(hw
->ident_sta_fw
.major
,
142 hw
->ident_sta_fw
.minor
,
143 hw
->ident_sta_fw
.variant
) <
144 HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
145 netdev_err(wlandev
->netdev
,
146 "HostScan not supported with current firmware (<1.3.2).\n");
148 msg
->resultcode
.data
= P80211ENUM_resultcode_not_supported
;
152 memset(&scanreq
, 0, sizeof(scanreq
));
154 /* save current roaming mode */
155 result
= hfa384x_drvr_getconfig16(hw
,
156 HFA384x_RID_CNFROAMINGMODE
,
159 netdev_err(wlandev
->netdev
,
160 "getconfig(ROAMMODE) failed. result=%d\n", result
);
161 msg
->resultcode
.data
=
162 P80211ENUM_resultcode_implementation_failure
;
166 /* drop into mode 3 for the scan */
167 result
= hfa384x_drvr_setconfig16(hw
,
168 HFA384x_RID_CNFROAMINGMODE
,
169 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM
);
171 netdev_err(wlandev
->netdev
,
172 "setconfig(ROAMINGMODE) failed. result=%d\n",
174 msg
->resultcode
.data
=
175 P80211ENUM_resultcode_implementation_failure
;
179 /* active or passive? */
180 if (HFA384x_FIRMWARE_VERSION(hw
->ident_sta_fw
.major
,
181 hw
->ident_sta_fw
.minor
,
182 hw
->ident_sta_fw
.variant
) >
183 HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
184 if (msg
->scantype
.data
!= P80211ENUM_scantype_active
)
185 word
= msg
->maxchanneltime
.data
;
190 hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFPASSIVESCANCTRL
,
193 netdev_warn(wlandev
->netdev
,
194 "Passive scan not supported with current firmware. (<1.5.1)\n");
198 /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
199 word
= HFA384x_RATEBIT_2
;
200 scanreq
.tx_rate
= cpu_to_le16(word
);
202 /* set up the channel list */
204 for (i
= 0; i
< msg
->channellist
.data
.len
; i
++) {
205 u8 channel
= msg
->channellist
.data
.data
[i
];
209 /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
210 word
|= (1 << (channel
- 1));
212 scanreq
.channel_list
= cpu_to_le16(word
);
214 /* set up the ssid, if present. */
215 scanreq
.ssid
.len
= cpu_to_le16(msg
->ssid
.data
.len
);
216 memcpy(scanreq
.ssid
.data
, msg
->ssid
.data
.data
, msg
->ssid
.data
.len
);
218 /* Enable the MAC port if it's not already enabled */
219 result
= hfa384x_drvr_getconfig16(hw
, HFA384x_RID_PORTSTATUS
, &word
);
221 netdev_err(wlandev
->netdev
,
222 "getconfig(PORTSTATUS) failed. result=%d\n", result
);
223 msg
->resultcode
.data
=
224 P80211ENUM_resultcode_implementation_failure
;
227 if (word
== HFA384x_PORTSTATUS_DISABLED
) {
230 result
= hfa384x_drvr_setconfig16(hw
,
231 HFA384x_RID_CNFROAMINGMODE
,
232 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM
);
234 netdev_err(wlandev
->netdev
,
235 "setconfig(ROAMINGMODE) failed. result=%d\n",
237 msg
->resultcode
.data
=
238 P80211ENUM_resultcode_implementation_failure
;
241 /* Construct a bogus SSID and assign it to OwnSSID and
244 wordbuf
[0] = cpu_to_le16(WLAN_SSID_MAXLEN
);
245 get_random_bytes(&wordbuf
[1], WLAN_SSID_MAXLEN
);
246 result
= hfa384x_drvr_setconfig(hw
, HFA384x_RID_CNFOWNSSID
,
248 HFA384x_RID_CNFOWNSSID_LEN
);
250 netdev_err(wlandev
->netdev
, "Failed to set OwnSSID.\n");
251 msg
->resultcode
.data
=
252 P80211ENUM_resultcode_implementation_failure
;
255 result
= hfa384x_drvr_setconfig(hw
, HFA384x_RID_CNFDESIREDSSID
,
257 HFA384x_RID_CNFDESIREDSSID_LEN
);
259 netdev_err(wlandev
->netdev
,
260 "Failed to set DesiredSSID.\n");
261 msg
->resultcode
.data
=
262 P80211ENUM_resultcode_implementation_failure
;
266 result
= hfa384x_drvr_setconfig16(hw
,
267 HFA384x_RID_CNFPORTTYPE
,
268 HFA384x_PORTTYPE_IBSS
);
270 netdev_err(wlandev
->netdev
,
271 "Failed to set CNFPORTTYPE.\n");
272 msg
->resultcode
.data
=
273 P80211ENUM_resultcode_implementation_failure
;
277 result
= hfa384x_drvr_setconfig16(hw
,
278 HFA384x_RID_CREATEIBSS
,
279 HFA384x_CREATEIBSS_JOINCREATEIBSS
);
281 netdev_err(wlandev
->netdev
,
282 "Failed to set CREATEIBSS.\n");
283 msg
->resultcode
.data
=
284 P80211ENUM_resultcode_implementation_failure
;
287 result
= hfa384x_drvr_enable(hw
, 0);
289 netdev_err(wlandev
->netdev
,
290 "drvr_enable(0) failed. result=%d\n",
292 msg
->resultcode
.data
=
293 P80211ENUM_resultcode_implementation_failure
;
299 /* Figure out our timeout first Kus, then HZ */
300 timeout
= msg
->channellist
.data
.len
* msg
->maxchanneltime
.data
;
301 timeout
= (timeout
* HZ
) / 1000;
303 /* Issue the scan request */
306 result
= hfa384x_drvr_setconfig(hw
,
307 HFA384x_RID_HOSTSCAN
, &scanreq
,
310 netdev_err(wlandev
->netdev
,
311 "setconfig(SCANREQUEST) failed. result=%d\n",
313 msg
->resultcode
.data
=
314 P80211ENUM_resultcode_implementation_failure
;
318 /* sleep until info frame arrives */
319 wait_event_interruptible_timeout(hw
->cmdq
, hw
->scanflag
, timeout
);
321 msg
->numbss
.status
= P80211ENUM_msgitem_status_data_ok
;
322 if (hw
->scanflag
== -1)
325 msg
->numbss
.data
= hw
->scanflag
;
329 /* Disable port if we temporarily enabled it. */
331 result
= hfa384x_drvr_disable(hw
, 0);
333 netdev_err(wlandev
->netdev
,
334 "drvr_disable(0) failed. result=%d\n",
336 msg
->resultcode
.data
=
337 P80211ENUM_resultcode_implementation_failure
;
342 /* restore original roaming mode */
343 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFROAMINGMODE
,
346 netdev_err(wlandev
->netdev
,
347 "setconfig(ROAMMODE) failed. result=%d\n", result
);
348 msg
->resultcode
.data
=
349 P80211ENUM_resultcode_implementation_failure
;
354 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
357 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
362 /*----------------------------------------------------------------
363 * prism2mgmt_scan_results
365 * Retrieve the BSS description for one of the BSSs identified in
369 * wlandev wlan device structure
370 * msgp ptr to msg buffer
374 * <0 success, but we're waiting for something to finish.
375 * >0 an error occurred while handling the message.
379 * process thread (usually)
381 *----------------------------------------------------------------
383 int prism2mgmt_scan_results(struct wlandevice
*wlandev
, void *msgp
)
386 struct p80211msg_dot11req_scan_results
*req
;
387 struct hfa384x
*hw
= wlandev
->priv
;
388 struct hfa384x_hscan_result_sub
*item
= NULL
;
394 req
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
396 if (!hw
->scanresults
) {
397 netdev_err(wlandev
->netdev
,
398 "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
400 req
->resultcode
.data
= P80211ENUM_resultcode_invalid_parameters
;
404 count
= (hw
->scanresults
->framelen
- 3) / 32;
405 if (count
> HFA384x_SCANRESULT_MAX
)
406 count
= HFA384x_SCANRESULT_MAX
;
408 if (req
->bssindex
.data
>= count
) {
409 netdev_dbg(wlandev
->netdev
,
410 "requested index (%d) out of range (%d)\n",
411 req
->bssindex
.data
, count
);
413 req
->resultcode
.data
= P80211ENUM_resultcode_invalid_parameters
;
417 item
= &hw
->scanresults
->info
.hscanresult
.result
[req
->bssindex
.data
];
418 /* signal and noise */
419 req
->signal
.status
= P80211ENUM_msgitem_status_data_ok
;
420 req
->noise
.status
= P80211ENUM_msgitem_status_data_ok
;
421 req
->signal
.data
= le16_to_cpu(item
->sl
);
422 req
->noise
.data
= le16_to_cpu(item
->anl
);
425 req
->bssid
.status
= P80211ENUM_msgitem_status_data_ok
;
426 req
->bssid
.data
.len
= WLAN_BSSID_LEN
;
427 memcpy(req
->bssid
.data
.data
, item
->bssid
, WLAN_BSSID_LEN
);
430 req
->ssid
.status
= P80211ENUM_msgitem_status_data_ok
;
431 req
->ssid
.data
.len
= le16_to_cpu(item
->ssid
.len
);
432 req
->ssid
.data
.len
= min_t(u16
, req
->ssid
.data
.len
, WLAN_SSID_MAXLEN
);
433 memcpy(req
->ssid
.data
.data
, item
->ssid
.data
, req
->ssid
.data
.len
);
435 /* supported rates */
436 for (count
= 0; count
< 10; count
++)
437 if (item
->supprates
[count
] == 0)
440 #define REQBASICRATE(N) \
442 if ((count >= (N)) && DOT11_RATE5_ISBASIC_GET( \
443 item->supprates[(N) - 1])) { \
444 req->basicrate ## N .data = item->supprates[(N) - 1]; \
445 req->basicrate ## N .status = \
446 P80211ENUM_msgitem_status_data_ok; \
459 #define REQSUPPRATE(N) \
461 if (count >= (N)) { \
462 req->supprate ## N .data = item->supprates[(N) - 1]; \
463 req->supprate ## N .status = \
464 P80211ENUM_msgitem_status_data_ok; \
478 req
->beaconperiod
.status
= P80211ENUM_msgitem_status_data_ok
;
479 req
->beaconperiod
.data
= le16_to_cpu(item
->bcnint
);
482 req
->timestamp
.status
= P80211ENUM_msgitem_status_data_ok
;
483 req
->timestamp
.data
= jiffies
;
484 req
->localtime
.status
= P80211ENUM_msgitem_status_data_ok
;
485 req
->localtime
.data
= jiffies
;
488 req
->ibssatimwindow
.status
= P80211ENUM_msgitem_status_data_ok
;
489 req
->ibssatimwindow
.data
= le16_to_cpu(item
->atim
);
492 req
->dschannel
.status
= P80211ENUM_msgitem_status_data_ok
;
493 req
->dschannel
.data
= le16_to_cpu(item
->chid
);
496 count
= le16_to_cpu(item
->capinfo
);
497 req
->capinfo
.status
= P80211ENUM_msgitem_status_data_ok
;
498 req
->capinfo
.data
= count
;
501 req
->privacy
.status
= P80211ENUM_msgitem_status_data_ok
;
502 req
->privacy
.data
= WLAN_GET_MGMT_CAP_INFO_PRIVACY(count
);
505 req
->cfpollable
.status
= P80211ENUM_msgitem_status_data_ok
;
506 req
->cfpollable
.data
= WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count
);
509 req
->cfpollreq
.status
= P80211ENUM_msgitem_status_data_ok
;
510 req
->cfpollreq
.data
= WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count
);
513 req
->bsstype
.status
= P80211ENUM_msgitem_status_data_ok
;
514 req
->bsstype
.data
= (WLAN_GET_MGMT_CAP_INFO_ESS(count
)) ?
515 P80211ENUM_bsstype_infrastructure
: P80211ENUM_bsstype_independent
;
518 req
->resultcode
.data
= P80211ENUM_resultcode_success
;
524 /*----------------------------------------------------------------
527 * Start a BSS. Any station can do this for IBSS, only AP for ESS.
530 * wlandev wlan device structure
531 * msgp ptr to msg buffer
535 * <0 success, but we're waiting for something to finish.
536 * >0 an error occurred while handling the message.
540 * process thread (usually)
542 *----------------------------------------------------------------
544 int prism2mgmt_start(struct wlandevice
*wlandev
, void *msgp
)
547 struct hfa384x
*hw
= wlandev
->priv
;
548 struct p80211msg_dot11req_start
*msg
= msgp
;
550 struct p80211pstrd
*pstr
;
552 struct hfa384x_bytestr
*p2bytestr
= (struct hfa384x_bytestr
*)bytebuf
;
555 wlandev
->macmode
= WLAN_MACMODE_NONE
;
558 memcpy(&wlandev
->ssid
, &msg
->ssid
.data
, sizeof(msg
->ssid
.data
));
561 /* see if current f/w is less than 8c3 */
562 if (HFA384x_FIRMWARE_VERSION(hw
->ident_sta_fw
.major
,
563 hw
->ident_sta_fw
.minor
,
564 hw
->ident_sta_fw
.variant
) <
565 HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
566 /* Ad-Hoc not quite supported on Prism2 */
567 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
568 msg
->resultcode
.data
= P80211ENUM_resultcode_not_supported
;
572 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
575 /* Set the REQUIRED config items */
577 pstr
= (struct p80211pstrd
*)&msg
->ssid
.data
;
578 prism2mgmt_pstr2bytestr(p2bytestr
, pstr
);
579 result
= hfa384x_drvr_setconfig(hw
, HFA384x_RID_CNFOWNSSID
,
580 bytebuf
, HFA384x_RID_CNFOWNSSID_LEN
);
582 netdev_err(wlandev
->netdev
, "Failed to set CnfOwnSSID\n");
585 result
= hfa384x_drvr_setconfig(hw
, HFA384x_RID_CNFDESIREDSSID
,
587 HFA384x_RID_CNFDESIREDSSID_LEN
);
589 netdev_err(wlandev
->netdev
, "Failed to set CnfDesiredSSID\n");
593 /* bsstype - we use the default in the ap firmware */
595 hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFPORTTYPE
, 0);
598 word
= msg
->beaconperiod
.data
;
599 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFAPBCNINT
, word
);
601 netdev_err(wlandev
->netdev
,
602 "Failed to set beacon period=%d.\n", word
);
607 word
= msg
->dschannel
.data
;
608 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFOWNCHANNEL
, word
);
610 netdev_err(wlandev
->netdev
,
611 "Failed to set channel=%d.\n", word
);
615 word
= p80211rate_to_p2bit(msg
->basicrate1
.data
);
616 if (msg
->basicrate2
.status
== P80211ENUM_msgitem_status_data_ok
)
617 word
|= p80211rate_to_p2bit(msg
->basicrate2
.data
);
619 if (msg
->basicrate3
.status
== P80211ENUM_msgitem_status_data_ok
)
620 word
|= p80211rate_to_p2bit(msg
->basicrate3
.data
);
622 if (msg
->basicrate4
.status
== P80211ENUM_msgitem_status_data_ok
)
623 word
|= p80211rate_to_p2bit(msg
->basicrate4
.data
);
625 if (msg
->basicrate5
.status
== P80211ENUM_msgitem_status_data_ok
)
626 word
|= p80211rate_to_p2bit(msg
->basicrate5
.data
);
628 if (msg
->basicrate6
.status
== P80211ENUM_msgitem_status_data_ok
)
629 word
|= p80211rate_to_p2bit(msg
->basicrate6
.data
);
631 if (msg
->basicrate7
.status
== P80211ENUM_msgitem_status_data_ok
)
632 word
|= p80211rate_to_p2bit(msg
->basicrate7
.data
);
634 if (msg
->basicrate8
.status
== P80211ENUM_msgitem_status_data_ok
)
635 word
|= p80211rate_to_p2bit(msg
->basicrate8
.data
);
637 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFBASICRATES
, word
);
639 netdev_err(wlandev
->netdev
,
640 "Failed to set basicrates=%d.\n", word
);
644 /* Operational rates (supprates and txratecontrol) */
645 word
= p80211rate_to_p2bit(msg
->operationalrate1
.data
);
646 if (msg
->operationalrate2
.status
== P80211ENUM_msgitem_status_data_ok
)
647 word
|= p80211rate_to_p2bit(msg
->operationalrate2
.data
);
649 if (msg
->operationalrate3
.status
== P80211ENUM_msgitem_status_data_ok
)
650 word
|= p80211rate_to_p2bit(msg
->operationalrate3
.data
);
652 if (msg
->operationalrate4
.status
== P80211ENUM_msgitem_status_data_ok
)
653 word
|= p80211rate_to_p2bit(msg
->operationalrate4
.data
);
655 if (msg
->operationalrate5
.status
== P80211ENUM_msgitem_status_data_ok
)
656 word
|= p80211rate_to_p2bit(msg
->operationalrate5
.data
);
658 if (msg
->operationalrate6
.status
== P80211ENUM_msgitem_status_data_ok
)
659 word
|= p80211rate_to_p2bit(msg
->operationalrate6
.data
);
661 if (msg
->operationalrate7
.status
== P80211ENUM_msgitem_status_data_ok
)
662 word
|= p80211rate_to_p2bit(msg
->operationalrate7
.data
);
664 if (msg
->operationalrate8
.status
== P80211ENUM_msgitem_status_data_ok
)
665 word
|= p80211rate_to_p2bit(msg
->operationalrate8
.data
);
667 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFSUPPRATES
, word
);
669 netdev_err(wlandev
->netdev
,
670 "Failed to set supprates=%d.\n", word
);
674 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_TXRATECNTL
, word
);
676 netdev_err(wlandev
->netdev
, "Failed to set txrates=%d.\n",
681 /* Set the macmode so the frame setup code knows what to do */
682 if (msg
->bsstype
.data
== P80211ENUM_bsstype_independent
) {
683 wlandev
->macmode
= WLAN_MACMODE_IBSS_STA
;
684 /* lets extend the data length a bit */
685 hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFMAXDATALEN
, 2304);
688 /* Enable the Port */
689 result
= hfa384x_drvr_enable(hw
, 0);
691 netdev_err(wlandev
->netdev
,
692 "Enable macport failed, result=%d.\n", result
);
696 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
700 netdev_dbg(wlandev
->netdev
,
701 "Failed to set a config option, result=%d\n", result
);
702 msg
->resultcode
.data
= P80211ENUM_resultcode_invalid_parameters
;
708 /*----------------------------------------------------------------
711 * Collect the PDA data and put it in the message.
714 * wlandev wlan device structure
715 * msgp ptr to msg buffer
719 * <0 success, but we're waiting for something to finish.
720 * >0 an error occurred while handling the message.
724 * process thread (usually)
725 *----------------------------------------------------------------
727 int prism2mgmt_readpda(struct wlandevice
*wlandev
, void *msgp
)
729 struct hfa384x
*hw
= wlandev
->priv
;
730 struct p80211msg_p2req_readpda
*msg
= msgp
;
733 /* We only support collecting the PDA when in the FWLOAD
736 if (wlandev
->msdstate
!= WLAN_MSD_FWLOAD
) {
737 netdev_err(wlandev
->netdev
,
738 "PDA may only be read in the fwload state.\n");
739 msg
->resultcode
.data
=
740 P80211ENUM_resultcode_implementation_failure
;
741 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
743 /* Call drvr_readpda(), it handles the auxport enable
744 * and validating the returned PDA.
746 result
= hfa384x_drvr_readpda(hw
,
748 HFA384x_PDA_LEN_MAX
);
750 netdev_err(wlandev
->netdev
,
751 "hfa384x_drvr_readpda() failed, result=%d\n",
754 msg
->resultcode
.data
=
755 P80211ENUM_resultcode_implementation_failure
;
756 msg
->resultcode
.status
=
757 P80211ENUM_msgitem_status_data_ok
;
760 msg
->pda
.status
= P80211ENUM_msgitem_status_data_ok
;
761 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
762 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
768 /*----------------------------------------------------------------
769 * prism2mgmt_ramdl_state
771 * Establishes the beginning/end of a card RAM download session.
773 * It is expected that the ramdl_write() function will be called
774 * one or more times between the 'enable' and 'disable' calls to
777 * Note: This function should not be called when a mac comm port
781 * wlandev wlan device structure
782 * msgp ptr to msg buffer
786 * <0 success, but we're waiting for something to finish.
787 * >0 an error occurred while handling the message.
791 * process thread (usually)
792 *----------------------------------------------------------------
794 int prism2mgmt_ramdl_state(struct wlandevice
*wlandev
, void *msgp
)
796 struct hfa384x
*hw
= wlandev
->priv
;
797 struct p80211msg_p2req_ramdl_state
*msg
= msgp
;
799 if (wlandev
->msdstate
!= WLAN_MSD_FWLOAD
) {
800 netdev_err(wlandev
->netdev
,
801 "ramdl_state(): may only be called in the fwload state.\n");
802 msg
->resultcode
.data
=
803 P80211ENUM_resultcode_implementation_failure
;
804 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
809 ** Note: Interrupts are locked out if this is an AP and are NOT
810 ** locked out if this is a station.
813 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
814 if (msg
->enable
.data
== P80211ENUM_truth_true
) {
815 if (hfa384x_drvr_ramdl_enable(hw
, msg
->exeaddr
.data
)) {
816 msg
->resultcode
.data
=
817 P80211ENUM_resultcode_implementation_failure
;
819 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
822 hfa384x_drvr_ramdl_disable(hw
);
823 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
829 /*----------------------------------------------------------------
830 * prism2mgmt_ramdl_write
832 * Writes a buffer to the card RAM using the download state. This
833 * is for writing code to card RAM. To just read or write raw data
834 * use the aux functions.
837 * wlandev wlan device structure
838 * msgp ptr to msg buffer
842 * <0 success, but we're waiting for something to finish.
843 * >0 an error occurred while handling the message.
847 * process thread (usually)
848 *----------------------------------------------------------------
850 int prism2mgmt_ramdl_write(struct wlandevice
*wlandev
, void *msgp
)
852 struct hfa384x
*hw
= wlandev
->priv
;
853 struct p80211msg_p2req_ramdl_write
*msg
= msgp
;
858 if (wlandev
->msdstate
!= WLAN_MSD_FWLOAD
) {
859 netdev_err(wlandev
->netdev
,
860 "ramdl_write(): may only be called in the fwload state.\n");
861 msg
->resultcode
.data
=
862 P80211ENUM_resultcode_implementation_failure
;
863 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
867 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
868 /* first validate the length */
869 if (msg
->len
.data
> sizeof(msg
->data
.data
)) {
870 msg
->resultcode
.status
=
871 P80211ENUM_resultcode_invalid_parameters
;
874 /* call the hfa384x function to do the write */
875 addr
= msg
->addr
.data
;
877 buf
= msg
->data
.data
;
878 if (hfa384x_drvr_ramdl_write(hw
, addr
, buf
, len
))
879 msg
->resultcode
.data
= P80211ENUM_resultcode_refused
;
881 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
886 /*----------------------------------------------------------------
887 * prism2mgmt_flashdl_state
889 * Establishes the beginning/end of a card Flash download session.
891 * It is expected that the flashdl_write() function will be called
892 * one or more times between the 'enable' and 'disable' calls to
895 * Note: This function should not be called when a mac comm port
899 * wlandev wlan device structure
900 * msgp ptr to msg buffer
904 * <0 success, but we're waiting for something to finish.
905 * >0 an error occurred while handling the message.
909 * process thread (usually)
910 *----------------------------------------------------------------
912 int prism2mgmt_flashdl_state(struct wlandevice
*wlandev
, void *msgp
)
915 struct hfa384x
*hw
= wlandev
->priv
;
916 struct p80211msg_p2req_flashdl_state
*msg
= msgp
;
918 if (wlandev
->msdstate
!= WLAN_MSD_FWLOAD
) {
919 netdev_err(wlandev
->netdev
,
920 "flashdl_state(): may only be called in the fwload state.\n");
921 msg
->resultcode
.data
=
922 P80211ENUM_resultcode_implementation_failure
;
923 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
928 ** Note: Interrupts are locked out if this is an AP and are NOT
929 ** locked out if this is a station.
932 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
933 if (msg
->enable
.data
== P80211ENUM_truth_true
) {
934 if (hfa384x_drvr_flashdl_enable(hw
)) {
935 msg
->resultcode
.data
=
936 P80211ENUM_resultcode_implementation_failure
;
938 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
941 hfa384x_drvr_flashdl_disable(hw
);
942 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
943 /* NOTE: At this point, the MAC is in the post-reset
944 * state and the driver is in the fwload state.
945 * We need to get the MAC back into the fwload
946 * state. To do this, we set the nsdstate to HWPRESENT
947 * and then call the ifstate function to redo everything
948 * that got us into the fwload state.
950 wlandev
->msdstate
= WLAN_MSD_HWPRESENT
;
951 result
= prism2sta_ifstate(wlandev
, P80211ENUM_ifstate_fwload
);
952 if (result
!= P80211ENUM_resultcode_success
) {
953 netdev_err(wlandev
->netdev
,
954 "prism2sta_ifstate(fwload) failed, P80211ENUM_resultcode=%d\n",
956 msg
->resultcode
.data
=
957 P80211ENUM_resultcode_implementation_failure
;
965 /*----------------------------------------------------------------
966 * prism2mgmt_flashdl_write
971 * wlandev wlan device structure
972 * msgp ptr to msg buffer
976 * <0 success, but we're waiting for something to finish.
977 * >0 an error occurred while handling the message.
981 * process thread (usually)
982 *----------------------------------------------------------------
984 int prism2mgmt_flashdl_write(struct wlandevice
*wlandev
, void *msgp
)
986 struct hfa384x
*hw
= wlandev
->priv
;
987 struct p80211msg_p2req_flashdl_write
*msg
= msgp
;
992 if (wlandev
->msdstate
!= WLAN_MSD_FWLOAD
) {
993 netdev_err(wlandev
->netdev
,
994 "flashdl_write(): may only be called in the fwload state.\n");
995 msg
->resultcode
.data
=
996 P80211ENUM_resultcode_implementation_failure
;
997 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
1002 ** Note: Interrupts are locked out if this is an AP and are NOT
1003 ** locked out if this is a station.
1006 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
1007 /* first validate the length */
1008 if (msg
->len
.data
> sizeof(msg
->data
.data
)) {
1009 msg
->resultcode
.status
=
1010 P80211ENUM_resultcode_invalid_parameters
;
1013 /* call the hfa384x function to do the write */
1014 addr
= msg
->addr
.data
;
1015 len
= msg
->len
.data
;
1016 buf
= msg
->data
.data
;
1017 if (hfa384x_drvr_flashdl_write(hw
, addr
, buf
, len
))
1018 msg
->resultcode
.data
= P80211ENUM_resultcode_refused
;
1020 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
1025 /*----------------------------------------------------------------
1026 * prism2mgmt_autojoin
1028 * Associate with an ESS.
1031 * wlandev wlan device structure
1032 * msgp ptr to msg buffer
1035 * 0 success and done
1036 * <0 success, but we're waiting for something to finish.
1037 * >0 an error occurred while handling the message.
1041 * process thread (usually)
1043 *----------------------------------------------------------------
1045 int prism2mgmt_autojoin(struct wlandevice
*wlandev
, void *msgp
)
1047 struct hfa384x
*hw
= wlandev
->priv
;
1051 struct p80211msg_lnxreq_autojoin
*msg
= msgp
;
1052 struct p80211pstrd
*pstr
;
1054 struct hfa384x_bytestr
*p2bytestr
= (struct hfa384x_bytestr
*)bytebuf
;
1056 wlandev
->macmode
= WLAN_MACMODE_NONE
;
1059 memcpy(&wlandev
->ssid
, &msg
->ssid
.data
, sizeof(msg
->ssid
.data
));
1061 /* Disable the Port */
1062 hfa384x_drvr_disable(hw
, 0);
1065 /* Set the TxRates */
1066 hfa384x_drvr_setconfig16(hw
, HFA384x_RID_TXRATECNTL
, 0x000f);
1068 /* Set the auth type */
1069 if (msg
->authtype
.data
== P80211ENUM_authalg_sharedkey
)
1070 reg
= HFA384x_CNFAUTHENTICATION_SHAREDKEY
;
1072 reg
= HFA384x_CNFAUTHENTICATION_OPENSYSTEM
;
1074 hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFAUTHENTICATION
, reg
);
1077 memset(bytebuf
, 0, 256);
1078 pstr
= (struct p80211pstrd
*)&msg
->ssid
.data
;
1079 prism2mgmt_pstr2bytestr(p2bytestr
, pstr
);
1080 result
= hfa384x_drvr_setconfig(hw
, HFA384x_RID_CNFDESIREDSSID
,
1082 HFA384x_RID_CNFDESIREDSSID_LEN
);
1083 port_type
= HFA384x_PORTTYPE_BSS
;
1084 /* Set the PortType */
1085 hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFPORTTYPE
, port_type
);
1087 /* Enable the Port */
1088 hfa384x_drvr_enable(hw
, 0);
1090 /* Set the resultcode */
1091 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
1092 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
1097 /*----------------------------------------------------------------
1098 * prism2mgmt_wlansniff
1100 * Start or stop sniffing.
1103 * wlandev wlan device structure
1104 * msgp ptr to msg buffer
1107 * 0 success and done
1108 * <0 success, but we're waiting for something to finish.
1109 * >0 an error occurred while handling the message.
1113 * process thread (usually)
1115 *----------------------------------------------------------------
1117 int prism2mgmt_wlansniff(struct wlandevice
*wlandev
, void *msgp
)
1120 struct p80211msg_lnxreq_wlansniff
*msg
= msgp
;
1122 struct hfa384x
*hw
= wlandev
->priv
;
1125 msg
->resultcode
.status
= P80211ENUM_msgitem_status_data_ok
;
1126 switch (msg
->enable
.data
) {
1127 case P80211ENUM_truth_false
:
1128 /* Confirm that we're in monitor mode */
1129 if (wlandev
->netdev
->type
== ARPHRD_ETHER
) {
1130 msg
->resultcode
.data
=
1131 P80211ENUM_resultcode_invalid_parameters
;
1134 /* Disable monitor mode */
1135 result
= hfa384x_cmd_monitor(hw
, HFA384x_MONITOR_DISABLE
);
1137 netdev_dbg(wlandev
->netdev
,
1138 "failed to disable monitor mode, result=%d\n",
1142 /* Disable port 0 */
1143 result
= hfa384x_drvr_disable(hw
, 0);
1147 "failed to disable port 0 after sniffing, result=%d\n",
1151 /* Clear the driver state */
1152 wlandev
->netdev
->type
= ARPHRD_ETHER
;
1154 /* Restore the wepflags */
1155 result
= hfa384x_drvr_setconfig16(hw
,
1156 HFA384x_RID_CNFWEPFLAGS
,
1157 hw
->presniff_wepflags
);
1161 "failed to restore wepflags=0x%04x, result=%d\n",
1162 hw
->presniff_wepflags
, result
);
1166 /* Set the port to its prior type and enable (if necessary) */
1167 if (hw
->presniff_port_type
!= 0) {
1168 word
= hw
->presniff_port_type
;
1169 result
= hfa384x_drvr_setconfig16(hw
,
1170 HFA384x_RID_CNFPORTTYPE
,
1175 "failed to restore porttype, result=%d\n",
1180 /* Enable the port */
1181 result
= hfa384x_drvr_enable(hw
, 0);
1183 netdev_dbg(wlandev
->netdev
,
1184 "failed to enable port to presniff setting, result=%d\n",
1189 result
= hfa384x_drvr_disable(hw
, 0);
1192 netdev_info(wlandev
->netdev
, "monitor mode disabled\n");
1193 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
1195 case P80211ENUM_truth_true
:
1196 /* Disable the port (if enabled), only check Port 0 */
1197 if (hw
->port_enabled
[0]) {
1198 if (wlandev
->netdev
->type
== ARPHRD_ETHER
) {
1199 /* Save macport 0 state */
1200 result
= hfa384x_drvr_getconfig16(hw
,
1201 HFA384x_RID_CNFPORTTYPE
,
1202 &hw
->presniff_port_type
);
1206 "failed to read porttype, result=%d\n",
1210 /* Save the wepflags state */
1211 result
= hfa384x_drvr_getconfig16(hw
,
1212 HFA384x_RID_CNFWEPFLAGS
,
1213 &hw
->presniff_wepflags
);
1217 "failed to read wepflags, result=%d\n",
1221 hfa384x_drvr_stop(hw
);
1222 result
= hfa384x_drvr_start(hw
);
1224 netdev_dbg(wlandev
->netdev
,
1225 "failed to restart the card for sniffing, result=%d\n",
1230 /* Disable the port */
1231 result
= hfa384x_drvr_disable(hw
, 0);
1233 netdev_dbg(wlandev
->netdev
,
1234 "failed to enable port for sniffing, result=%d\n",
1240 hw
->presniff_port_type
= 0;
1243 /* Set the channel we wish to sniff */
1244 word
= msg
->channel
.data
;
1245 result
= hfa384x_drvr_setconfig16(hw
,
1246 HFA384x_RID_CNFOWNCHANNEL
,
1248 hw
->sniff_channel
= word
;
1251 netdev_dbg(wlandev
->netdev
,
1252 "failed to set channel %d, result=%d\n",
1257 /* Now if we're already sniffing, we can skip the rest */
1258 if (wlandev
->netdev
->type
!= ARPHRD_ETHER
) {
1259 /* Set the port type to pIbss */
1260 word
= HFA384x_PORTTYPE_PSUEDOIBSS
;
1261 result
= hfa384x_drvr_setconfig16(hw
,
1262 HFA384x_RID_CNFPORTTYPE
,
1267 "failed to set porttype %d, result=%d\n",
1271 if ((msg
->keepwepflags
.status
==
1272 P80211ENUM_msgitem_status_data_ok
) &&
1273 (msg
->keepwepflags
.data
!= P80211ENUM_truth_true
)) {
1274 /* Set the wepflags for no decryption */
1275 word
= HFA384x_WEPFLAGS_DISABLE_TXCRYPT
|
1276 HFA384x_WEPFLAGS_DISABLE_RXCRYPT
;
1278 hfa384x_drvr_setconfig16(hw
,
1279 HFA384x_RID_CNFWEPFLAGS
,
1286 "failed to set wepflags=0x%04x, result=%d\n",
1292 /* Do we want to strip the FCS in monitor mode? */
1293 if ((msg
->stripfcs
.status
==
1294 P80211ENUM_msgitem_status_data_ok
) &&
1295 (msg
->stripfcs
.data
== P80211ENUM_truth_true
)) {
1301 /* Do we want to truncate the packets? */
1302 if (msg
->packet_trunc
.status
==
1303 P80211ENUM_msgitem_status_data_ok
) {
1304 hw
->sniff_truncate
= msg
->packet_trunc
.data
;
1306 hw
->sniff_truncate
= 0;
1309 /* Enable the port */
1310 result
= hfa384x_drvr_enable(hw
, 0);
1314 "failed to enable port for sniffing, result=%d\n",
1318 /* Enable monitor mode */
1319 result
= hfa384x_cmd_monitor(hw
, HFA384x_MONITOR_ENABLE
);
1321 netdev_dbg(wlandev
->netdev
,
1322 "failed to enable monitor mode, result=%d\n",
1327 if (wlandev
->netdev
->type
== ARPHRD_ETHER
)
1328 netdev_info(wlandev
->netdev
, "monitor mode enabled\n");
1330 /* Set the driver state */
1331 /* Do we want the prism2 header? */
1332 if ((msg
->prismheader
.status
==
1333 P80211ENUM_msgitem_status_data_ok
) &&
1334 (msg
->prismheader
.data
== P80211ENUM_truth_true
)) {
1336 wlandev
->netdev
->type
= ARPHRD_IEEE80211_PRISM
;
1337 } else if ((msg
->wlanheader
.status
==
1338 P80211ENUM_msgitem_status_data_ok
) &&
1339 (msg
->wlanheader
.data
== P80211ENUM_truth_true
)) {
1341 wlandev
->netdev
->type
= ARPHRD_IEEE80211_PRISM
;
1343 wlandev
->netdev
->type
= ARPHRD_IEEE80211
;
1346 msg
->resultcode
.data
= P80211ENUM_resultcode_success
;
1349 msg
->resultcode
.data
= P80211ENUM_resultcode_invalid_parameters
;
1354 msg
->resultcode
.data
= P80211ENUM_resultcode_refused
;