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