Root/drivers/staging/wlan-ng/prism2mgmt.c

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

Archive Download this file



interactive