staging: wlags49_h2: Stop playing with length in GIWESSID handler
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / wlags49_h2 / wl_wext.c
blob1f6b4dce438092ebf7efca60398ca2fd526528d0
1 /*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
14 * SOFTWARE LICENSE
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.
21 * Copyright © 2003 Agere Systems Inc.
22 * All rights reserved.
24 * Redistribution and use in source or binary forms, with or without
25 * modifications, are permitted provided that the following conditions are met:
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.
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.
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.
40 * Disclaimer
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.
55 ******************************************************************************/
57 /*******************************************************************************
58 * include files
59 ******************************************************************************/
60 #include <wl_version.h>
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <asm/uaccess.h>
67 #include <debug.h>
68 #include <hcf.h>
69 #include <hcfdef.h>
71 #include <wl_if.h>
72 #include <wl_internal.h>
73 #include <wl_util.h>
74 #include <wl_main.h>
75 #include <wl_wext.h>
76 #include <wl_priv.h>
80 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
81 iwe_stream_add_event(info, buf, end, iwe, len)
82 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
83 iwe_stream_add_point(info, buf, end, iwe, msg)
87 /*******************************************************************************
88 * global definitions
89 ******************************************************************************/
90 #if DBG
91 extern dbg_info_t *DbgInfo;
92 #endif // DBG
97 /*******************************************************************************
98 * wireless_commit()
99 *******************************************************************************
101 * DESCRIPTION:
103 * Commit
104 * protocol used.
106 * PARAMETERS:
108 * wrq - the wireless request buffer
110 * RETURNS:
112 * N/A
114 ******************************************************************************/
115 static int wireless_commit(struct net_device *dev,
116 struct iw_request_info *info,
117 union iwreq_data *rqu, char *extra)
119 struct wl_private *lp = wl_priv(dev);
120 unsigned long flags;
121 int ret = 0;
122 /*------------------------------------------------------------------------*/
124 DBG_FUNC( "wireless_commit" );
125 DBG_ENTER(DbgInfo);
127 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
128 ret = -EBUSY;
129 goto out;
132 wl_lock( lp, &flags );
134 wl_act_int_off( lp );
136 wl_apply(lp);
138 wl_act_int_on( lp );
140 wl_unlock(lp, &flags);
142 out:
143 DBG_LEAVE( DbgInfo );
144 return ret;
145 } // wireless_commit
146 /*============================================================================*/
151 /*******************************************************************************
152 * wireless_get_protocol()
153 *******************************************************************************
155 * DESCRIPTION:
157 * Returns a vendor-defined string that should identify the wireless
158 * protocol used.
160 * PARAMETERS:
162 * wrq - the wireless request buffer
164 * RETURNS:
166 * N/A
168 ******************************************************************************/
169 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
171 DBG_FUNC( "wireless_get_protocol" );
172 DBG_ENTER( DbgInfo );
174 /* Originally, the driver was placing the string "Wireless" here. However,
175 the wireless extensions (/linux/wireless.h) indicate this string should
176 describe the wireless protocol. */
178 strcpy(name, "IEEE 802.11b");
180 DBG_LEAVE(DbgInfo);
181 return 0;
182 } // wireless_get_protocol
183 /*============================================================================*/
188 /*******************************************************************************
189 * wireless_set_frequency()
190 *******************************************************************************
192 * DESCRIPTION:
194 * Sets the frequency (channel) on which the card should Tx/Rx.
196 * PARAMETERS:
198 * wrq - the wireless request buffer
199 * lp - the device's private adapter structure
201 * RETURNS:
203 * 0 on success
204 * errno value otherwise
206 ******************************************************************************/
207 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
209 struct wl_private *lp = wl_priv(dev);
210 unsigned long flags;
211 int channel = 0;
212 int ret = 0;
213 /*------------------------------------------------------------------------*/
216 DBG_FUNC( "wireless_set_frequency" );
217 DBG_ENTER( DbgInfo );
219 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
220 ret = -EBUSY;
221 goto out;
224 if( !capable( CAP_NET_ADMIN )) {
225 ret = -EPERM;
226 DBG_LEAVE( DbgInfo );
227 return ret;
231 /* If frequency specified, look up channel */
232 if( freq->e == 1 ) {
233 int f = freq->m / 100000;
234 channel = wl_get_chan_from_freq( f );
238 /* Channel specified */
239 if( freq->e == 0 ) {
240 channel = freq->m;
244 /* If the channel is an 802.11a channel, set Bit 8 */
245 if( channel > 14 ) {
246 channel = channel | 0x100;
250 wl_lock( lp, &flags );
252 wl_act_int_off( lp );
254 lp->Channel = channel;
257 /* Commit the adapter parameters */
258 wl_apply( lp );
260 /* Send an event that channel/freq has been set */
261 wl_wext_event_freq( lp->dev );
263 wl_act_int_on( lp );
265 wl_unlock(lp, &flags);
267 out:
268 DBG_LEAVE( DbgInfo );
269 return ret;
270 } // wireless_set_frequency
271 /*============================================================================*/
276 /*******************************************************************************
277 * wireless_get_frequency()
278 *******************************************************************************
280 * DESCRIPTION:
282 * Gets the frequency (channel) on which the card is Tx/Rx.
284 * PARAMETERS:
286 * wrq - the wireless request buffer
287 * lp - the device's private adapter structure
289 * RETURNS:
291 * N/A
293 ******************************************************************************/
294 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
297 struct wl_private *lp = wl_priv(dev);
298 unsigned long flags;
299 int ret = -1;
300 /*------------------------------------------------------------------------*/
303 DBG_FUNC( "wireless_get_frequency" );
304 DBG_ENTER( DbgInfo );
306 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
307 ret = -EBUSY;
308 goto out;
311 wl_lock( lp, &flags );
313 wl_act_int_off( lp );
315 lp->ltvRecord.len = 2;
316 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
318 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
319 if( ret == HCF_SUCCESS ) {
320 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
322 freq->m = wl_get_freq_from_chan( channel ) * 100000;
323 freq->e = 1;
326 wl_act_int_on( lp );
328 wl_unlock(lp, &flags);
330 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
332 out:
333 DBG_LEAVE( DbgInfo );
334 return ret;
335 } // wireless_get_frequency
336 /*============================================================================*/
341 /*******************************************************************************
342 * wireless_get_range()
343 *******************************************************************************
345 * DESCRIPTION:
347 * This function is used to provide misc info and statistics about the
348 * wireless device.
350 * PARAMETERS:
352 * wrq - the wireless request buffer
353 * lp - the device's private adapter structure
355 * RETURNS:
357 * 0 on success
358 * errno value otherwise
360 ******************************************************************************/
361 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
363 struct wl_private *lp = wl_priv(dev);
364 unsigned long flags;
365 struct iw_range *range = (struct iw_range *) extra;
366 int ret = 0;
367 int status = -1;
368 int count;
369 __u16 *pTxRate;
370 int retries = 0;
371 /*------------------------------------------------------------------------*/
374 DBG_FUNC( "wireless_get_range" );
375 DBG_ENTER( DbgInfo );
377 /* Set range information */
378 data->length = sizeof(struct iw_range);
379 memset(range, 0, sizeof(struct iw_range));
381 wl_lock( lp, &flags );
383 wl_act_int_off( lp );
385 /* Set range information */
386 memset( range, 0, sizeof( struct iw_range ));
388 retry:
389 /* Get the current transmit rate from the adapter */
390 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
391 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
393 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
394 if( status != HCF_SUCCESS ) {
395 /* Recovery action: reset and retry up to 10 times */
396 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
398 if (retries < 10) {
399 retries++;
401 /* Holding the lock too long, make a gap to allow other processes */
402 wl_unlock(lp, &flags);
403 wl_lock( lp, &flags );
405 status = wl_reset( dev );
406 if ( status != HCF_SUCCESS ) {
407 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
409 ret = -EFAULT;
410 goto out_unlock;
413 /* Holding the lock too long, make a gap to allow other processes */
414 wl_unlock(lp, &flags);
415 wl_lock( lp, &flags );
417 goto retry;
419 } else {
420 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
421 ret = -EFAULT;
422 goto out_unlock;
426 /* Holding the lock too long, make a gap to allow other processes */
427 wl_unlock(lp, &flags);
428 wl_lock( lp, &flags );
430 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
432 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
434 if (retries > 0) {
435 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
438 // NWID - NOT SUPPORTED
441 /* Channel/Frequency Info */
442 range->num_channels = RADIO_CHANNELS;
445 /* Signal Level Thresholds */
446 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
449 /* Link quality */
450 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
452 /* If the value returned in /proc/net/wireless is greater than the maximum range,
453 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
454 it requires a bit of contorsion... */
456 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
457 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
460 /* Set available rates */
461 range->num_bitrates = 0;
463 lp->ltvRecord.len = 6;
464 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
466 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
467 if( status == HCF_SUCCESS ) {
468 for( count = 0; count < MAX_RATES; count++ )
469 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
470 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
471 range->num_bitrates++;
473 } else {
474 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
475 ret = -EFAULT;
476 goto out_unlock;
479 /* RTS Threshold info */
480 range->min_rts = MIN_RTS_BYTES;
481 range->max_rts = MAX_RTS_BYTES;
483 // Frag Threshold info - NOT SUPPORTED
485 // Power Management info - NOT SUPPORTED
487 /* Encryption */
489 /* Holding the lock too long, make a gap to allow other processes */
490 wl_unlock(lp, &flags);
491 wl_lock( lp, &flags );
493 /* Is WEP supported? */
495 if( wl_has_wep( &( lp->hcfCtx ))) {
496 /* WEP: RC4 40 bits */
497 range->encoding_size[0] = MIN_KEY_SIZE;
499 /* RC4 ~128 bits */
500 range->encoding_size[1] = MAX_KEY_SIZE;
501 range->num_encoding_sizes = 2;
502 range->max_encoding_tokens = MAX_KEYS;
505 /* Tx Power Info */
506 range->txpower_capa = IW_TXPOW_MWATT;
507 range->num_txpower = 1;
508 range->txpower[0] = RADIO_TX_POWER_MWATT;
510 /* Wireless Extension Info */
511 range->we_version_compiled = WIRELESS_EXT;
512 range->we_version_source = WIRELESS_SUPPORT;
514 // Retry Limits and Lifetime - NOT SUPPORTED
516 /* Holding the lock too long, make a gap to allow other processes */
517 wl_unlock(lp, &flags);
518 wl_lock( lp, &flags );
520 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
521 wl_wireless_stats( lp->dev );
522 range->avg_qual = lp->wstats.qual;
523 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
525 /* Event capability (kernel + driver) */
526 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
527 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
528 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
529 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
530 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
531 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
532 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
533 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
535 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
536 range->scan_capa = IW_SCAN_CAPA_NONE;
538 out_unlock:
539 wl_act_int_on( lp );
541 wl_unlock(lp, &flags);
543 DBG_LEAVE(DbgInfo);
544 return ret;
545 } // wireless_get_range
546 /*============================================================================*/
549 /*******************************************************************************
550 * wireless_get_bssid()
551 *******************************************************************************
553 * DESCRIPTION:
555 * Gets the BSSID the wireless device is currently associated with.
557 * PARAMETERS:
559 * wrq - the wireless request buffer
560 * lp - the device's private adapter structure
562 * RETURNS:
564 * 0 on success
565 * errno value otherwise
567 ******************************************************************************/
568 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
570 struct wl_private *lp = wl_priv(dev);
571 unsigned long flags;
572 int ret = 0;
573 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
574 int status = -1;
575 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
576 /*------------------------------------------------------------------------*/
579 DBG_FUNC( "wireless_get_bssid" );
580 DBG_ENTER( DbgInfo );
582 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
583 ret = -EBUSY;
584 goto out;
587 wl_lock( lp, &flags );
589 wl_act_int_off( lp );
591 memset( &ap_addr->sa_data, 0, ETH_ALEN );
593 ap_addr->sa_family = ARPHRD_ETHER;
595 /* Assume AP mode here, which means the BSSID is our own MAC address. In
596 STA mode, this address will be overwritten with the actual BSSID using
597 the code below. */
598 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
601 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
602 //;?should we return an error status in AP mode
604 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
605 /* Get Current BSSID */
606 lp->ltvRecord.typ = CFG_CUR_BSSID;
607 lp->ltvRecord.len = 4;
608 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
610 if( status == HCF_SUCCESS ) {
611 /* Copy info into sockaddr struct */
612 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
613 } else {
614 ret = -EFAULT;
618 #endif // (HCF_TYPE) & HCF_TYPE_STA
620 wl_act_int_on( lp );
622 wl_unlock(lp, &flags);
624 out:
625 DBG_LEAVE(DbgInfo);
626 return ret;
627 } // wireless_get_bssid
628 /*============================================================================*/
633 /*******************************************************************************
634 * wireless_get_ap_list()
635 *******************************************************************************
637 * DESCRIPTION:
639 * Gets the results of a network scan.
641 * PARAMETERS:
643 * wrq - the wireless request buffer
644 * lp - the device's private adapter structure
646 * RETURNS:
648 * 0 on success
649 * errno value otherwise
651 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
652 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
653 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
655 ******************************************************************************/
656 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
658 struct wl_private *lp = wl_priv(dev);
659 unsigned long flags;
660 int ret;
661 int num_aps = -1;
662 int sec_count = 0;
663 hcf_32 count;
664 struct sockaddr *hwa = NULL;
665 struct iw_quality *qual = NULL;
666 #ifdef WARP
667 ScanResult *p = &lp->scan_results;
668 #else
669 ProbeResult *p = &lp->probe_results;
670 #endif // WARP
671 /*------------------------------------------------------------------------*/
673 DBG_FUNC( "wireless_get_ap_list" );
674 DBG_ENTER( DbgInfo );
676 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
677 ret = -EBUSY;
678 goto out;
681 wl_lock( lp, &flags );
683 wl_act_int_off( lp );
685 /* Set the completion state to FALSE */
686 lp->scan_results.scan_complete = FALSE;
687 lp->probe_results.scan_complete = FALSE;
688 /* Channels to scan */
689 lp->ltvRecord.len = 2;
690 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
691 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
692 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
693 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
695 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
696 disassociate from the network we are currently on */
697 lp->ltvRecord.len = 2;
698 lp->ltvRecord.typ = CFG_SCAN_SSID;
699 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
700 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
701 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
703 /* Initiate the scan */
704 #ifdef WARP
705 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
706 #else
707 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
708 #endif // WARP
710 wl_act_int_on( lp );
712 //;? unlock? what about the access to lp below? is it broken?
713 wl_unlock(lp, &flags);
715 if( ret == HCF_SUCCESS ) {
716 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
717 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
718 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
719 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
720 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
721 ret = -EIO;
722 } else {
723 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
724 other things in the meantime, This prevents system lockups by
725 giving some time back to the kernel */
726 for( count = 0; count < 100; count ++ ) {
727 mdelay( 10 );
728 schedule( );
733 rmb();
735 if ( ret != HCF_SUCCESS ) {
736 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
737 } else {
738 num_aps = (*p)/*lp->probe_results*/.num_aps;
739 if (num_aps > IW_MAX_AP) {
740 num_aps = IW_MAX_AP;
742 data->length = num_aps;
743 hwa = (struct sockaddr *)extra;
744 qual = (struct iw_quality *) extra +
745 ( sizeof( struct sockaddr ) * num_aps );
747 /* This flag is used to tell the user if we provide quality
748 information. Since we provide signal/noise levels but no
749 quality info on a scan, this is set to 0. Setting to 1 and
750 providing a quality of 0 produces weird results. If we ever
751 provide quality (or can calculate it), this can be changed */
752 data->flags = 0;
754 for( count = 0; count < num_aps; count++ ) {
755 #ifdef WARP
756 memcpy( hwa[count].sa_data,
757 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
758 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
759 DBG_PRINT("BSSID: %pM\n",
760 (*p).ProbeTable[count].BSSID);
761 memcpy( hwa[count].sa_data,
762 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
763 #endif // WARP
765 /* Once the data is copied to the wireless struct, invalidate the
766 scan result to initiate a rescan on the next request */
767 (*p)/*lp->probe_results*/.scan_complete = FALSE;
768 /* Send the wireless event that the scan has completed, just in case
769 it's needed */
770 wl_wext_event_scan_complete( lp->dev );
773 out:
774 DBG_LEAVE( DbgInfo );
775 return ret;
776 } // wireless_get_ap_list
777 /*============================================================================*/
782 /*******************************************************************************
783 * wireless_set_sensitivity()
784 *******************************************************************************
786 * DESCRIPTION:
788 * Sets the sensitivity (distance between APs) of the wireless card.
790 * PARAMETERS:
792 * wrq - the wireless request buffer
793 * lp - the device's private adapter structure
795 * RETURNS:
797 * 0 on success
798 * errno value otherwise
800 ******************************************************************************/
801 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
803 struct wl_private *lp = wl_priv(dev);
804 unsigned long flags;
805 int ret = 0;
806 int dens = sens->value;
807 /*------------------------------------------------------------------------*/
810 DBG_FUNC( "wireless_set_sensitivity" );
811 DBG_ENTER( DbgInfo );
813 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
814 ret = -EBUSY;
815 goto out;
818 if(( dens < 1 ) || ( dens > 3 )) {
819 ret = -EINVAL;
820 goto out;
823 wl_lock( lp, &flags );
825 wl_act_int_off( lp );
827 lp->DistanceBetweenAPs = dens;
828 wl_apply( lp );
830 wl_act_int_on( lp );
832 wl_unlock(lp, &flags);
834 out:
835 DBG_LEAVE( DbgInfo );
836 return ret;
837 } // wireless_set_sensitivity
838 /*============================================================================*/
843 /*******************************************************************************
844 * wireless_get_sensitivity()
845 *******************************************************************************
847 * DESCRIPTION:
849 * Gets the sensitivity (distance between APs) of the wireless card.
851 * PARAMETERS:
853 * wrq - the wireless request buffer
854 * lp - the device's private adapter structure
856 * RETURNS:
858 * 0 on success
859 * errno value otherwise
861 ******************************************************************************/
862 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
864 struct wl_private *lp = wl_priv(dev);
865 int ret = 0;
866 /*------------------------------------------------------------------------*/
867 /*------------------------------------------------------------------------*/
870 DBG_FUNC( "wireless_get_sensitivity" );
871 DBG_ENTER( DbgInfo );
873 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
874 ret = -EBUSY;
875 goto out;
878 /* not worth locking ... */
879 sens->value = lp->DistanceBetweenAPs;
880 sens->fixed = 0; /* auto */
881 out:
882 DBG_LEAVE( DbgInfo );
883 return ret;
884 } // wireless_get_sensitivity
885 /*============================================================================*/
890 /*******************************************************************************
891 * wireless_set_essid()
892 *******************************************************************************
894 * DESCRIPTION:
896 * Sets the ESSID (network name) that the wireless device should associate
897 * with.
899 * PARAMETERS:
901 * wrq - the wireless request buffer
902 * lp - the device's private adapter structure
904 * RETURNS:
906 * 0 on success
907 * errno value otherwise
909 ******************************************************************************/
910 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
912 struct wl_private *lp = wl_priv(dev);
913 unsigned long flags;
914 int ret = 0;
916 DBG_FUNC( "wireless_set_essid" );
917 DBG_ENTER( DbgInfo );
919 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
920 ret = -EBUSY;
921 goto out;
924 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
925 ret = -EINVAL;
926 goto out;
929 wl_lock( lp, &flags );
931 wl_act_int_off( lp );
933 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
935 /* data->flags is zero to ask for "any" */
936 if( data->flags == 0 ) {
937 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
938 * ;?but there ain't no STAP anymore*/
939 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
940 strcpy( lp->NetworkName, "ANY" );
941 } else {
942 //strcpy( lp->NetworkName, "ANY" );
943 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
945 } else {
946 memcpy( lp->NetworkName, ssid, data->length );
949 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
951 /* Commit the adapter parameters */
952 wl_apply( lp );
954 /* Send an event that ESSID has been set */
955 wl_wext_event_essid( lp->dev );
957 wl_act_int_on( lp );
959 wl_unlock(lp, &flags);
961 out:
962 DBG_LEAVE( DbgInfo );
963 return ret;
964 } // wireless_set_essid
965 /*============================================================================*/
970 /*******************************************************************************
971 * wireless_get_essid()
972 *******************************************************************************
974 * DESCRIPTION:
976 * Gets the ESSID (network name) that the wireless device is associated
977 * with.
979 * PARAMETERS:
981 * wrq - the wireless request buffer
982 * lp - the device's private adapter structure
984 * RETURNS:
986 * 0 on success
987 * errno value otherwise
989 ******************************************************************************/
990 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
993 struct wl_private *lp = wl_priv(dev);
994 unsigned long flags;
995 int ret = 0;
996 int status = -1;
997 wvName_t *pName;
998 /*------------------------------------------------------------------------*/
1001 DBG_FUNC( "wireless_get_essid" );
1002 DBG_ENTER( DbgInfo );
1004 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1005 ret = -EBUSY;
1006 goto out;
1009 wl_lock( lp, &flags );
1011 wl_act_int_off( lp );
1013 /* Get the desired network name */
1014 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1017 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1018 //;?should we return an error status in AP mode
1020 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1022 #endif
1025 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1026 //;?should we restore this to allow smaller memory footprint
1028 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1029 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1032 #endif // HCF_AP
1035 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1036 if( status == HCF_SUCCESS ) {
1037 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1039 /* Endian translate the string length */
1040 pName->length = CNV_LITTLE_TO_INT( pName->length );
1042 /* Copy the information into the user buffer */
1043 data->length = pName->length;
1045 if( pName->length < HCF_MAX_NAME_LEN ) {
1046 pName->name[pName->length] = '\0';
1049 data->flags = 1;
1052 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1053 //;?should we return an error status in AP mode
1055 /* if desired is null ("any"), return current or "any" */
1056 if( pName->name[0] == '\0' ) {
1057 /* Get the current network name */
1058 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1059 lp->ltvRecord.typ = CFG_CUR_SSID;
1061 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1063 if( status == HCF_SUCCESS ) {
1064 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1066 /* Endian translate the string length */
1067 pName->length = CNV_LITTLE_TO_INT( pName->length );
1069 /* Copy the information into the user buffer */
1070 data->length = pName->length;
1071 data->flags = 1;
1072 } else {
1073 ret = -EFAULT;
1074 goto out_unlock;
1078 #endif // HCF_STA
1080 if (pName->length > IW_ESSID_MAX_SIZE) {
1081 ret = -EFAULT;
1082 goto out_unlock;
1085 memcpy(essid, pName->name, pName->length);
1086 } else {
1087 ret = -EFAULT;
1088 goto out_unlock;
1091 out_unlock:
1092 wl_act_int_on( lp );
1094 wl_unlock(lp, &flags);
1096 out:
1097 DBG_LEAVE( DbgInfo );
1098 return ret;
1099 } // wireless_get_essid
1100 /*============================================================================*/
1105 /*******************************************************************************
1106 * wireless_set_encode()
1107 *******************************************************************************
1109 * DESCRIPTION:
1111 * Sets the encryption keys and status (enable or disable).
1113 * PARAMETERS:
1115 * wrq - the wireless request buffer
1116 * lp - the device's private adapter structure
1118 * RETURNS:
1120 * 0 on success
1121 * errno value otherwise
1123 ******************************************************************************/
1124 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1126 struct wl_private *lp = wl_priv(dev);
1127 unsigned long flags;
1128 int ret = 0;
1129 hcf_8 encryption_state;
1130 /*------------------------------------------------------------------------*/
1133 DBG_FUNC( "wireless_set_encode" );
1134 DBG_ENTER( DbgInfo );
1136 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1137 ret = -EBUSY;
1138 goto out;
1141 wl_lock( lp, &flags );
1143 wl_act_int_off( lp );
1145 /* Is encryption supported? */
1146 if( !wl_has_wep( &( lp->hcfCtx ))) {
1147 DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1148 ret = -EOPNOTSUPP;
1149 goto out_unlock;
1152 DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1153 keybuf, erq->length,
1154 erq->flags);
1156 /* Save state of Encryption switch */
1157 encryption_state = lp->EnableEncryption;
1159 /* Basic checking: do we have a key to set? */
1160 if((erq->length) != 0) {
1161 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1162 int tk = lp->TransmitKeyID - 1; // current key
1165 /* Check the size of the key */
1166 switch(erq->length) {
1167 case 0:
1168 break;
1170 case MIN_KEY_SIZE:
1171 case MAX_KEY_SIZE:
1173 /* Check the index */
1174 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1175 index = tk;
1178 /* Cleanup */
1179 memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1181 /* Copy the key in the driver */
1182 memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1184 /* Set the length */
1185 lp->DefaultKeys.key[index].len = erq->length;
1187 DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1188 DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1189 lp->DefaultKeys.key[index].len, index );
1191 /* Enable WEP (if possible) */
1192 if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1193 lp->EnableEncryption = 1;
1196 break;
1198 default:
1199 DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1200 ret = -EINVAL;
1201 goto out_unlock;
1203 } else {
1204 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1207 /* Do we want to just set the current transmit key? */
1208 if(( index >= 0 ) && ( index < MAX_KEYS )) {
1209 DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1210 lp->DefaultKeys.key[index].len );
1212 if( lp->DefaultKeys.key[index].len > 0 ) {
1213 lp->TransmitKeyID = index + 1;
1214 lp->EnableEncryption = 1;
1215 } else {
1216 DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1217 DBG_LEAVE( DbgInfo );
1218 ret = -EINVAL;
1223 /* Read the flags */
1224 if( erq->flags & IW_ENCODE_DISABLED ) {
1225 lp->EnableEncryption = 0; // disable encryption
1226 } else {
1227 lp->EnableEncryption = 1;
1230 if( erq->flags & IW_ENCODE_RESTRICTED ) {
1231 DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1232 ret = -EINVAL; // Invalid
1235 DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state );
1236 DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption );
1237 DBG_TRACE( DbgInfo, "erq->length : %d\n",
1238 erq->length);
1239 DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n",
1240 erq->flags);
1242 /* Write the changes to the card */
1243 if( ret == 0 ) {
1244 DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1245 lp->TransmitKeyID );
1247 if( lp->EnableEncryption == encryption_state ) {
1248 if( erq->length != 0 ) {
1249 /* Dynamic WEP key update */
1250 wl_set_wep_keys( lp );
1252 } else {
1253 /* To switch encryption on/off, soft reset is required */
1254 wl_apply( lp );
1258 /* Send an event that Encryption has been set */
1259 wl_wext_event_encode( dev );
1261 out_unlock:
1263 wl_act_int_on( lp );
1265 wl_unlock(lp, &flags);
1267 out:
1268 DBG_LEAVE( DbgInfo );
1269 return ret;
1270 } // wireless_set_encode
1271 /*============================================================================*/
1276 /*******************************************************************************
1277 * wireless_get_encode()
1278 *******************************************************************************
1280 * DESCRIPTION:
1282 * Gets the encryption keys and status.
1284 * PARAMETERS:
1286 * wrq - the wireless request buffer
1287 * lp - the device's private adapter structure
1289 * RETURNS:
1291 * 0 on success
1292 * errno value otherwise
1294 ******************************************************************************/
1295 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1298 struct wl_private *lp = wl_priv(dev);
1299 unsigned long flags;
1300 int ret = 0;
1301 int index;
1302 /*------------------------------------------------------------------------*/
1305 DBG_FUNC( "wireless_get_encode" );
1306 DBG_ENTER( DbgInfo );
1307 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1309 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1310 ret = -EBUSY;
1311 goto out;
1314 /* Only super-user can see WEP key */
1315 if( !capable( CAP_NET_ADMIN )) {
1316 ret = -EPERM;
1317 DBG_LEAVE( DbgInfo );
1318 return ret;
1321 wl_lock( lp, &flags );
1323 wl_act_int_off( lp );
1325 /* Is it supported? */
1326 if( !wl_has_wep( &( lp->hcfCtx ))) {
1327 ret = -EOPNOTSUPP;
1328 goto out_unlock;
1331 /* Basic checking */
1332 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1335 /* Set the flags */
1336 erq->flags = 0;
1338 if( lp->EnableEncryption == 0 ) {
1339 erq->flags |= IW_ENCODE_DISABLED;
1342 /* Which key do we want */
1343 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1344 index = lp->TransmitKeyID - 1;
1347 erq->flags |= index + 1;
1349 /* Copy the key to the user buffer */
1350 erq->length = lp->DefaultKeys.key[index].len;
1352 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1354 out_unlock:
1356 wl_act_int_on( lp );
1358 wl_unlock(lp, &flags);
1360 out:
1361 DBG_LEAVE( DbgInfo );
1362 return ret;
1363 } // wireless_get_encode
1364 /*============================================================================*/
1369 /*******************************************************************************
1370 * wireless_set_nickname()
1371 *******************************************************************************
1373 * DESCRIPTION:
1375 * Sets the nickname, or station name, of the wireless device.
1377 * PARAMETERS:
1379 * wrq - the wireless request buffer
1380 * lp - the device's private adapter structure
1382 * RETURNS:
1384 * 0 on success
1385 * errno value otherwise
1387 ******************************************************************************/
1388 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1390 struct wl_private *lp = wl_priv(dev);
1391 unsigned long flags;
1392 int ret = 0;
1393 /*------------------------------------------------------------------------*/
1396 DBG_FUNC( "wireless_set_nickname" );
1397 DBG_ENTER( DbgInfo );
1399 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1400 ret = -EBUSY;
1401 goto out;
1404 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1405 if( !capable(CAP_NET_ADMIN )) {
1406 ret = -EPERM;
1407 DBG_LEAVE( DbgInfo );
1408 return ret;
1410 #endif
1412 /* Validate the new value */
1413 if(data->length > HCF_MAX_NAME_LEN) {
1414 ret = -EINVAL;
1415 goto out;
1418 wl_lock( lp, &flags );
1420 wl_act_int_off( lp );
1422 memset( lp->StationName, 0, sizeof( lp->StationName ));
1424 memcpy( lp->StationName, nickname, data->length );
1426 /* Commit the adapter parameters */
1427 wl_apply( lp );
1429 wl_act_int_on( lp );
1431 wl_unlock(lp, &flags);
1433 out:
1434 DBG_LEAVE( DbgInfo );
1435 return ret;
1436 } // wireless_set_nickname
1437 /*============================================================================*/
1442 /*******************************************************************************
1443 * wireless_get_nickname()
1444 *******************************************************************************
1446 * DESCRIPTION:
1448 * Gets the nickname, or station name, of the wireless device.
1450 * PARAMETERS:
1452 * wrq - the wireless request buffer
1453 * lp - the device's private adapter structure
1455 * RETURNS:
1457 * 0 on success
1458 * errno value otherwise
1460 ******************************************************************************/
1461 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1463 struct wl_private *lp = wl_priv(dev);
1464 unsigned long flags;
1465 int ret = 0;
1466 int status = -1;
1467 wvName_t *pName;
1468 /*------------------------------------------------------------------------*/
1471 DBG_FUNC( "wireless_get_nickname" );
1472 DBG_ENTER( DbgInfo );
1474 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1475 ret = -EBUSY;
1476 goto out;
1479 wl_lock( lp, &flags );
1481 wl_act_int_off( lp );
1483 /* Get the current station name */
1484 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1485 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1487 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1489 if( status == HCF_SUCCESS ) {
1490 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1492 /* Endian translate the length */
1493 pName->length = CNV_LITTLE_TO_INT( pName->length );
1495 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1496 ret = -EFAULT;
1497 } else {
1498 /* Copy the information into the user buffer */
1499 data->length = pName->length;
1500 memcpy(nickname, pName->name, pName->length);
1502 } else {
1503 ret = -EFAULT;
1506 wl_act_int_on( lp );
1508 wl_unlock(lp, &flags);
1510 out:
1511 DBG_LEAVE(DbgInfo);
1512 return ret;
1513 } // wireless_get_nickname
1514 /*============================================================================*/
1519 /*******************************************************************************
1520 * wireless_set_porttype()
1521 *******************************************************************************
1523 * DESCRIPTION:
1525 * Sets the port type of the wireless device.
1527 * PARAMETERS:
1529 * wrq - the wireless request buffer
1530 * lp - the device's private adapter structure
1532 * RETURNS:
1534 * 0 on success
1535 * errno value otherwise
1537 ******************************************************************************/
1538 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1540 struct wl_private *lp = wl_priv(dev);
1541 unsigned long flags;
1542 int ret = 0;
1543 hcf_16 portType;
1544 hcf_16 createIBSS;
1545 /*------------------------------------------------------------------------*/
1547 DBG_FUNC( "wireless_set_porttype" );
1548 DBG_ENTER( DbgInfo );
1550 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1551 ret = -EBUSY;
1552 goto out;
1555 wl_lock( lp, &flags );
1557 wl_act_int_off( lp );
1559 /* Validate the new value */
1560 switch( *mode ) {
1561 case IW_MODE_ADHOC:
1563 /* When user requests ad-hoc, set IBSS mode! */
1564 portType = 1;
1565 createIBSS = 1;
1567 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1569 break;
1572 case IW_MODE_AUTO:
1573 case IW_MODE_INFRA:
1575 /* Both automatic and infrastructure set port to BSS/STA mode */
1576 portType = 1;
1577 createIBSS = 0;
1579 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1581 break;
1584 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1586 case IW_MODE_MASTER:
1588 /* Set BSS/AP mode */
1589 portType = 1;
1591 lp->CreateIBSS = 0;
1592 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1594 break;
1596 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1599 default:
1601 portType = 0;
1602 createIBSS = 0;
1603 ret = -EINVAL;
1606 if( portType != 0 ) {
1607 /* Only do something if there is a mode change */
1608 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1609 lp->PortType = portType;
1610 lp->CreateIBSS = createIBSS;
1612 /* Commit the adapter parameters */
1613 wl_go( lp );
1615 /* Send an event that mode has been set */
1616 wl_wext_event_mode( lp->dev );
1620 wl_act_int_on( lp );
1622 wl_unlock(lp, &flags);
1624 out:
1625 DBG_LEAVE( DbgInfo );
1626 return ret;
1627 } // wireless_set_porttype
1628 /*============================================================================*/
1633 /*******************************************************************************
1634 * wireless_get_porttype()
1635 *******************************************************************************
1637 * DESCRIPTION:
1639 * Gets the port type of the wireless device.
1641 * PARAMETERS:
1643 * wrq - the wireless request buffer
1644 * lp - the device's private adapter structure
1646 * RETURNS:
1648 * 0 on success
1649 * errno value otherwise
1651 ******************************************************************************/
1652 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1655 struct wl_private *lp = wl_priv(dev);
1656 unsigned long flags;
1657 int ret = 0;
1658 int status = -1;
1659 hcf_16 *pPortType;
1660 /*------------------------------------------------------------------------*/
1663 DBG_FUNC( "wireless_get_porttype" );
1664 DBG_ENTER( DbgInfo );
1666 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1667 ret = -EBUSY;
1668 goto out;
1671 wl_lock( lp, &flags );
1673 wl_act_int_off( lp );
1675 /* Get the current port type */
1676 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1677 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1679 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1681 if( status == HCF_SUCCESS ) {
1682 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1684 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1686 switch( *pPortType ) {
1687 case 1:
1689 #if 0
1690 #if (HCF_TYPE) & HCF_TYPE_AP
1692 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1693 *mode = IW_MODE_MASTER;
1694 } else {
1695 *mode = IW_MODE_INFRA;
1698 #else
1700 *mode = IW_MODE_INFRA;
1702 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1703 #endif
1705 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1706 *mode = IW_MODE_MASTER;
1707 } else {
1708 if( lp->CreateIBSS ) {
1709 *mode = IW_MODE_ADHOC;
1710 } else {
1711 *mode = IW_MODE_INFRA;
1715 break;
1718 case 3:
1719 *mode = IW_MODE_ADHOC;
1720 break;
1722 default:
1723 ret = -EFAULT;
1724 break;
1726 } else {
1727 ret = -EFAULT;
1730 wl_act_int_on( lp );
1732 wl_unlock(lp, &flags);
1734 out:
1735 DBG_LEAVE( DbgInfo );
1736 return ret;
1737 } // wireless_get_porttype
1738 /*============================================================================*/
1743 /*******************************************************************************
1744 * wireless_set_power()
1745 *******************************************************************************
1747 * DESCRIPTION:
1749 * Sets the power management settings of the wireless device.
1751 * PARAMETERS:
1753 * wrq - the wireless request buffer
1754 * lp - the device's private adapter structure
1756 * RETURNS:
1758 * 0 on success
1759 * errno value otherwise
1761 ******************************************************************************/
1762 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1764 struct wl_private *lp = wl_priv(dev);
1765 unsigned long flags;
1766 int ret = 0;
1767 /*------------------------------------------------------------------------*/
1770 DBG_FUNC( "wireless_set_power" );
1771 DBG_ENTER( DbgInfo );
1773 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1774 ret = -EBUSY;
1775 goto out;
1778 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1780 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1781 if( !capable( CAP_NET_ADMIN )) {
1782 ret = -EPERM;
1784 DBG_LEAVE( DbgInfo );
1785 return ret;
1787 #endif
1789 wl_lock( lp, &flags );
1791 wl_act_int_off( lp );
1793 /* Set the power management state based on the 'disabled' value */
1794 if( wrq->disabled ) {
1795 lp->PMEnabled = 0;
1796 } else {
1797 lp->PMEnabled = 1;
1800 /* Commit the adapter parameters */
1801 wl_apply( lp );
1803 wl_act_int_on( lp );
1805 wl_unlock(lp, &flags);
1807 out:
1808 DBG_LEAVE( DbgInfo );
1809 return ret;
1810 } // wireless_set_power
1811 /*============================================================================*/
1816 /*******************************************************************************
1817 * wireless_get_power()
1818 *******************************************************************************
1820 * DESCRIPTION:
1822 * Gets the power management settings of the wireless device.
1824 * PARAMETERS:
1826 * wrq - the wireless request buffer
1827 * lp - the device's private adapter structure
1829 * RETURNS:
1831 * 0 on success
1832 * errno value otherwise
1834 ******************************************************************************/
1835 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1838 struct wl_private *lp = wl_priv(dev);
1839 unsigned long flags;
1840 int ret = 0;
1841 /*------------------------------------------------------------------------*/
1842 DBG_FUNC( "wireless_get_power" );
1843 DBG_ENTER( DbgInfo );
1845 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1846 ret = -EBUSY;
1847 goto out;
1850 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1852 wl_lock( lp, &flags );
1854 wl_act_int_off( lp );
1856 rrq->flags = 0;
1857 rrq->value = 0;
1859 if( lp->PMEnabled ) {
1860 rrq->disabled = 0;
1861 } else {
1862 rrq->disabled = 1;
1865 wl_act_int_on( lp );
1867 wl_unlock(lp, &flags);
1869 out:
1870 DBG_LEAVE( DbgInfo );
1871 return ret;
1872 } // wireless_get_power
1873 /*============================================================================*/
1878 /*******************************************************************************
1879 * wireless_get_tx_power()
1880 *******************************************************************************
1882 * DESCRIPTION:
1884 * Gets the transmit power of the wireless device's radio.
1886 * PARAMETERS:
1888 * wrq - the wireless request buffer
1889 * lp - the device's private adapter structure
1891 * RETURNS:
1893 * 0 on success
1894 * errno value otherwise
1896 ******************************************************************************/
1897 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1899 struct wl_private *lp = wl_priv(dev);
1900 unsigned long flags;
1901 int ret = 0;
1902 /*------------------------------------------------------------------------*/
1903 DBG_FUNC( "wireless_get_tx_power" );
1904 DBG_ENTER( DbgInfo );
1906 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1907 ret = -EBUSY;
1908 goto out;
1911 wl_lock( lp, &flags );
1913 wl_act_int_off( lp );
1915 #ifdef USE_POWER_DBM
1916 rrq->value = RADIO_TX_POWER_DBM;
1917 rrq->flags = IW_TXPOW_DBM;
1918 #else
1919 rrq->value = RADIO_TX_POWER_MWATT;
1920 rrq->flags = IW_TXPOW_MWATT;
1921 #endif
1922 rrq->fixed = 1;
1923 rrq->disabled = 0;
1925 wl_act_int_on( lp );
1927 wl_unlock(lp, &flags);
1929 out:
1930 DBG_LEAVE( DbgInfo );
1931 return ret;
1932 } // wireless_get_tx_power
1933 /*============================================================================*/
1938 /*******************************************************************************
1939 * wireless_set_rts_threshold()
1940 *******************************************************************************
1942 * DESCRIPTION:
1944 * Sets the RTS threshold for the wireless card.
1946 * PARAMETERS:
1948 * wrq - the wireless request buffer
1949 * lp - the device's private adapter structure
1951 * RETURNS:
1953 * 0 on success
1954 * errno value otherwise
1956 ******************************************************************************/
1957 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
1959 int ret = 0;
1960 struct wl_private *lp = wl_priv(dev);
1961 unsigned long flags;
1962 int rthr = rts->value;
1963 /*------------------------------------------------------------------------*/
1966 DBG_FUNC( "wireless_set_rts_threshold" );
1967 DBG_ENTER( DbgInfo );
1969 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1970 ret = -EBUSY;
1971 goto out;
1974 if(rts->fixed == 0) {
1975 ret = -EINVAL;
1976 goto out;
1979 if( rts->disabled ) {
1980 rthr = 2347;
1983 if(( rthr < 256 ) || ( rthr > 2347 )) {
1984 ret = -EINVAL;
1985 goto out;
1988 wl_lock( lp, &flags );
1990 wl_act_int_off( lp );
1992 lp->RTSThreshold = rthr;
1994 wl_apply( lp );
1996 wl_act_int_on( lp );
1998 wl_unlock(lp, &flags);
2000 out:
2001 DBG_LEAVE( DbgInfo );
2002 return ret;
2003 } // wireless_set_rts_threshold
2004 /*============================================================================*/
2009 /*******************************************************************************
2010 * wireless_get_rts_threshold()
2011 *******************************************************************************
2013 * DESCRIPTION:
2015 * Gets the RTS threshold for the wireless card.
2017 * PARAMETERS:
2019 * wrq - the wireless request buffer
2020 * lp - the device's private adapter structure
2022 * RETURNS:
2024 * 0 on success
2025 * errno value otherwise
2027 ******************************************************************************/
2028 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2030 int ret = 0;
2031 struct wl_private *lp = wl_priv(dev);
2032 unsigned long flags;
2033 /*------------------------------------------------------------------------*/
2035 DBG_FUNC( "wireless_get_rts_threshold" );
2036 DBG_ENTER( DbgInfo );
2038 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2039 ret = -EBUSY;
2040 goto out;
2043 wl_lock( lp, &flags );
2045 wl_act_int_off( lp );
2047 rts->value = lp->RTSThreshold;
2049 rts->disabled = ( rts->value == 2347 );
2051 rts->fixed = 1;
2053 wl_act_int_on( lp );
2055 wl_unlock(lp, &flags);
2057 out:
2058 DBG_LEAVE( DbgInfo );
2059 return ret;
2060 } // wireless_get_rts_threshold
2061 /*============================================================================*/
2067 /*******************************************************************************
2068 * wireless_set_rate()
2069 *******************************************************************************
2071 * DESCRIPTION:
2073 * Set the default data rate setting used by the wireless device.
2075 * PARAMETERS:
2077 * wrq - the wireless request buffer
2078 * lp - the device's private adapter structure
2080 * RETURNS:
2082 * 0 on success
2083 * errno value otherwise
2085 ******************************************************************************/
2086 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2088 struct wl_private *lp = wl_priv(dev);
2089 unsigned long flags;
2090 int ret = 0;
2091 #ifdef WARP
2092 int status = -1;
2093 int index = 0;
2094 #endif // WARP
2095 /*------------------------------------------------------------------------*/
2098 DBG_FUNC( "wireless_set_rate" );
2099 DBG_ENTER( DbgInfo );
2101 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2102 ret = -EBUSY;
2103 goto out;
2106 wl_lock( lp, &flags );
2108 wl_act_int_off( lp );
2110 #ifdef WARP
2112 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2113 if Bit 9 is set in the current channel RID */
2114 lp->ltvRecord.len = 2;
2115 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2117 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2119 if( status == HCF_SUCCESS ) {
2120 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2122 DBG_PRINT( "Index: %d\n", index );
2123 } else {
2124 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2125 DBG_LEAVE( DbgInfo );
2126 ret = -EINVAL;
2127 goto out_unlock;
2130 if( rrq->value > 0 &&
2131 rrq->value <= 1 * MEGABIT ) {
2132 lp->TxRateControl[index] = 0x0001;
2134 else if( rrq->value > 1 * MEGABIT &&
2135 rrq->value <= 2 * MEGABIT ) {
2136 if( rrq->fixed == 1 ) {
2137 lp->TxRateControl[index] = 0x0002;
2138 } else {
2139 lp->TxRateControl[index] = 0x0003;
2142 else if( rrq->value > 2 * MEGABIT &&
2143 rrq->value <= 5 * MEGABIT ) {
2144 if( rrq->fixed == 1 ) {
2145 lp->TxRateControl[index] = 0x0004;
2146 } else {
2147 lp->TxRateControl[index] = 0x0007;
2150 else if( rrq->value > 5 * MEGABIT &&
2151 rrq->value <= 6 * MEGABIT ) {
2152 if( rrq->fixed == 1 ) {
2153 lp->TxRateControl[index] = 0x0010;
2154 } else {
2155 lp->TxRateControl[index] = 0x0017;
2158 else if( rrq->value > 6 * MEGABIT &&
2159 rrq->value <= 9 * MEGABIT ) {
2160 if( rrq->fixed == 1 ) {
2161 lp->TxRateControl[index] = 0x0020;
2162 } else {
2163 lp->TxRateControl[index] = 0x0037;
2166 else if( rrq->value > 9 * MEGABIT &&
2167 rrq->value <= 11 * MEGABIT ) {
2168 if( rrq->fixed == 1 ) {
2169 lp->TxRateControl[index] = 0x0008;
2170 } else {
2171 lp->TxRateControl[index] = 0x003F;
2174 else if( rrq->value > 11 * MEGABIT &&
2175 rrq->value <= 12 * MEGABIT ) {
2176 if( rrq->fixed == 1 ) {
2177 lp->TxRateControl[index] = 0x0040;
2178 } else {
2179 lp->TxRateControl[index] = 0x007F;
2182 else if( rrq->value > 12 * MEGABIT &&
2183 rrq->value <= 18 * MEGABIT ) {
2184 if( rrq->fixed == 1 ) {
2185 lp->TxRateControl[index] = 0x0080;
2186 } else {
2187 lp->TxRateControl[index] = 0x00FF;
2190 else if( rrq->value > 18 * MEGABIT &&
2191 rrq->value <= 24 * MEGABIT ) {
2192 if( rrq->fixed == 1 ) {
2193 lp->TxRateControl[index] = 0x0100;
2194 } else {
2195 lp->TxRateControl[index] = 0x01FF;
2198 else if( rrq->value > 24 * MEGABIT &&
2199 rrq->value <= 36 * MEGABIT ) {
2200 if( rrq->fixed == 1 ) {
2201 lp->TxRateControl[index] = 0x0200;
2202 } else {
2203 lp->TxRateControl[index] = 0x03FF;
2206 else if( rrq->value > 36 * MEGABIT &&
2207 rrq->value <= 48 * MEGABIT ) {
2208 if( rrq->fixed == 1 ) {
2209 lp->TxRateControl[index] = 0x0400;
2210 } else {
2211 lp->TxRateControl[index] = 0x07FF;
2214 else if( rrq->value > 48 * MEGABIT &&
2215 rrq->value <= 54 * MEGABIT ) {
2216 if( rrq->fixed == 1 ) {
2217 lp->TxRateControl[index] = 0x0800;
2218 } else {
2219 lp->TxRateControl[index] = 0x0FFF;
2222 else if( rrq->fixed == 0 ) {
2223 /* In this case, the user has not specified a bitrate, only the "auto"
2224 moniker. So, set to all supported rates */
2225 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2226 } else {
2227 rrq->value = 0;
2228 ret = -EINVAL;
2229 goto out_unlock;
2233 #else
2235 if( rrq->value > 0 &&
2236 rrq->value <= 1 * MEGABIT ) {
2237 lp->TxRateControl[0] = 1;
2239 else if( rrq->value > 1 * MEGABIT &&
2240 rrq->value <= 2 * MEGABIT ) {
2241 if( rrq->fixed ) {
2242 lp->TxRateControl[0] = 2;
2243 } else {
2244 lp->TxRateControl[0] = 6;
2247 else if( rrq->value > 2 * MEGABIT &&
2248 rrq->value <= 5 * MEGABIT ) {
2249 if( rrq->fixed ) {
2250 lp->TxRateControl[0] = 4;
2251 } else {
2252 lp->TxRateControl[0] = 7;
2255 else if( rrq->value > 5 * MEGABIT &&
2256 rrq->value <= 11 * MEGABIT ) {
2257 if( rrq->fixed) {
2258 lp->TxRateControl[0] = 5;
2259 } else {
2260 lp->TxRateControl[0] = 3;
2263 else if( rrq->fixed == 0 ) {
2264 /* In this case, the user has not specified a bitrate, only the "auto"
2265 moniker. So, set the rate to 11Mb auto */
2266 lp->TxRateControl[0] = 3;
2267 } else {
2268 rrq->value = 0;
2269 ret = -EINVAL;
2270 goto out_unlock;
2273 #endif // WARP
2276 /* Commit the adapter parameters */
2277 wl_apply( lp );
2279 out_unlock:
2281 wl_act_int_on( lp );
2283 wl_unlock(lp, &flags);
2285 out:
2286 DBG_LEAVE( DbgInfo );
2287 return ret;
2288 } // wireless_set_rate
2289 /*============================================================================*/
2294 /*******************************************************************************
2295 * wireless_get_rate()
2296 *******************************************************************************
2298 * DESCRIPTION:
2300 * Get the default data rate setting used by the wireless device.
2302 * PARAMETERS:
2304 * wrq - the wireless request buffer
2305 * lp - the device's private adapter structure
2307 * RETURNS:
2309 * 0 on success
2310 * errno value otherwise
2312 ******************************************************************************/
2313 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2316 struct wl_private *lp = wl_priv(dev);
2317 unsigned long flags;
2318 int ret = 0;
2319 int status = -1;
2320 hcf_16 txRate;
2321 /*------------------------------------------------------------------------*/
2324 DBG_FUNC( "wireless_get_rate" );
2325 DBG_ENTER( DbgInfo );
2327 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2328 ret = -EBUSY;
2329 goto out;
2332 wl_lock( lp, &flags );
2334 wl_act_int_off( lp );
2336 /* Get the current transmit rate from the adapter */
2337 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2338 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2340 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2342 if( status == HCF_SUCCESS ) {
2343 #ifdef WARP
2345 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2347 if( txRate & 0x0001 ) {
2348 txRate = 1;
2350 else if( txRate & 0x0002 ) {
2351 txRate = 2;
2353 else if( txRate & 0x0004 ) {
2354 txRate = 5;
2356 else if( txRate & 0x0008 ) {
2357 txRate = 11;
2359 else if( txRate & 0x00010 ) {
2360 txRate = 6;
2362 else if( txRate & 0x00020 ) {
2363 txRate = 9;
2365 else if( txRate & 0x00040 ) {
2366 txRate = 12;
2368 else if( txRate & 0x00080 ) {
2369 txRate = 18;
2371 else if( txRate & 0x00100 ) {
2372 txRate = 24;
2374 else if( txRate & 0x00200 ) {
2375 txRate = 36;
2377 else if( txRate & 0x00400 ) {
2378 txRate = 48;
2380 else if( txRate & 0x00800 ) {
2381 txRate = 54;
2384 #else
2386 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2388 #endif // WARP
2390 rrq->value = txRate * MEGABIT;
2391 } else {
2392 rrq->value = 0;
2393 ret = -EFAULT;
2396 wl_act_int_on( lp );
2398 wl_unlock(lp, &flags);
2400 out:
2401 DBG_LEAVE( DbgInfo );
2402 return ret;
2403 } // wireless_get_rate
2404 /*============================================================================*/
2409 #if 0 //;? Not used anymore
2410 /*******************************************************************************
2411 * wireless_get_private_interface()
2412 *******************************************************************************
2414 * DESCRIPTION:
2416 * Returns the Linux Wireless Extensions' compatible private interface of
2417 * the driver.
2419 * PARAMETERS:
2421 * wrq - the wireless request buffer
2422 * lp - the device's private adapter structure
2424 * RETURNS:
2426 * 0 on success
2427 * errno value otherwise
2429 ******************************************************************************/
2430 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2432 int ret = 0;
2433 /*------------------------------------------------------------------------*/
2436 DBG_FUNC( "wireless_get_private_interface" );
2437 DBG_ENTER( DbgInfo );
2439 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2440 ret = -EBUSY;
2441 goto out;
2444 if( wrq->u.data.pointer != NULL ) {
2445 struct iw_priv_args priv[] =
2447 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2448 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2449 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2450 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2451 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2452 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2455 /* Verify the user buffer */
2456 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2458 if( ret != 0 ) {
2459 DBG_LEAVE( DbgInfo );
2460 return ret;
2463 /* Copy the data into the user's buffer */
2464 wrq->u.data.length = NELEM( priv );
2465 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2468 out:
2469 DBG_LEAVE( DbgInfo );
2470 return ret;
2471 } // wireless_get_private_interface
2472 /*============================================================================*/
2473 #endif
2477 /*******************************************************************************
2478 * wireless_set_scan()
2479 *******************************************************************************
2481 * DESCRIPTION:
2483 * Instructs the driver to initiate a network scan.
2485 * PARAMETERS:
2487 * wrq - the wireless request buffer
2488 * lp - the device's private adapter structure
2490 * RETURNS:
2492 * 0 on success
2493 * errno value otherwise
2495 ******************************************************************************/
2496 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2498 struct wl_private *lp = wl_priv(dev);
2499 unsigned long flags;
2500 int ret = 0;
2501 int status = -1;
2502 int retries = 0;
2503 /*------------------------------------------------------------------------*/
2505 //;? Note: shows results as trace, retruns always 0 unless BUSY
2507 DBG_FUNC( "wireless_set_scan" );
2508 DBG_ENTER( DbgInfo );
2510 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2511 ret = -EBUSY;
2512 goto out;
2515 wl_lock( lp, &flags );
2517 wl_act_int_off( lp );
2520 * This looks like a nice place to test if the HCF is still
2521 * communicating with the card. It seems that sometimes BAP_1
2522 * gets corrupted. By looking at the comments in HCF the
2523 * cause is still a mystery. Okay, the communication to the
2524 * card is dead, reset the card to revive.
2526 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2528 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2529 wl_reset( dev );
2532 retry:
2533 /* Set the completion state to FALSE */
2534 lp->probe_results.scan_complete = FALSE;
2537 /* Channels to scan */
2538 #ifdef WARP
2539 lp->ltvRecord.len = 5;
2540 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2541 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2542 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2543 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2544 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2545 #else
2546 lp->ltvRecord.len = 2;
2547 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2548 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2549 #endif // WARP
2551 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2553 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2555 // Holding the lock too long, make a gap to allow other processes
2556 wl_unlock(lp, &flags);
2557 wl_lock( lp, &flags );
2559 if( status != HCF_SUCCESS ) {
2560 //Recovery
2561 retries++;
2562 if(retries <= 10) {
2563 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2564 wl_reset( dev );
2566 // Holding the lock too long, make a gap to allow other processes
2567 wl_unlock(lp, &flags);
2568 wl_lock( lp, &flags );
2570 goto retry;
2574 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2575 disassociate from the network we are currently on */
2576 lp->ltvRecord.len = 18;
2577 lp->ltvRecord.typ = CFG_SCAN_SSID;
2578 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2579 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2581 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2583 // Holding the lock too long, make a gap to allow other processes
2584 wl_unlock(lp, &flags);
2585 wl_lock( lp, &flags );
2587 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2589 /* Initiate the scan */
2590 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2591 retrieve probe responses must always be used to support WPA */
2592 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2594 if( status == HCF_SUCCESS ) {
2595 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2596 } else {
2597 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2600 wl_act_int_on( lp );
2602 wl_unlock(lp, &flags);
2604 out:
2605 DBG_LEAVE(DbgInfo);
2606 return ret;
2607 } // wireless_set_scan
2608 /*============================================================================*/
2613 /*******************************************************************************
2614 * wireless_get_scan()
2615 *******************************************************************************
2617 * DESCRIPTION:
2619 * Instructs the driver to gather and return the results of a network scan.
2621 * PARAMETERS:
2623 * wrq - the wireless request buffer
2624 * lp - the device's private adapter structure
2626 * RETURNS:
2628 * 0 on success
2629 * errno value otherwise
2631 ******************************************************************************/
2632 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2634 struct wl_private *lp = wl_priv(dev);
2635 unsigned long flags;
2636 int ret = 0;
2637 int count;
2638 char *buf;
2639 char *buf_end;
2640 struct iw_event iwe;
2641 PROBE_RESP *probe_resp;
2642 hcf_8 msg[512];
2643 hcf_8 *wpa_ie;
2644 hcf_16 wpa_ie_len;
2645 /*------------------------------------------------------------------------*/
2648 DBG_FUNC( "wireless_get_scan" );
2649 DBG_ENTER( DbgInfo );
2651 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2652 ret = -EBUSY;
2653 goto out;
2656 wl_lock( lp, &flags );
2658 wl_act_int_off( lp );
2660 /* If the scan is not done, tell the calling process to try again later */
2661 if( !lp->probe_results.scan_complete ) {
2662 ret = -EAGAIN;
2663 goto out_unlock;
2666 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2667 lp->probe_results.num_aps );
2669 buf = extra;
2670 buf_end = extra + IW_SCAN_MAX_DATA;
2672 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2673 /* Reference the probe response from the table */
2674 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2677 /* First entry MUST be the MAC address */
2678 memset( &iwe, 0, sizeof( iwe ));
2680 iwe.cmd = SIOCGIWAP;
2681 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2682 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2683 iwe.len = IW_EV_ADDR_LEN;
2685 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2688 /* Use the mode to indicate if it's a station or AP */
2689 /* Won't always be an AP if in IBSS mode */
2690 memset( &iwe, 0, sizeof( iwe ));
2692 iwe.cmd = SIOCGIWMODE;
2694 if( probe_resp->capability & CAPABILITY_IBSS ) {
2695 iwe.u.mode = IW_MODE_INFRA;
2696 } else {
2697 iwe.u.mode = IW_MODE_MASTER;
2700 iwe.len = IW_EV_UINT_LEN;
2702 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2705 /* Any quality information */
2706 memset(&iwe, 0, sizeof(iwe));
2708 iwe.cmd = IWEVQUAL;
2709 iwe.u.qual.level = dbm(probe_resp->signal);
2710 iwe.u.qual.noise = dbm(probe_resp->silence);
2711 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2712 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2713 iwe.len = IW_EV_QUAL_LEN;
2715 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2718 /* ESSID information */
2719 if( probe_resp->rawData[1] > 0 ) {
2720 memset( &iwe, 0, sizeof( iwe ));
2722 iwe.cmd = SIOCGIWESSID;
2723 iwe.u.data.length = probe_resp->rawData[1];
2724 iwe.u.data.flags = 1;
2726 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2730 /* Encryption Information */
2731 memset( &iwe, 0, sizeof( iwe ));
2733 iwe.cmd = SIOCGIWENCODE;
2734 iwe.u.data.length = 0;
2736 /* Check the capabilities field of the Probe Response to see if
2737 'privacy' is supported on the AP in question */
2738 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2739 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2740 } else {
2741 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2744 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2747 /* Frequency Info */
2748 memset( &iwe, 0, sizeof( iwe ));
2750 iwe.cmd = SIOCGIWFREQ;
2751 iwe.len = IW_EV_FREQ_LEN;
2752 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2753 iwe.u.freq.e = 0;
2755 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2758 /* Custom info (Beacon Interval) */
2759 memset( &iwe, 0, sizeof( iwe ));
2760 memset( msg, 0, sizeof( msg ));
2762 iwe.cmd = IWEVCUSTOM;
2763 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2764 iwe.u.data.length = strlen( msg );
2766 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2769 /* Custom info (WPA-IE) */
2770 wpa_ie = NULL;
2771 wpa_ie_len = 0;
2773 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2774 if( wpa_ie != NULL ) {
2775 memset( &iwe, 0, sizeof( iwe ));
2776 memset( msg, 0, sizeof( msg ));
2778 iwe.cmd = IWEVCUSTOM;
2779 sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2780 iwe.u.data.length = strlen( msg );
2782 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2785 /* Add other custom info in formatted string format as needed... */
2788 data->length = buf - extra;
2790 out_unlock:
2792 wl_act_int_on( lp );
2794 wl_unlock(lp, &flags);
2796 out:
2797 DBG_LEAVE( DbgInfo );
2798 return ret;
2799 } // wireless_get_scan
2800 /*============================================================================*/
2804 static int wireless_set_auth(struct net_device *dev,
2805 struct iw_request_info *info,
2806 struct iw_param *data, char *extra)
2808 struct wl_private *lp = wl_priv(dev);
2809 unsigned long flags;
2810 int ret;
2811 int iwa_idx = data->flags & IW_AUTH_INDEX;
2812 int iwa_val = data->value;
2814 DBG_FUNC( "wireless_set_auth" );
2815 DBG_ENTER( DbgInfo );
2817 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2818 ret = -EBUSY;
2819 goto out;
2822 wl_lock( lp, &flags );
2824 wl_act_int_off( lp );
2826 switch (iwa_idx) {
2827 case IW_AUTH_WPA_VERSION:
2828 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2829 /* We do support WPA only; how should DISABLED be treated? */
2830 if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2831 ret = 0;
2832 else
2833 ret = -EINVAL;
2834 break;
2836 case IW_AUTH_WPA_ENABLED:
2837 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2838 if (iwa_val)
2839 lp->EnableEncryption = 2;
2840 else
2841 lp->EnableEncryption = 0;
2842 ret = 0;
2843 break;
2845 case IW_AUTH_TKIP_COUNTERMEASURES:
2846 DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2847 lp->driverEnable = !iwa_val;
2848 if(lp->driverEnable)
2849 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2850 else
2851 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2852 ret = 0;
2853 break;
2855 case IW_AUTH_DROP_UNENCRYPTED:
2856 DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2857 /* We do not actually do anything here, just to silence
2858 * wpa_supplicant */
2859 ret = 0;
2860 break;
2862 case IW_AUTH_CIPHER_PAIRWISE:
2863 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2864 /* not implemented, return an error */
2865 ret = -EINVAL;
2866 break;
2868 case IW_AUTH_CIPHER_GROUP:
2869 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2870 /* not implemented, return an error */
2871 ret = -EINVAL;
2872 break;
2874 case IW_AUTH_KEY_MGMT:
2875 DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2876 /* not implemented, return an error */
2877 ret = -EINVAL;
2878 break;
2880 case IW_AUTH_80211_AUTH_ALG:
2881 DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2882 /* not implemented, return an error */
2883 ret = -EINVAL;
2884 break;
2886 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2887 DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2888 /* not implemented, return an error */
2889 ret = -EINVAL;
2890 break;
2892 case IW_AUTH_ROAMING_CONTROL:
2893 DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2894 /* not implemented, return an error */
2895 ret = -EINVAL;
2896 break;
2898 case IW_AUTH_PRIVACY_INVOKED:
2899 DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2900 /* not implemented, return an error */
2901 ret = -EINVAL;
2902 break;
2904 default:
2905 DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2906 /* return an error */
2907 ret = -EINVAL;
2908 break;
2911 wl_act_int_on( lp );
2913 wl_unlock(lp, &flags);
2915 out:
2916 DBG_LEAVE( DbgInfo );
2917 return ret;
2918 } // wireless_set_auth
2919 /*============================================================================*/
2923 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
2924 int set_tx, u8 *seq, u8 *key, size_t key_len)
2926 int ret = -EINVAL;
2927 // int count = 0;
2928 int buf_idx = 0;
2929 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
2930 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
2932 DBG_FUNC( "hermes_set_key" );
2933 DBG_ENTER( DbgInfo );
2936 * Check the key index here; if 0, load as Pairwise Key, otherwise,
2937 * load as a group key. Note that for the Hermes, the RIDs for
2938 * group/pariwise keys are different from each other and different
2939 * than the default WEP keys as well.
2941 switch (alg)
2943 case IW_ENCODE_ALG_TKIP:
2944 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
2945 #if 0
2947 * Make sure that there is no data queued up in the firmware
2948 * before setting the TKIP keys. If this check is not
2949 * performed, some data may be sent out with incorrect MIC
2950 * and cause synchronizarion errors with the AP
2952 /* Check every 1ms for 100ms */
2953 for( count = 0; count < 100; count++ )
2955 usleep( 1000 );
2957 ltv.len = 2;
2958 ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
2959 ltv.u.u16[0] = 0;
2961 wl_get_info( sock, &ltv, ifname );
2963 if( ltv.u.u16[0] == 0 )
2965 break;
2969 if( count == 100 )
2971 wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
2973 #endif
2975 switch (key_idx) {
2976 case 0:
2977 ltv->len = 28;
2978 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
2980 /* Load the BSSID */
2981 memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
2982 buf_idx += ETH_ALEN;
2984 /* Load the TKIP key */
2985 memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
2986 buf_idx += 16;
2988 /* Load the TSC */
2989 memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
2990 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
2992 /* Load the RSC */
2993 memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
2994 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
2996 /* Load the TxMIC key */
2997 memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
2998 buf_idx += 8;
3000 /* Load the RxMIC key */
3001 memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
3003 ret = 0;
3004 break;
3005 case 1:
3006 case 2:
3007 case 3:
3008 ltv->len = 26;
3009 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3011 /* Load the key Index */
3012 ltv->u.u16[buf_idx] = key_idx;
3013 /* If this is a Tx Key, set bit 8000 */
3014 if(set_tx)
3015 ltv->u.u16[buf_idx] |= 0x8000;
3016 buf_idx += 2;
3018 /* Load the RSC */
3019 memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3020 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3022 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3023 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3024 memcpy(&ltv->u.u8[buf_idx], key, key_len);
3025 buf_idx += key_len;
3027 /* Load the TSC */
3028 memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3030 ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3032 ret = 0;
3033 break;
3034 default:
3035 break;
3038 break;
3040 case IW_ENCODE_ALG_WEP:
3041 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3042 break;
3044 case IW_ENCODE_ALG_CCMP:
3045 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3046 break;
3048 case IW_ENCODE_ALG_NONE:
3049 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3050 switch (key_idx) {
3051 case 0:
3052 if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3053 //if (addr != NULL) {
3054 ltv->len = 7;
3055 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3056 memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
3057 ret = 0;
3059 break;
3060 case 1:
3061 case 2:
3062 case 3:
3063 /* Clear the Group TKIP keys by index */
3064 ltv->len = 2;
3065 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3066 ltv->u.u16[0] = key_idx;
3068 ret = 0;
3069 break;
3070 default:
3071 break;
3073 break;
3074 default:
3075 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3076 break;
3079 DBG_LEAVE( DbgInfo );
3080 return ret;
3081 } // hermes_set_key
3082 /*============================================================================*/
3086 static int wireless_set_encodeext (struct net_device *dev,
3087 struct iw_request_info *info,
3088 struct iw_point *erq, char *keybuf)
3090 struct wl_private *lp = wl_priv(dev);
3091 unsigned long flags;
3092 int ret;
3093 int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3094 ltv_t ltv;
3095 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3097 DBG_FUNC( "wireless_set_encodeext" );
3098 DBG_ENTER( DbgInfo );
3100 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3101 ret = -EBUSY;
3102 goto out;
3105 if (sizeof(ext->rx_seq) != 8) {
3106 DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3107 DBG_LEAVE(DbgInfo);
3108 return -EINVAL;
3111 /* Handle WEP keys via the old set encode procedure */
3112 if(ext->alg == IW_ENCODE_ALG_WEP) {
3113 struct iw_point wep_erq;
3114 char *wep_keybuf;
3116 /* Build request structure */
3117 wep_erq.flags = erq->flags; // take over flags with key index
3118 wep_erq.length = ext->key_len; // take length from extended key info
3119 wep_keybuf = ext->key; // pointer to the key text
3121 /* Call wireless_set_encode tot handle the WEP key */
3122 ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3123 goto out;
3126 /* Proceed for extended encode functions for WAP and NONE */
3127 wl_lock( lp, &flags );
3129 wl_act_int_off( lp );
3131 memset(&ltv, 0, sizeof(ltv));
3132 ret = hermes_set_key(&ltv, ext->alg, key_idx, ext->addr.sa_data,
3133 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3134 ext->rx_seq, ext->key, ext->key_len);
3136 if (ret != 0) {
3137 DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3138 goto out_unlock;
3141 /* Put the key in HCF */
3142 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3144 out_unlock:
3145 if(ret == HCF_SUCCESS) {
3146 DBG_TRACE( DbgInfo, "Put key info succes\n");
3147 } else {
3148 DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3151 wl_act_int_on( lp );
3153 wl_unlock(lp, &flags);
3155 out:
3156 DBG_LEAVE( DbgInfo );
3157 return ret;
3158 } // wireless_set_encodeext
3159 /*============================================================================*/
3163 static int wireless_get_genie(struct net_device *dev,
3164 struct iw_request_info *info,
3165 struct iw_point *data, char *extra)
3168 struct wl_private *lp = wl_priv(dev);
3169 unsigned long flags;
3170 int ret = 0;
3171 ltv_t ltv;
3173 DBG_FUNC( "wireless_get_genie" );
3174 DBG_ENTER( DbgInfo );
3176 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3177 ret = -EBUSY;
3178 goto out;
3181 wl_lock( lp, &flags );
3183 wl_act_int_off( lp );
3185 memset(&ltv, 0, sizeof(ltv));
3186 ltv.len = 2;
3187 ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3188 lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3189 ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3191 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3193 wl_act_int_on( lp );
3195 wl_unlock(lp, &flags);
3197 out:
3198 DBG_LEAVE( DbgInfo );
3199 return ret;
3201 /*============================================================================*/
3204 /*******************************************************************************
3205 * wl_wireless_stats()
3206 *******************************************************************************
3208 * DESCRIPTION:
3210 * Return the current device wireless statistics.
3212 * PARAMETERS:
3214 * wrq - the wireless request buffer
3215 * lp - the device's private adapter structure
3217 * RETURNS:
3219 * 0 on success
3220 * errno value otherwise
3222 ******************************************************************************/
3223 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3225 struct iw_statistics *pStats;
3226 struct wl_private *lp = wl_priv(dev);
3227 /*------------------------------------------------------------------------*/
3230 DBG_FUNC( "wl_wireless_stats" );
3231 DBG_ENTER(DbgInfo);
3232 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3234 pStats = NULL;
3236 /* Initialize the statistics */
3237 pStats = &( lp->wstats );
3238 pStats->qual.updated = 0x00;
3240 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3242 CFG_COMMS_QUALITY_STRCT *pQual;
3243 CFG_HERMES_TALLIES_STRCT tallies;
3244 int status;
3246 /* Update driver status */
3247 pStats->status = 0;
3249 /* Get the current link quality information */
3250 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3251 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3252 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3254 if( status == HCF_SUCCESS ) {
3255 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3257 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3258 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3259 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3261 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3262 IW_QUAL_LEVEL_UPDATED |
3263 IW_QUAL_NOISE_UPDATED |
3264 IW_QUAL_DBM);
3265 } else {
3266 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3269 /* Get the current tallies from the adapter */
3270 /* Only possible when the device is open */
3271 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3272 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3273 /* No endian translation is needed here, as CFG_TALLIES is an
3274 MSF RID; all processing is done on the host, not the card! */
3275 pStats->discard.nwid = 0L;
3276 pStats->discard.code = tallies.RxWEPUndecryptable;
3277 pStats->discard.misc = tallies.TxDiscards +
3278 tallies.RxFCSErrors +
3279 //tallies.RxDiscardsNoBuffer +
3280 tallies.TxDiscardsWrongSA;
3281 //;? Extra taken over from Linux driver based on 7.18 version
3282 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3283 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3284 } else {
3285 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3287 } else {
3288 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3292 DBG_LEAVE( DbgInfo );
3293 return pStats;
3294 } // wl_wireless_stats
3295 /*============================================================================*/
3300 /*******************************************************************************
3301 * wl_get_wireless_stats()
3302 *******************************************************************************
3304 * DESCRIPTION:
3306 * Return the current device wireless statistics. This function calls
3307 * wl_wireless_stats, but acquires spinlocks first as it can be called
3308 * directly by the network layer.
3310 * PARAMETERS:
3312 * wrq - the wireless request buffer
3313 * lp - the device's private adapter structure
3315 * RETURNS:
3317 * 0 on success
3318 * errno value otherwise
3320 ******************************************************************************/
3321 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3323 unsigned long flags;
3324 struct wl_private *lp = wl_priv(dev);
3325 struct iw_statistics *pStats = NULL;
3326 /*------------------------------------------------------------------------*/
3328 DBG_FUNC( "wl_get_wireless_stats" );
3329 DBG_ENTER(DbgInfo);
3331 wl_lock( lp, &flags );
3333 wl_act_int_off( lp );
3335 #ifdef USE_RTS
3336 if( lp->useRTS == 1 ) {
3337 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3338 } else
3339 #endif
3341 pStats = wl_wireless_stats( dev );
3343 wl_act_int_on( lp );
3345 wl_unlock(lp, &flags);
3347 DBG_LEAVE( DbgInfo );
3348 return pStats;
3349 } // wl_get_wireless_stats
3352 /*******************************************************************************
3353 * wl_spy_gather()
3354 *******************************************************************************
3356 * DESCRIPTION:
3358 * Gather wireless spy statistics.
3360 * PARAMETERS:
3362 * wrq - the wireless request buffer
3363 * lp - the device's private adapter structure
3365 * RETURNS:
3367 * 0 on success
3368 * errno value otherwise
3370 ******************************************************************************/
3371 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3373 struct iw_quality wstats;
3374 int status;
3375 u_char stats[2];
3376 DESC_STRCT desc[1];
3377 struct wl_private *lp = wl_priv(dev);
3378 /*------------------------------------------------------------------------*/
3380 /* shortcut */
3381 if (!lp->spy_data.spy_number) {
3382 return;
3385 /* Gather wireless spy statistics: for each packet, compare the source
3386 address with out list, and if match, get the stats. */
3387 memset( stats, 0, sizeof(stats));
3388 memset( desc, 0, sizeof(DESC_STRCT));
3390 desc[0].buf_addr = stats;
3391 desc[0].BUF_SIZE = sizeof(stats);
3392 desc[0].next_desc_addr = 0; // terminate list
3394 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3396 if( status == HCF_SUCCESS ) {
3397 wstats.level = (u_char) dbm(stats[1]);
3398 wstats.noise = (u_char) dbm(stats[0]);
3399 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3401 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3402 IW_QUAL_LEVEL_UPDATED |
3403 IW_QUAL_NOISE_UPDATED |
3404 IW_QUAL_DBM);
3406 wireless_spy_update( dev, mac, &wstats );
3408 } // wl_spy_gather
3409 /*============================================================================*/
3414 /*******************************************************************************
3415 * wl_wext_event_freq()
3416 *******************************************************************************
3418 * DESCRIPTION:
3420 * This function is used to send an event that the channel/freq
3421 * configuration for a specific device has changed.
3424 * PARAMETERS:
3426 * dev - the network device for which this event is to be issued
3428 * RETURNS:
3430 * N/A
3432 ******************************************************************************/
3433 void wl_wext_event_freq( struct net_device *dev )
3435 union iwreq_data wrqu;
3436 struct wl_private *lp = wl_priv(dev);
3437 /*------------------------------------------------------------------------*/
3440 memset( &wrqu, 0, sizeof( wrqu ));
3442 wrqu.freq.m = lp->Channel;
3443 wrqu.freq.e = 0;
3445 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3447 return;
3448 } // wl_wext_event_freq
3449 /*============================================================================*/
3454 /*******************************************************************************
3455 * wl_wext_event_mode()
3456 *******************************************************************************
3458 * DESCRIPTION:
3460 * This function is used to send an event that the mode of operation
3461 * for a specific device has changed.
3464 * PARAMETERS:
3466 * dev - the network device for which this event is to be issued
3468 * RETURNS:
3470 * N/A
3472 ******************************************************************************/
3473 void wl_wext_event_mode( struct net_device *dev )
3475 union iwreq_data wrqu;
3476 struct wl_private *lp = wl_priv(dev);
3477 /*------------------------------------------------------------------------*/
3480 memset( &wrqu, 0, sizeof( wrqu ));
3482 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3483 wrqu.mode = IW_MODE_INFRA;
3484 } else {
3485 wrqu.mode = IW_MODE_MASTER;
3488 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3490 return;
3491 } // wl_wext_event_mode
3492 /*============================================================================*/
3497 /*******************************************************************************
3498 * wl_wext_event_essid()
3499 *******************************************************************************
3501 * DESCRIPTION:
3503 * This function is used to send an event that the ESSID configuration for
3504 * a specific device has changed.
3507 * PARAMETERS:
3509 * dev - the network device for which this event is to be issued
3511 * RETURNS:
3513 * N/A
3515 ******************************************************************************/
3516 void wl_wext_event_essid( struct net_device *dev )
3518 union iwreq_data wrqu;
3519 struct wl_private *lp = wl_priv(dev);
3520 /*------------------------------------------------------------------------*/
3523 memset( &wrqu, 0, sizeof( wrqu ));
3525 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3526 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3527 the call to wireless_send_event() must also point to where the ESSID
3528 lives */
3529 wrqu.essid.length = strlen( lp->NetworkName );
3530 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3531 wrqu.essid.flags = 1;
3533 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3535 return;
3536 } // wl_wext_event_essid
3537 /*============================================================================*/
3542 /*******************************************************************************
3543 * wl_wext_event_encode()
3544 *******************************************************************************
3546 * DESCRIPTION:
3548 * This function is used to send an event that the encryption configuration
3549 * for a specific device has changed.
3552 * PARAMETERS:
3554 * dev - the network device for which this event is to be issued
3556 * RETURNS:
3558 * N/A
3560 ******************************************************************************/
3561 void wl_wext_event_encode( struct net_device *dev )
3563 union iwreq_data wrqu;
3564 struct wl_private *lp = wl_priv(dev);
3565 int index = 0;
3566 /*------------------------------------------------------------------------*/
3569 memset( &wrqu, 0, sizeof( wrqu ));
3571 if( lp->EnableEncryption == 0 ) {
3572 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3573 } else {
3574 wrqu.encoding.flags |= lp->TransmitKeyID;
3576 index = lp->TransmitKeyID - 1;
3578 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3579 if we're in AP mode */
3580 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3581 //;?should we restore this to allow smaller memory footprint
3583 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3584 if( lp->ExcludeUnencrypted ) {
3585 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3586 } else {
3587 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3591 #endif // HCF_TYPE_AP
3593 /* Only provide the key if permissions allow */
3594 if( capable( CAP_NET_ADMIN )) {
3595 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3596 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3597 } else {
3598 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3602 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3603 lp->DefaultKeys.key[index].key );
3605 return;
3606 } // wl_wext_event_encode
3607 /*============================================================================*/
3612 /*******************************************************************************
3613 * wl_wext_event_ap()
3614 *******************************************************************************
3616 * DESCRIPTION:
3618 * This function is used to send an event that the device has been
3619 * associated to a new AP.
3622 * PARAMETERS:
3624 * dev - the network device for which this event is to be issued
3626 * RETURNS:
3628 * N/A
3630 ******************************************************************************/
3631 void wl_wext_event_ap( struct net_device *dev )
3633 union iwreq_data wrqu;
3634 struct wl_private *lp = wl_priv(dev);
3635 int status;
3636 /*------------------------------------------------------------------------*/
3639 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3640 this event BEFORE sending the association event, as there are timing
3641 issues with the hostap supplicant. The supplicant will attempt to process
3642 an EAPOL-Key frame from an AP before receiving this information, which
3643 is required properly process the said frame. */
3644 wl_wext_event_assoc_ie( dev );
3646 /* Get the BSSID */
3647 lp->ltvRecord.typ = CFG_CUR_BSSID;
3648 lp->ltvRecord.len = 4;
3650 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3651 if( status == HCF_SUCCESS ) {
3652 memset( &wrqu, 0, sizeof( wrqu ));
3654 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3656 wrqu.addr.sa_family = ARPHRD_ETHER;
3658 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3661 return;
3662 } // wl_wext_event_ap
3663 /*============================================================================*/
3667 /*******************************************************************************
3668 * wl_wext_event_scan_complete()
3669 *******************************************************************************
3671 * DESCRIPTION:
3673 * This function is used to send an event that a request for a network scan
3674 * has completed.
3677 * PARAMETERS:
3679 * dev - the network device for which this event is to be issued
3681 * RETURNS:
3683 * N/A
3685 ******************************************************************************/
3686 void wl_wext_event_scan_complete( struct net_device *dev )
3688 union iwreq_data wrqu;
3689 /*------------------------------------------------------------------------*/
3692 memset( &wrqu, 0, sizeof( wrqu ));
3694 wrqu.addr.sa_family = ARPHRD_ETHER;
3695 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3697 return;
3698 } // wl_wext_event_scan_complete
3699 /*============================================================================*/
3704 /*******************************************************************************
3705 * wl_wext_event_new_sta()
3706 *******************************************************************************
3708 * DESCRIPTION:
3710 * This function is used to send an event that an AP has registered a new
3711 * station.
3714 * PARAMETERS:
3716 * dev - the network device for which this event is to be issued
3718 * RETURNS:
3720 * N/A
3722 ******************************************************************************/
3723 void wl_wext_event_new_sta( struct net_device *dev )
3725 union iwreq_data wrqu;
3726 /*------------------------------------------------------------------------*/
3729 memset( &wrqu, 0, sizeof( wrqu ));
3731 /* Send the station's mac address here */
3732 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3733 wrqu.addr.sa_family = ARPHRD_ETHER;
3734 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3736 return;
3737 } // wl_wext_event_new_sta
3738 /*============================================================================*/
3743 /*******************************************************************************
3744 * wl_wext_event_expired_sta()
3745 *******************************************************************************
3747 * DESCRIPTION:
3749 * This function is used to send an event that an AP has deregistered a
3750 * station.
3753 * PARAMETERS:
3755 * dev - the network device for which this event is to be issued
3757 * RETURNS:
3759 * N/A
3761 ******************************************************************************/
3762 void wl_wext_event_expired_sta( struct net_device *dev )
3764 union iwreq_data wrqu;
3765 /*------------------------------------------------------------------------*/
3768 memset( &wrqu, 0, sizeof( wrqu ));
3770 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3771 wrqu.addr.sa_family = ARPHRD_ETHER;
3772 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3774 return;
3775 } // wl_wext_event_expired_sta
3776 /*============================================================================*/
3781 /*******************************************************************************
3782 * wl_wext_event_mic_failed()
3783 *******************************************************************************
3785 * DESCRIPTION:
3787 * This function is used to send an event that MIC calculations failed.
3790 * PARAMETERS:
3792 * dev - the network device for which this event is to be issued
3794 * RETURNS:
3796 * N/A
3798 ******************************************************************************/
3799 void wl_wext_event_mic_failed( struct net_device *dev )
3801 union iwreq_data wrqu;
3802 struct wl_private *lp = wl_priv(dev);
3803 struct iw_michaelmicfailure wxmic;
3804 int key_idx;
3805 char *addr1;
3806 char *addr2;
3807 WVLAN_RX_WMP_HDR *hdr;
3808 /*------------------------------------------------------------------------*/
3811 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3812 key_idx &= 0x03;
3814 /* Cast the lookahead buffer into a RFS format */
3815 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3817 /* Cast the addresses to byte buffers, as in the above RFS they are word
3818 length */
3819 addr1 = (char *)hdr->address1;
3820 addr2 = (char *)hdr->address2;
3822 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3823 hdr->status );
3825 memset(&wrqu, 0, sizeof(wrqu));
3826 memset(&wxmic, 0, sizeof(wxmic));
3828 wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3829 wxmic.flags |= (addr1[0] & 1) ?
3830 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
3831 wxmic.src_addr.sa_family = ARPHRD_ETHER;
3832 memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3834 wrqu.data.length = sizeof(wxmic);
3835 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3837 return;
3838 } // wl_wext_event_mic_failed
3839 /*============================================================================*/
3844 /*******************************************************************************
3845 * wl_wext_event_assoc_ie()
3846 *******************************************************************************
3848 * DESCRIPTION:
3850 * This function is used to send an event containing the WPA-IE generated
3851 * by the firmware in an association request.
3854 * PARAMETERS:
3856 * dev - the network device for which this event is to be issued
3858 * RETURNS:
3860 * N/A
3862 ******************************************************************************/
3863 void wl_wext_event_assoc_ie( struct net_device *dev )
3865 union iwreq_data wrqu;
3866 struct wl_private *lp = wl_priv(dev);
3867 int status;
3868 PROBE_RESP data;
3869 hcf_16 length;
3870 hcf_8 *wpa_ie;
3871 /*------------------------------------------------------------------------*/
3874 memset( &wrqu, 0, sizeof( wrqu ));
3876 /* Retrieve the Association Request IE */
3877 lp->ltvRecord.len = 45;
3878 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3880 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3881 if( status == HCF_SUCCESS )
3883 length = 0;
3884 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3885 wpa_ie = wl_parse_wpa_ie( &data, &length );
3887 if( length != 0 )
3889 wrqu.data.length = wpa_ie[1] + 2;
3890 wireless_send_event(dev, IWEVASSOCREQIE,
3891 &wrqu, wpa_ie);
3893 /* This bit is a hack. We send the respie
3894 * event at the same time */
3895 wireless_send_event(dev, IWEVASSOCRESPIE,
3896 &wrqu, wpa_ie);
3900 return;
3901 } // wl_wext_event_assoc_ie
3902 /*============================================================================*/
3903 /* Structures to export the Wireless Handlers */
3905 static const iw_handler wl_handler[] =
3907 (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */
3908 (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */
3909 (iw_handler) NULL, /* SIOCSIWNWID */
3910 (iw_handler) NULL, /* SIOCGIWNWID */
3911 (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */
3912 (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */
3913 (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */
3914 (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */
3915 (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */
3916 (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */
3917 (iw_handler) NULL , /* SIOCSIWRANGE */
3918 (iw_handler) wireless_get_range, /* SIOCGIWRANGE */
3919 (iw_handler) NULL , /* SIOCSIWPRIV */
3920 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
3921 (iw_handler) NULL , /* SIOCSIWSTATS */
3922 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
3923 iw_handler_set_spy, /* SIOCSIWSPY */
3924 iw_handler_get_spy, /* SIOCGIWSPY */
3925 NULL, /* SIOCSIWTHRSPY */
3926 NULL, /* SIOCGIWTHRSPY */
3927 (iw_handler) NULL, /* SIOCSIWAP */
3928 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3929 (iw_handler) wireless_get_bssid, /* SIOCGIWAP */
3930 #else
3931 (iw_handler) NULL, /* SIOCGIWAP */
3932 #endif
3933 (iw_handler) NULL, /* SIOCSIWMLME */
3934 (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */
3935 (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */
3936 (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */
3937 (iw_handler) wireless_set_essid, /* SIOCSIWESSID */
3938 (iw_handler) wireless_get_essid, /* SIOCGIWESSID */
3939 (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */
3940 (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */
3941 (iw_handler) NULL, /* -- hole -- */
3942 (iw_handler) NULL, /* -- hole -- */
3943 (iw_handler) wireless_set_rate, /* SIOCSIWRATE */
3944 (iw_handler) wireless_get_rate, /* SIOCGIWRATE */
3945 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
3946 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
3947 (iw_handler) NULL, /* SIOCSIWFRAG */
3948 (iw_handler) NULL, /* SIOCGIWFRAG */
3949 (iw_handler) NULL, /* SIOCSIWTXPOW */
3950 (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */
3951 (iw_handler) NULL, /* SIOCSIWRETRY */
3952 (iw_handler) NULL, /* SIOCGIWRETRY */
3953 (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */
3954 (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */
3955 (iw_handler) wireless_set_power, /* SIOCSIWPOWER */
3956 (iw_handler) wireless_get_power, /* SIOCGIWPOWER */
3957 (iw_handler) NULL, /* -- hole -- */
3958 (iw_handler) NULL, /* -- hole -- */
3959 (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */
3960 (iw_handler) NULL, /* SIOCGIWGENIE */
3961 (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */
3962 (iw_handler) NULL, /* SIOCGIWAUTH */
3963 (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */
3964 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
3965 (iw_handler) NULL, /* SIOCSIWPMKSA */
3966 (iw_handler) NULL, /* -- hole -- */
3969 static const iw_handler wl_private_handler[] =
3970 { /* SIOCIWFIRSTPRIV + */
3971 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3972 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3973 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3974 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3975 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3976 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3977 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3978 #endif
3981 struct iw_priv_args wl_priv_args[] = {
3982 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3983 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3984 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3985 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3986 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3987 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3988 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3989 #endif
3992 const struct iw_handler_def wl_iw_handler_def =
3994 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3995 .private = (iw_handler *) wl_private_handler,
3996 .private_args = (struct iw_priv_args *) wl_priv_args,
3997 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3998 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3999 .standard = (iw_handler *) wl_handler,
4000 .get_wireless_stats = wl_get_wireless_stats,