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