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