blob: 953142ae9296d0aae44226cabe6c4c5ba41b6e32 [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 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070062
63#include <linux/if_arp.h>
64#include <linux/module.h>
65#include <linux/kernel.h>
66#include <linux/wait.h>
67#include <linux/sched.h>
68#include <linux/types.h>
69#include <linux/slab.h>
70#include <linux/wireless.h>
71#include <linux/netdevice.h>
72#include <linux/delay.h>
73#include <asm/io.h>
74#include <asm/byteorder.h>
75#include <linux/random.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070076#include <linux/usb.h>
Moritz Muehlenhoff7f6e0e42009-01-25 21:54:55 +010077#include <linux/bitops.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070078
79#include "wlan_compat.h"
80
81/*================================================================*/
82/* Project Includes */
83
84#include "p80211types.h"
85#include "p80211hdr.h"
86#include "p80211mgmt.h"
87#include "p80211conv.h"
88#include "p80211msg.h"
89#include "p80211netdev.h"
90#include "p80211metadef.h"
91#include "p80211metastruct.h"
92#include "hfa384x.h"
93#include "prism2mgmt.h"
94
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070095/* Converts 802.11 format rate specifications to prism2 */
Moritz Muehlenhoff7f6e0e42009-01-25 21:54:55 +010096#define p80211rate_to_p2bit(n) ((((n)&~BIT(7)) == 2) ? BIT(0) : \
97 (((n)&~BIT(7)) == 4) ? BIT(1) : \
98 (((n)&~BIT(7)) == 11) ? BIT(2) : \
99 (((n)&~BIT(7)) == 22) ? BIT(3) : 0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700100
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700101/*----------------------------------------------------------------
102* prism2mgmt_scan
103*
104* Initiate a scan for BSSs.
105*
106* This function corresponds to MLME-scan.request and part of
107* MLME-scan.confirm. As far as I can tell in the standard, there
108* are no restrictions on when a scan.request may be issued. We have
109* to handle in whatever state the driver/MAC happen to be.
110*
111* Arguments:
112* wlandev wlan device structure
113* msgp ptr to msg buffer
114*
115* Returns:
116* 0 success and done
117* <0 success, but we're waiting for something to finish.
118* >0 an error occurred while handling the message.
119* Side effects:
120*
121* Call context:
122* process thread (usually)
123* interrupt
124----------------------------------------------------------------*/
125int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
126{
127 int result = 0;
128 hfa384x_t *hw = wlandev->priv;
129 p80211msg_dot11req_scan_t *msg = msgp;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400130 u16 roamingmode, word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700131 int i, timeout;
132 int istmpenable = 0;
133
134 hfa384x_HostScanRequest_data_t scanreq;
135
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700136 /* gatekeeper check */
137 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
138 hw->ident_sta_fw.minor,
139 hw->ident_sta_fw.variant) <
140 HFA384x_FIRMWARE_VERSION(1,3,2)) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100141 printk(KERN_ERR "HostScan not supported with current firmware (<1.3.2).\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700142 result = 1;
143 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
144 goto exit;
145 }
146
147 memset(&scanreq, 0, sizeof(scanreq));
148
149 /* save current roaming mode */
150 result = hfa384x_drvr_getconfig16(hw,
151 HFA384x_RID_CNFROAMINGMODE, &roamingmode);
152 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100153 printk(KERN_ERR "getconfig(ROAMMODE) failed. result=%d\n",
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700154 result);
155 msg->resultcode.data =
156 P80211ENUM_resultcode_implementation_failure;
157 goto exit;
158 }
159
160 /* drop into mode 3 for the scan */
161 result = hfa384x_drvr_setconfig16(hw,
162 HFA384x_RID_CNFROAMINGMODE,
163 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
164 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100165 printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n",
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700166 result);
167 msg->resultcode.data =
168 P80211ENUM_resultcode_implementation_failure;
169 goto exit;
170 }
171
172 /* active or passive? */
173 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
174 hw->ident_sta_fw.minor,
175 hw->ident_sta_fw.variant) >
176 HFA384x_FIRMWARE_VERSION(1,5,0)) {
177 if (msg->scantype.data != P80211ENUM_scantype_active) {
178 word = host2hfa384x_16(msg->maxchanneltime.data);
179 } else {
180 word = 0;
181 }
182 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word);
183 if ( result ) {
Moritz Muehlenhoff9b9556e2009-01-25 21:55:01 +0100184 printk(KERN_WARNING "Passive scan not supported with "
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700185 "current firmware. (<1.5.1)\n");
186 }
187 }
188
189 /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
190 word = HFA384x_RATEBIT_2;
191 scanreq.txRate = host2hfa384x_16(word);
192
193 /* set up the channel list */
194 word = 0;
195 for (i = 0; i < msg->channellist.data.len; i++) {
Solomon Peachyaaad4302008-10-29 10:42:53 -0400196 u8 channel = msg->channellist.data.data[i];
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700197 if (channel > 14) continue;
Moritz Muehlenhoff7f6e0e42009-01-25 21:54:55 +0100198 /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700199 word |= (1 << (channel-1));
200 }
201 scanreq.channelList = host2hfa384x_16(word);
202
203 /* set up the ssid, if present. */
204 scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
205 memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
206
207 /* Enable the MAC port if it's not already enabled */
208 result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
209 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100210 printk(KERN_ERR "getconfig(PORTSTATUS) failed. "
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700211 "result=%d\n", result);
212 msg->resultcode.data =
213 P80211ENUM_resultcode_implementation_failure;
214 goto exit;
215 }
216 if (word == HFA384x_PORTSTATUS_DISABLED) {
Solomon Peachyaaad4302008-10-29 10:42:53 -0400217 u16 wordbuf[17];
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700218
219 result = hfa384x_drvr_setconfig16(hw,
220 HFA384x_RID_CNFROAMINGMODE,
221 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
222 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100223 printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700224 msg->resultcode.data =
225 P80211ENUM_resultcode_implementation_failure;
226 goto exit;
227 }
228 /* Construct a bogus SSID and assign it to OwnSSID and
229 * DesiredSSID
230 */
231 wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN);
232 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
233 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
234 wordbuf, HFA384x_RID_CNFOWNSSID_LEN);
235 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100236 printk(KERN_ERR "Failed to set OwnSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700237 msg->resultcode.data =
238 P80211ENUM_resultcode_implementation_failure;
239 goto exit;
240 }
241 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
242 wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN);
243 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100244 printk(KERN_ERR "Failed to set DesiredSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700245 msg->resultcode.data =
246 P80211ENUM_resultcode_implementation_failure;
247 goto exit;
248 }
249 /* bsstype */
250 result = hfa384x_drvr_setconfig16(hw,
251 HFA384x_RID_CNFPORTTYPE,
252 HFA384x_PORTTYPE_IBSS);
253 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100254 printk(KERN_ERR "Failed to set CNFPORTTYPE.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700255 msg->resultcode.data =
256 P80211ENUM_resultcode_implementation_failure;
257 goto exit;
258 }
259 /* ibss options */
260 result = hfa384x_drvr_setconfig16(hw,
261 HFA384x_RID_CREATEIBSS,
262 HFA384x_CREATEIBSS_JOINCREATEIBSS);
263 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100264 printk(KERN_ERR "Failed to set CREATEIBSS.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700265 msg->resultcode.data =
266 P80211ENUM_resultcode_implementation_failure;
267 goto exit;
268 }
269 result = hfa384x_drvr_enable(hw, 0);
270 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100271 printk(KERN_ERR "drvr_enable(0) failed. "
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700272 "result=%d\n", result);
273 msg->resultcode.data =
274 P80211ENUM_resultcode_implementation_failure;
275 goto exit;
276 }
277 istmpenable = 1;
278 }
279
280 /* Figure out our timeout first Kus, then HZ */
281 timeout = msg->channellist.data.len * msg->maxchanneltime.data;
282 timeout = (timeout * HZ)/1000;
283
284 /* Issue the scan request */
285 hw->scanflag = 0;
286
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700287 result = hfa384x_drvr_setconfig( hw,
288 HFA384x_RID_HOSTSCAN, &scanreq,
289 sizeof(hfa384x_HostScanRequest_data_t));
290 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100291 printk(KERN_ERR "setconfig(SCANREQUEST) failed. result=%d\n",
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700292 result);
293 msg->resultcode.data =
294 P80211ENUM_resultcode_implementation_failure;
295 goto exit;
296 }
297
298 /* sleep until info frame arrives */
299 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
300
301 msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
302 if (hw->scanflag == -1)
303 hw->scanflag = 0;
304
305 msg->numbss.data = hw->scanflag;
306
307 hw->scanflag = 0;
308
309 /* Disable port if we temporarily enabled it. */
310 if (istmpenable) {
311 result = hfa384x_drvr_disable(hw, 0);
312 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100313 printk(KERN_ERR "drvr_disable(0) failed. "
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700314 "result=%d\n", result);
315 msg->resultcode.data =
316 P80211ENUM_resultcode_implementation_failure;
317 goto exit;
318 }
319 }
320
321 /* restore original roaming mode */
322 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
323 roamingmode);
324 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100325 printk(KERN_ERR "setconfig(ROAMMODE) failed. result=%d\n",
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700326 result);
327 msg->resultcode.data =
328 P80211ENUM_resultcode_implementation_failure;
329 goto exit;
330 }
331
332 result = 0;
333 msg->resultcode.data = P80211ENUM_resultcode_success;
334
335 exit:
336 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
337
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700338 return result;
339}
340
341
342/*----------------------------------------------------------------
343* prism2mgmt_scan_results
344*
345* Retrieve the BSS description for one of the BSSs identified in
346* a scan.
347*
348* Arguments:
349* wlandev wlan device structure
350* msgp ptr to msg buffer
351*
352* Returns:
353* 0 success and done
354* <0 success, but we're waiting for something to finish.
355* >0 an error occurred while handling the message.
356* Side effects:
357*
358* Call context:
359* process thread (usually)
360* interrupt
361----------------------------------------------------------------*/
362int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
363{
364 int result = 0;
365 p80211msg_dot11req_scan_results_t *req;
366 hfa384x_t *hw = wlandev->priv;
367 hfa384x_HScanResultSub_t *item = NULL;
368
369 int count;
370
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700371 req = (p80211msg_dot11req_scan_results_t *) msgp;
372
373 req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
374
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700375 if (! hw->scanresults) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100376 printk(KERN_ERR "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700377 result = 2;
378 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
379 goto exit;
380 }
381
382 count = (hw->scanresults->framelen - 3) / 32;
383 if (count > 32) count = 32;
384
385 if (req->bssindex.data >= count) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100386 pr_debug("requested index (%d) out of range (%d)\n",
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700387 req->bssindex.data, count);
388 result = 2;
389 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
390 goto exit;
391 }
392
393 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
394 /* signal and noise */
395 req->signal.status = P80211ENUM_msgitem_status_data_ok;
396 req->noise.status = P80211ENUM_msgitem_status_data_ok;
397 req->signal.data = hfa384x2host_16(item->sl);
398 req->noise.data = hfa384x2host_16(item->anl);
399
400 /* BSSID */
401 req->bssid.status = P80211ENUM_msgitem_status_data_ok;
402 req->bssid.data.len = WLAN_BSSID_LEN;
403 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
404
405 /* SSID */
406 req->ssid.status = P80211ENUM_msgitem_status_data_ok;
407 req->ssid.data.len = hfa384x2host_16(item->ssid.len);
408 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
409
410 /* supported rates */
411 for (count = 0; count < 10 ; count++)
412 if (item->supprates[count] == 0)
413 break;
414
415#define REQBASICRATE(N) \
416 if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
417 req->basicrate ## N .data = item->supprates[(N)-1]; \
418 req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \
419 }
420
421 REQBASICRATE(1);
422 REQBASICRATE(2);
423 REQBASICRATE(3);
424 REQBASICRATE(4);
425 REQBASICRATE(5);
426 REQBASICRATE(6);
427 REQBASICRATE(7);
428 REQBASICRATE(8);
429
430#define REQSUPPRATE(N) \
431 if (count >= N) { \
432 req->supprate ## N .data = item->supprates[(N)-1]; \
433 req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \
434 }
435
436 REQSUPPRATE(1);
437 REQSUPPRATE(2);
438 REQSUPPRATE(3);
439 REQSUPPRATE(4);
440 REQSUPPRATE(5);
441 REQSUPPRATE(6);
442 REQSUPPRATE(7);
443 REQSUPPRATE(8);
444
445 /* beacon period */
446 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
447 req->beaconperiod.data = hfa384x2host_16(item->bcnint);
448
449 /* timestamps */
450 req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
451 req->timestamp.data = jiffies;
452 req->localtime.status = P80211ENUM_msgitem_status_data_ok;
453 req->localtime.data = jiffies;
454
455 /* atim window */
456 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
457 req->ibssatimwindow.data = hfa384x2host_16(item->atim);
458
459 /* Channel */
460 req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
461 req->dschannel.data = hfa384x2host_16(item->chid);
462
463 /* capinfo bits */
464 count = hfa384x2host_16(item->capinfo);
465
466 /* privacy flag */
467 req->privacy.status = P80211ENUM_msgitem_status_data_ok;
468 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
469
470 /* cfpollable */
471 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
472 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
473
474 /* cfpollreq */
475 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
476 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
477
478 /* bsstype */
479 req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
480 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
481 P80211ENUM_bsstype_infrastructure :
482 P80211ENUM_bsstype_independent;
483
484 // item->proberesp_rate
485/*
486 req->fhdwelltime
487 req->fhhopset
488 req->fhhoppattern
489 req->fhhopindex
490 req->cfpdurremaining
491*/
492
493 result = 0;
494 req->resultcode.data = P80211ENUM_resultcode_success;
495
496 exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700497 return result;
498}
499
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700500/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700501* prism2mgmt_start
502*
503* Start a BSS. Any station can do this for IBSS, only AP for ESS.
504*
505* Arguments:
506* wlandev wlan device structure
507* msgp ptr to msg buffer
508*
509* Returns:
510* 0 success and done
511* <0 success, but we're waiting for something to finish.
512* >0 an error occurred while handling the message.
513* Side effects:
514*
515* Call context:
516* process thread (usually)
517* interrupt
518----------------------------------------------------------------*/
519int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
520{
521 int result = 0;
522 hfa384x_t *hw = wlandev->priv;
523 p80211msg_dot11req_start_t *msg = msgp;
524
525 p80211pstrd_t *pstr;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400526 u8 bytebuf[80];
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700527 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400528 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700529
530 wlandev->macmode = WLAN_MACMODE_NONE;
531
532 /* Set the SSID */
533 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
534
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400535 /*** ADHOC IBSS ***/
536 /* see if current f/w is less than 8c3 */
537 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
538 hw->ident_sta_fw.minor,
539 hw->ident_sta_fw.variant) <
540 HFA384x_FIRMWARE_VERSION(0,8,3)) {
541 /* Ad-Hoc not quite supported on Prism2 */
542 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
543 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700544 goto done;
545 }
546
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700547 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
548
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400549 /*** STATION ***/
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700550 /* Set the REQUIRED config items */
551 /* SSID */
552 pstr = (p80211pstrd_t*)&(msg->ssid.data);
553 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
554 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400555 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700556 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100557 printk(KERN_ERR "Failed to set CnfOwnSSID\n");
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400558 goto failed;
559 }
560 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
561 bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
562 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100563 printk(KERN_ERR "Failed to set CnfDesiredSSID\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700564 goto failed;
565 }
566
567 /* bsstype - we use the default in the ap firmware */
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400568 /* IBSS port */
569 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700570
571 /* beacon period */
572 word = msg->beaconperiod.data;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400573 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700574 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100575 printk(KERN_ERR "Failed to set beacon period=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700576 goto failed;
577 }
578
579 /* dschannel */
580 word = msg->dschannel.data;
581 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
582 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100583 printk(KERN_ERR "Failed to set channel=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700584 goto failed;
585 }
586 /* Basic rates */
587 word = p80211rate_to_p2bit(msg->basicrate1.data);
588 if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
589 word |= p80211rate_to_p2bit(msg->basicrate2.data);
590 }
591 if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
592 word |= p80211rate_to_p2bit(msg->basicrate3.data);
593 }
594 if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
595 word |= p80211rate_to_p2bit(msg->basicrate4.data);
596 }
597 if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
598 word |= p80211rate_to_p2bit(msg->basicrate5.data);
599 }
600 if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
601 word |= p80211rate_to_p2bit(msg->basicrate6.data);
602 }
603 if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
604 word |= p80211rate_to_p2bit(msg->basicrate7.data);
605 }
606 if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
607 word |= p80211rate_to_p2bit(msg->basicrate8.data);
608 }
609 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
610 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100611 printk(KERN_ERR "Failed to set basicrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700612 goto failed;
613 }
614
615 /* Operational rates (supprates and txratecontrol) */
616 word = p80211rate_to_p2bit(msg->operationalrate1.data);
617 if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
618 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
619 }
620 if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
621 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
622 }
623 if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
624 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
625 }
626 if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
627 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
628 }
629 if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
630 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
631 }
632 if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
633 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
634 }
635 if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
636 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
637 }
638 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
639 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100640 printk(KERN_ERR "Failed to set supprates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700641 goto failed;
642 }
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400643
644 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700645 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100646 printk(KERN_ERR "Failed to set txrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700647 goto failed;
648 }
649
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700650 /* Set the macmode so the frame setup code knows what to do */
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400651 if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) {
652 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700653 /* lets extend the data length a bit */
654 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
655 }
656
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700657 /* Enable the Port */
658 result = hfa384x_drvr_enable(hw, 0);
659 if ( result ) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100660 printk(KERN_ERR "Enable macport failed, result=%d.\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700661 goto failed;
662 }
663
664 msg->resultcode.data = P80211ENUM_resultcode_success;
665
666 goto done;
667failed:
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100668 pr_debug("Failed to set a config option, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700669 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
670
671done:
672 result = 0;
673
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700674 return result;
675}
676
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700677/*----------------------------------------------------------------
678* prism2mgmt_readpda
679*
680* Collect the PDA data and put it in the message.
681*
682* Arguments:
683* wlandev wlan device structure
684* msgp ptr to msg buffer
685*
686* Returns:
687* 0 success and done
688* <0 success, but we're waiting for something to finish.
689* >0 an error occurred while handling the message.
690* Side effects:
691*
692* Call context:
693* process thread (usually)
694----------------------------------------------------------------*/
695int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
696{
697 hfa384x_t *hw = wlandev->priv;
698 p80211msg_p2req_readpda_t *msg = msgp;
699 int result;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700700
701 /* We only support collecting the PDA when in the FWLOAD
702 * state.
703 */
704 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100705 printk(KERN_ERR
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700706 "PDA may only be read "
707 "in the fwload state.\n");
708 msg->resultcode.data =
709 P80211ENUM_resultcode_implementation_failure;
710 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
711 } else {
712 /* Call drvr_readpda(), it handles the auxport enable
713 * and validating the returned PDA.
714 */
715 result = hfa384x_drvr_readpda(
716 hw,
717 msg->pda.data,
718 HFA384x_PDA_LEN_MAX);
719 if (result) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100720 printk(KERN_ERR
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700721 "hfa384x_drvr_readpda() failed, "
722 "result=%d\n",
723 result);
724
725 msg->resultcode.data =
726 P80211ENUM_resultcode_implementation_failure;
727 msg->resultcode.status =
728 P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700729 return 0;
730 }
731 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
732 msg->resultcode.data = P80211ENUM_resultcode_success;
733 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
734 }
735
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700736 return 0;
737}
738
739/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700740* prism2mgmt_ramdl_state
741*
742* Establishes the beginning/end of a card RAM download session.
743*
744* It is expected that the ramdl_write() function will be called
745* one or more times between the 'enable' and 'disable' calls to
746* this function.
747*
748* Note: This function should not be called when a mac comm port
749* is active.
750*
751* Arguments:
752* wlandev wlan device structure
753* msgp ptr to msg buffer
754*
755* Returns:
756* 0 success and done
757* <0 success, but we're waiting for something to finish.
758* >0 an error occurred while handling the message.
759* Side effects:
760*
761* Call context:
762* process thread (usually)
763----------------------------------------------------------------*/
764int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
765{
766 hfa384x_t *hw = wlandev->priv;
767 p80211msg_p2req_ramdl_state_t *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700768
769 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100770 printk(KERN_ERR
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700771 "ramdl_state(): may only be called "
772 "in the fwload state.\n");
773 msg->resultcode.data =
774 P80211ENUM_resultcode_implementation_failure;
775 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700776 return 0;
777 }
778
779 /*
780 ** Note: Interrupts are locked out if this is an AP and are NOT
781 ** locked out if this is a station.
782 */
783
784 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
785 if ( msg->enable.data == P80211ENUM_truth_true ) {
786 if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) {
787 msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
788 } else {
789 msg->resultcode.data = P80211ENUM_resultcode_success;
790 }
791 } else {
792 hfa384x_drvr_ramdl_disable(hw);
793 msg->resultcode.data = P80211ENUM_resultcode_success;
794 }
795
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700796 return 0;
797}
798
799
800/*----------------------------------------------------------------
801* prism2mgmt_ramdl_write
802*
803* Writes a buffer to the card RAM using the download state. This
804* is for writing code to card RAM. To just read or write raw data
805* use the aux functions.
806*
807* Arguments:
808* wlandev wlan device structure
809* msgp ptr to msg buffer
810*
811* Returns:
812* 0 success and done
813* <0 success, but we're waiting for something to finish.
814* >0 an error occurred while handling the message.
815* Side effects:
816*
817* Call context:
818* process thread (usually)
819----------------------------------------------------------------*/
820int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
821{
822 hfa384x_t *hw = wlandev->priv;
823 p80211msg_p2req_ramdl_write_t *msg = msgp;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400824 u32 addr;
825 u32 len;
826 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700827
828 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100829 printk(KERN_ERR
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700830 "ramdl_write(): may only be called "
831 "in the fwload state.\n");
832 msg->resultcode.data =
833 P80211ENUM_resultcode_implementation_failure;
834 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700835 return 0;
836 }
837
838 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
839 /* first validate the length */
840 if ( msg->len.data > sizeof(msg->data.data) ) {
841 msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters;
842 return 0;
843 }
844 /* call the hfa384x function to do the write */
845 addr = msg->addr.data;
846 len = msg->len.data;
847 buf = msg->data.data;
848 if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) {
849 msg->resultcode.data = P80211ENUM_resultcode_refused;
850
851 }
852 msg->resultcode.data = P80211ENUM_resultcode_success;
853
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700854 return 0;
855}
856
857
858/*----------------------------------------------------------------
859* prism2mgmt_flashdl_state
860*
861* Establishes the beginning/end of a card Flash download session.
862*
863* It is expected that the flashdl_write() function will be called
864* one or more times between the 'enable' and 'disable' calls to
865* this function.
866*
867* Note: This function should not be called when a mac comm port
868* is active.
869*
870* Arguments:
871* wlandev wlan device structure
872* msgp ptr to msg buffer
873*
874* Returns:
875* 0 success and done
876* <0 success, but we're waiting for something to finish.
877* >0 an error occurred while handling the message.
878* Side effects:
879*
880* Call context:
881* process thread (usually)
882----------------------------------------------------------------*/
883int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
884{
885 int result = 0;
886 hfa384x_t *hw = wlandev->priv;
887 p80211msg_p2req_flashdl_state_t *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700888
889 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100890 printk(KERN_ERR
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700891 "flashdl_state(): may only be called "
892 "in the fwload state.\n");
893 msg->resultcode.data =
894 P80211ENUM_resultcode_implementation_failure;
895 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700896 return 0;
897 }
898
899 /*
900 ** Note: Interrupts are locked out if this is an AP and are NOT
901 ** locked out if this is a station.
902 */
903
904 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
905 if ( msg->enable.data == P80211ENUM_truth_true ) {
906 if ( hfa384x_drvr_flashdl_enable(hw) ) {
907 msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
908 } else {
909 msg->resultcode.data = P80211ENUM_resultcode_success;
910 }
911 } else {
912 hfa384x_drvr_flashdl_disable(hw);
913 msg->resultcode.data = P80211ENUM_resultcode_success;
914 /* NOTE: At this point, the MAC is in the post-reset
915 * state and the driver is in the fwload state.
916 * We need to get the MAC back into the fwload
917 * state. To do this, we set the nsdstate to HWPRESENT
918 * and then call the ifstate function to redo everything
919 * that got us into the fwload state.
920 */
921 wlandev->msdstate = WLAN_MSD_HWPRESENT;
922 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
923 if (result != P80211ENUM_resultcode_success) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100924 printk(KERN_ERR "prism2sta_ifstate(fwload) failed,"
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700925 "P80211ENUM_resultcode=%d\n", result);
926 msg->resultcode.data =
927 P80211ENUM_resultcode_implementation_failure;
928 result = -1;
929 }
930 }
931
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700932 return 0;
933}
934
935
936/*----------------------------------------------------------------
937* prism2mgmt_flashdl_write
938*
939*
940*
941* Arguments:
942* wlandev wlan device structure
943* msgp ptr to msg buffer
944*
945* Returns:
946* 0 success and done
947* <0 success, but we're waiting for something to finish.
948* >0 an error occurred while handling the message.
949* Side effects:
950*
951* Call context:
952* process thread (usually)
953----------------------------------------------------------------*/
954int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
955{
956 hfa384x_t *hw = wlandev->priv;
957 p80211msg_p2req_flashdl_write_t *msg = msgp;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400958 u32 addr;
959 u32 len;
960 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700961
962 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Moritz Muehlenhoffedbd6062009-01-25 21:55:00 +0100963 printk(KERN_ERR
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700964 "flashdl_write(): may only be called "
965 "in the fwload state.\n");
966 msg->resultcode.data =
967 P80211ENUM_resultcode_implementation_failure;
968 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700969 return 0;
970 }
971
972 /*
973 ** Note: Interrupts are locked out if this is an AP and are NOT
974 ** locked out if this is a station.
975 */
976
977 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
978 /* first validate the length */
979 if ( msg->len.data > sizeof(msg->data.data) ) {
980 msg->resultcode.status =
981 P80211ENUM_resultcode_invalid_parameters;
982 return 0;
983 }
984 /* call the hfa384x function to do the write */
985 addr = msg->addr.data;
986 len = msg->len.data;
987 buf = msg->data.data;
988 if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) {
989 msg->resultcode.data = P80211ENUM_resultcode_refused;
990
991 }
992 msg->resultcode.data = P80211ENUM_resultcode_success;
993
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700994 return 0;
995}
996
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700997/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700998* prism2mgmt_autojoin
999*
1000* Associate with an ESS.
1001*
1002* Arguments:
1003* wlandev wlan device structure
1004* msgp ptr to msg buffer
1005*
1006* Returns:
1007* 0 success and done
1008* <0 success, but we're waiting for something to finish.
1009* >0 an error occurred while handling the message.
1010* Side effects:
1011*
1012* Call context:
1013* process thread (usually)
1014* interrupt
1015----------------------------------------------------------------*/
1016int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
1017{
1018 hfa384x_t *hw = wlandev->priv;
1019 int result = 0;
Solomon Peachyaaad4302008-10-29 10:42:53 -04001020 u16 reg;
1021 u16 port_type;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001022 p80211msg_lnxreq_autojoin_t *msg = msgp;
1023 p80211pstrd_t *pstr;
Solomon Peachyaaad4302008-10-29 10:42:53 -04001024 u8 bytebuf[256];
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001025 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001026
1027 wlandev->macmode = WLAN_MACMODE_NONE;
1028
1029 /* Set the SSID */
1030 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1031
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001032 /* Disable the Port */
1033 hfa384x_drvr_disable(hw, 0);
1034
1035 /*** STATION ***/
1036 /* Set the TxRates */
1037 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1038
1039 /* Set the auth type */
1040 if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
1041 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
1042 } else {
1043 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
1044 }
1045 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1046
1047 /* Set the ssid */
1048 memset(bytebuf, 0, 256);
1049 pstr = (p80211pstrd_t*)&(msg->ssid.data);
1050 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1051 result = hfa384x_drvr_setconfig(
1052 hw, HFA384x_RID_CNFDESIREDSSID,
1053 bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001054 port_type = HFA384x_PORTTYPE_BSS;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001055 /* Set the PortType */
1056 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1057
1058 /* Enable the Port */
1059 hfa384x_drvr_enable(hw, 0);
1060
1061 /* Set the resultcode */
1062 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1063 msg->resultcode.data = P80211ENUM_resultcode_success;
1064
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001065 return result;
1066}
1067
1068
1069/*----------------------------------------------------------------
1070* prism2mgmt_wlansniff
1071*
1072* Start or stop sniffing.
1073*
1074* Arguments:
1075* wlandev wlan device structure
1076* msgp ptr to msg buffer
1077*
1078* Returns:
1079* 0 success and done
1080* <0 success, but we're waiting for something to finish.
1081* >0 an error occurred while handling the message.
1082* Side effects:
1083*
1084* Call context:
1085* process thread (usually)
1086* interrupt
1087----------------------------------------------------------------*/
1088int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
1089{
1090 int result = 0;
1091 p80211msg_lnxreq_wlansniff_t *msg = msgp;
1092
1093 hfa384x_t *hw = wlandev->priv;
Solomon Peachyaaad4302008-10-29 10:42:53 -04001094 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001095
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001096 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1097 switch (msg->enable.data)
1098 {
1099 case P80211ENUM_truth_false:
1100 /* Confirm that we're in monitor mode */
1101 if ( wlandev->netdev->type == ARPHRD_ETHER ) {
1102 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1103 result = 0;
1104 goto exit;
1105 }
1106 /* Disable monitor mode */
1107 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
1108 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001109 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001110 "failed to disable monitor mode, result=%d\n",
1111 result);
1112 goto failed;
1113 }
1114 /* Disable port 0 */
1115 result = hfa384x_drvr_disable(hw, 0);
1116 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001117 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001118 "failed to disable port 0 after sniffing, result=%d\n",
1119 result);
1120 goto failed;
1121 }
1122 /* Clear the driver state */
1123 wlandev->netdev->type = ARPHRD_ETHER;
1124
1125 /* Restore the wepflags */
1126 result = hfa384x_drvr_setconfig16(hw,
1127 HFA384x_RID_CNFWEPFLAGS,
1128 hw->presniff_wepflags);
1129 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001130 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001131 "failed to restore wepflags=0x%04x, result=%d\n",
1132 hw->presniff_wepflags,
1133 result);
1134 goto failed;
1135 }
1136
1137 /* Set the port to its prior type and enable (if necessary) */
1138 if (hw->presniff_port_type != 0 ) {
1139 word = hw->presniff_port_type;
1140 result = hfa384x_drvr_setconfig16(hw,
1141 HFA384x_RID_CNFPORTTYPE, word);
1142 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001143 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001144 "failed to restore porttype, result=%d\n",
1145 result);
1146 goto failed;
1147 }
1148
1149 /* Enable the port */
1150 result = hfa384x_drvr_enable(hw, 0);
1151 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001152 pr_debug("failed to enable port to presniff setting, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001153 goto failed;
1154 }
1155 } else {
1156 result = hfa384x_drvr_disable(hw, 0);
1157
1158 }
1159
Moritz Muehlenhoff350f2f4b2009-01-25 21:54:57 +01001160 printk(KERN_INFO "monitor mode disabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001161 msg->resultcode.data = P80211ENUM_resultcode_success;
1162 result = 0;
1163 goto exit;
1164 break;
1165 case P80211ENUM_truth_true:
1166 /* Disable the port (if enabled), only check Port 0 */
1167 if ( hw->port_enabled[0]) {
1168 if (wlandev->netdev->type == ARPHRD_ETHER) {
1169 /* Save macport 0 state */
1170 result = hfa384x_drvr_getconfig16(hw,
1171 HFA384x_RID_CNFPORTTYPE,
1172 &(hw->presniff_port_type));
1173 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001174 pr_debug("failed to read porttype, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001175 goto failed;
1176 }
1177 /* Save the wepflags state */
1178 result = hfa384x_drvr_getconfig16(hw,
1179 HFA384x_RID_CNFWEPFLAGS,
1180 &(hw->presniff_wepflags));
1181 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001182 pr_debug("failed to read wepflags, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001183 goto failed;
1184 }
1185 hfa384x_drvr_stop(hw);
1186 result = hfa384x_drvr_start(hw);
1187 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001188 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001189 "failed to restart the card for sniffing, result=%d\n",
1190 result);
1191 goto failed;
1192 }
1193 } else {
1194 /* Disable the port */
1195 result = hfa384x_drvr_disable(hw, 0);
1196 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001197 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001198 "failed to enable port for sniffing, result=%d\n",
1199 result);
1200 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,
1210 HFA384x_RID_CNFOWNCHANNEL, word);
1211 hw->sniff_channel=word;
1212
1213 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001214 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001215 "failed to set channel %d, result=%d\n",
1216 word,
1217 result);
1218 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,
1226 HFA384x_RID_CNFPORTTYPE, word);
1227 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001228 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001229 "failed to set porttype %d, result=%d\n",
1230 word,
1231 result);
1232 goto failed;
1233 }
1234 if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) {
1235 /* Set the wepflags for no decryption */
1236 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
1237 HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1238 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word);
1239 }
1240
1241 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001242 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001243 "failed to set wepflags=0x%04x, result=%d\n",
1244 word,
1245 result);
1246 goto failed;
1247 }
1248 }
1249
1250 /* Do we want to strip the FCS in monitor mode? */
1251 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) {
1252 hw->sniff_fcs = 0;
1253 } else {
1254 hw->sniff_fcs = 1;
1255 }
1256
1257 /* Do we want to truncate the packets? */
1258 if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) {
1259 hw->sniff_truncate = msg->packet_trunc.data;
1260 } else {
1261 hw->sniff_truncate = 0;
1262 }
1263
1264 /* Enable the port */
1265 result = hfa384x_drvr_enable(hw, 0);
1266 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001267 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001268 "failed to enable port for sniffing, result=%d\n",
1269 result);
1270 goto failed;
1271 }
1272 /* Enable monitor mode */
1273 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
1274 if ( result ) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +01001275 pr_debug(
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001276 "failed to enable monitor mode, result=%d\n",
1277 result);
1278 goto failed;
1279 }
1280
1281 if (wlandev->netdev->type == ARPHRD_ETHER) {
Moritz Muehlenhoff350f2f4b2009-01-25 21:54:57 +01001282 printk(KERN_INFO "monitor mode enabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001283 }
1284
1285 /* Set the driver state */
1286 /* Do we want the prism2 header? */
1287 if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) {
1288 hw->sniffhdr = 0;
1289 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1290 } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) {
1291 hw->sniffhdr = 1;
1292 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1293 } else {
1294 wlandev->netdev->type = ARPHRD_IEEE80211;
1295 }
1296
1297 msg->resultcode.data = P80211ENUM_resultcode_success;
1298 result = 0;
1299 goto exit;
1300 break;
1301 default:
1302 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1303 result = 0;
1304 goto exit;
1305 break;
1306 }
1307
1308failed:
1309 msg->resultcode.data = P80211ENUM_resultcode_refused;
1310 result = 0;
1311exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001312 return result;
1313}