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