xen/balloon: Move dec_totalhigh_pages() from __balloon_append() to balloon_append()
[pandora-kernel.git] / drivers / staging / wlags49_h2 / wl_wext.c
1 /*******************************************************************************
2  * Agere Systems Inc.
3  * Wireless device driver for Linux (wlags49).
4  *
5  * Copyright (c) 1998-2003 Agere Systems Inc.
6  * All rights reserved.
7  *   http://www.agere.com
8  *
9  * Initially developed by TriplePoint, Inc.
10  *   http://www.triplepoint.com
11  *
12  *------------------------------------------------------------------------------
13  *
14  * SOFTWARE LICENSE
15  *
16  * This software is provided subject to the following terms and conditions,
17  * which you should read carefully before using the software.  Using this
18  * software indicates your acceptance of these terms and conditions.  If you do
19  * not agree with these terms and conditions, do not use the software.
20  *
21  * Copyright © 2003 Agere Systems Inc.
22  * All rights reserved.
23  *
24  * Redistribution and use in source or binary forms, with or without
25  * modifications, are permitted provided that the following conditions are met:
26  *
27  * . Redistributions of source code must retain the above copyright notice, this
28  *    list of conditions and the following Disclaimer as comments in the code as
29  *    well as in the documentation and/or other materials provided with the
30  *    distribution.
31  *
32  * . Redistributions in binary form must reproduce the above copyright notice,
33  *    this list of conditions and the following Disclaimer in the documentation
34  *    and/or other materials provided with the distribution.
35  *
36  * . Neither the name of Agere Systems Inc. nor the names of the contributors
37  *    may be used to endorse or promote products derived from this software
38  *    without specific prior written permission.
39  *
40  * Disclaimer
41  *
42  * THIS SOFTWARE IS PROVIDED \93AS IS\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
43  * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
44  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
45  * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
46  * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
47  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50  * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
51  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53  * DAMAGE.
54  *
55  ******************************************************************************/
56
57 /*******************************************************************************
58  *  include files
59  ******************************************************************************/
60 #include <wl_version.h>
61
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <asm/uaccess.h>
66
67 #include <debug.h>
68 #include <hcf.h>
69 #include <hcfdef.h>
70
71 #include <wl_if.h>
72 #include <wl_internal.h>
73 #include <wl_util.h>
74 #include <wl_main.h>
75 #include <wl_wext.h>
76 #include <wl_priv.h>
77
78
79
80 /* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS
81    #including linux/wireless.h), then these functions do not need to be included
82    in the build. */
83 #ifdef WIRELESS_EXT
84
85 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
86     iwe_stream_add_event(info, buf, end, iwe, len)
87 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
88     iwe_stream_add_point(info, buf, end, iwe, msg)
89
90
91
92 /*******************************************************************************
93  * global definitions
94  ******************************************************************************/
95 #if DBG
96 extern dbg_info_t *DbgInfo;
97 #endif  // DBG
98
99
100
101
102 /*******************************************************************************
103  *      wireless_commit()
104  *******************************************************************************
105  *
106  *  DESCRIPTION:
107  *
108  *      Commit
109  *  protocol used.
110  *
111  *  PARAMETERS:
112  *
113  *      wrq - the wireless request buffer
114  *
115  *  RETURNS:
116  *
117  *      N/A
118  *
119  ******************************************************************************/
120 static int wireless_commit(struct net_device *dev,
121                            struct iw_request_info *info,
122                            union iwreq_data *rqu, char *extra)
123 {
124         struct wl_private *lp = wl_priv(dev);
125         unsigned long flags;
126         int ret = 0;
127         /*------------------------------------------------------------------------*/
128
129         DBG_FUNC( "wireless_commit" );
130         DBG_ENTER(DbgInfo);
131
132         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
133                 ret = -EBUSY;
134                 goto out;
135         }
136
137         wl_lock( lp, &flags );
138
139         wl_act_int_off( lp );
140
141         wl_apply(lp);
142
143         wl_act_int_on( lp );
144
145         wl_unlock(lp, &flags);
146
147 out:
148         DBG_LEAVE( DbgInfo );
149         return ret;
150 } // wireless_commit
151 /*============================================================================*/
152
153
154
155
156 /*******************************************************************************
157  *      wireless_get_protocol()
158  *******************************************************************************
159  *
160  *  DESCRIPTION:
161  *
162  *      Returns a vendor-defined string that should identify the wireless
163  *  protocol used.
164  *
165  *  PARAMETERS:
166  *
167  *      wrq - the wireless request buffer
168  *
169  *  RETURNS:
170  *
171  *      N/A
172  *
173  ******************************************************************************/
174 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
175 {
176         DBG_FUNC( "wireless_get_protocol" );
177         DBG_ENTER( DbgInfo );
178
179         /* Originally, the driver was placing the string "Wireless" here. However,
180            the wireless extensions (/linux/wireless.h) indicate this string should
181            describe the wireless protocol. */
182
183         strcpy(name, "IEEE 802.11b");
184
185         DBG_LEAVE(DbgInfo);
186         return 0;
187 } // wireless_get_protocol
188 /*============================================================================*/
189
190
191
192
193 /*******************************************************************************
194  *      wireless_set_frequency()
195  *******************************************************************************
196  *
197  *  DESCRIPTION:
198  *
199  *      Sets the frequency (channel) on which the card should Tx/Rx.
200  *
201  *  PARAMETERS:
202  *
203  *      wrq - the wireless request buffer
204  *      lp  - the device's private adapter structure
205  *
206  *  RETURNS:
207  *
208  *      0 on success
209  *      errno value otherwise
210  *
211  ******************************************************************************/
212 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
213 {
214         struct wl_private *lp = wl_priv(dev);
215         unsigned long flags;
216         int channel = 0;
217         int ret     = 0;
218         /*------------------------------------------------------------------------*/
219
220
221         DBG_FUNC( "wireless_set_frequency" );
222         DBG_ENTER( DbgInfo );
223
224         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
225                 ret = -EBUSY;
226                 goto out;
227         }
228
229         if( !capable( CAP_NET_ADMIN )) {
230                 ret = -EPERM;
231                 DBG_LEAVE( DbgInfo );
232                 return ret;
233         }
234
235
236         /* If frequency specified, look up channel */
237         if( freq->e == 1 ) {
238                 int f = freq->m / 100000;
239                 channel = wl_get_chan_from_freq( f );
240         }
241
242
243         /* Channel specified */
244         if( freq->e == 0 ) {
245                 channel = freq->m;
246         }
247
248
249         /* If the channel is an 802.11a channel, set Bit 8 */
250         if( channel > 14 ) {
251                 channel = channel | 0x100;
252         }
253
254
255         wl_lock( lp, &flags );
256
257         wl_act_int_off( lp );
258
259         lp->Channel = channel;
260
261
262         /* Commit the adapter parameters */
263         wl_apply( lp );
264
265         /* Send an event that channel/freq has been set */
266         wl_wext_event_freq( lp->dev );
267
268         wl_act_int_on( lp );
269
270         wl_unlock(lp, &flags);
271
272 out:
273         DBG_LEAVE( DbgInfo );
274         return ret;
275 } // wireless_set_frequency
276 /*============================================================================*/
277
278
279
280
281 /*******************************************************************************
282  *      wireless_get_frequency()
283  *******************************************************************************
284  *
285  *  DESCRIPTION:
286  *
287  *      Gets the frequency (channel) on which the card is Tx/Rx.
288  *
289  *  PARAMETERS:
290  *
291  *      wrq - the wireless request buffer
292  *      lp  - the device's private adapter structure
293  *
294  *  RETURNS:
295  *
296  *      N/A
297  *
298  ******************************************************************************/
299 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
300
301 {
302         struct wl_private *lp = wl_priv(dev);
303         unsigned long flags;
304         int ret = -1;
305         /*------------------------------------------------------------------------*/
306
307
308         DBG_FUNC( "wireless_get_frequency" );
309         DBG_ENTER( DbgInfo );
310
311         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
312                 ret = -EBUSY;
313                 goto out;
314         }
315
316         wl_lock( lp, &flags );
317
318         wl_act_int_off( lp );
319
320         lp->ltvRecord.len = 2;
321         lp->ltvRecord.typ = CFG_CUR_CHANNEL;
322
323         ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
324         if( ret == HCF_SUCCESS ) {
325                 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
326
327 #ifdef USE_FREQUENCY
328
329                 freq->m = wl_get_freq_from_chan( channel ) * 100000;
330                 freq->e = 1;
331 #else
332
333                 freq->m = channel;
334                 freq->e = 0;
335
336 #endif /* USE_FREQUENCY */
337         }
338
339         wl_act_int_on( lp );
340
341         wl_unlock(lp, &flags);
342
343         ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
344
345 out:
346         DBG_LEAVE( DbgInfo );
347         return ret;
348 } // wireless_get_frequency
349 /*============================================================================*/
350
351
352
353
354 /*******************************************************************************
355  *      wireless_get_range()
356  *******************************************************************************
357  *
358  *  DESCRIPTION:
359  *
360  *      This function is used to provide misc info and statistics about the
361  *  wireless device.
362  *
363  *  PARAMETERS:
364  *
365  *      wrq - the wireless request buffer
366  *      lp  - the device's private adapter structure
367  *
368  *  RETURNS:
369  *
370  *      0 on success
371  *      errno value otherwise
372  *
373  ******************************************************************************/
374 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
375 {
376         struct wl_private *lp = wl_priv(dev);
377         unsigned long      flags;
378         struct iw_range   *range = (struct iw_range *) extra;
379         int                ret = 0;
380         int                status = -1;
381         int                count;
382         __u16             *pTxRate;
383         int                retries = 0;
384         /*------------------------------------------------------------------------*/
385
386
387         DBG_FUNC( "wireless_get_range" );
388         DBG_ENTER( DbgInfo );
389
390         /* Set range information */
391         data->length = sizeof(struct iw_range);
392         memset(range, 0, sizeof(struct iw_range));
393
394         wl_lock( lp, &flags );
395
396         wl_act_int_off( lp );
397
398         /* Set range information */
399         memset( range, 0, sizeof( struct iw_range ));
400
401 retry:
402         /* Get the current transmit rate from the adapter */
403         lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
404         lp->ltvRecord.typ = CFG_CUR_TX_RATE;
405
406         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
407         if( status != HCF_SUCCESS ) {
408                 /* Recovery action: reset and retry up to 10 times */
409                 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
410
411                 if (retries < 10) {
412                         retries++;
413
414                         /* Holding the lock too long, make a gap to allow other processes */
415                         wl_unlock(lp, &flags);
416                         wl_lock( lp, &flags );
417
418                         status = wl_reset( dev );
419                         if ( status != HCF_SUCCESS ) {
420                                 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
421
422                                 ret = -EFAULT;
423                                 goto out_unlock;
424                         }
425
426                         /* Holding the lock too long, make a gap to allow other processes */
427                         wl_unlock(lp, &flags);
428                         wl_lock( lp, &flags );
429
430                         goto retry;
431
432                 } else {
433                         DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
434                         ret = -EFAULT;
435                         goto out_unlock;
436                 }
437         }
438
439         /* Holding the lock too long, make a gap to allow other processes */
440         wl_unlock(lp, &flags);
441         wl_lock( lp, &flags );
442
443         pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
444
445         range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
446
447         if (retries > 0) {
448                 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
449         }
450
451         // NWID - NOT SUPPORTED
452
453
454         /* Channel/Frequency Info */
455         range->num_channels = RADIO_CHANNELS;
456
457
458         /* Signal Level Thresholds */
459         range->sensitivity = RADIO_SENSITIVITY_LEVELS;
460
461
462         /* Link quality */
463 #ifdef USE_DBM
464
465         range->max_qual.qual     = (u_char)HCF_MAX_COMM_QUALITY;
466
467         /* If the value returned in /proc/net/wireless is greater than the maximum range,
468            iwconfig assumes that the value is in dBm. Because an unsigned char is used,
469            it requires a bit of contorsion... */
470
471         range->max_qual.level   = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
472         range->max_qual.noise   = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
473 #else
474
475         range->max_qual.qual    = 100;
476         range->max_qual.level   = 100;
477         range->max_qual.noise   = 100;
478
479 #endif /* USE_DBM */
480
481
482         /* Set available rates */
483         range->num_bitrates = 0;
484
485         lp->ltvRecord.len = 6;
486         lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
487
488         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
489         if( status == HCF_SUCCESS ) {
490                 for( count = 0; count < MAX_RATES; count++ )
491                         if( lp->ltvRecord.u.u8[count+2] != 0 ) {
492                                 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
493                                 range->num_bitrates++;
494                         }
495         } else {
496                 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
497                 ret = -EFAULT;
498                 goto out_unlock;
499         }
500
501         /* RTS Threshold info */
502         range->min_rts   = MIN_RTS_BYTES;
503         range->max_rts   = MAX_RTS_BYTES;
504
505         // Frag Threshold info - NOT SUPPORTED
506
507         // Power Management info - NOT SUPPORTED
508
509         /* Encryption */
510
511 #if WIRELESS_EXT > 8
512
513         /* Holding the lock too long, make a gap to allow other processes */
514         wl_unlock(lp, &flags);
515         wl_lock( lp, &flags );
516
517         /* Is WEP supported? */
518
519         if( wl_has_wep( &( lp->hcfCtx ))) {
520                 /* WEP: RC4 40 bits */
521                 range->encoding_size[0]      = MIN_KEY_SIZE;
522
523                 /* RC4 ~128 bits */
524                 range->encoding_size[1]      = MAX_KEY_SIZE;
525                 range->num_encoding_sizes    = 2;
526                 range->max_encoding_tokens   = MAX_KEYS;
527         }
528
529 #endif /* WIRELESS_EXT > 8 */
530
531         /* Tx Power Info */
532         range->txpower_capa  = IW_TXPOW_MWATT;
533         range->num_txpower   = 1;
534         range->txpower[0]    = RADIO_TX_POWER_MWATT;
535
536 #if WIRELESS_EXT > 10
537
538         /* Wireless Extension Info */
539         range->we_version_compiled   = WIRELESS_EXT;
540         range->we_version_source     = WIRELESS_SUPPORT;
541
542         // Retry Limits and Lifetime - NOT SUPPORTED
543
544 #endif
545
546
547 #if WIRELESS_EXT > 11
548
549         /* Holding the lock too long, make a gap to allow other processes */
550         wl_unlock(lp, &flags);
551         wl_lock( lp, &flags );
552
553         DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
554         wl_wireless_stats( lp->dev );
555         range->avg_qual = lp->wstats.qual;
556         DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
557
558 #endif
559
560         /* Event capability (kernel + driver) */
561         range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
562                                 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
563                                 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
564         range->event_capa[1] = IW_EVENT_CAPA_K_1;
565         range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
566                                 IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
567                                 IW_EVENT_CAPA_MASK(IWEVEXPIRED));
568
569         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
570
571 out_unlock:
572         wl_act_int_on( lp );
573
574         wl_unlock(lp, &flags);
575
576         DBG_LEAVE(DbgInfo);
577         return ret;
578 } // wireless_get_range
579 /*============================================================================*/
580
581
582 /*******************************************************************************
583  *      wireless_get_bssid()
584  *******************************************************************************
585  *
586  *  DESCRIPTION:
587  *
588  *      Gets the BSSID the wireless device is currently associated with.
589  *
590  *  PARAMETERS:
591  *
592  *      wrq - the wireless request buffer
593  *      lp  - the device's private adapter structure
594  *
595  *  RETURNS:
596  *
597  *      0 on success
598  *      errno value otherwise
599  *
600  ******************************************************************************/
601 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
602 {
603         struct wl_private *lp = wl_priv(dev);
604         unsigned long flags;
605         int ret = 0;
606 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
607         int status = -1;
608 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
609         /*------------------------------------------------------------------------*/
610
611
612         DBG_FUNC( "wireless_get_bssid" );
613         DBG_ENTER( DbgInfo );
614
615         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
616                 ret = -EBUSY;
617                 goto out;
618         }
619
620         wl_lock( lp, &flags );
621
622         wl_act_int_off( lp );
623
624         memset( &ap_addr->sa_data, 0, ETH_ALEN );
625
626         ap_addr->sa_family = ARPHRD_ETHER;
627
628         /* Assume AP mode here, which means the BSSID is our own MAC address. In
629            STA mode, this address will be overwritten with the actual BSSID using
630            the code below. */
631         memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
632
633
634 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
635                                         //;?should we return an error status in AP mode
636
637         if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
638                 /* Get Current BSSID */
639                 lp->ltvRecord.typ = CFG_CUR_BSSID;
640                 lp->ltvRecord.len = 4;
641                 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
642
643                 if( status == HCF_SUCCESS ) {
644                         /* Copy info into sockaddr struct */
645                         memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
646                 } else {
647                         ret = -EFAULT;
648                 }
649         }
650
651 #endif // (HCF_TYPE) & HCF_TYPE_STA
652
653         wl_act_int_on( lp );
654
655         wl_unlock(lp, &flags);
656
657 out:
658         DBG_LEAVE(DbgInfo);
659         return ret;
660 } // wireless_get_bssid
661 /*============================================================================*/
662
663
664
665
666 /*******************************************************************************
667  *      wireless_get_ap_list()
668  *******************************************************************************
669  *
670  *  DESCRIPTION:
671  *
672  *      Gets the results of a network scan.
673  *
674  *  PARAMETERS:
675  *
676  *      wrq - the wireless request buffer
677  *      lp  - the device's private adapter structure
678  *
679  *  RETURNS:
680  *
681  *      0 on success
682  *      errno value otherwise
683  *
684  *  NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
685  *       implements SIOCGIWAPLIST only to provide backwards compatibility. For
686  *       all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
687  *
688  ******************************************************************************/
689 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
690 {
691         struct wl_private *lp = wl_priv(dev);
692         unsigned long     flags;
693         int                 ret;
694         int                 num_aps = -1;
695         int                 sec_count = 0;
696         hcf_32              count;
697         struct sockaddr     *hwa = NULL;
698         struct iw_quality   *qual = NULL;
699 #ifdef WARP
700         ScanResult                      *p = &lp->scan_results;
701 #else
702         ProbeResult         *p = &lp->probe_results;
703 #endif  // WARP
704         /*------------------------------------------------------------------------*/
705
706         DBG_FUNC( "wireless_get_ap_list" );
707         DBG_ENTER( DbgInfo );
708
709         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
710                 ret = -EBUSY;
711                 goto out;
712         }
713
714         wl_lock( lp, &flags );
715
716         wl_act_int_off( lp );
717
718         /* Set the completion state to FALSE */
719         lp->scan_results.scan_complete = FALSE;
720         lp->probe_results.scan_complete = FALSE;
721         /* Channels to scan */
722         lp->ltvRecord.len       = 2;
723         lp->ltvRecord.typ       = CFG_SCAN_CHANNELS_2GHZ;
724         lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x7FFF );
725         ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
726         DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
727
728         /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
729            disassociate from the network we are currently on */
730         lp->ltvRecord.len       = 2;
731         lp->ltvRecord.typ       = CFG_SCAN_SSID;
732         lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
733         ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
734         DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
735
736         /* Initiate the scan */
737 #ifdef WARP
738         ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
739 #else
740         ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
741 #endif  // WARP
742
743         wl_act_int_on( lp );
744
745         //;? unlock? what about the access to lp below? is it broken?
746         wl_unlock(lp, &flags);
747
748         if( ret == HCF_SUCCESS ) {
749                 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
750                 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
751                         DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
752                         /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
753                         if( sec_count++ > MAX_SCAN_TIME_SEC ) {
754                                 ret = -EIO;
755                         } else {
756                                 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
757                                    other things in the meantime, This prevents system lockups by
758                                    giving some time back to the kernel */
759                                 for( count = 0; count < 100; count ++ ) {
760                                         mdelay( 10 );
761                                         schedule( );
762                                 }
763                         }
764                 }
765
766                 rmb();
767
768                 if ( ret != HCF_SUCCESS ) {
769                         DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
770                 } else {
771                         num_aps             = (*p)/*lp->probe_results*/.num_aps;
772                         if (num_aps > IW_MAX_AP) {
773                                 num_aps = IW_MAX_AP;
774                         }
775                         data->length = num_aps;
776                         hwa = (struct sockaddr *)extra;
777                         qual = (struct iw_quality *) extra +
778                                         ( sizeof( struct sockaddr ) * num_aps );
779
780                         /* This flag is used to tell the user if we provide quality
781                            information. Since we provide signal/noise levels but no
782                            quality info on a scan, this is set to 0. Setting to 1 and
783                            providing a quality of 0 produces weird results. If we ever
784                            provide quality (or can calculate it), this can be changed */
785                         data->flags = 0;
786
787                         for( count = 0; count < num_aps; count++ ) {
788 #ifdef WARP
789                                 memcpy( hwa[count].sa_data,
790                                                 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
791 #else  //;?why use BSSID and bssid as names in seemingly very comparable situations
792                                 DBG_PRINT("BSSID: %pM\n",
793                                                 (*p).ProbeTable[count].BSSID);
794                                 memcpy( hwa[count].sa_data,
795                                                 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
796 #endif // WARP
797                         }
798                         /* Once the data is copied to the wireless struct, invalidate the
799                            scan result to initiate a rescan on the next request */
800                         (*p)/*lp->probe_results*/.scan_complete = FALSE;
801                         /* Send the wireless event that the scan has completed, just in case
802                            it's needed */
803                         wl_wext_event_scan_complete( lp->dev );
804                 }
805         }
806 out:
807         DBG_LEAVE( DbgInfo );
808         return ret;
809 } // wireless_get_ap_list
810 /*============================================================================*/
811
812
813
814
815 /*******************************************************************************
816  *      wireless_set_sensitivity()
817  *******************************************************************************
818  *
819  *  DESCRIPTION:
820  *
821  *      Sets the sensitivity (distance between APs) of the wireless card.
822  *
823  *  PARAMETERS:
824  *
825  *      wrq - the wireless request buffer
826  *      lp  - the device's private adapter structure
827  *
828  *  RETURNS:
829  *
830  *      0 on success
831  *      errno value otherwise
832  *
833  ******************************************************************************/
834 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
835 {
836         struct wl_private *lp = wl_priv(dev);
837         unsigned long flags;
838         int ret = 0;
839         int dens = sens->value;
840         /*------------------------------------------------------------------------*/
841
842
843         DBG_FUNC( "wireless_set_sensitivity" );
844         DBG_ENTER( DbgInfo );
845
846         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
847                 ret = -EBUSY;
848                 goto out;
849         }
850
851         if(( dens < 1 ) || ( dens > 3 )) {
852                 ret = -EINVAL;
853                 goto out;
854         }
855
856         wl_lock( lp, &flags );
857
858         wl_act_int_off( lp );
859
860         lp->DistanceBetweenAPs = dens;
861         wl_apply( lp );
862
863         wl_act_int_on( lp );
864
865         wl_unlock(lp, &flags);
866
867 out:
868         DBG_LEAVE( DbgInfo );
869         return ret;
870 } // wireless_set_sensitivity
871 /*============================================================================*/
872
873
874
875
876 /*******************************************************************************
877  *      wireless_get_sensitivity()
878  *******************************************************************************
879  *
880  *  DESCRIPTION:
881  *
882  *      Gets the sensitivity (distance between APs) of the wireless card.
883  *
884  *  PARAMETERS:
885  *
886  *      wrq - the wireless request buffer
887  *      lp  - the device's private adapter structure
888  *
889  *  RETURNS:
890  *
891  *      0 on success
892  *      errno value otherwise
893  *
894  ******************************************************************************/
895 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
896 {
897         struct wl_private *lp = wl_priv(dev);
898         int ret = 0;
899         /*------------------------------------------------------------------------*/
900         /*------------------------------------------------------------------------*/
901
902
903         DBG_FUNC( "wireless_get_sensitivity" );
904         DBG_ENTER( DbgInfo );
905
906         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
907                 ret = -EBUSY;
908                 goto out;
909         }
910
911         /* not worth locking ... */
912         sens->value = lp->DistanceBetweenAPs;
913         sens->fixed = 0;        /* auto */
914 out:
915         DBG_LEAVE( DbgInfo );
916         return ret;
917 } // wireless_get_sensitivity
918 /*============================================================================*/
919
920
921
922
923 /*******************************************************************************
924  *      wireless_set_essid()
925  *******************************************************************************
926  *
927  *  DESCRIPTION:
928  *
929  *      Sets the ESSID (network name) that the wireless device should associate
930  *  with.
931  *
932  *  PARAMETERS:
933  *
934  *      wrq - the wireless request buffer
935  *      lp  - the device's private adapter structure
936  *
937  *  RETURNS:
938  *
939  *      0 on success
940  *      errno value otherwise
941  *
942  ******************************************************************************/
943 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
944 {
945         struct wl_private *lp = wl_priv(dev);
946         unsigned long flags;
947         int ret = 0;
948
949         DBG_FUNC( "wireless_set_essid" );
950         DBG_ENTER( DbgInfo );
951
952         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
953                 ret = -EBUSY;
954                 goto out;
955         }
956
957         if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
958                 ret = -EINVAL;
959                 goto out;
960         }
961
962         wl_lock( lp, &flags );
963
964         wl_act_int_off( lp );
965
966         memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
967
968         /* data->flags is zero to ask for "any" */
969         if( data->flags == 0 ) {
970                 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
971                  * ;?but there ain't no STAP anymore*/
972                 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
973                         strcpy( lp->NetworkName, "ANY" );
974                 } else {
975                         //strcpy( lp->NetworkName, "ANY" );
976                         strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
977                 }
978         } else {
979                 memcpy( lp->NetworkName, ssid, data->length );
980         }
981
982         DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
983
984         /* Commit the adapter parameters */
985         wl_apply( lp );
986
987         /* Send an event that ESSID has been set */
988         wl_wext_event_essid( lp->dev );
989
990         wl_act_int_on( lp );
991
992         wl_unlock(lp, &flags);
993
994 out:
995         DBG_LEAVE( DbgInfo );
996         return ret;
997 } // wireless_set_essid
998 /*============================================================================*/
999
1000
1001
1002
1003 /*******************************************************************************
1004  *      wireless_get_essid()
1005  *******************************************************************************
1006  *
1007  *  DESCRIPTION:
1008  *
1009  *      Gets the ESSID (network name) that the wireless device is associated
1010  *  with.
1011  *
1012  *  PARAMETERS:
1013  *
1014  *      wrq - the wireless request buffer
1015  *      lp  - the device's private adapter structure
1016  *
1017  *  RETURNS:
1018  *
1019  *      0 on success
1020  *      errno value otherwise
1021  *
1022  ******************************************************************************/
1023 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1024
1025 {
1026         struct wl_private *lp = wl_priv(dev);
1027         unsigned long flags;
1028         int         ret = 0;
1029         int         status = -1;
1030         wvName_t    *pName;
1031         /*------------------------------------------------------------------------*/
1032
1033
1034         DBG_FUNC( "wireless_get_essid" );
1035         DBG_ENTER( DbgInfo );
1036
1037         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1038                 ret = -EBUSY;
1039                 goto out;
1040         }
1041
1042         wl_lock( lp, &flags );
1043
1044         wl_act_int_off( lp );
1045
1046         /* Get the desired network name */
1047         lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1048
1049
1050 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1051                                         //;?should we return an error status in AP mode
1052
1053         lp->ltvRecord.typ = CFG_DESIRED_SSID;
1054
1055 #endif
1056
1057
1058 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1059                 //;?should we restore this to allow smaller memory footprint
1060
1061         if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1062                 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1063         }
1064
1065 #endif // HCF_AP
1066
1067
1068         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1069         if( status == HCF_SUCCESS ) {
1070                 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1071
1072                 /* Endian translate the string length */
1073                 pName->length = CNV_LITTLE_TO_INT( pName->length );
1074
1075                 /* Copy the information into the user buffer */
1076                 data->length = pName->length;
1077
1078                 /* NOTE: Null terminating is necessary for proper display of the SSID in
1079                    the wireless tools */
1080                 data->length = pName->length + 1;
1081                 if( pName->length < HCF_MAX_NAME_LEN ) {
1082                         pName->name[pName->length] = '\0';
1083                 }
1084
1085                 data->flags = 1;
1086
1087
1088 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1089                                         //;?should we return an error status in AP mode
1090 #ifdef RETURN_CURRENT_NETWORKNAME
1091
1092                 /* if desired is null ("any"), return current or "any" */
1093                 if( pName->name[0] == '\0' ) {
1094                         /* Get the current network name */
1095                         lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1096                         lp->ltvRecord.typ = CFG_CUR_SSID;
1097
1098                         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1099
1100                         if( status == HCF_SUCCESS ) {
1101                                 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1102
1103                                 /* Endian translate the string length */
1104                                 pName->length = CNV_LITTLE_TO_INT( pName->length );
1105
1106                                 /* Copy the information into the user buffer */
1107                                 data->length = pName->length + 1;
1108                                 if( pName->length < HCF_MAX_NAME_LEN ) {
1109                                         pName->name[pName->length] = '\0';
1110                                 }
1111
1112                                 data->flags = 1;
1113                         } else {
1114                                 ret = -EFAULT;
1115                                 goto out_unlock;
1116                         }
1117                 }
1118
1119 #endif // RETURN_CURRENT_NETWORKNAME
1120 #endif // HCF_STA
1121
1122                 data->length--;
1123
1124                 if (pName->length > IW_ESSID_MAX_SIZE) {
1125                         ret = -EFAULT;
1126                         goto out_unlock;
1127                 }
1128
1129                 memcpy(essid, pName->name, pName->length);
1130         } else {
1131                 ret = -EFAULT;
1132                 goto out_unlock;
1133         }
1134
1135 out_unlock:
1136         wl_act_int_on( lp );
1137
1138         wl_unlock(lp, &flags);
1139
1140 out:
1141         DBG_LEAVE( DbgInfo );
1142         return ret;
1143 } // wireless_get_essid
1144 /*============================================================================*/
1145
1146
1147
1148
1149 /*******************************************************************************
1150  *      wireless_set_encode()
1151  *******************************************************************************
1152  *
1153  *  DESCRIPTION:
1154  *
1155  *     Sets the encryption keys and status (enable or disable).
1156  *
1157  *  PARAMETERS:
1158  *
1159  *      wrq - the wireless request buffer
1160  *      lp  - the device's private adapter structure
1161  *
1162  *  RETURNS:
1163  *
1164  *      0 on success
1165  *      errno value otherwise
1166  *
1167  ******************************************************************************/
1168 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1169 {
1170         struct wl_private *lp = wl_priv(dev);
1171         unsigned long flags;
1172         int     ret = 0;
1173
1174 #if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
1175         hcf_8   encryption_state;
1176 #endif // WIRELESS_EXT > 8
1177         /*------------------------------------------------------------------------*/
1178
1179
1180         DBG_FUNC( "wireless_set_encode" );
1181         DBG_ENTER( DbgInfo );
1182
1183         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1184                 ret = -EBUSY;
1185                 goto out;
1186         }
1187
1188         wl_lock( lp, &flags );
1189
1190         wl_act_int_off( lp );
1191
1192         /* Is encryption supported? */
1193         if( !wl_has_wep( &( lp->hcfCtx ))) {
1194                 DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1195                 ret = -EOPNOTSUPP;
1196                 goto out_unlock;
1197         }
1198
1199         DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1200                                 keybuf, erq->length,
1201                                 erq->flags);
1202
1203         /* Save state of Encryption switch */
1204         encryption_state = lp->EnableEncryption;
1205
1206         /* Basic checking: do we have a key to set? */
1207         if((erq->length) != 0) {
1208                 int index   = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1209                 int tk      = lp->TransmitKeyID - 1;            // current key
1210
1211
1212                 /* Check the size of the key */
1213                 switch(erq->length) {
1214                 case 0:
1215                         break;
1216
1217                 case MIN_KEY_SIZE:
1218                 case MAX_KEY_SIZE:
1219
1220                         /* Check the index */
1221                         if(( index < 0 ) || ( index >= MAX_KEYS )) {
1222                                 index = tk;
1223                         }
1224
1225                         /* Cleanup */
1226                         memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1227
1228                         /* Copy the key in the driver */
1229                         memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1230
1231                         /* Set the length */
1232                         lp->DefaultKeys.key[index].len = erq->length;
1233
1234                         DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1235                         DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1236                                                 lp->DefaultKeys.key[index].len, index );
1237
1238                         /* Enable WEP (if possible) */
1239                         if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1240                                 lp->EnableEncryption = 1;
1241                         }
1242
1243                         break;
1244
1245                 default:
1246                         DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1247                         ret = -EINVAL;
1248                         goto out_unlock;
1249                 }
1250         } else {
1251                 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1252
1253
1254                 /* Do we want to just set the current transmit key? */
1255                 if(( index >= 0 ) && ( index < MAX_KEYS )) {
1256                         DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1257                                                 lp->DefaultKeys.key[index].len );
1258
1259                         if( lp->DefaultKeys.key[index].len > 0 ) {
1260                                 lp->TransmitKeyID       = index + 1;
1261                                 lp->EnableEncryption    = 1;
1262                         } else {
1263                                 DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1264                                 DBG_LEAVE( DbgInfo );
1265                                 ret = -EINVAL;
1266                         }
1267                 }
1268         }
1269
1270         /* Read the flags */
1271         if( erq->flags & IW_ENCODE_DISABLED ) {
1272                 lp->EnableEncryption = 0;       // disable encryption
1273         } else {
1274                 lp->EnableEncryption = 1;
1275         }
1276
1277         if( erq->flags & IW_ENCODE_RESTRICTED ) {
1278                 DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1279                 ret = -EINVAL;          // Invalid
1280         }
1281
1282         DBG_TRACE( DbgInfo, "encryption_state :       %d\n", encryption_state );
1283         DBG_TRACE( DbgInfo, "lp->EnableEncryption :   %d\n", lp->EnableEncryption );
1284         DBG_TRACE( DbgInfo, "erq->length            : %d\n",
1285                            erq->length);
1286         DBG_TRACE( DbgInfo, "erq->flags             : 0x%x\n",
1287                            erq->flags);
1288
1289         /* Write the changes to the card */
1290         if( ret == 0 ) {
1291                 DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1292                                         lp->TransmitKeyID );
1293
1294                 if( lp->EnableEncryption == encryption_state ) {
1295                         if( erq->length != 0 ) {
1296                                 /* Dynamic WEP key update */
1297                                 wl_set_wep_keys( lp );
1298                         }
1299                 } else {
1300                         /* To switch encryption on/off, soft reset is required */
1301                         wl_apply( lp );
1302                 }
1303         }
1304
1305         /* Send an event that Encryption has been set */
1306         wl_wext_event_encode( dev );
1307
1308 out_unlock:
1309
1310         wl_act_int_on( lp );
1311
1312         wl_unlock(lp, &flags);
1313
1314 out:
1315         DBG_LEAVE( DbgInfo );
1316         return ret;
1317 } // wireless_set_encode
1318 /*============================================================================*/
1319
1320
1321
1322
1323 /*******************************************************************************
1324  *      wireless_get_encode()
1325  *******************************************************************************
1326  *
1327  *  DESCRIPTION:
1328  *
1329  *     Gets the encryption keys and status.
1330  *
1331  *  PARAMETERS:
1332  *
1333  *      wrq - the wireless request buffer
1334  *      lp  - the device's private adapter structure
1335  *
1336  *  RETURNS:
1337  *
1338  *      0 on success
1339  *      errno value otherwise
1340  *
1341  ******************************************************************************/
1342 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1343
1344 {
1345         struct wl_private *lp = wl_priv(dev);
1346         unsigned long flags;
1347         int ret = 0;
1348         int index;
1349         /*------------------------------------------------------------------------*/
1350
1351
1352         DBG_FUNC( "wireless_get_encode" );
1353         DBG_ENTER( DbgInfo );
1354         DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1355
1356         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1357                 ret = -EBUSY;
1358                 goto out;
1359         }
1360
1361         /* Only super-user can see WEP key */
1362         if( !capable( CAP_NET_ADMIN )) {
1363                 ret = -EPERM;
1364                 DBG_LEAVE( DbgInfo );
1365                 return ret;
1366         }
1367
1368         wl_lock( lp, &flags );
1369
1370         wl_act_int_off( lp );
1371
1372         /* Is it supported? */
1373         if( !wl_has_wep( &( lp->hcfCtx ))) {
1374                 ret = -EOPNOTSUPP;
1375                 goto out_unlock;
1376         }
1377
1378         /* Basic checking */
1379         index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1380
1381
1382         /* Set the flags */
1383         erq->flags = 0;
1384
1385         if( lp->EnableEncryption == 0 ) {
1386                 erq->flags |= IW_ENCODE_DISABLED;
1387         }
1388
1389         /* Which key do we want */
1390         if(( index < 0 ) || ( index >= MAX_KEYS )) {
1391                 index = lp->TransmitKeyID - 1;
1392         }
1393
1394         erq->flags |= index + 1;
1395
1396         /* Copy the key to the user buffer */
1397         erq->length = lp->DefaultKeys.key[index].len;
1398
1399         memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1400
1401 out_unlock:
1402
1403         wl_act_int_on( lp );
1404
1405         wl_unlock(lp, &flags);
1406
1407 out:
1408         DBG_LEAVE( DbgInfo );
1409         return ret;
1410 } // wireless_get_encode
1411 /*============================================================================*/
1412
1413
1414
1415
1416 /*******************************************************************************
1417  *      wireless_set_nickname()
1418  *******************************************************************************
1419  *
1420  *  DESCRIPTION:
1421  *
1422  *     Sets the nickname, or station name, of the wireless device.
1423  *
1424  *  PARAMETERS:
1425  *
1426  *      wrq - the wireless request buffer
1427  *      lp  - the device's private adapter structure
1428  *
1429  *  RETURNS:
1430  *
1431  *      0 on success
1432  *      errno value otherwise
1433  *
1434  ******************************************************************************/
1435 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1436 {
1437         struct wl_private *lp = wl_priv(dev);
1438         unsigned long flags;
1439         int ret = 0;
1440         /*------------------------------------------------------------------------*/
1441
1442
1443         DBG_FUNC( "wireless_set_nickname" );
1444         DBG_ENTER( DbgInfo );
1445
1446         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1447                 ret = -EBUSY;
1448                 goto out;
1449         }
1450
1451 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1452         if( !capable(CAP_NET_ADMIN )) {
1453                 ret = -EPERM;
1454                 DBG_LEAVE( DbgInfo );
1455                 return ret;
1456         }
1457 #endif
1458
1459         /* Validate the new value */
1460         if(data->length > HCF_MAX_NAME_LEN) {
1461                 ret = -EINVAL;
1462                 goto out;
1463         }
1464
1465         wl_lock( lp, &flags );
1466
1467         wl_act_int_off( lp );
1468
1469         memset( lp->StationName, 0, sizeof( lp->StationName ));
1470
1471         memcpy( lp->StationName, nickname, data->length );
1472
1473         /* Commit the adapter parameters */
1474         wl_apply( lp );
1475
1476         wl_act_int_on( lp );
1477
1478         wl_unlock(lp, &flags);
1479
1480 out:
1481         DBG_LEAVE( DbgInfo );
1482         return ret;
1483 } // wireless_set_nickname
1484 /*============================================================================*/
1485
1486
1487
1488
1489 /*******************************************************************************
1490  *      wireless_get_nickname()
1491  *******************************************************************************
1492  *
1493  *  DESCRIPTION:
1494  *
1495  *     Gets the nickname, or station name, of the wireless device.
1496  *
1497  *  PARAMETERS:
1498  *
1499  *      wrq - the wireless request buffer
1500  *      lp  - the device's private adapter structure
1501  *
1502  *  RETURNS:
1503  *
1504  *      0 on success
1505  *      errno value otherwise
1506  *
1507  ******************************************************************************/
1508 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1509 {
1510         struct wl_private *lp = wl_priv(dev);
1511         unsigned long flags;
1512         int         ret = 0;
1513         int         status = -1;
1514         wvName_t    *pName;
1515         /*------------------------------------------------------------------------*/
1516
1517
1518         DBG_FUNC( "wireless_get_nickname" );
1519         DBG_ENTER( DbgInfo );
1520
1521         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1522                 ret = -EBUSY;
1523                 goto out;
1524         }
1525
1526         wl_lock( lp, &flags );
1527
1528         wl_act_int_off( lp );
1529
1530         /* Get the current station name */
1531         lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1532         lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1533
1534         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1535
1536         if( status == HCF_SUCCESS ) {
1537                 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1538
1539                 /* Endian translate the length */
1540                 pName->length = CNV_LITTLE_TO_INT( pName->length );
1541
1542                 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1543                         ret = -EFAULT;
1544                 } else {
1545                         /* Copy the information into the user buffer */
1546                         data->length = pName->length;
1547                         memcpy(nickname, pName->name, pName->length);
1548                 }
1549         } else {
1550                 ret = -EFAULT;
1551         }
1552
1553         wl_act_int_on( lp );
1554
1555         wl_unlock(lp, &flags);
1556
1557 out:
1558         DBG_LEAVE(DbgInfo);
1559         return ret;
1560 } // wireless_get_nickname
1561 /*============================================================================*/
1562
1563
1564
1565
1566 /*******************************************************************************
1567  *      wireless_set_porttype()
1568  *******************************************************************************
1569  *
1570  *  DESCRIPTION:
1571  *
1572  *     Sets the port type of the wireless device.
1573  *
1574  *  PARAMETERS:
1575  *
1576  *      wrq - the wireless request buffer
1577  *      lp  - the device's private adapter structure
1578  *
1579  *  RETURNS:
1580  *
1581  *      0 on success
1582  *      errno value otherwise
1583  *
1584  ******************************************************************************/
1585 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1586 {
1587         struct wl_private *lp = wl_priv(dev);
1588         unsigned long flags;
1589         int ret = 0;
1590         hcf_16  portType;
1591         hcf_16  createIBSS;
1592         /*------------------------------------------------------------------------*/
1593
1594         DBG_FUNC( "wireless_set_porttype" );
1595         DBG_ENTER( DbgInfo );
1596
1597         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1598                 ret = -EBUSY;
1599                 goto out;
1600         }
1601
1602         wl_lock( lp, &flags );
1603
1604         wl_act_int_off( lp );
1605
1606         /* Validate the new value */
1607         switch( *mode ) {
1608         case IW_MODE_ADHOC:
1609
1610                 /* When user requests ad-hoc, set IBSS mode! */
1611                 portType         = 1;
1612                 createIBSS       = 1;
1613
1614                 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1615
1616                 break;
1617
1618
1619         case IW_MODE_AUTO:
1620         case IW_MODE_INFRA:
1621
1622                 /* Both automatic and infrastructure set port to BSS/STA mode */
1623                 portType         = 1;
1624                 createIBSS       = 0;
1625
1626                 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1627
1628                 break;
1629
1630
1631 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1632
1633         case IW_MODE_MASTER:
1634
1635                 /* Set BSS/AP mode */
1636                 portType             = 1;
1637
1638                 lp->CreateIBSS       = 0;
1639                 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1640
1641                 break;
1642
1643 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1644
1645
1646         default:
1647
1648                 portType   = 0;
1649                 createIBSS = 0;
1650                 ret = -EINVAL;
1651         }
1652
1653         if( portType != 0 ) {
1654                 /* Only do something if there is a mode change */
1655                 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1656                         lp->PortType   = portType;
1657                         lp->CreateIBSS = createIBSS;
1658
1659                         /* Commit the adapter parameters */
1660                         wl_go( lp );
1661
1662                         /* Send an event that mode has been set */
1663                         wl_wext_event_mode( lp->dev );
1664                 }
1665         }
1666
1667         wl_act_int_on( lp );
1668
1669         wl_unlock(lp, &flags);
1670
1671 out:
1672         DBG_LEAVE( DbgInfo );
1673         return ret;
1674 } // wireless_set_porttype
1675 /*============================================================================*/
1676
1677
1678
1679
1680 /*******************************************************************************
1681  *      wireless_get_porttype()
1682  *******************************************************************************
1683  *
1684  *  DESCRIPTION:
1685  *
1686  *     Gets the port type of the wireless device.
1687  *
1688  *  PARAMETERS:
1689  *
1690  *      wrq - the wireless request buffer
1691  *      lp  - the device's private adapter structure
1692  *
1693  *  RETURNS:
1694  *
1695  *      0 on success
1696  *      errno value otherwise
1697  *
1698  ******************************************************************************/
1699 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1700
1701 {
1702         struct wl_private *lp = wl_priv(dev);
1703         unsigned long flags;
1704         int     ret = 0;
1705         int     status = -1;
1706         hcf_16  *pPortType;
1707         /*------------------------------------------------------------------------*/
1708
1709
1710         DBG_FUNC( "wireless_get_porttype" );
1711         DBG_ENTER( DbgInfo );
1712
1713         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1714                 ret = -EBUSY;
1715                 goto out;
1716         }
1717
1718         wl_lock( lp, &flags );
1719
1720         wl_act_int_off( lp );
1721
1722         /* Get the current port type */
1723         lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1724         lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1725
1726         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1727
1728         if( status == HCF_SUCCESS ) {
1729                 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1730
1731                 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1732
1733                 switch( *pPortType ) {
1734                 case 1:
1735
1736 #if 0
1737 #if (HCF_TYPE) & HCF_TYPE_AP
1738
1739                         if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1740                                 *mode = IW_MODE_MASTER;
1741                         } else {
1742                                 *mode = IW_MODE_INFRA;
1743                         }
1744
1745 #else
1746
1747                         *mode = IW_MODE_INFRA;
1748
1749 #endif  /* (HCF_TYPE) & HCF_TYPE_AP */
1750 #endif
1751
1752                         if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1753                                 *mode =  IW_MODE_MASTER;
1754                         } else {
1755                                 if( lp->CreateIBSS ) {
1756                                         *mode = IW_MODE_ADHOC;
1757                                 } else {
1758                                         *mode = IW_MODE_INFRA;
1759                                 }
1760                         }
1761
1762                         break;
1763
1764
1765                 case 3:
1766                         *mode = IW_MODE_ADHOC;
1767                         break;
1768
1769                 default:
1770                         ret = -EFAULT;
1771                         break;
1772                 }
1773         } else {
1774                 ret = -EFAULT;
1775         }
1776
1777         wl_act_int_on( lp );
1778
1779         wl_unlock(lp, &flags);
1780
1781 out:
1782         DBG_LEAVE( DbgInfo );
1783         return ret;
1784 } // wireless_get_porttype
1785 /*============================================================================*/
1786
1787
1788
1789
1790 /*******************************************************************************
1791  *      wireless_set_power()
1792  *******************************************************************************
1793  *
1794  *  DESCRIPTION:
1795  *
1796  *     Sets the power management settings of the wireless device.
1797  *
1798  *  PARAMETERS:
1799  *
1800  *      wrq - the wireless request buffer
1801  *      lp  - the device's private adapter structure
1802  *
1803  *  RETURNS:
1804  *
1805  *      0 on success
1806  *      errno value otherwise
1807  *
1808  ******************************************************************************/
1809 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1810 {
1811         struct wl_private *lp = wl_priv(dev);
1812         unsigned long flags;
1813         int ret = 0;
1814         /*------------------------------------------------------------------------*/
1815
1816
1817         DBG_FUNC( "wireless_set_power" );
1818         DBG_ENTER( DbgInfo );
1819
1820         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1821                 ret = -EBUSY;
1822                 goto out;
1823         }
1824
1825         DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1826
1827 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1828         if( !capable( CAP_NET_ADMIN )) {
1829                 ret = -EPERM;
1830
1831                 DBG_LEAVE( DbgInfo );
1832                 return ret;
1833         }
1834 #endif
1835
1836         wl_lock( lp, &flags );
1837
1838         wl_act_int_off( lp );
1839
1840         /* Set the power management state based on the 'disabled' value */
1841         if( wrq->disabled ) {
1842                 lp->PMEnabled = 0;
1843         } else {
1844                 lp->PMEnabled = 1;
1845         }
1846
1847         /* Commit the adapter parameters */
1848         wl_apply( lp );
1849
1850         wl_act_int_on( lp );
1851
1852         wl_unlock(lp, &flags);
1853
1854 out:
1855         DBG_LEAVE( DbgInfo );
1856         return ret;
1857 } // wireless_set_power
1858 /*============================================================================*/
1859
1860
1861
1862
1863 /*******************************************************************************
1864  *      wireless_get_power()
1865  *******************************************************************************
1866  *
1867  *  DESCRIPTION:
1868  *
1869  *     Gets the power management settings of the wireless device.
1870  *
1871  *  PARAMETERS:
1872  *
1873  *      wrq - the wireless request buffer
1874  *      lp  - the device's private adapter structure
1875  *
1876  *  RETURNS:
1877  *
1878  *      0 on success
1879  *      errno value otherwise
1880  *
1881  ******************************************************************************/
1882 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1883
1884 {
1885         struct wl_private *lp = wl_priv(dev);
1886         unsigned long flags;
1887         int ret = 0;
1888         /*------------------------------------------------------------------------*/
1889         DBG_FUNC( "wireless_get_power" );
1890         DBG_ENTER( DbgInfo );
1891
1892         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1893                 ret = -EBUSY;
1894                 goto out;
1895         }
1896
1897         DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1898
1899         wl_lock( lp, &flags );
1900
1901         wl_act_int_off( lp );
1902
1903         rrq->flags = 0;
1904         rrq->value = 0;
1905
1906         if( lp->PMEnabled ) {
1907                 rrq->disabled = 0;
1908         } else {
1909                 rrq->disabled = 1;
1910         }
1911
1912         wl_act_int_on( lp );
1913
1914         wl_unlock(lp, &flags);
1915
1916 out:
1917         DBG_LEAVE( DbgInfo );
1918         return ret;
1919 } // wireless_get_power
1920 /*============================================================================*/
1921
1922
1923
1924
1925 /*******************************************************************************
1926  *      wireless_get_tx_power()
1927  *******************************************************************************
1928  *
1929  *  DESCRIPTION:
1930  *
1931  *     Gets the transmit power of the wireless device's radio.
1932  *
1933  *  PARAMETERS:
1934  *
1935  *      wrq - the wireless request buffer
1936  *      lp  - the device's private adapter structure
1937  *
1938  *  RETURNS:
1939  *
1940  *      0 on success
1941  *      errno value otherwise
1942  *
1943  ******************************************************************************/
1944 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1945 {
1946         struct wl_private *lp = wl_priv(dev);
1947         unsigned long flags;
1948         int ret = 0;
1949         /*------------------------------------------------------------------------*/
1950         DBG_FUNC( "wireless_get_tx_power" );
1951         DBG_ENTER( DbgInfo );
1952
1953         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1954                 ret = -EBUSY;
1955                 goto out;
1956         }
1957
1958         wl_lock( lp, &flags );
1959
1960         wl_act_int_off( lp );
1961
1962 #ifdef USE_POWER_DBM
1963         rrq->value = RADIO_TX_POWER_DBM;
1964         rrq->flags = IW_TXPOW_DBM;
1965 #else
1966         rrq->value = RADIO_TX_POWER_MWATT;
1967         rrq->flags = IW_TXPOW_MWATT;
1968 #endif
1969         rrq->fixed = 1;
1970         rrq->disabled = 0;
1971
1972         wl_act_int_on( lp );
1973
1974         wl_unlock(lp, &flags);
1975
1976 out:
1977         DBG_LEAVE( DbgInfo );
1978         return ret;
1979 } // wireless_get_tx_power
1980 /*============================================================================*/
1981
1982
1983
1984
1985 /*******************************************************************************
1986  *      wireless_set_rts_threshold()
1987  *******************************************************************************
1988  *
1989  *  DESCRIPTION:
1990  *
1991  *     Sets the RTS threshold for the wireless card.
1992  *
1993  *  PARAMETERS:
1994  *
1995  *      wrq - the wireless request buffer
1996  *      lp  - the device's private adapter structure
1997  *
1998  *  RETURNS:
1999  *
2000  *      0 on success
2001  *      errno value otherwise
2002  *
2003  ******************************************************************************/
2004 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2005 {
2006         int ret = 0;
2007         struct wl_private *lp = wl_priv(dev);
2008         unsigned long flags;
2009         int rthr = rts->value;
2010         /*------------------------------------------------------------------------*/
2011
2012
2013         DBG_FUNC( "wireless_set_rts_threshold" );
2014         DBG_ENTER( DbgInfo );
2015
2016         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2017                 ret = -EBUSY;
2018                 goto out;
2019         }
2020
2021         if(rts->fixed == 0) {
2022                 ret = -EINVAL;
2023                 goto out;
2024         }
2025
2026 #if WIRELESS_EXT > 8
2027         if( rts->disabled ) {
2028                 rthr = 2347;
2029         }
2030 #endif /* WIRELESS_EXT > 8 */
2031
2032         if(( rthr < 256 ) || ( rthr > 2347 )) {
2033                 ret = -EINVAL;
2034                 goto out;
2035         }
2036
2037         wl_lock( lp, &flags );
2038
2039         wl_act_int_off( lp );
2040
2041         lp->RTSThreshold = rthr;
2042
2043         wl_apply( lp );
2044
2045         wl_act_int_on( lp );
2046
2047         wl_unlock(lp, &flags);
2048
2049 out:
2050         DBG_LEAVE( DbgInfo );
2051         return ret;
2052 } // wireless_set_rts_threshold
2053 /*============================================================================*/
2054
2055
2056
2057
2058 /*******************************************************************************
2059  *      wireless_get_rts_threshold()
2060  *******************************************************************************
2061  *
2062  *  DESCRIPTION:
2063  *
2064  *     Gets the RTS threshold for the wireless card.
2065  *
2066  *  PARAMETERS:
2067  *
2068  *      wrq - the wireless request buffer
2069  *      lp  - the device's private adapter structure
2070  *
2071  *  RETURNS:
2072  *
2073  *      0 on success
2074  *      errno value otherwise
2075  *
2076  ******************************************************************************/
2077 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2078 {
2079         int ret = 0;
2080         struct wl_private *lp = wl_priv(dev);
2081         unsigned long flags;
2082         /*------------------------------------------------------------------------*/
2083
2084         DBG_FUNC( "wireless_get_rts_threshold" );
2085         DBG_ENTER( DbgInfo );
2086
2087         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2088                 ret = -EBUSY;
2089                 goto out;
2090         }
2091
2092         wl_lock( lp, &flags );
2093
2094         wl_act_int_off( lp );
2095
2096         rts->value = lp->RTSThreshold;
2097
2098 #if WIRELESS_EXT > 8
2099
2100         rts->disabled = ( rts->value == 2347 );
2101
2102 #endif /* WIRELESS_EXT > 8 */
2103
2104         rts->fixed = 1;
2105
2106         wl_act_int_on( lp );
2107
2108         wl_unlock(lp, &flags);
2109
2110 out:
2111         DBG_LEAVE( DbgInfo );
2112         return ret;
2113 } // wireless_get_rts_threshold
2114 /*============================================================================*/
2115
2116
2117
2118
2119
2120 /*******************************************************************************
2121  *      wireless_set_rate()
2122  *******************************************************************************
2123  *
2124  *  DESCRIPTION:
2125  *
2126  *      Set the default data rate setting used by the wireless device.
2127  *
2128  *  PARAMETERS:
2129  *
2130  *      wrq - the wireless request buffer
2131  *      lp  - the device's private adapter structure
2132  *
2133  *  RETURNS:
2134  *
2135  *      0 on success
2136  *      errno value otherwise
2137  *
2138  ******************************************************************************/
2139 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2140 {
2141         struct wl_private *lp = wl_priv(dev);
2142         unsigned long flags;
2143         int ret = 0;
2144 #ifdef WARP
2145         int status = -1;
2146         int index = 0;
2147 #endif  // WARP
2148         /*------------------------------------------------------------------------*/
2149
2150
2151         DBG_FUNC( "wireless_set_rate" );
2152         DBG_ENTER( DbgInfo );
2153
2154         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2155                 ret = -EBUSY;
2156                 goto out;
2157         }
2158
2159         wl_lock( lp, &flags );
2160
2161         wl_act_int_off( lp );
2162
2163 #ifdef WARP
2164
2165         /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2166            if Bit 9 is set in the current channel RID */
2167         lp->ltvRecord.len = 2;
2168         lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2169
2170         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2171
2172         if( status == HCF_SUCCESS ) {
2173                 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2174
2175                 DBG_PRINT( "Index: %d\n", index );
2176         } else {
2177                 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2178                 DBG_LEAVE( DbgInfo );
2179                 ret = -EINVAL;
2180                 goto out_unlock;
2181         }
2182
2183         if( rrq->value > 0 &&
2184                 rrq->value <= 1 * MEGABIT ) {
2185                 lp->TxRateControl[index] = 0x0001;
2186         }
2187         else if( rrq->value > 1 * MEGABIT &&
2188                         rrq->value <= 2 * MEGABIT ) {
2189                 if( rrq->fixed == 1 ) {
2190                         lp->TxRateControl[index] = 0x0002;
2191                 } else {
2192                         lp->TxRateControl[index] = 0x0003;
2193                 }
2194         }
2195         else if( rrq->value > 2 * MEGABIT &&
2196                         rrq->value <= 5 * MEGABIT ) {
2197                 if( rrq->fixed == 1 ) {
2198                         lp->TxRateControl[index] = 0x0004;
2199                 } else {
2200                         lp->TxRateControl[index] = 0x0007;
2201                 }
2202         }
2203         else if( rrq->value > 5 * MEGABIT &&
2204                         rrq->value <= 6 * MEGABIT ) {
2205                 if( rrq->fixed == 1 ) {
2206                         lp->TxRateControl[index] = 0x0010;
2207                 } else {
2208                         lp->TxRateControl[index] = 0x0017;
2209                 }
2210         }
2211         else if( rrq->value > 6 * MEGABIT &&
2212                         rrq->value <= 9 * MEGABIT ) {
2213                 if( rrq->fixed == 1 ) {
2214                         lp->TxRateControl[index] = 0x0020;
2215                 } else {
2216                         lp->TxRateControl[index] = 0x0037;
2217                 }
2218         }
2219         else if( rrq->value > 9 * MEGABIT &&
2220                         rrq->value <= 11 * MEGABIT ) {
2221                 if( rrq->fixed == 1 ) {
2222                         lp->TxRateControl[index] = 0x0008;
2223                 } else {
2224                         lp->TxRateControl[index] = 0x003F;
2225                 }
2226         }
2227         else if( rrq->value > 11 * MEGABIT &&
2228                         rrq->value <= 12 * MEGABIT ) {
2229                 if( rrq->fixed == 1 ) {
2230                         lp->TxRateControl[index] = 0x0040;
2231                 } else {
2232                         lp->TxRateControl[index] = 0x007F;
2233                 }
2234         }
2235         else if( rrq->value > 12 * MEGABIT &&
2236                         rrq->value <= 18 * MEGABIT ) {
2237                 if( rrq->fixed == 1 ) {
2238                         lp->TxRateControl[index] = 0x0080;
2239                 } else {
2240                         lp->TxRateControl[index] = 0x00FF;
2241                 }
2242         }
2243         else if( rrq->value > 18 * MEGABIT &&
2244                         rrq->value <= 24 * MEGABIT ) {
2245                 if( rrq->fixed == 1 ) {
2246                         lp->TxRateControl[index] = 0x0100;
2247                 } else {
2248                         lp->TxRateControl[index] = 0x01FF;
2249                 }
2250         }
2251         else if( rrq->value > 24 * MEGABIT &&
2252                         rrq->value <= 36 * MEGABIT ) {
2253                 if( rrq->fixed == 1 ) {
2254                         lp->TxRateControl[index] = 0x0200;
2255                 } else {
2256                         lp->TxRateControl[index] = 0x03FF;
2257                 }
2258         }
2259         else if( rrq->value > 36 * MEGABIT &&
2260                         rrq->value <= 48 * MEGABIT ) {
2261                 if( rrq->fixed == 1 ) {
2262                         lp->TxRateControl[index] = 0x0400;
2263                 } else {
2264                         lp->TxRateControl[index] = 0x07FF;
2265                 }
2266         }
2267         else if( rrq->value > 48 * MEGABIT &&
2268                         rrq->value <= 54 * MEGABIT ) {
2269                 if( rrq->fixed == 1 ) {
2270                         lp->TxRateControl[index] = 0x0800;
2271                 } else {
2272                         lp->TxRateControl[index] = 0x0FFF;
2273                 }
2274         }
2275         else if( rrq->fixed == 0 ) {
2276                 /* In this case, the user has not specified a bitrate, only the "auto"
2277                    moniker. So, set to all supported rates */
2278                 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2279         } else {
2280                 rrq->value = 0;
2281                 ret = -EINVAL;
2282                 goto out_unlock;
2283         }
2284
2285
2286 #else
2287
2288         if( rrq->value > 0 &&
2289                         rrq->value <= 1 * MEGABIT ) {
2290                 lp->TxRateControl[0] = 1;
2291         }
2292         else if( rrq->value > 1 * MEGABIT &&
2293                         rrq->value <= 2 * MEGABIT ) {
2294                 if( rrq->fixed ) {
2295                         lp->TxRateControl[0] = 2;
2296                 } else {
2297                         lp->TxRateControl[0] = 6;
2298                 }
2299         }
2300         else if( rrq->value > 2 * MEGABIT &&
2301                         rrq->value <= 5 * MEGABIT ) {
2302                 if( rrq->fixed ) {
2303                         lp->TxRateControl[0] = 4;
2304                 } else {
2305                         lp->TxRateControl[0] = 7;
2306                 }
2307         }
2308         else if( rrq->value > 5 * MEGABIT &&
2309                         rrq->value <= 11 * MEGABIT ) {
2310                 if( rrq->fixed)  {
2311                         lp->TxRateControl[0] = 5;
2312                 } else {
2313                         lp->TxRateControl[0] = 3;
2314                 }
2315         }
2316         else if( rrq->fixed == 0 ) {
2317                 /* In this case, the user has not specified a bitrate, only the "auto"
2318                    moniker. So, set the rate to 11Mb auto */
2319                 lp->TxRateControl[0] = 3;
2320         } else {
2321                 rrq->value = 0;
2322                 ret = -EINVAL;
2323                 goto out_unlock;
2324         }
2325
2326 #endif  // WARP
2327
2328
2329         /* Commit the adapter parameters */
2330         wl_apply( lp );
2331
2332 out_unlock:
2333
2334         wl_act_int_on( lp );
2335
2336         wl_unlock(lp, &flags);
2337
2338 out:
2339         DBG_LEAVE( DbgInfo );
2340         return ret;
2341 } // wireless_set_rate
2342 /*============================================================================*/
2343
2344
2345
2346
2347 /*******************************************************************************
2348  *      wireless_get_rate()
2349  *******************************************************************************
2350  *
2351  *  DESCRIPTION:
2352  *
2353  *      Get the default data rate setting used by the wireless device.
2354  *
2355  *  PARAMETERS:
2356  *
2357  *      wrq - the wireless request buffer
2358  *      lp  - the device's private adapter structure
2359  *
2360  *  RETURNS:
2361  *
2362  *      0 on success
2363  *      errno value otherwise
2364  *
2365  ******************************************************************************/
2366 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2367
2368 {
2369         struct wl_private *lp = wl_priv(dev);
2370         unsigned long flags;
2371         int     ret = 0;
2372         int     status = -1;
2373         hcf_16  txRate;
2374         /*------------------------------------------------------------------------*/
2375
2376
2377         DBG_FUNC( "wireless_get_rate" );
2378         DBG_ENTER( DbgInfo );
2379
2380         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2381                 ret = -EBUSY;
2382                 goto out;
2383         }
2384
2385         wl_lock( lp, &flags );
2386
2387         wl_act_int_off( lp );
2388
2389         /* Get the current transmit rate from the adapter */
2390         lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2391         lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2392
2393         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2394
2395         if( status == HCF_SUCCESS ) {
2396 #ifdef WARP
2397
2398                 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2399
2400                 if( txRate & 0x0001 ) {
2401                         txRate = 1;
2402                 }
2403                 else if( txRate & 0x0002 ) {
2404                         txRate = 2;
2405                 }
2406                 else if( txRate & 0x0004 ) {
2407                         txRate = 5;
2408                 }
2409                 else if( txRate & 0x0008 ) {
2410                         txRate = 11;
2411                 }
2412                 else if( txRate & 0x00010 ) {
2413                         txRate = 6;
2414                 }
2415                 else if( txRate & 0x00020 ) {
2416                         txRate = 9;
2417                 }
2418                 else if( txRate & 0x00040 ) {
2419                         txRate = 12;
2420                 }
2421                 else if( txRate & 0x00080 ) {
2422                         txRate = 18;
2423                 }
2424                 else if( txRate & 0x00100 ) {
2425                         txRate = 24;
2426                 }
2427                 else if( txRate & 0x00200 ) {
2428                         txRate = 36;
2429                 }
2430                 else if( txRate & 0x00400 ) {
2431                         txRate = 48;
2432                 }
2433                 else if( txRate & 0x00800 ) {
2434                         txRate = 54;
2435                 }
2436
2437 #else
2438
2439                 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2440
2441 #endif  // WARP
2442
2443                 rrq->value = txRate * MEGABIT;
2444         } else {
2445                 rrq->value = 0;
2446                 ret = -EFAULT;
2447         }
2448
2449         wl_act_int_on( lp );
2450
2451         wl_unlock(lp, &flags);
2452
2453 out:
2454         DBG_LEAVE( DbgInfo );
2455         return ret;
2456 } // wireless_get_rate
2457 /*============================================================================*/
2458
2459
2460
2461
2462 #if 0 //;? Not used anymore
2463 /*******************************************************************************
2464  *      wireless_get_private_interface()
2465  *******************************************************************************
2466  *
2467  *  DESCRIPTION:
2468  *
2469  *      Returns the Linux Wireless Extensions' compatible private interface of
2470  *  the driver.
2471  *
2472  *  PARAMETERS:
2473  *
2474  *      wrq - the wireless request buffer
2475  *      lp  - the device's private adapter structure
2476  *
2477  *  RETURNS:
2478  *
2479  *      0 on success
2480  *      errno value otherwise
2481  *
2482  ******************************************************************************/
2483 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2484 {
2485         int ret = 0;
2486         /*------------------------------------------------------------------------*/
2487
2488
2489         DBG_FUNC( "wireless_get_private_interface" );
2490         DBG_ENTER( DbgInfo );
2491
2492         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2493                 ret = -EBUSY;
2494                 goto out;
2495         }
2496
2497         if( wrq->u.data.pointer != NULL ) {
2498                 struct iw_priv_args priv[] =
2499                 {
2500                         { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2501                         { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2502                         { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2503                         { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2504                         { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2505                         { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2506                 };
2507
2508                 /* Verify the user buffer */
2509                 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2510
2511                 if( ret != 0 ) {
2512                         DBG_LEAVE( DbgInfo );
2513                         return ret;
2514                 }
2515
2516                 /* Copy the data into the user's buffer */
2517                 wrq->u.data.length = NELEM( priv );
2518                 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2519         }
2520
2521 out:
2522         DBG_LEAVE( DbgInfo );
2523         return ret;
2524 } // wireless_get_private_interface
2525 /*============================================================================*/
2526 #endif
2527
2528
2529
2530 #if WIRELESS_EXT > 13
2531
2532 /*******************************************************************************
2533  *      wireless_set_scan()
2534  *******************************************************************************
2535  *
2536  *  DESCRIPTION:
2537  *
2538  *      Instructs the driver to initiate a network scan.
2539  *
2540  *  PARAMETERS:
2541  *
2542  *      wrq - the wireless request buffer
2543  *      lp  - the device's private adapter structure
2544  *
2545  *  RETURNS:
2546  *
2547  *      0 on success
2548  *      errno value otherwise
2549  *
2550  ******************************************************************************/
2551 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2552 {
2553         struct wl_private *lp = wl_priv(dev);
2554         unsigned long flags;
2555         int                 ret = 0;
2556         int                 status = -1;
2557         int                 retries = 0;
2558         /*------------------------------------------------------------------------*/
2559
2560         //;? Note: shows results as trace, retruns always 0 unless BUSY
2561
2562         DBG_FUNC( "wireless_set_scan" );
2563         DBG_ENTER( DbgInfo );
2564
2565         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2566                 ret = -EBUSY;
2567                 goto out;
2568         }
2569
2570         wl_lock( lp, &flags );
2571
2572         wl_act_int_off( lp );
2573
2574         /*
2575          * This looks like a nice place to test if the HCF is still
2576          * communicating with the card. It seems that sometimes BAP_1
2577          * gets corrupted. By looking at the comments in HCF the
2578          * cause is still a mistery. Okay, the communication to the
2579          * card is dead, reset the card to revive.
2580          */
2581         if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2582         {
2583                 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2584                 wl_reset( dev );
2585         }
2586
2587 retry:
2588         /* Set the completion state to FALSE */
2589         lp->probe_results.scan_complete = FALSE;
2590
2591
2592         /* Channels to scan */
2593 #ifdef WARP
2594         lp->ltvRecord.len       = 5;
2595         lp->ltvRecord.typ       = CFG_SCAN_CHANNEL;
2596         lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x3FFF );  // 2.4 GHz Band
2597         lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( 0xFFFF );  // 5.0 GHz Band
2598         lp->ltvRecord.u.u16[2]  = CNV_INT_TO_LITTLE( 0xFFFF );  //      ..
2599         lp->ltvRecord.u.u16[3]  = CNV_INT_TO_LITTLE( 0x0007 );  //      ..
2600 #else
2601         lp->ltvRecord.len       = 2;
2602         lp->ltvRecord.typ       = CFG_SCAN_CHANNEL;
2603         lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x7FFF );
2604 #endif  // WARP
2605
2606         status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2607
2608         DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result      : 0x%x\n", status );
2609
2610         // Holding the lock too long, make a gap to allow other processes
2611         wl_unlock(lp, &flags);
2612         wl_lock( lp, &flags );
2613
2614         if( status != HCF_SUCCESS ) {
2615                 //Recovery
2616                 retries++;
2617                 if(retries <= 10) {
2618                         DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2619                         wl_reset( dev );
2620
2621                         // Holding the lock too long, make a gap to allow other processes
2622                         wl_unlock(lp, &flags);
2623                         wl_lock( lp, &flags );
2624
2625                         goto retry;
2626                 }
2627         }
2628
2629         /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2630            disassociate from the network we are currently on */
2631         lp->ltvRecord.len       = 18;
2632         lp->ltvRecord.typ       = CFG_SCAN_SSID;
2633         lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
2634         lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( 0 );
2635
2636         status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2637
2638         // Holding the lock too long, make a gap to allow other processes
2639         wl_unlock(lp, &flags);
2640         wl_lock( lp, &flags );
2641
2642         DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2643
2644         /* Initiate the scan */
2645         /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2646            retrieve probe responses must always be used to support WPA */
2647         status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2648
2649         if( status == HCF_SUCCESS ) {
2650                 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2651         } else {
2652                 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2653         }
2654
2655         wl_act_int_on( lp );
2656
2657         wl_unlock(lp, &flags);
2658
2659 out:
2660         DBG_LEAVE(DbgInfo);
2661         return ret;
2662 } // wireless_set_scan
2663 /*============================================================================*/
2664
2665
2666
2667
2668 /*******************************************************************************
2669  *      wireless_get_scan()
2670  *******************************************************************************
2671  *
2672  *  DESCRIPTION:
2673  *
2674  *      Instructs the driver to gather and return the results of a network scan.
2675  *
2676  *  PARAMETERS:
2677  *
2678  *      wrq - the wireless request buffer
2679  *      lp  - the device's private adapter structure
2680  *
2681  *  RETURNS:
2682  *
2683  *      0 on success
2684  *      errno value otherwise
2685  *
2686  ******************************************************************************/
2687 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2688 {
2689         struct wl_private *lp = wl_priv(dev);
2690         unsigned long flags;
2691         int                 ret = 0;
2692         int                 count;
2693         char                *buf;
2694         char                *buf_end;
2695         struct iw_event     iwe;
2696         PROBE_RESP          *probe_resp;
2697         hcf_8               msg[512];
2698         hcf_8               *wpa_ie;
2699         hcf_16              wpa_ie_len;
2700         /*------------------------------------------------------------------------*/
2701
2702
2703         DBG_FUNC( "wireless_get_scan" );
2704         DBG_ENTER( DbgInfo );
2705
2706         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2707                 ret = -EBUSY;
2708                 goto out;
2709         }
2710
2711         wl_lock( lp, &flags );
2712
2713         wl_act_int_off( lp );
2714
2715         /* If the scan is not done, tell the calling process to try again later */
2716         if( !lp->probe_results.scan_complete ) {
2717                 ret = -EAGAIN;
2718                 goto out_unlock;
2719         }
2720
2721         DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2722                            lp->probe_results.num_aps );
2723
2724         buf     = extra;
2725         buf_end = extra + IW_SCAN_MAX_DATA;
2726
2727         for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2728                 /* Reference the probe response from the table */
2729                 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2730
2731
2732                 /* First entry MUST be the MAC address */
2733                 memset( &iwe, 0, sizeof( iwe ));
2734
2735                 iwe.cmd                 = SIOCGIWAP;
2736                 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2737                 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2738                 iwe.len                 = IW_EV_ADDR_LEN;
2739
2740                 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2741
2742
2743                 /* Use the mode to indicate if it's a station or AP */
2744                 /* Won't always be an AP if in IBSS mode */
2745                 memset( &iwe, 0, sizeof( iwe ));
2746
2747                 iwe.cmd = SIOCGIWMODE;
2748
2749                 if( probe_resp->capability & CAPABILITY_IBSS ) {
2750                         iwe.u.mode = IW_MODE_INFRA;
2751                 } else {
2752                         iwe.u.mode = IW_MODE_MASTER;
2753                 }
2754
2755                 iwe.len = IW_EV_UINT_LEN;
2756
2757                 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2758
2759
2760                 /* Any quality information */
2761                 memset(&iwe, 0, sizeof(iwe));
2762
2763                 iwe.cmd             = IWEVQUAL;
2764                 iwe.u.qual.level    = dbm(probe_resp->signal);
2765                 iwe.u.qual.noise    = dbm(probe_resp->silence);
2766                 iwe.u.qual.qual     = iwe.u.qual.level - iwe.u.qual.noise;
2767                 iwe.u.qual.updated  = lp->probe_results.scan_complete | IW_QUAL_DBM;
2768                 iwe.len             = IW_EV_QUAL_LEN;
2769
2770                 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2771
2772
2773                 /* ESSID information */
2774                 if( probe_resp->rawData[1] > 0 ) {
2775                         memset( &iwe, 0, sizeof( iwe ));
2776
2777                         iwe.cmd = SIOCGIWESSID;
2778                         iwe.u.data.length = probe_resp->rawData[1];
2779                         iwe.u.data.flags = 1;
2780
2781                         buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2782                 }
2783
2784
2785                 /* Encryption Information */
2786                 memset( &iwe, 0, sizeof( iwe ));
2787
2788                 iwe.cmd             = SIOCGIWENCODE;
2789                 iwe.u.data.length   = 0;
2790
2791                 /* Check the capabilities field of the Probe Response to see if
2792                    'privacy' is supported on the AP in question */
2793                 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2794                         iwe.u.data.flags |= IW_ENCODE_ENABLED;
2795                 } else {
2796                         iwe.u.data.flags |= IW_ENCODE_DISABLED;
2797                 }
2798
2799                 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2800
2801
2802                 /* Frequency Info */
2803                 memset( &iwe, 0, sizeof( iwe ));
2804
2805                 iwe.cmd = SIOCGIWFREQ;
2806                 iwe.len = IW_EV_FREQ_LEN;
2807                 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2808                 iwe.u.freq.e = 0;
2809
2810                 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2811
2812
2813 #if WIRELESS_EXT > 14
2814                 /* Custom info (Beacon Interval) */
2815                 memset( &iwe, 0, sizeof( iwe ));
2816                 memset( msg, 0, sizeof( msg ));
2817
2818                 iwe.cmd = IWEVCUSTOM;
2819                 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2820                 iwe.u.data.length = strlen( msg );
2821
2822                 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2823
2824
2825                 /* Custom info (WPA-IE) */
2826                 wpa_ie = NULL;
2827                 wpa_ie_len = 0;
2828
2829                 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2830                 if( wpa_ie != NULL ) {
2831                         memset( &iwe, 0, sizeof( iwe ));
2832                         memset( msg, 0, sizeof( msg ));
2833
2834                         iwe.cmd = IWEVCUSTOM;
2835                         sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2836                         iwe.u.data.length = strlen( msg );
2837
2838                         buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2839                 }
2840
2841                 /* Add other custom info in formatted string format as needed... */
2842 #endif
2843         }
2844
2845         data->length = buf - extra;
2846
2847 out_unlock:
2848
2849         wl_act_int_on( lp );
2850
2851         wl_unlock(lp, &flags);
2852
2853 out:
2854         DBG_LEAVE( DbgInfo );
2855         return ret;
2856 } // wireless_get_scan
2857 /*============================================================================*/
2858
2859 #endif  // WIRELESS_EXT > 13
2860
2861
2862 #if WIRELESS_EXT > 17
2863
2864 static int wireless_set_auth(struct net_device *dev,
2865                           struct iw_request_info *info,
2866                           struct iw_param *data, char *extra)
2867 {
2868         struct wl_private *lp = wl_priv(dev);
2869         unsigned long flags;
2870         int                           ret;
2871         int                           iwa_idx = data->flags & IW_AUTH_INDEX;
2872         int                           iwa_val = data->value;
2873
2874         DBG_FUNC( "wireless_set_auth" );
2875         DBG_ENTER( DbgInfo );
2876
2877         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2878                 ret = -EBUSY;
2879                 goto out;
2880         }
2881
2882         wl_lock( lp, &flags );
2883
2884         wl_act_int_off( lp );
2885
2886         switch (iwa_idx) {
2887                 case IW_AUTH_WPA_VERSION:
2888                         DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2889                         /* We do support WPA only; how should DISABLED be treated? */
2890                         if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2891                                 ret = 0;
2892                         else
2893                                 ret = -EINVAL;
2894                         break;
2895
2896                 case IW_AUTH_WPA_ENABLED:
2897                         DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2898                         if (iwa_val)
2899                                 lp->EnableEncryption = 2;
2900                         else
2901                                 lp->EnableEncryption = 0;
2902                         ret = 0;
2903                         break;
2904
2905                 case IW_AUTH_TKIP_COUNTERMEASURES:
2906                         DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2907                         lp->driverEnable = !iwa_val;
2908                         if(lp->driverEnable)
2909                                 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2910                         else
2911                                 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2912                         ret = 0;
2913                         break;
2914
2915                 case IW_AUTH_DROP_UNENCRYPTED:
2916                         DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2917                         /* We do not actually do anything here, just to silence
2918                          * wpa_supplicant */
2919                         ret = 0;
2920                         break;
2921
2922                 case IW_AUTH_CIPHER_PAIRWISE:
2923                         DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2924                         /* not implemented, return an error */
2925                         ret = -EINVAL;
2926                         break;
2927
2928                 case IW_AUTH_CIPHER_GROUP:
2929                         DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2930                         /* not implemented, return an error */
2931                         ret = -EINVAL;
2932                         break;
2933
2934                 case IW_AUTH_KEY_MGMT:
2935                         DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2936                         /* not implemented, return an error */
2937                         ret = -EINVAL;
2938                         break;
2939
2940                 case IW_AUTH_80211_AUTH_ALG:
2941                         DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2942                         /* not implemented, return an error */
2943                         ret = -EINVAL;
2944                         break;
2945
2946                 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2947                         DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2948                         /* not implemented, return an error */
2949                         ret = -EINVAL;
2950                         break;
2951
2952                 case IW_AUTH_ROAMING_CONTROL:
2953                         DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2954                         /* not implemented, return an error */
2955                         ret = -EINVAL;
2956                         break;
2957
2958                 case IW_AUTH_PRIVACY_INVOKED:
2959                         DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2960                         /* not implemented, return an error */
2961                         ret = -EINVAL;
2962                         break;
2963
2964                 default:
2965                         DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2966                         /* return an error */
2967                         ret = -EINVAL;
2968                         break;
2969         }
2970
2971         wl_act_int_on( lp );
2972
2973         wl_unlock(lp, &flags);
2974
2975 out:
2976         DBG_LEAVE( DbgInfo );
2977         return ret;
2978 } // wireless_set_auth
2979 /*============================================================================*/
2980
2981
2982
2983 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
2984                           int set_tx, u8 *seq, u8 *key, size_t key_len)
2985 {
2986         int ret = -EINVAL;
2987         // int   count = 0;
2988         int   buf_idx = 0;
2989         hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
2990                 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
2991
2992         DBG_FUNC( "hermes_set_key" );
2993         DBG_ENTER( DbgInfo );
2994
2995         /*
2996          * Check the key index here; if 0, load as Pairwise Key, otherwise,
2997          * load as a group key. Note that for the Hermes, the RIDs for
2998          * group/pariwise keys are different from each other and different
2999          * than the default WEP keys as well.
3000          */
3001         switch (alg)
3002         {
3003         case IW_ENCODE_ALG_TKIP:
3004                 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3005 #if 0
3006                 /*
3007                  * Make sure that there is no data queued up in the firmware
3008                  * before setting the TKIP keys. If this check is not
3009                  * performed, some data may be sent out with incorrect MIC
3010                  * and cause synchronizarion errors with the AP
3011                  */
3012                 /* Check every 1ms for 100ms */
3013                 for( count = 0; count < 100; count++ )
3014                 {
3015                         usleep( 1000 );
3016
3017                         ltv.len = 2;
3018                         ltv.typ = 0xFD91;  // This RID not defined in HCF yet!!!
3019                         ltv.u.u16[0] = 0;
3020
3021                         wl_get_info( sock, &ltv, ifname );
3022
3023                         if( ltv.u.u16[0] == 0 )
3024                         {
3025                                 break;
3026                         }
3027                 }
3028
3029                 if( count == 100 )
3030                 {
3031                         wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
3032                 }
3033 #endif
3034
3035                 switch (key_idx) {
3036                 case 0:
3037                         ltv->len = 28;
3038                         ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
3039
3040                         /* Load the BSSID */
3041                         memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
3042                         buf_idx += ETH_ALEN;
3043
3044                         /* Load the TKIP key */
3045                         memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
3046                         buf_idx += 16;
3047
3048                         /* Load the TSC */
3049                         memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3050                         buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3051
3052                         /* Load the RSC */
3053                         memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3054                         buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3055
3056                         /* Load the TxMIC key */
3057                         memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
3058                         buf_idx += 8;
3059
3060                         /* Load the RxMIC key */
3061                         memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
3062
3063                         ret = 0;
3064                         break;
3065                 case 1:
3066                 case 2:
3067                 case 3:
3068                         ltv->len = 26;
3069                         ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3070
3071                         /* Load the key Index */
3072                         ltv->u.u16[buf_idx] = key_idx;
3073                         /* If this is a Tx Key, set bit 8000 */
3074                         if(set_tx)
3075                                 ltv->u.u16[buf_idx] |= 0x8000;
3076                         buf_idx += 2;
3077
3078                         /* Load the RSC */
3079                         memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3080                         buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3081
3082                         /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3083                            CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3084                         memcpy(&ltv->u.u8[buf_idx], key, key_len);
3085                         buf_idx += key_len;
3086
3087                         /* Load the TSC */
3088                         memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3089
3090                         ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3091
3092                         ret = 0;
3093                         break;
3094                 default:
3095                         break;
3096                 }
3097
3098                 break;
3099
3100         case IW_ENCODE_ALG_WEP:
3101                 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3102                 break;
3103
3104         case IW_ENCODE_ALG_CCMP:
3105                 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3106                 break;
3107
3108         case IW_ENCODE_ALG_NONE:
3109                 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3110                 switch (key_idx) {
3111                 case 0:
3112                         if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3113                         //if (addr != NULL) {
3114                                 ltv->len = 7;
3115                                 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3116                                 memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
3117                                 ret = 0;
3118                         }
3119                         break;
3120                 case 1:
3121                 case 2:
3122                 case 3:
3123                         /* Clear the Group TKIP keys by index */
3124                         ltv->len = 2;
3125                         ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3126                         ltv->u.u16[0] = key_idx;
3127
3128                         ret = 0;
3129                         break;
3130                 default:
3131                         break;
3132                 }
3133                 break;
3134         default:
3135                 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3136                 break;
3137         }
3138
3139         DBG_LEAVE( DbgInfo );
3140         return ret;
3141 } // hermes_set_key
3142 /*============================================================================*/
3143
3144
3145
3146 static int wireless_set_encodeext (struct net_device *dev,
3147                                         struct iw_request_info *info,
3148                                         struct iw_point *erq, char *keybuf)
3149 {
3150         struct wl_private *lp = wl_priv(dev);
3151         unsigned long flags;
3152         int                           ret;
3153         int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3154         ltv_t ltv;
3155         struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3156
3157         DBG_FUNC( "wireless_set_encodeext" );
3158         DBG_ENTER( DbgInfo );
3159
3160         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3161                 ret = -EBUSY;
3162                 goto out;
3163         }
3164
3165         if (sizeof(ext->rx_seq) != 8) {
3166                 DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3167                 DBG_LEAVE(DbgInfo);
3168                 return -EINVAL;
3169         }
3170
3171         /* Handle WEP keys via the old set encode procedure */
3172         if(ext->alg == IW_ENCODE_ALG_WEP) {
3173                 struct iw_point  wep_erq;
3174                 char            *wep_keybuf;
3175
3176                 /* Build request structure */
3177                 wep_erq.flags  = erq->flags;   // take over flags with key index
3178                 wep_erq.length = ext->key_len; // take length from extended key info
3179                 wep_keybuf     = ext->key;     // pointer to the key text
3180
3181                 /* Call wireless_set_encode tot handle the WEP key */
3182                 ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3183                 goto out;
3184         }
3185
3186         /* Proceed for extended encode functions for WAP and NONE */
3187         wl_lock( lp, &flags );
3188
3189         wl_act_int_off( lp );
3190
3191         memset(&ltv, 0, sizeof(ltv));
3192         ret = hermes_set_key(&ltv, ext->alg, key_idx, ext->addr.sa_data,
3193                                 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3194                                 ext->rx_seq, ext->key, ext->key_len);
3195
3196         if (ret != 0) {
3197                 DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3198                 goto out_unlock;
3199         }
3200
3201         /* Put the key in HCF */
3202         ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3203
3204 out_unlock:
3205         if(ret == HCF_SUCCESS) {
3206                 DBG_TRACE( DbgInfo, "Put key info succes\n");
3207         } else {
3208                 DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3209         }
3210
3211         wl_act_int_on( lp );
3212
3213         wl_unlock(lp, &flags);
3214
3215 out:
3216         DBG_LEAVE( DbgInfo );
3217         return ret;
3218 } // wireless_set_encodeext
3219 /*============================================================================*/
3220
3221
3222
3223 static int wireless_get_genie(struct net_device *dev,
3224                                            struct iw_request_info *info,
3225                                            struct iw_point *data, char *extra)
3226
3227 {
3228         struct wl_private *lp = wl_priv(dev);
3229         unsigned long flags;
3230         int   ret = 0;
3231         ltv_t ltv;
3232
3233         DBG_FUNC( "wireless_get_genie" );
3234         DBG_ENTER( DbgInfo );
3235
3236         if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3237                 ret = -EBUSY;
3238                 goto out;
3239         }
3240
3241         wl_lock( lp, &flags );
3242
3243         wl_act_int_off( lp );
3244
3245         memset(&ltv, 0, sizeof(ltv));
3246         ltv.len = 2;
3247         ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3248         lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3249         ltv.u.u16[0]  = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3250
3251         ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3252
3253         wl_act_int_on( lp );
3254
3255         wl_unlock(lp, &flags);
3256
3257 out:
3258         DBG_LEAVE( DbgInfo );
3259         return ret;
3260 }
3261 /*============================================================================*/
3262
3263
3264 #endif // WIRELESS_EXT > 17
3265
3266 /*******************************************************************************
3267  *      wl_wireless_stats()
3268  *******************************************************************************
3269  *
3270  *  DESCRIPTION:
3271  *
3272  *      Return the current device wireless statistics.
3273  *
3274  *  PARAMETERS:
3275  *
3276  *      wrq - the wireless request buffer
3277  *      lp  - the device's private adapter structure
3278  *
3279  *  RETURNS:
3280  *
3281  *      0 on success
3282  *      errno value otherwise
3283  *
3284  ******************************************************************************/
3285 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3286 {
3287         struct iw_statistics    *pStats;
3288         struct wl_private       *lp = wl_priv(dev);
3289         /*------------------------------------------------------------------------*/
3290
3291
3292         DBG_FUNC( "wl_wireless_stats" );
3293         DBG_ENTER(DbgInfo);
3294         DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3295
3296         pStats = NULL;
3297
3298         /* Initialize the statistics */
3299         pStats                  = &( lp->wstats );
3300         pStats->qual.updated    = 0x00;
3301
3302         if( !( lp->flags & WVLAN2_UIL_BUSY ))
3303         {
3304                 CFG_COMMS_QUALITY_STRCT *pQual;
3305                 CFG_HERMES_TALLIES_STRCT tallies;
3306                 int                         status;
3307
3308                 /* Update driver status */
3309                 pStats->status = 0;
3310
3311                 /* Get the current link quality information */
3312                 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3313                 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3314                 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3315
3316                 if( status == HCF_SUCCESS ) {
3317                         pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3318
3319 #ifdef USE_DBM
3320                         pStats->qual.qual  = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3321                         pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3322                         pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3323
3324                         pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED  |
3325                                                  IW_QUAL_LEVEL_UPDATED |
3326                                                  IW_QUAL_NOISE_UPDATED |
3327                                                  IW_QUAL_DBM);
3328 #else
3329                         pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
3330                                                      HCF_MIN_COMM_QUALITY,
3331                                                      HCF_MAX_COMM_QUALITY );
3332
3333                         pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
3334                                                       HCF_MIN_SIGNAL_LEVEL,
3335                                                       HCF_MAX_SIGNAL_LEVEL );
3336
3337                         pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
3338                                                       HCF_MIN_NOISE_LEVEL,
3339                                                       HCF_MAX_NOISE_LEVEL );
3340
3341                         pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED  |
3342                                                  IW_QUAL_LEVEL_UPDATED |
3343                                                  IW_QUAL_NOISE_UPDATED);
3344 #endif /* USE_DBM */
3345                 } else {
3346                         memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3347                 }
3348
3349                 /* Get the current tallies from the adapter */
3350                 /* Only possible when the device is open */
3351                 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3352                         if( wl_get_tallies( lp, &tallies ) == 0 ) {
3353                                 /* No endian translation is needed here, as CFG_TALLIES is an
3354                                    MSF RID; all processing is done on the host, not the card! */
3355                                 pStats->discard.nwid = 0L;
3356                                 pStats->discard.code = tallies.RxWEPUndecryptable;
3357                                 pStats->discard.misc = tallies.TxDiscards +
3358                                                        tallies.RxFCSErrors +
3359                                                        //tallies.RxDiscardsNoBuffer +
3360                                                        tallies.TxDiscardsWrongSA;
3361                                 //;? Extra taken over from Linux driver based on 7.18 version
3362                                 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3363                                 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3364                         } else {
3365                                 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3366                         }
3367                 } else {
3368                         memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3369                 }
3370         }
3371
3372         DBG_LEAVE( DbgInfo );
3373         return pStats;
3374 } // wl_wireless_stats
3375 /*============================================================================*/
3376
3377
3378
3379
3380 /*******************************************************************************
3381  *      wl_get_wireless_stats()
3382  *******************************************************************************
3383  *
3384  *  DESCRIPTION:
3385  *
3386  *      Return the current device wireless statistics. This function calls
3387  *      wl_wireless_stats, but acquires spinlocks first as it can be called
3388  *      directly by the network layer.
3389  *
3390  *  PARAMETERS:
3391  *
3392  *      wrq - the wireless request buffer
3393  *      lp  - the device's private adapter structure
3394  *
3395  *  RETURNS:
3396  *
3397  *      0 on success
3398  *      errno value otherwise
3399  *
3400  ******************************************************************************/
3401 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3402 {
3403         unsigned long           flags;
3404         struct wl_private       *lp = wl_priv(dev);
3405         struct iw_statistics    *pStats = NULL;
3406         /*------------------------------------------------------------------------*/
3407
3408         DBG_FUNC( "wl_get_wireless_stats" );
3409         DBG_ENTER(DbgInfo);
3410
3411         wl_lock( lp, &flags );
3412
3413         wl_act_int_off( lp );
3414
3415 #ifdef USE_RTS
3416         if( lp->useRTS == 1 ) {
3417                 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3418         } else
3419 #endif
3420         {
3421                 pStats = wl_wireless_stats( dev );
3422         }
3423         wl_act_int_on( lp );
3424
3425         wl_unlock(lp, &flags);
3426
3427         DBG_LEAVE( DbgInfo );
3428         return pStats;
3429 } // wl_get_wireless_stats
3430
3431
3432 /*******************************************************************************
3433  *      wl_spy_gather()
3434  *******************************************************************************
3435  *
3436  *  DESCRIPTION:
3437  *
3438  *      Gather wireless spy statistics.
3439  *
3440  *  PARAMETERS:
3441  *
3442  *      wrq - the wireless request buffer
3443  *      lp  - the device's private adapter structure
3444  *
3445  *  RETURNS:
3446  *
3447  *      0 on success
3448  *      errno value otherwise
3449  *
3450  ******************************************************************************/
3451 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3452 {
3453         struct iw_quality wstats;
3454         int                     status;
3455         u_char                  stats[2];
3456         DESC_STRCT              desc[1];
3457         struct wl_private   *lp = wl_priv(dev);
3458         /*------------------------------------------------------------------------*/
3459
3460         /* shortcut */
3461         if (!lp->spy_data.spy_number) {
3462                 return;
3463         }
3464
3465         /* Gather wireless spy statistics: for each packet, compare the source
3466            address with out list, and if match, get the stats. */
3467         memset( stats, 0, sizeof(stats));
3468         memset( desc, 0, sizeof(DESC_STRCT));
3469
3470         desc[0].buf_addr        = stats;
3471         desc[0].BUF_SIZE        = sizeof(stats);
3472         desc[0].next_desc_addr  = 0;            // terminate list
3473
3474         status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3475
3476         if( status == HCF_SUCCESS ) {
3477                 wstats.level = (u_char) dbm(stats[1]);
3478                 wstats.noise = (u_char) dbm(stats[0]);
3479                 wstats.qual  = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3480
3481                 wstats.updated = (IW_QUAL_QUAL_UPDATED  |
3482                                   IW_QUAL_LEVEL_UPDATED |
3483                                   IW_QUAL_NOISE_UPDATED |
3484                                   IW_QUAL_DBM);
3485
3486                 wireless_spy_update( dev, mac, &wstats );
3487         }
3488 } // wl_spy_gather
3489 /*============================================================================*/
3490
3491
3492
3493
3494 /*******************************************************************************
3495  *      wl_wext_event_freq()
3496  *******************************************************************************
3497  *
3498  *  DESCRIPTION:
3499  *
3500  *      This function is used to send an event that the channel/freq
3501  *      configuration for a specific device has changed.
3502  *
3503  *
3504  *  PARAMETERS:
3505  *
3506  *      dev - the network device for which this event is to be issued
3507  *
3508  *  RETURNS:
3509  *
3510  *      N/A
3511  *
3512  ******************************************************************************/
3513 void wl_wext_event_freq( struct net_device *dev )
3514 {
3515 #if WIRELESS_EXT > 13
3516         union iwreq_data wrqu;
3517         struct wl_private *lp = wl_priv(dev);
3518         /*------------------------------------------------------------------------*/
3519
3520
3521         memset( &wrqu, 0, sizeof( wrqu ));
3522
3523         wrqu.freq.m = lp->Channel;
3524         wrqu.freq.e = 0;
3525
3526         wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3527 #endif /* WIRELESS_EXT > 13 */
3528
3529         return;
3530 } // wl_wext_event_freq
3531 /*============================================================================*/
3532
3533
3534
3535
3536 /*******************************************************************************
3537  *      wl_wext_event_mode()
3538  *******************************************************************************
3539  *
3540  *  DESCRIPTION:
3541  *
3542  *      This function is used to send an event that the mode of operation
3543  *      for a specific device has changed.
3544  *
3545  *
3546  *  PARAMETERS:
3547  *
3548  *      dev - the network device for which this event is to be issued
3549  *
3550  *  RETURNS:
3551  *
3552  *      N/A
3553  *
3554  ******************************************************************************/
3555 void wl_wext_event_mode( struct net_device *dev )
3556 {
3557 #if WIRELESS_EXT > 13
3558         union iwreq_data wrqu;
3559         struct wl_private *lp = wl_priv(dev);
3560         /*------------------------------------------------------------------------*/
3561
3562
3563         memset( &wrqu, 0, sizeof( wrqu ));
3564
3565         if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
3566                 wrqu.mode = IW_MODE_INFRA;
3567         } else {
3568                 wrqu.mode = IW_MODE_MASTER;
3569         }
3570
3571         wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3572 #endif /* WIRELESS_EXT > 13 */
3573
3574         return;
3575 } // wl_wext_event_mode
3576 /*============================================================================*/
3577
3578
3579
3580
3581 /*******************************************************************************
3582  *      wl_wext_event_essid()
3583  *******************************************************************************
3584  *
3585  *  DESCRIPTION:
3586  *
3587  *      This function is used to send an event that the ESSID configuration for
3588  *      a specific device has changed.
3589  *
3590  *
3591  *  PARAMETERS:
3592  *
3593  *      dev - the network device for which this event is to be issued
3594  *
3595  *  RETURNS:
3596  *
3597  *      N/A
3598  *
3599  ******************************************************************************/
3600 void wl_wext_event_essid( struct net_device *dev )
3601 {
3602 #if WIRELESS_EXT > 13
3603         union iwreq_data wrqu;
3604         struct wl_private *lp = wl_priv(dev);
3605         /*------------------------------------------------------------------------*/
3606
3607
3608         memset( &wrqu, 0, sizeof( wrqu ));
3609
3610         /* Fill out the buffer. Note that the buffer doesn't actually contain the
3611            ESSID, but a pointer to the contents. In addition, the 'extra' field of
3612            the call to wireless_send_event() must also point to where the ESSID
3613            lives */
3614         wrqu.essid.length  = strlen( lp->NetworkName );
3615         wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3616         wrqu.essid.flags   = 1;
3617
3618         wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3619 #endif /* WIRELESS_EXT > 13 */
3620
3621         return;
3622 } // wl_wext_event_essid
3623 /*============================================================================*/
3624
3625
3626
3627
3628 /*******************************************************************************
3629  *      wl_wext_event_encode()
3630  *******************************************************************************
3631  *
3632  *  DESCRIPTION:
3633  *
3634  *      This function is used to send an event that the encryption configuration
3635  *      for a specific device has changed.
3636  *
3637  *
3638  *  PARAMETERS:
3639  *
3640  *      dev - the network device for which this event is to be issued
3641  *
3642  *  RETURNS:
3643  *
3644  *      N/A
3645  *
3646  ******************************************************************************/
3647 void wl_wext_event_encode( struct net_device *dev )
3648 {
3649 #if WIRELESS_EXT > 13
3650         union iwreq_data wrqu;
3651         struct wl_private *lp = wl_priv(dev);
3652         int index = 0;
3653         /*------------------------------------------------------------------------*/
3654
3655
3656         memset( &wrqu, 0, sizeof( wrqu ));
3657
3658         if( lp->EnableEncryption == 0 ) {
3659                 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3660         } else {
3661                 wrqu.encoding.flags |= lp->TransmitKeyID;
3662
3663                 index = lp->TransmitKeyID - 1;
3664
3665                 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3666                    if we're in AP mode */
3667 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3668                 //;?should we restore this to allow smaller memory footprint
3669
3670                 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
3671                         if( lp->ExcludeUnencrypted ) {
3672                                 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3673                         } else {
3674                                 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3675                         }
3676                 }
3677
3678 #endif  // HCF_TYPE_AP
3679
3680                 /* Only provide the key if permissions allow */
3681                 if( capable( CAP_NET_ADMIN )) {
3682                         wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3683                         wrqu.encoding.length  = lp->DefaultKeys.key[index].len;
3684                 } else {
3685                         wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3686                 }
3687         }
3688
3689         wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3690                                                  lp->DefaultKeys.key[index].key );
3691 #endif /* WIRELESS_EXT > 13 */
3692
3693         return;
3694 } // wl_wext_event_encode
3695 /*============================================================================*/
3696
3697
3698
3699
3700 /*******************************************************************************
3701  *      wl_wext_event_ap()
3702  *******************************************************************************
3703  *
3704  *  DESCRIPTION:
3705  *
3706  *      This function is used to send an event that the device has been
3707  *      associated to a new AP.
3708  *
3709  *
3710  *  PARAMETERS:
3711  *
3712  *      dev - the network device for which this event is to be issued
3713  *
3714  *  RETURNS:
3715  *
3716  *      N/A
3717  *
3718  ******************************************************************************/
3719 void wl_wext_event_ap( struct net_device *dev )
3720 {
3721 #if WIRELESS_EXT > 13
3722         union iwreq_data wrqu;
3723         struct wl_private *lp = wl_priv(dev);
3724         int status;
3725         /*------------------------------------------------------------------------*/
3726
3727
3728         /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3729            this event BEFORE sending the association event, as there are timing
3730            issues with the hostap supplicant. The supplicant will attempt to process
3731            an EAPOL-Key frame from an AP before receiving this information, which
3732            is required properly process the said frame. */
3733         wl_wext_event_assoc_ie( dev );
3734
3735         /* Get the BSSID */
3736         lp->ltvRecord.typ = CFG_CUR_BSSID;
3737         lp->ltvRecord.len = 4;
3738
3739         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3740         if( status == HCF_SUCCESS ) {
3741                 memset( &wrqu, 0, sizeof( wrqu ));
3742
3743                 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3744
3745                 wrqu.addr.sa_family = ARPHRD_ETHER;
3746
3747                 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3748         }
3749
3750 #endif /* WIRELESS_EXT > 13 */
3751
3752         return;
3753 } // wl_wext_event_ap
3754 /*============================================================================*/
3755
3756
3757
3758 /*******************************************************************************
3759  *      wl_wext_event_scan_complete()
3760  *******************************************************************************
3761  *
3762  *  DESCRIPTION:
3763  *
3764  *      This function is used to send an event that a request for a network scan
3765  *      has completed.
3766  *
3767  *
3768  *  PARAMETERS:
3769  *
3770  *      dev - the network device for which this event is to be issued
3771  *
3772  *  RETURNS:
3773  *
3774  *      N/A
3775  *
3776  ******************************************************************************/
3777 void wl_wext_event_scan_complete( struct net_device *dev )
3778 {
3779 #if WIRELESS_EXT > 13
3780         union iwreq_data wrqu;
3781         /*------------------------------------------------------------------------*/
3782
3783
3784         memset( &wrqu, 0, sizeof( wrqu ));
3785
3786         wrqu.addr.sa_family = ARPHRD_ETHER;
3787         wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3788 #endif /* WIRELESS_EXT > 13 */
3789
3790         return;
3791 } // wl_wext_event_scan_complete
3792 /*============================================================================*/
3793
3794
3795
3796
3797 /*******************************************************************************
3798  *      wl_wext_event_new_sta()
3799  *******************************************************************************
3800  *
3801  *  DESCRIPTION:
3802  *
3803  *      This function is used to send an event that an AP has registered a new
3804  *      station.
3805  *
3806  *
3807  *  PARAMETERS:
3808  *
3809  *      dev - the network device for which this event is to be issued
3810  *
3811  *  RETURNS:
3812  *
3813  *      N/A
3814  *
3815  ******************************************************************************/
3816 void wl_wext_event_new_sta( struct net_device *dev )
3817 {
3818 #if WIRELESS_EXT > 14
3819         union iwreq_data wrqu;
3820         /*------------------------------------------------------------------------*/
3821
3822
3823         memset( &wrqu, 0, sizeof( wrqu ));
3824
3825         /* Send the station's mac address here */
3826         memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3827         wrqu.addr.sa_family = ARPHRD_ETHER;
3828         wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3829 #endif /* WIRELESS_EXT > 14 */
3830
3831         return;
3832 } // wl_wext_event_new_sta
3833 /*============================================================================*/
3834
3835
3836
3837
3838 /*******************************************************************************
3839  *      wl_wext_event_expired_sta()
3840  *******************************************************************************
3841  *
3842  *  DESCRIPTION:
3843  *
3844  *      This function is used to send an event that an AP has deregistered a
3845  *      station.
3846  *
3847  *
3848  *  PARAMETERS:
3849  *
3850  *      dev - the network device for which this event is to be issued
3851  *
3852  *  RETURNS:
3853  *
3854  *      N/A
3855  *
3856  ******************************************************************************/
3857 void wl_wext_event_expired_sta( struct net_device *dev )
3858 {
3859 #if WIRELESS_EXT > 14
3860         union iwreq_data wrqu;
3861         /*------------------------------------------------------------------------*/
3862
3863
3864         memset( &wrqu, 0, sizeof( wrqu ));
3865
3866         memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3867         wrqu.addr.sa_family = ARPHRD_ETHER;
3868         wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3869 #endif /* WIRELESS_EXT > 14 */
3870
3871         return;
3872 } // wl_wext_event_expired_sta
3873 /*============================================================================*/
3874
3875
3876
3877
3878 /*******************************************************************************
3879  *      wl_wext_event_mic_failed()
3880  *******************************************************************************
3881  *
3882  *  DESCRIPTION:
3883  *
3884  *      This function is used to send an event that MIC calculations failed.
3885  *
3886  *
3887  *  PARAMETERS:
3888  *
3889  *      dev - the network device for which this event is to be issued
3890  *
3891  *  RETURNS:
3892  *
3893  *      N/A
3894  *
3895  ******************************************************************************/
3896 void wl_wext_event_mic_failed( struct net_device *dev )
3897 {
3898 #if WIRELESS_EXT > 14
3899         char               msg[512];
3900         union iwreq_data   wrqu;
3901         struct wl_private *lp = wl_priv(dev);
3902         int                key_idx;
3903         char              *addr1;
3904         char              *addr2;
3905         WVLAN_RX_WMP_HDR  *hdr;
3906         /*------------------------------------------------------------------------*/
3907
3908
3909         key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3910         key_idx &= 0x03;
3911
3912         /* Cast the lookahead buffer into a RFS format */
3913         hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3914
3915         /* Cast the addresses to byte buffers, as in the above RFS they are word
3916            length */
3917         addr1 = (char *)hdr->address1;
3918         addr2 = (char *)hdr->address2;
3919
3920         DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3921                            hdr->status );
3922
3923         memset( &wrqu, 0, sizeof( wrqu ));
3924         memset( msg, 0, sizeof( msg ));
3925
3926
3927         /* Becuase MIC failures are not part of the Wireless Extensions yet, they
3928            must be passed as a string using an IWEVCUSTOM event. In order for the
3929            event to be effective, the string format must be known by both the
3930            driver and the supplicant. The following is the string format used by the
3931            hostap project's WPA supplicant, and will be used here until the Wireless
3932            Extensions interface adds this support:
3933
3934            MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
3935    */
3936
3937         /* NOTE: Format of MAC address (using colons to separate bytes) may cause
3938                          a problem in future versions of the supplicant, if they ever
3939                          actually parse these parameters */
3940 #if DBG
3941         sprintf(msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast "
3942                         "addr=%pM)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
3943                         addr2);
3944 #endif
3945         wrqu.data.length = strlen( msg );
3946         wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
3947 #endif /* WIRELESS_EXT > 14 */
3948
3949         return;
3950 } // wl_wext_event_mic_failed
3951 /*============================================================================*/
3952
3953
3954
3955
3956 /*******************************************************************************
3957  *      wl_wext_event_assoc_ie()
3958  *******************************************************************************
3959  *
3960  *  DESCRIPTION:
3961  *
3962  *      This function is used to send an event containing the WPA-IE generated
3963  *      by the firmware in an association request.
3964  *
3965  *
3966  *  PARAMETERS:
3967  *
3968  *      dev - the network device for which this event is to be issued
3969  *
3970  *  RETURNS:
3971  *
3972  *      N/A
3973  *
3974  ******************************************************************************/
3975 void wl_wext_event_assoc_ie( struct net_device *dev )
3976 {
3977 #if WIRELESS_EXT > 14
3978         char               msg[512];
3979         union iwreq_data   wrqu;
3980         struct wl_private *lp = wl_priv(dev);
3981         int status;
3982         PROBE_RESP         data;
3983         hcf_16             length;
3984         hcf_8              *wpa_ie;
3985         /*------------------------------------------------------------------------*/
3986
3987
3988         memset( &wrqu, 0, sizeof( wrqu ));
3989         memset( msg, 0, sizeof( msg ));
3990
3991         /* Retrieve the Association Request IE */
3992         lp->ltvRecord.len = 45;
3993         lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3994
3995         status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3996         if( status == HCF_SUCCESS )
3997         {
3998                 length = 0;
3999                 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
4000                 wpa_ie = wl_parse_wpa_ie( &data, &length );
4001
4002                 /* Becuase this event (Association WPA-IE) is not part of the Wireless
4003                 Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
4004                 In order for the event to be effective, the string format must be known
4005                 by both the driver and the supplicant. The following is the string format
4006                 used by the hostap project's WPA supplicant, and will be used here until
4007                 the Wireless Extensions interface adds this support:
4008
4009                 ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
4010                 */
4011
4012                 if( length != 0 )
4013                 {
4014                         sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
4015                         wrqu.data.length = strlen( msg );
4016                         wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
4017                 }
4018         }
4019 #endif /* WIRELESS_EXT > 14 */
4020
4021         return;
4022 }  // wl_wext_event_assoc_ie
4023 /*============================================================================*/
4024 /* Structures to export the Wireless Handlers */
4025
4026 static const iw_handler wl_handler[] =
4027 {
4028                 (iw_handler) wireless_commit,           /* SIOCSIWCOMMIT */
4029                 (iw_handler) wireless_get_protocol,     /* SIOCGIWNAME */
4030                 (iw_handler) NULL,                      /* SIOCSIWNWID */
4031                 (iw_handler) NULL,                      /* SIOCGIWNWID */
4032                 (iw_handler) wireless_set_frequency,    /* SIOCSIWFREQ */
4033                 (iw_handler) wireless_get_frequency,    /* SIOCGIWFREQ */
4034                 (iw_handler) wireless_set_porttype,     /* SIOCSIWMODE */
4035                 (iw_handler) wireless_get_porttype,     /* SIOCGIWMODE */
4036                 (iw_handler) wireless_set_sensitivity,  /* SIOCSIWSENS */
4037                 (iw_handler) wireless_get_sensitivity,  /* SIOCGIWSENS */
4038                 (iw_handler) NULL ,                     /* SIOCSIWRANGE */
4039                 (iw_handler) wireless_get_range,        /* SIOCGIWRANGE */
4040                 (iw_handler) NULL ,                     /* SIOCSIWPRIV */
4041                 (iw_handler) NULL /* kernel code */,    /* SIOCGIWPRIV */
4042                 (iw_handler) NULL ,                     /* SIOCSIWSTATS */
4043                 (iw_handler) NULL /* kernel code */,    /* SIOCGIWSTATS */
4044                 iw_handler_set_spy,                     /* SIOCSIWSPY */
4045                 iw_handler_get_spy,                     /* SIOCGIWSPY */
4046                 NULL,                                   /* SIOCSIWTHRSPY */
4047                 NULL,                                   /* SIOCGIWTHRSPY */
4048                 (iw_handler) NULL,                      /* SIOCSIWAP */
4049 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4050                 (iw_handler) wireless_get_bssid,        /* SIOCGIWAP */
4051 #else
4052                 (iw_handler) NULL,                      /* SIOCGIWAP */
4053 #endif
4054                 (iw_handler) NULL,                      /* SIOCSIWMLME */
4055                 (iw_handler) wireless_get_ap_list,      /* SIOCGIWAPLIST */
4056                 (iw_handler) wireless_set_scan,         /* SIOCSIWSCAN */
4057                 (iw_handler) wireless_get_scan,         /* SIOCGIWSCAN */
4058                 (iw_handler) wireless_set_essid,        /* SIOCSIWESSID */
4059                 (iw_handler) wireless_get_essid,        /* SIOCGIWESSID */
4060                 (iw_handler) wireless_set_nickname,     /* SIOCSIWNICKN */
4061                 (iw_handler) wireless_get_nickname,     /* SIOCGIWNICKN */
4062                 (iw_handler) NULL,                      /* -- hole -- */
4063                 (iw_handler) NULL,                      /* -- hole -- */
4064                 (iw_handler) wireless_set_rate,         /* SIOCSIWRATE */
4065                 (iw_handler) wireless_get_rate,         /* SIOCGIWRATE */
4066                 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
4067                 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
4068                 (iw_handler) NULL,                      /* SIOCSIWFRAG */
4069                 (iw_handler) NULL,                      /* SIOCGIWFRAG */
4070                 (iw_handler) NULL,                      /* SIOCSIWTXPOW */
4071                 (iw_handler) wireless_get_tx_power,     /* SIOCGIWTXPOW */
4072                 (iw_handler) NULL,                      /* SIOCSIWRETRY */
4073                 (iw_handler) NULL,                      /* SIOCGIWRETRY */
4074                 (iw_handler) wireless_set_encode,       /* SIOCSIWENCODE */
4075                 (iw_handler) wireless_get_encode,       /* SIOCGIWENCODE */
4076                 (iw_handler) wireless_set_power,        /* SIOCSIWPOWER */
4077                 (iw_handler) wireless_get_power,        /* SIOCGIWPOWER */
4078                 (iw_handler) NULL,                      /* -- hole -- */
4079                 (iw_handler) NULL,                      /* -- hole -- */
4080                 (iw_handler) wireless_get_genie,        /* SIOCSIWGENIE */
4081                 (iw_handler) NULL,                      /* SIOCGIWGENIE */
4082                 (iw_handler) wireless_set_auth,         /* SIOCSIWAUTH */
4083                 (iw_handler) NULL,                      /* SIOCGIWAUTH */
4084                 (iw_handler) wireless_set_encodeext,    /* SIOCSIWENCODEEXT */
4085                 (iw_handler) NULL,                      /* SIOCGIWENCODEEXT */
4086                 (iw_handler) NULL,                      /* SIOCSIWPMKSA */
4087                 (iw_handler) NULL,                      /* -- hole -- */
4088 };
4089
4090 static const iw_handler wl_private_handler[] =
4091 {                                                       /* SIOCIWFIRSTPRIV + */
4092                 wvlan_set_netname,                      /* 0: SIOCSIWNETNAME */
4093                 wvlan_get_netname,                      /* 1: SIOCGIWNETNAME */
4094                 wvlan_set_station_nickname,             /* 2: SIOCSIWSTANAME */
4095                 wvlan_get_station_nickname,             /* 3: SIOCGIWSTANAME */
4096 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4097                 wvlan_set_porttype,                     /* 4: SIOCSIWPORTTYPE */
4098                 wvlan_get_porttype,                     /* 5: SIOCGIWPORTTYPE */
4099 #endif
4100 };
4101
4102 struct iw_priv_args wl_priv_args[] = {
4103         {SIOCSIWNETNAME,    IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
4104         {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN,    "gnetwork_name" },
4105         {SIOCSIWSTANAME,    IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
4106         {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN,    "gstation_name" },
4107 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
4108         {SIOCSIWPORTTYPE,    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
4109         {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,    "gport_type" },
4110 #endif
4111 };
4112
4113 const struct iw_handler_def wl_iw_handler_def =
4114 {
4115         .num_private        = sizeof(wl_private_handler) / sizeof(iw_handler),
4116         .private            = (iw_handler *) wl_private_handler,
4117         .private_args       = (struct iw_priv_args *) wl_priv_args,
4118         .num_private_args   = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
4119         .num_standard       = sizeof(wl_handler) / sizeof(iw_handler),
4120         .standard           = (iw_handler *) wl_handler,
4121         .get_wireless_stats = wl_get_wireless_stats,
4122 };
4123
4124 #endif // WIRELESS_EXT