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