blob: 8a36c09694dadcf76a5a01c771427195b6493e83 [file] [log] [blame]
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001/* 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
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070060#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/slab.h>
67#include <linux/wireless.h>
68#include <linux/netdevice.h>
69#include <linux/delay.h>
70#include <asm/io.h>
71#include <asm/byteorder.h>
72#include <linux/random.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070073#include <linux/usb.h>
Moritz Muehlenhoff7f6e0e42009-01-25 21:54:55 +010074#include <linux/bitops.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070075
76#include "wlan_compat.h"
77
78/*================================================================*/
79/* Project Includes */
80
81#include "p80211types.h"
82#include "p80211hdr.h"
83#include "p80211mgmt.h"
84#include "p80211conv.h"
85#include "p80211msg.h"
86#include "p80211netdev.h"
87#include "p80211metadef.h"
88#include "p80211metastruct.h"
89#include "hfa384x.h"
90#include "prism2mgmt.h"
91
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070092/* Converts 802.11 format rate specifications to prism2 */
Moritz Muehlenhoff7f6e0e42009-01-25 21:54:55 +010093#define p80211rate_to_p2bit(n) ((((n)&~BIT(7)) == 2) ? BIT(0) : \
94 (((n)&~BIT(7)) == 4) ? BIT(1) : \
95 (((n)&~BIT(7)) == 11) ? BIT(2) : \
96 (((n)&~BIT(7)) == 22) ? BIT(3) : 0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070097
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070098/*----------------------------------------------------------------
99* prism2mgmt_scan
100*
101* Initiate a scan for BSSs.
102*
103* This function corresponds to MLME-scan.request and part of
104* MLME-scan.confirm. As far as I can tell in the standard, there
105* are no restrictions on when a scan.request may be issued. We have
106* to handle in whatever state the driver/MAC happen to be.
107*
108* Arguments:
109* wlandev wlan device structure
110* msgp ptr to msg buffer
111*
112* Returns:
113* 0 success and done
114* <0 success, but we're waiting for something to finish.
115* >0 an error occurred while handling the message.
116* Side effects:
117*
118* Call context:
119* process thread (usually)
120* interrupt
121----------------------------------------------------------------*/
122int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
123{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100124 int result = 0;
125 hfa384x_t *hw = wlandev->priv;
126 p80211msg_dot11req_scan_t *msg = msgp;
127 u16 roamingmode, word;
128 int i, timeout;
129 int istmpenable = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700130
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100131 hfa384x_HostScanRequest_data_t scanreq;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700132
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100133 /* gatekeeper check */
134 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
135 hw->ident_sta_fw.minor,
136 hw->ident_sta_fw.variant) <
137 HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
138 printk(KERN_ERR
139 "HostScan not supported with current firmware (<1.3.2).\n");
140 result = 1;
141 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700142 goto exit;
143 }
144
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100145 memset(&scanreq, 0, sizeof(scanreq));
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700146
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100147 /* save current roaming mode */
148 result = hfa384x_drvr_getconfig16(hw,
149 HFA384x_RID_CNFROAMINGMODE,
150 &roamingmode);
151 if (result) {
152 printk(KERN_ERR "getconfig(ROAMMODE) failed. result=%d\n",
153 result);
154 msg->resultcode.data =
155 P80211ENUM_resultcode_implementation_failure;
156 goto exit;
157 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700158
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100159 /* drop into mode 3 for the scan */
160 result = hfa384x_drvr_setconfig16(hw,
161 HFA384x_RID_CNFROAMINGMODE,
162 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
163 if (result) {
164 printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n",
165 result);
166 msg->resultcode.data =
167 P80211ENUM_resultcode_implementation_failure;
168 goto exit;
169 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700170
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100171 /* active or passive? */
172 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
173 hw->ident_sta_fw.minor,
174 hw->ident_sta_fw.variant) >
175 HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
176 if (msg->scantype.data != P80211ENUM_scantype_active)
177 word = host2hfa384x_16(msg->maxchanneltime.data);
178 else
179 word = 0;
180
181 result =
182 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
183 word);
184 if (result) {
185 printk(KERN_WARNING "Passive scan not supported with "
186 "current firmware. (<1.5.1)\n");
187 }
188 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700189
190 /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
191 word = HFA384x_RATEBIT_2;
192 scanreq.txRate = host2hfa384x_16(word);
193
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100194 /* set up the channel list */
195 word = 0;
196 for (i = 0; i < msg->channellist.data.len; i++) {
197 u8 channel = msg->channellist.data.data[i];
198 if (channel > 14)
199 continue;
200 /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
201 word |= (1 << (channel - 1));
202 }
203 scanreq.channelList = host2hfa384x_16(word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700204
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100205 /* set up the ssid, if present. */
206 scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
207 memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700208
209 /* Enable the MAC port if it's not already enabled */
210 result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100211 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100212 printk(KERN_ERR "getconfig(PORTSTATUS) failed. "
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100213 "result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700214 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100215 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700216 goto exit;
217 }
218 if (word == HFA384x_PORTSTATUS_DISABLED) {
Solomon Peachyaaad4302008-10-29 10:42:53 -0400219 u16 wordbuf[17];
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700220
221 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100222 HFA384x_RID_CNFROAMINGMODE,
223 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
224 if (result) {
225 printk(KERN_ERR
226 "setconfig(ROAMINGMODE) failed. result=%d\n",
227 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700228 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100229 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700230 goto exit;
231 }
232 /* Construct a bogus SSID and assign it to OwnSSID and
233 * DesiredSSID
234 */
235 wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN);
236 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100237 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
238 wordbuf,
239 HFA384x_RID_CNFOWNSSID_LEN);
240 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100241 printk(KERN_ERR "Failed to set OwnSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700242 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100243 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700244 goto exit;
245 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100246 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
247 wordbuf,
248 HFA384x_RID_CNFDESIREDSSID_LEN);
249 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100250 printk(KERN_ERR "Failed to set DesiredSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700251 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100252 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700253 goto exit;
254 }
255 /* bsstype */
256 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100257 HFA384x_RID_CNFPORTTYPE,
258 HFA384x_PORTTYPE_IBSS);
259 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100260 printk(KERN_ERR "Failed to set CNFPORTTYPE.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700261 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100262 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700263 goto exit;
264 }
265 /* ibss options */
266 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100267 HFA384x_RID_CREATEIBSS,
268 HFA384x_CREATEIBSS_JOINCREATEIBSS);
269 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100270 printk(KERN_ERR "Failed to set CREATEIBSS.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700271 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100272 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700273 goto exit;
274 }
275 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100276 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100277 printk(KERN_ERR "drvr_enable(0) failed. "
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100278 "result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700279 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100280 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700281 goto exit;
282 }
283 istmpenable = 1;
284 }
285
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100286 /* Figure out our timeout first Kus, then HZ */
287 timeout = msg->channellist.data.len * msg->maxchanneltime.data;
288 timeout = (timeout * HZ) / 1000;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700289
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100290 /* Issue the scan request */
291 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700292
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100293 result = hfa384x_drvr_setconfig(hw,
294 HFA384x_RID_HOSTSCAN, &scanreq,
295 sizeof(hfa384x_HostScanRequest_data_t));
296 if (result) {
297 printk(KERN_ERR "setconfig(SCANREQUEST) failed. result=%d\n",
298 result);
299 msg->resultcode.data =
300 P80211ENUM_resultcode_implementation_failure;
301 goto exit;
302 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700303
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100304 /* sleep until info frame arrives */
305 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700306
307 msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
308 if (hw->scanflag == -1)
309 hw->scanflag = 0;
310
311 msg->numbss.data = hw->scanflag;
312
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100313 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700314
315 /* Disable port if we temporarily enabled it. */
316 if (istmpenable) {
317 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100318 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100319 printk(KERN_ERR "drvr_disable(0) failed. "
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100320 "result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700321 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100322 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700323 goto exit;
324 }
325 }
326
327 /* restore original roaming mode */
328 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
329 roamingmode);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100330 if (result) {
331 printk(KERN_ERR "setconfig(ROAMMODE) failed. result=%d\n",
332 result);
333 msg->resultcode.data =
334 P80211ENUM_resultcode_implementation_failure;
335 goto exit;
336 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700337
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100338 result = 0;
339 msg->resultcode.data = P80211ENUM_resultcode_success;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700340
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100341exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700342 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
343
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700344 return result;
345}
346
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700347/*----------------------------------------------------------------
348* prism2mgmt_scan_results
349*
350* Retrieve the BSS description for one of the BSSs identified in
351* a scan.
352*
353* Arguments:
354* wlandev wlan device structure
355* msgp ptr to msg buffer
356*
357* Returns:
358* 0 success and done
359* <0 success, but we're waiting for something to finish.
360* >0 an error occurred while handling the message.
361* Side effects:
362*
363* Call context:
364* process thread (usually)
365* interrupt
366----------------------------------------------------------------*/
367int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
368{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100369 int result = 0;
370 p80211msg_dot11req_scan_results_t *req;
371 hfa384x_t *hw = wlandev->priv;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700372 hfa384x_HScanResultSub_t *item = NULL;
373
374 int count;
375
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100376 req = (p80211msg_dot11req_scan_results_t *) msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700377
378 req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
379
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100380 if (!hw->scanresults) {
381 printk(KERN_ERR
382 "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700383 result = 2;
384 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
385 goto exit;
386 }
387
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100388 count = (hw->scanresults->framelen - 3) / 32;
389 if (count > 32)
390 count = 32;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700391
392 if (req->bssindex.data >= count) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100393 pr_debug("requested index (%d) out of range (%d)\n",
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100394 req->bssindex.data, count);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700395 result = 2;
396 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
397 goto exit;
398 }
399
400 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
401 /* signal and noise */
402 req->signal.status = P80211ENUM_msgitem_status_data_ok;
403 req->noise.status = P80211ENUM_msgitem_status_data_ok;
404 req->signal.data = hfa384x2host_16(item->sl);
405 req->noise.data = hfa384x2host_16(item->anl);
406
407 /* BSSID */
408 req->bssid.status = P80211ENUM_msgitem_status_data_ok;
409 req->bssid.data.len = WLAN_BSSID_LEN;
410 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
411
412 /* SSID */
413 req->ssid.status = P80211ENUM_msgitem_status_data_ok;
414 req->ssid.data.len = hfa384x2host_16(item->ssid.len);
415 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
416
417 /* supported rates */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100418 for (count = 0; count < 10; count++)
419 if (item->supprates[count] == 0)
420 break;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700421
422#define REQBASICRATE(N) \
423 if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
424 req->basicrate ## N .data = item->supprates[(N)-1]; \
425 req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \
426 }
427
428 REQBASICRATE(1);
429 REQBASICRATE(2);
430 REQBASICRATE(3);
431 REQBASICRATE(4);
432 REQBASICRATE(5);
433 REQBASICRATE(6);
434 REQBASICRATE(7);
435 REQBASICRATE(8);
436
437#define REQSUPPRATE(N) \
438 if (count >= N) { \
439 req->supprate ## N .data = item->supprates[(N)-1]; \
440 req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \
441 }
442
443 REQSUPPRATE(1);
444 REQSUPPRATE(2);
445 REQSUPPRATE(3);
446 REQSUPPRATE(4);
447 REQSUPPRATE(5);
448 REQSUPPRATE(6);
449 REQSUPPRATE(7);
450 REQSUPPRATE(8);
451
452 /* beacon period */
453 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
454 req->beaconperiod.data = hfa384x2host_16(item->bcnint);
455
456 /* timestamps */
457 req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
458 req->timestamp.data = jiffies;
459 req->localtime.status = P80211ENUM_msgitem_status_data_ok;
460 req->localtime.data = jiffies;
461
462 /* atim window */
463 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
464 req->ibssatimwindow.data = hfa384x2host_16(item->atim);
465
466 /* Channel */
467 req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
468 req->dschannel.data = hfa384x2host_16(item->chid);
469
470 /* capinfo bits */
471 count = hfa384x2host_16(item->capinfo);
472
473 /* privacy flag */
474 req->privacy.status = P80211ENUM_msgitem_status_data_ok;
475 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
476
477 /* cfpollable */
478 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
479 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
480
481 /* cfpollreq */
482 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
483 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
484
485 /* bsstype */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100486 req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700487 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100488 P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700489
490 result = 0;
491 req->resultcode.data = P80211ENUM_resultcode_success;
492
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100493exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700494 return result;
495}
496
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700497/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700498* prism2mgmt_start
499*
500* Start a BSS. Any station can do this for IBSS, only AP for ESS.
501*
502* Arguments:
503* wlandev wlan device structure
504* msgp ptr to msg buffer
505*
506* Returns:
507* 0 success and done
508* <0 success, but we're waiting for something to finish.
509* >0 an error occurred while handling the message.
510* Side effects:
511*
512* Call context:
513* process thread (usually)
514* interrupt
515----------------------------------------------------------------*/
516int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
517{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100518 int result = 0;
519 hfa384x_t *hw = wlandev->priv;
520 p80211msg_dot11req_start_t *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700521
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100522 p80211pstrd_t *pstr;
523 u8 bytebuf[80];
524 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf;
525 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700526
527 wlandev->macmode = WLAN_MACMODE_NONE;
528
529 /* Set the SSID */
530 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
531
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400532 /*** ADHOC IBSS ***/
533 /* see if current f/w is less than 8c3 */
534 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
535 hw->ident_sta_fw.minor,
536 hw->ident_sta_fw.variant) <
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100537 HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400538 /* Ad-Hoc not quite supported on Prism2 */
539 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
540 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700541 goto done;
542 }
543
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700544 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
545
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400546 /*** STATION ***/
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700547 /* Set the REQUIRED config items */
548 /* SSID */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100549 pstr = (p80211pstrd_t *)&(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700550 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100551 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
552 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
553 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100554 printk(KERN_ERR "Failed to set CnfOwnSSID\n");
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400555 goto failed;
556 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100557 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
558 bytebuf,
559 HFA384x_RID_CNFDESIREDSSID_LEN);
560 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100561 printk(KERN_ERR "Failed to set CnfDesiredSSID\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700562 goto failed;
563 }
564
565 /* bsstype - we use the default in the ap firmware */
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400566 /* IBSS port */
567 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700568
569 /* beacon period */
570 word = msg->beaconperiod.data;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400571 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100572 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100573 printk(KERN_ERR "Failed to set beacon period=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700574 goto failed;
575 }
576
577 /* dschannel */
578 word = msg->dschannel.data;
579 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100580 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100581 printk(KERN_ERR "Failed to set channel=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700582 goto failed;
583 }
584 /* Basic rates */
585 word = p80211rate_to_p2bit(msg->basicrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100586 if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700587 word |= p80211rate_to_p2bit(msg->basicrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100588
589 if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700590 word |= p80211rate_to_p2bit(msg->basicrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100591
592 if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700593 word |= p80211rate_to_p2bit(msg->basicrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100594
595 if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700596 word |= p80211rate_to_p2bit(msg->basicrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100597
598 if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700599 word |= p80211rate_to_p2bit(msg->basicrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100600
601 if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700602 word |= p80211rate_to_p2bit(msg->basicrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100603
604 if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700605 word |= p80211rate_to_p2bit(msg->basicrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100606
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700607 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100608 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100609 printk(KERN_ERR "Failed to set basicrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700610 goto failed;
611 }
612
613 /* Operational rates (supprates and txratecontrol) */
614 word = p80211rate_to_p2bit(msg->operationalrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100615 if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700616 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100617
618 if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700619 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100620
621 if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700622 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100623
624 if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700625 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100626
627 if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700628 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100629
630 if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700631 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100632
633 if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700634 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100635
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700636 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100637 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100638 printk(KERN_ERR "Failed to set supprates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700639 goto failed;
640 }
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400641
642 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100643 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100644 printk(KERN_ERR "Failed to set txrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700645 goto failed;
646 }
647
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700648 /* Set the macmode so the frame setup code knows what to do */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100649 if (msg->bsstype.data == P80211ENUM_bsstype_independent) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400650 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700651 /* lets extend the data length a bit */
652 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
653 }
654
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700655 /* Enable the Port */
656 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100657 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100658 printk(KERN_ERR "Enable macport failed, result=%d.\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700659 goto failed;
660 }
661
662 msg->resultcode.data = P80211ENUM_resultcode_success;
663
664 goto done;
665failed:
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100666 pr_debug("Failed to set a config option, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700667 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
668
669done:
670 result = 0;
671
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700672 return result;
673}
674
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700675/*----------------------------------------------------------------
676* prism2mgmt_readpda
677*
678* Collect the PDA data and put it in the message.
679*
680* Arguments:
681* wlandev wlan device structure
682* msgp ptr to msg buffer
683*
684* Returns:
685* 0 success and done
686* <0 success, but we're waiting for something to finish.
687* >0 an error occurred while handling the message.
688* Side effects:
689*
690* Call context:
691* process thread (usually)
692----------------------------------------------------------------*/
693int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
694{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100695 hfa384x_t *hw = wlandev->priv;
696 p80211msg_p2req_readpda_t *msg = msgp;
697 int result;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700698
699 /* We only support collecting the PDA when in the FWLOAD
700 * state.
701 */
702 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100703 printk(KERN_ERR
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100704 "PDA may only be read " "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700705 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100706 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700707 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
708 } else {
709 /* Call drvr_readpda(), it handles the auxport enable
710 * and validating the returned PDA.
711 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100712 result = hfa384x_drvr_readpda(hw,
713 msg->pda.data,
714 HFA384x_PDA_LEN_MAX);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700715 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100716 printk(KERN_ERR
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100717 "hfa384x_drvr_readpda() failed, "
718 "result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700719
720 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100721 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700722 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100723 P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700724 return 0;
725 }
726 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
727 msg->resultcode.data = P80211ENUM_resultcode_success;
728 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
729 }
730
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700731 return 0;
732}
733
734/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700735* prism2mgmt_ramdl_state
736*
737* Establishes the beginning/end of a card RAM download session.
738*
739* It is expected that the ramdl_write() function will be called
740* one or more times between the 'enable' and 'disable' calls to
741* this function.
742*
743* Note: This function should not be called when a mac comm port
744* is active.
745*
746* Arguments:
747* wlandev wlan device structure
748* msgp ptr to msg buffer
749*
750* Returns:
751* 0 success and done
752* <0 success, but we're waiting for something to finish.
753* >0 an error occurred while handling the message.
754* Side effects:
755*
756* Call context:
757* process thread (usually)
758----------------------------------------------------------------*/
759int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
760{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100761 hfa384x_t *hw = wlandev->priv;
762 p80211msg_p2req_ramdl_state_t *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700763
764 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100765 printk(KERN_ERR
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100766 "ramdl_state(): may only be called "
767 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700768 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100769 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700770 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700771 return 0;
772 }
773
774 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100775 ** Note: Interrupts are locked out if this is an AP and are NOT
776 ** locked out if this is a station.
777 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700778
779 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100780 if (msg->enable.data == P80211ENUM_truth_true) {
781 if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
782 msg->resultcode.data =
783 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700784 } else {
785 msg->resultcode.data = P80211ENUM_resultcode_success;
786 }
787 } else {
788 hfa384x_drvr_ramdl_disable(hw);
789 msg->resultcode.data = P80211ENUM_resultcode_success;
790 }
791
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700792 return 0;
793}
794
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700795/*----------------------------------------------------------------
796* prism2mgmt_ramdl_write
797*
798* Writes a buffer to the card RAM using the download state. This
799* is for writing code to card RAM. To just read or write raw data
800* use the aux functions.
801*
802* Arguments:
803* wlandev wlan device structure
804* msgp ptr to msg buffer
805*
806* Returns:
807* 0 success and done
808* <0 success, but we're waiting for something to finish.
809* >0 an error occurred while handling the message.
810* Side effects:
811*
812* Call context:
813* process thread (usually)
814----------------------------------------------------------------*/
815int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
816{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100817 hfa384x_t *hw = wlandev->priv;
818 p80211msg_p2req_ramdl_write_t *msg = msgp;
819 u32 addr;
820 u32 len;
821 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700822
823 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100824 printk(KERN_ERR
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100825 "ramdl_write(): may only be called "
826 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700827 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100828 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700829 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700830 return 0;
831 }
832
833 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
834 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100835 if (msg->len.data > sizeof(msg->data.data)) {
836 msg->resultcode.status =
837 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700838 return 0;
839 }
840 /* call the hfa384x function to do the write */
841 addr = msg->addr.data;
842 len = msg->len.data;
843 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100844 if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700845 msg->resultcode.data = P80211ENUM_resultcode_refused;
846
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700847 msg->resultcode.data = P80211ENUM_resultcode_success;
848
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700849 return 0;
850}
851
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700852/*----------------------------------------------------------------
853* prism2mgmt_flashdl_state
854*
855* Establishes the beginning/end of a card Flash download session.
856*
857* It is expected that the flashdl_write() function will be called
858* one or more times between the 'enable' and 'disable' calls to
859* this function.
860*
861* Note: This function should not be called when a mac comm port
862* is active.
863*
864* Arguments:
865* wlandev wlan device structure
866* msgp ptr to msg buffer
867*
868* Returns:
869* 0 success and done
870* <0 success, but we're waiting for something to finish.
871* >0 an error occurred while handling the message.
872* Side effects:
873*
874* Call context:
875* process thread (usually)
876----------------------------------------------------------------*/
877int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
878{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100879 int result = 0;
880 hfa384x_t *hw = wlandev->priv;
881 p80211msg_p2req_flashdl_state_t *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700882
883 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100884 printk(KERN_ERR
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100885 "flashdl_state(): may only be called "
886 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700887 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100888 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700889 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700890 return 0;
891 }
892
893 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100894 ** Note: Interrupts are locked out if this is an AP and are NOT
895 ** locked out if this is a station.
896 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700897
898 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100899 if (msg->enable.data == P80211ENUM_truth_true) {
900 if (hfa384x_drvr_flashdl_enable(hw)) {
901 msg->resultcode.data =
902 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700903 } else {
904 msg->resultcode.data = P80211ENUM_resultcode_success;
905 }
906 } else {
907 hfa384x_drvr_flashdl_disable(hw);
908 msg->resultcode.data = P80211ENUM_resultcode_success;
909 /* NOTE: At this point, the MAC is in the post-reset
910 * state and the driver is in the fwload state.
911 * We need to get the MAC back into the fwload
912 * state. To do this, we set the nsdstate to HWPRESENT
913 * and then call the ifstate function to redo everything
914 * that got us into the fwload state.
915 */
916 wlandev->msdstate = WLAN_MSD_HWPRESENT;
917 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
918 if (result != P80211ENUM_resultcode_success) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100919 printk(KERN_ERR "prism2sta_ifstate(fwload) failed,"
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100920 "P80211ENUM_resultcode=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700921 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100922 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700923 result = -1;
924 }
925 }
926
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700927 return 0;
928}
929
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700930/*----------------------------------------------------------------
931* prism2mgmt_flashdl_write
932*
933*
934*
935* Arguments:
936* wlandev wlan device structure
937* msgp ptr to msg buffer
938*
939* Returns:
940* 0 success and done
941* <0 success, but we're waiting for something to finish.
942* >0 an error occurred while handling the message.
943* Side effects:
944*
945* Call context:
946* process thread (usually)
947----------------------------------------------------------------*/
948int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
949{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100950 hfa384x_t *hw = wlandev->priv;
951 p80211msg_p2req_flashdl_write_t *msg = msgp;
952 u32 addr;
953 u32 len;
954 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700955
956 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100957 printk(KERN_ERR
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100958 "flashdl_write(): may only be called "
959 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700960 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100961 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700962 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700963 return 0;
964 }
965
966 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100967 ** Note: Interrupts are locked out if this is an AP and are NOT
968 ** locked out if this is a station.
969 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700970
971 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
972 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100973 if (msg->len.data > sizeof(msg->data.data)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700974 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100975 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700976 return 0;
977 }
978 /* call the hfa384x function to do the write */
979 addr = msg->addr.data;
980 len = msg->len.data;
981 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100982 if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700983 msg->resultcode.data = P80211ENUM_resultcode_refused;
984
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700985 msg->resultcode.data = P80211ENUM_resultcode_success;
986
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700987 return 0;
988}
989
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700990/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700991* prism2mgmt_autojoin
992*
993* Associate with an ESS.
994*
995* Arguments:
996* wlandev wlan device structure
997* msgp ptr to msg buffer
998*
999* Returns:
1000* 0 success and done
1001* <0 success, but we're waiting for something to finish.
1002* >0 an error occurred while handling the message.
1003* Side effects:
1004*
1005* Call context:
1006* process thread (usually)
1007* interrupt
1008----------------------------------------------------------------*/
1009int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
1010{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001011 hfa384x_t *hw = wlandev->priv;
1012 int result = 0;
1013 u16 reg;
1014 u16 port_type;
1015 p80211msg_lnxreq_autojoin_t *msg = msgp;
1016 p80211pstrd_t *pstr;
1017 u8 bytebuf[256];
1018 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001019
1020 wlandev->macmode = WLAN_MACMODE_NONE;
1021
1022 /* Set the SSID */
1023 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1024
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001025 /* Disable the Port */
1026 hfa384x_drvr_disable(hw, 0);
1027
1028 /*** STATION ***/
1029 /* Set the TxRates */
1030 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1031
1032 /* Set the auth type */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001033 if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001034 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001035 else
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001036 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001037
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001038 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1039
1040 /* Set the ssid */
1041 memset(bytebuf, 0, 256);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001042 pstr = (p80211pstrd_t *)&(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001043 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001044 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
1045 bytebuf,
1046 HFA384x_RID_CNFDESIREDSSID_LEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001047 port_type = HFA384x_PORTTYPE_BSS;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001048 /* Set the PortType */
1049 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1050
1051 /* Enable the Port */
1052 hfa384x_drvr_enable(hw, 0);
1053
1054 /* Set the resultcode */
1055 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1056 msg->resultcode.data = P80211ENUM_resultcode_success;
1057
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001058 return result;
1059}
1060
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001061/*----------------------------------------------------------------
1062* prism2mgmt_wlansniff
1063*
1064* Start or stop sniffing.
1065*
1066* Arguments:
1067* wlandev wlan device structure
1068* msgp ptr to msg buffer
1069*
1070* Returns:
1071* 0 success and done
1072* <0 success, but we're waiting for something to finish.
1073* >0 an error occurred while handling the message.
1074* Side effects:
1075*
1076* Call context:
1077* process thread (usually)
1078* interrupt
1079----------------------------------------------------------------*/
1080int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
1081{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001082 int result = 0;
1083 p80211msg_lnxreq_wlansniff_t *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001084
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001085 hfa384x_t *hw = wlandev->priv;
1086 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001087
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001088 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001089 switch (msg->enable.data) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001090 case P80211ENUM_truth_false:
1091 /* Confirm that we're in monitor mode */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001092 if (wlandev->netdev->type == ARPHRD_ETHER) {
1093 msg->resultcode.data =
1094 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001095 result = 0;
1096 goto exit;
1097 }
1098 /* Disable monitor mode */
1099 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001100 if (result) {
1101 printk(KERN_DEBUG
1102 "failed to disable monitor mode, result=%d\n",
1103 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001104 goto failed;
1105 }
1106 /* Disable port 0 */
1107 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001108 if (result) {
1109 printk(KERN_DEBUG
1110 "failed to disable port 0 after sniffing, result=%d\n",
1111 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001112 goto failed;
1113 }
1114 /* Clear the driver state */
1115 wlandev->netdev->type = ARPHRD_ETHER;
1116
1117 /* Restore the wepflags */
1118 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001119 HFA384x_RID_CNFWEPFLAGS,
1120 hw->presniff_wepflags);
1121 if (result) {
1122 printk(KERN_DEBUG
1123 "failed to restore wepflags=0x%04x, result=%d\n",
1124 hw->presniff_wepflags, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001125 goto failed;
1126 }
1127
1128 /* Set the port to its prior type and enable (if necessary) */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001129 if (hw->presniff_port_type != 0) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001130 word = hw->presniff_port_type;
1131 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001132 HFA384x_RID_CNFPORTTYPE,
1133 word);
1134 if (result) {
1135 printk(KERN_DEBUG
1136 "failed to restore porttype, result=%d\n",
1137 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001138 goto failed;
1139 }
1140
1141 /* Enable the port */
1142 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001143 if (result) {
1144 printk(KERN_DEBUG
1145 "failed to enable port to presniff setting, result=%d\n",
1146 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001147 goto failed;
1148 }
1149 } else {
1150 result = hfa384x_drvr_disable(hw, 0);
1151
1152 }
1153
Moritz Muehlenhoff350f2f4b2009-01-25 21:54:57 +01001154 printk(KERN_INFO "monitor mode disabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001155 msg->resultcode.data = P80211ENUM_resultcode_success;
1156 result = 0;
1157 goto exit;
1158 break;
1159 case P80211ENUM_truth_true:
1160 /* Disable the port (if enabled), only check Port 0 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001161 if (hw->port_enabled[0]) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001162 if (wlandev->netdev->type == ARPHRD_ETHER) {
1163 /* Save macport 0 state */
1164 result = hfa384x_drvr_getconfig16(hw,
1165 HFA384x_RID_CNFPORTTYPE,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001166 &(hw->
1167 presniff_port_type));
1168 if (result) {
1169 printk(KERN_DEBUG
1170 "failed to read porttype, result=%d\n",
1171 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001172 goto failed;
1173 }
1174 /* Save the wepflags state */
1175 result = hfa384x_drvr_getconfig16(hw,
1176 HFA384x_RID_CNFWEPFLAGS,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001177 &(hw->
1178 presniff_wepflags));
1179 if (result) {
1180 printk(KERN_DEBUG
1181 "failed to read wepflags, result=%d\n",
1182 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001183 goto failed;
1184 }
1185 hfa384x_drvr_stop(hw);
1186 result = hfa384x_drvr_start(hw);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001187 if (result) {
1188 printk(KERN_DEBUG
1189 "failed to restart the card for sniffing, result=%d\n",
1190 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001191 goto failed;
1192 }
1193 } else {
1194 /* Disable the port */
1195 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001196 if (result) {
1197 printk(KERN_DEBUG
1198 "failed to enable port for sniffing, result=%d\n",
1199 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001200 goto failed;
1201 }
1202 }
1203 } else {
1204 hw->presniff_port_type = 0;
1205 }
1206
1207 /* Set the channel we wish to sniff */
1208 word = msg->channel.data;
1209 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001210 HFA384x_RID_CNFOWNCHANNEL,
1211 word);
1212 hw->sniff_channel = word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001213
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001214 if (result) {
1215 printk(KERN_DEBUG
1216 "failed to set channel %d, result=%d\n",
1217 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001218 goto failed;
1219 }
1220
1221 /* Now if we're already sniffing, we can skip the rest */
1222 if (wlandev->netdev->type != ARPHRD_ETHER) {
1223 /* Set the port type to pIbss */
1224 word = HFA384x_PORTTYPE_PSUEDOIBSS;
1225 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001226 HFA384x_RID_CNFPORTTYPE,
1227 word);
1228 if (result) {
1229 printk(KERN_DEBUG
1230 "failed to set porttype %d, result=%d\n",
1231 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001232 goto failed;
1233 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001234 if ((msg->keepwepflags.status ==
1235 P80211ENUM_msgitem_status_data_ok)
1236 && (msg->keepwepflags.data !=
1237 P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001238 /* Set the wepflags for no decryption */
1239 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001240 HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1241 result =
1242 hfa384x_drvr_setconfig16(hw,
1243 HFA384x_RID_CNFWEPFLAGS,
1244 word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001245 }
1246
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001247 if (result) {
1248 printk(KERN_DEBUG
1249 "failed to set wepflags=0x%04x, result=%d\n",
1250 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001251 goto failed;
1252 }
1253 }
1254
1255 /* Do we want to strip the FCS in monitor mode? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001256 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok)
1257 && (msg->stripfcs.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001258 hw->sniff_fcs = 0;
1259 } else {
1260 hw->sniff_fcs = 1;
1261 }
1262
1263 /* Do we want to truncate the packets? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001264 if (msg->packet_trunc.status ==
1265 P80211ENUM_msgitem_status_data_ok) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001266 hw->sniff_truncate = msg->packet_trunc.data;
1267 } else {
1268 hw->sniff_truncate = 0;
1269 }
1270
1271 /* Enable the port */
1272 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001273 if (result) {
1274 printk(KERN_DEBUG
1275 "failed to enable port for sniffing, result=%d\n",
1276 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001277 goto failed;
1278 }
1279 /* Enable monitor mode */
1280 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001281 if (result) {
1282 printk(KERN_DEBUG
1283 "failed to enable monitor mode, result=%d\n",
1284 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001285 goto failed;
1286 }
1287
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001288 if (wlandev->netdev->type == ARPHRD_ETHER)
Moritz Muehlenhoff350f2f4b2009-01-25 21:54:57 +01001289 printk(KERN_INFO "monitor mode enabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001290
1291 /* Set the driver state */
1292 /* Do we want the prism2 header? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001293 if ((msg->prismheader.status ==
1294 P80211ENUM_msgitem_status_data_ok)
1295 && (msg->prismheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001296 hw->sniffhdr = 0;
1297 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001298 } else
1299 if ((msg->wlanheader.status ==
1300 P80211ENUM_msgitem_status_data_ok)
1301 && (msg->wlanheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001302 hw->sniffhdr = 1;
1303 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1304 } else {
1305 wlandev->netdev->type = ARPHRD_IEEE80211;
1306 }
1307
1308 msg->resultcode.data = P80211ENUM_resultcode_success;
1309 result = 0;
1310 goto exit;
1311 break;
1312 default:
1313 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1314 result = 0;
1315 goto exit;
1316 break;
1317 }
1318
1319failed:
1320 msg->resultcode.data = P80211ENUM_resultcode_refused;
1321 result = 0;
1322exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001323 return result;
1324}