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