1 /*******************************************************************************
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
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
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.
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
55 ******************************************************************************/
57 /*******************************************************************************
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>
72 #include <wl_internal.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 /*******************************************************************************
89 ******************************************************************************/
91 extern dbg_info_t
*DbgInfo
;
97 /*******************************************************************************
99 *******************************************************************************
108 * wrq - the wireless request buffer
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
);
122 /*------------------------------------------------------------------------*/
124 DBG_FUNC( "wireless_commit" );
127 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
132 wl_lock( lp
, &flags
);
134 wl_act_int_off( lp
);
140 wl_unlock(lp
, &flags
);
143 DBG_LEAVE( DbgInfo
);
146 /*============================================================================*/
151 /*******************************************************************************
152 * wireless_get_protocol()
153 *******************************************************************************
157 * Returns a vendor-defined string that should identify the wireless
162 * wrq - the wireless request buffer
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");
182 } // wireless_get_protocol
183 /*============================================================================*/
188 /*******************************************************************************
189 * wireless_set_frequency()
190 *******************************************************************************
194 * Sets the frequency (channel) on which the card should Tx/Rx.
198 * wrq - the wireless request buffer
199 * lp - the device's private adapter structure
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
);
213 /*------------------------------------------------------------------------*/
216 DBG_FUNC( "wireless_set_frequency" );
217 DBG_ENTER( DbgInfo
);
219 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
224 if( !capable( CAP_NET_ADMIN
)) {
226 DBG_LEAVE( DbgInfo
);
231 /* If frequency specified, look up channel */
233 int f
= freq
->m
/ 100000;
234 channel
= wl_get_chan_from_freq( f
);
238 /* Channel specified */
244 /* If the channel is an 802.11a channel, set Bit 8 */
246 channel
= channel
| 0x100;
250 wl_lock( lp
, &flags
);
252 wl_act_int_off( lp
);
254 lp
->Channel
= channel
;
257 /* Commit the adapter parameters */
260 /* Send an event that channel/freq has been set */
261 wl_wext_event_freq( lp
->dev
);
265 wl_unlock(lp
, &flags
);
268 DBG_LEAVE( DbgInfo
);
270 } // wireless_set_frequency
271 /*============================================================================*/
276 /*******************************************************************************
277 * wireless_get_frequency()
278 *******************************************************************************
282 * Gets the frequency (channel) on which the card is Tx/Rx.
286 * wrq - the wireless request buffer
287 * lp - the device's private adapter structure
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
);
300 /*------------------------------------------------------------------------*/
303 DBG_FUNC( "wireless_get_frequency" );
304 DBG_ENTER( DbgInfo
);
306 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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;
328 wl_unlock(lp
, &flags
);
330 ret
= (ret
== HCF_SUCCESS
? 0 : -EFAULT
);
333 DBG_LEAVE( DbgInfo
);
335 } // wireless_get_frequency
336 /*============================================================================*/
341 /*******************************************************************************
342 * wireless_get_range()
343 *******************************************************************************
347 * This function is used to provide misc info and statistics about the
352 * wrq - the wireless request buffer
353 * lp - the device's private adapter structure
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
);
365 struct iw_range
*range
= (struct iw_range
*) extra
;
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
));
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
);
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
);
413 /* Holding the lock too long, make a gap to allow other processes */
414 wl_unlock(lp
, &flags
);
415 wl_lock( lp
, &flags
);
420 DBG_TRACE( DbgInfo
, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries
);
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
;
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
;
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
++;
474 DBG_TRACE( DbgInfo
, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status
);
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
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
;
500 range
->encoding_size
[1] = MAX_KEY_SIZE
;
501 range
->num_encoding_sizes
= 2;
502 range
->max_encoding_tokens
= MAX_KEYS
;
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
;
541 wl_unlock(lp
, &flags
);
545 } // wireless_get_range
546 /*============================================================================*/
549 /*******************************************************************************
550 * wireless_get_bssid()
551 *******************************************************************************
555 * Gets the BSSID the wireless device is currently associated with.
559 * wrq - the wireless request buffer
560 * lp - the device's private adapter structure
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
);
573 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
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
) {
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
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
);
618 #endif // (HCF_TYPE) & HCF_TYPE_STA
622 wl_unlock(lp
, &flags
);
627 } // wireless_get_bssid
628 /*============================================================================*/
633 /*******************************************************************************
634 * wireless_get_ap_list()
635 *******************************************************************************
639 * Gets the results of a network scan.
643 * wrq - the wireless request buffer
644 * lp - the device's private adapter structure
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
);
664 struct sockaddr
*hwa
= NULL
;
665 struct iw_quality
*qual
= NULL
;
667 ScanResult
*p
= &lp
->scan_results
;
669 ProbeResult
*p
= &lp
->probe_results
;
671 /*------------------------------------------------------------------------*/
673 DBG_FUNC( "wireless_get_ap_list" );
674 DBG_ENTER( DbgInfo
);
676 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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 */
705 ret
= hcf_action( &( lp
->hcfCtx
), MDD_ACT_SCAN
);
707 ret
= hcf_action( &( lp
->hcfCtx
), HCF_ACT_ACS_SCAN
);
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
) {
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
++ ) {
735 if ( ret
!= HCF_SUCCESS
) {
736 DBG_ERROR( DbgInfo
, "timeout waiting for scan results\n" );
738 num_aps
= (*p
)/*lp->probe_results*/.num_aps
;
739 if (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 */
754 for( count
= 0; count
< num_aps
; count
++ ) {
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
);
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
770 wl_wext_event_scan_complete( lp
->dev
);
774 DBG_LEAVE( DbgInfo
);
776 } // wireless_get_ap_list
777 /*============================================================================*/
782 /*******************************************************************************
783 * wireless_set_sensitivity()
784 *******************************************************************************
788 * Sets the sensitivity (distance between APs) of the wireless card.
792 * wrq - the wireless request buffer
793 * lp - the device's private adapter structure
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
);
806 int dens
= sens
->value
;
807 /*------------------------------------------------------------------------*/
810 DBG_FUNC( "wireless_set_sensitivity" );
811 DBG_ENTER( DbgInfo
);
813 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
818 if(( dens
< 1 ) || ( dens
> 3 )) {
823 wl_lock( lp
, &flags
);
825 wl_act_int_off( lp
);
827 lp
->DistanceBetweenAPs
= dens
;
832 wl_unlock(lp
, &flags
);
835 DBG_LEAVE( DbgInfo
);
837 } // wireless_set_sensitivity
838 /*============================================================================*/
843 /*******************************************************************************
844 * wireless_get_sensitivity()
845 *******************************************************************************
849 * Gets the sensitivity (distance between APs) of the wireless card.
853 * wrq - the wireless request buffer
854 * lp - the device's private adapter structure
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
);
866 /*------------------------------------------------------------------------*/
867 /*------------------------------------------------------------------------*/
870 DBG_FUNC( "wireless_get_sensitivity" );
871 DBG_ENTER( DbgInfo
);
873 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
878 /* not worth locking ... */
879 sens
->value
= lp
->DistanceBetweenAPs
;
880 sens
->fixed
= 0; /* auto */
882 DBG_LEAVE( DbgInfo
);
884 } // wireless_get_sensitivity
885 /*============================================================================*/
890 /*******************************************************************************
891 * wireless_set_essid()
892 *******************************************************************************
896 * Sets the ESSID (network name) that the wireless device should associate
901 * wrq - the wireless request buffer
902 * lp - the device's private adapter structure
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
);
916 DBG_FUNC( "wireless_set_essid" );
917 DBG_ENTER( DbgInfo
);
919 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
924 if (data
->flags
!= 0 && data
->length
> HCF_MAX_NAME_LEN
+ 1) {
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" );
942 //strcpy( lp->NetworkName, "ANY" );
943 strcpy( lp
->NetworkName
, PARM_DEFAULT_SSID
);
946 memcpy( lp
->NetworkName
, ssid
, data
->length
);
949 DBG_NOTICE( DbgInfo
, "set NetworkName: %s\n", ssid
);
951 /* Commit the adapter parameters */
954 /* Send an event that ESSID has been set */
955 wl_wext_event_essid( lp
->dev
);
959 wl_unlock(lp
, &flags
);
962 DBG_LEAVE( DbgInfo
);
964 } // wireless_set_essid
965 /*============================================================================*/
970 /*******************************************************************************
971 * wireless_get_essid()
972 *******************************************************************************
976 * Gets the ESSID (network name) that the wireless device is associated
981 * wrq - the wireless request buffer
982 * lp - the device's private adapter structure
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
);
998 /*------------------------------------------------------------------------*/
1001 DBG_FUNC( "wireless_get_essid" );
1002 DBG_ENTER( DbgInfo
);
1004 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
;
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
;
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';
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
;
1080 if (pName
->length
> IW_ESSID_MAX_SIZE
) {
1085 memcpy(essid
, pName
->name
, pName
->length
);
1092 wl_act_int_on( lp
);
1094 wl_unlock(lp
, &flags
);
1097 DBG_LEAVE( DbgInfo
);
1099 } // wireless_get_essid
1100 /*============================================================================*/
1105 /*******************************************************************************
1106 * wireless_set_encode()
1107 *******************************************************************************
1111 * Sets the encryption keys and status (enable or disable).
1115 * wrq - the wireless request buffer
1116 * lp - the device's private adapter structure
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
;
1129 hcf_8 encryption_state
;
1130 /*------------------------------------------------------------------------*/
1133 DBG_FUNC( "wireless_set_encode" );
1134 DBG_ENTER( DbgInfo
);
1136 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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" );
1152 DBG_NOTICE( DbgInfo
, "pointer: %p, length: %d, flags: %#x\n",
1153 keybuf
, erq
->length
,
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
) {
1173 /* Check the index */
1174 if(( index
< 0 ) || ( index
>= MAX_KEYS
)) {
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;
1199 DBG_WARNING( DbgInfo
, "Invalid Key length\n" );
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;
1216 DBG_WARNING( DbgInfo
, "Problem setting the current TxKey\n" );
1217 DBG_LEAVE( DbgInfo
);
1223 /* Read the flags */
1224 if( erq
->flags
& IW_ENCODE_DISABLED
) {
1225 lp
->EnableEncryption
= 0; // disable encryption
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",
1239 DBG_TRACE( DbgInfo
, "erq->flags : 0x%x\n",
1242 /* Write the changes to the card */
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
);
1253 /* To switch encryption on/off, soft reset is required */
1258 /* Send an event that Encryption has been set */
1259 wl_wext_event_encode( dev
);
1263 wl_act_int_on( lp
);
1265 wl_unlock(lp
, &flags
);
1268 DBG_LEAVE( DbgInfo
);
1270 } // wireless_set_encode
1271 /*============================================================================*/
1276 /*******************************************************************************
1277 * wireless_get_encode()
1278 *******************************************************************************
1282 * Gets the encryption keys and status.
1286 * wrq - the wireless request buffer
1287 * lp - the device's private adapter structure
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
;
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
) {
1314 /* Only super-user can see WEP key */
1315 if( !capable( CAP_NET_ADMIN
)) {
1317 DBG_LEAVE( DbgInfo
);
1321 wl_lock( lp
, &flags
);
1323 wl_act_int_off( lp
);
1325 /* Is it supported? */
1326 if( !wl_has_wep( &( lp
->hcfCtx
))) {
1331 /* Basic checking */
1332 index
= (erq
->flags
& IW_ENCODE_INDEX
) - 1;
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
);
1356 wl_act_int_on( lp
);
1358 wl_unlock(lp
, &flags
);
1361 DBG_LEAVE( DbgInfo
);
1363 } // wireless_get_encode
1364 /*============================================================================*/
1369 /*******************************************************************************
1370 * wireless_set_nickname()
1371 *******************************************************************************
1375 * Sets the nickname, or station name, of the wireless device.
1379 * wrq - the wireless request buffer
1380 * lp - the device's private adapter structure
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
;
1393 /*------------------------------------------------------------------------*/
1396 DBG_FUNC( "wireless_set_nickname" );
1397 DBG_ENTER( DbgInfo
);
1399 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
)) {
1407 DBG_LEAVE( DbgInfo
);
1412 /* Validate the new value */
1413 if(data
->length
> HCF_MAX_NAME_LEN
) {
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 */
1429 wl_act_int_on( lp
);
1431 wl_unlock(lp
, &flags
);
1434 DBG_LEAVE( DbgInfo
);
1436 } // wireless_set_nickname
1437 /*============================================================================*/
1442 /*******************************************************************************
1443 * wireless_get_nickname()
1444 *******************************************************************************
1448 * Gets the nickname, or station name, of the wireless device.
1452 * wrq - the wireless request buffer
1453 * lp - the device's private adapter structure
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
;
1468 /*------------------------------------------------------------------------*/
1471 DBG_FUNC( "wireless_get_nickname" );
1472 DBG_ENTER( DbgInfo
);
1474 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
) {
1498 /* Copy the information into the user buffer */
1499 data
->length
= pName
->length
;
1500 memcpy(nickname
, pName
->name
, pName
->length
);
1506 wl_act_int_on( lp
);
1508 wl_unlock(lp
, &flags
);
1513 } // wireless_get_nickname
1514 /*============================================================================*/
1519 /*******************************************************************************
1520 * wireless_set_porttype()
1521 *******************************************************************************
1525 * Sets the port type of the wireless device.
1529 * wrq - the wireless request buffer
1530 * lp - the device's private adapter structure
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
;
1545 /*------------------------------------------------------------------------*/
1547 DBG_FUNC( "wireless_set_porttype" );
1548 DBG_ENTER( DbgInfo
);
1550 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
1555 wl_lock( lp
, &flags
);
1557 wl_act_int_off( lp
);
1559 /* Validate the new value */
1563 /* When user requests ad-hoc, set IBSS mode! */
1567 lp
->DownloadFirmware
= WVLAN_DRV_MODE_STA
; //1;
1575 /* Both automatic and infrastructure set port to BSS/STA mode */
1579 lp
->DownloadFirmware
= WVLAN_DRV_MODE_STA
; //1;
1584 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1586 case IW_MODE_MASTER
:
1588 /* Set BSS/AP mode */
1592 lp
->DownloadFirmware
= WVLAN_DRV_MODE_AP
; //2;
1596 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
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 */
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
);
1625 DBG_LEAVE( DbgInfo
);
1627 } // wireless_set_porttype
1628 /*============================================================================*/
1633 /*******************************************************************************
1634 * wireless_get_porttype()
1635 *******************************************************************************
1639 * Gets the port type of the wireless device.
1643 * wrq - the wireless request buffer
1644 * lp - the device's private adapter structure
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
;
1660 /*------------------------------------------------------------------------*/
1663 DBG_FUNC( "wireless_get_porttype" );
1664 DBG_ENTER( DbgInfo
);
1666 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
) {
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
;
1695 *mode
= IW_MODE_INFRA
;
1700 *mode
= IW_MODE_INFRA
;
1702 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1705 if ( CNV_INT_TO_LITTLE( lp
->hcfCtx
.IFB_FWIdentity
.comp_id
) == COMP_ID_FW_AP
) {
1706 *mode
= IW_MODE_MASTER
;
1708 if( lp
->CreateIBSS
) {
1709 *mode
= IW_MODE_ADHOC
;
1711 *mode
= IW_MODE_INFRA
;
1719 *mode
= IW_MODE_ADHOC
;
1730 wl_act_int_on( lp
);
1732 wl_unlock(lp
, &flags
);
1735 DBG_LEAVE( DbgInfo
);
1737 } // wireless_get_porttype
1738 /*============================================================================*/
1743 /*******************************************************************************
1744 * wireless_set_power()
1745 *******************************************************************************
1749 * Sets the power management settings of the wireless device.
1753 * wrq - the wireless request buffer
1754 * lp - the device's private adapter structure
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
;
1767 /*------------------------------------------------------------------------*/
1770 DBG_FUNC( "wireless_set_power" );
1771 DBG_ENTER( DbgInfo
);
1773 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
)) {
1784 DBG_LEAVE( DbgInfo
);
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
) {
1800 /* Commit the adapter parameters */
1803 wl_act_int_on( lp
);
1805 wl_unlock(lp
, &flags
);
1808 DBG_LEAVE( DbgInfo
);
1810 } // wireless_set_power
1811 /*============================================================================*/
1816 /*******************************************************************************
1817 * wireless_get_power()
1818 *******************************************************************************
1822 * Gets the power management settings of the wireless device.
1826 * wrq - the wireless request buffer
1827 * lp - the device's private adapter structure
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
;
1841 /*------------------------------------------------------------------------*/
1842 DBG_FUNC( "wireless_get_power" );
1843 DBG_ENTER( DbgInfo
);
1845 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
1850 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1852 wl_lock( lp
, &flags
);
1854 wl_act_int_off( lp
);
1859 if( lp
->PMEnabled
) {
1865 wl_act_int_on( lp
);
1867 wl_unlock(lp
, &flags
);
1870 DBG_LEAVE( DbgInfo
);
1872 } // wireless_get_power
1873 /*============================================================================*/
1878 /*******************************************************************************
1879 * wireless_get_tx_power()
1880 *******************************************************************************
1884 * Gets the transmit power of the wireless device's radio.
1888 * wrq - the wireless request buffer
1889 * lp - the device's private adapter structure
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
;
1902 /*------------------------------------------------------------------------*/
1903 DBG_FUNC( "wireless_get_tx_power" );
1904 DBG_ENTER( DbgInfo
);
1906 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
;
1919 rrq
->value
= RADIO_TX_POWER_MWATT
;
1920 rrq
->flags
= IW_TXPOW_MWATT
;
1925 wl_act_int_on( lp
);
1927 wl_unlock(lp
, &flags
);
1930 DBG_LEAVE( DbgInfo
);
1932 } // wireless_get_tx_power
1933 /*============================================================================*/
1938 /*******************************************************************************
1939 * wireless_set_rts_threshold()
1940 *******************************************************************************
1944 * Sets the RTS threshold for the wireless card.
1948 * wrq - the wireless request buffer
1949 * lp - the device's private adapter structure
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
)
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
) {
1974 if(rts
->fixed
== 0) {
1979 if( rts
->disabled
) {
1983 if(( rthr
< 256 ) || ( rthr
> 2347 )) {
1988 wl_lock( lp
, &flags
);
1990 wl_act_int_off( lp
);
1992 lp
->RTSThreshold
= rthr
;
1996 wl_act_int_on( lp
);
1998 wl_unlock(lp
, &flags
);
2001 DBG_LEAVE( DbgInfo
);
2003 } // wireless_set_rts_threshold
2004 /*============================================================================*/
2009 /*******************************************************************************
2010 * wireless_get_rts_threshold()
2011 *******************************************************************************
2015 * Gets the RTS threshold for the wireless card.
2019 * wrq - the wireless request buffer
2020 * lp - the device's private adapter structure
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
)
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
) {
2043 wl_lock( lp
, &flags
);
2045 wl_act_int_off( lp
);
2047 rts
->value
= lp
->RTSThreshold
;
2049 rts
->disabled
= ( rts
->value
== 2347 );
2053 wl_act_int_on( lp
);
2055 wl_unlock(lp
, &flags
);
2058 DBG_LEAVE( DbgInfo
);
2060 } // wireless_get_rts_threshold
2061 /*============================================================================*/
2067 /*******************************************************************************
2068 * wireless_set_rate()
2069 *******************************************************************************
2073 * Set the default data rate setting used by the wireless device.
2077 * wrq - the wireless request buffer
2078 * lp - the device's private adapter structure
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
;
2095 /*------------------------------------------------------------------------*/
2098 DBG_FUNC( "wireless_set_rate" );
2099 DBG_ENTER( DbgInfo
);
2101 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
2106 wl_lock( lp
, &flags
);
2108 wl_act_int_off( lp
);
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
);
2124 DBG_ERROR( DbgInfo
, "Could not determine radio frequency\n" );
2125 DBG_LEAVE( DbgInfo
);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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
;
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
) {
2242 lp
->TxRateControl
[0] = 2;
2244 lp
->TxRateControl
[0] = 6;
2247 else if( rrq
->value
> 2 * MEGABIT
&&
2248 rrq
->value
<= 5 * MEGABIT
) {
2250 lp
->TxRateControl
[0] = 4;
2252 lp
->TxRateControl
[0] = 7;
2255 else if( rrq
->value
> 5 * MEGABIT
&&
2256 rrq
->value
<= 11 * MEGABIT
) {
2258 lp
->TxRateControl
[0] = 5;
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;
2276 /* Commit the adapter parameters */
2281 wl_act_int_on( lp
);
2283 wl_unlock(lp
, &flags
);
2286 DBG_LEAVE( DbgInfo
);
2288 } // wireless_set_rate
2289 /*============================================================================*/
2294 /*******************************************************************************
2295 * wireless_get_rate()
2296 *******************************************************************************
2300 * Get the default data rate setting used by the wireless device.
2304 * wrq - the wireless request buffer
2305 * lp - the device's private adapter structure
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
;
2321 /*------------------------------------------------------------------------*/
2324 DBG_FUNC( "wireless_get_rate" );
2325 DBG_ENTER( DbgInfo
);
2327 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
) {
2345 txRate
= CNV_LITTLE_TO_INT( lp
->ltvRecord
.u
.u16
[0] );
2347 if( txRate
& 0x0001 ) {
2350 else if( txRate
& 0x0002 ) {
2353 else if( txRate
& 0x0004 ) {
2356 else if( txRate
& 0x0008 ) {
2359 else if( txRate
& 0x00010 ) {
2362 else if( txRate
& 0x00020 ) {
2365 else if( txRate
& 0x00040 ) {
2368 else if( txRate
& 0x00080 ) {
2371 else if( txRate
& 0x00100 ) {
2374 else if( txRate
& 0x00200 ) {
2377 else if( txRate
& 0x00400 ) {
2380 else if( txRate
& 0x00800 ) {
2386 txRate
= (hcf_16
)CNV_LITTLE_TO_LONG( lp
->ltvRecord
.u
.u32
[0] );
2390 rrq
->value
= txRate
* MEGABIT
;
2396 wl_act_int_on( lp
);
2398 wl_unlock(lp
, &flags
);
2401 DBG_LEAVE( DbgInfo
);
2403 } // wireless_get_rate
2404 /*============================================================================*/
2409 #if 0 //;? Not used anymore
2410 /*******************************************************************************
2411 * wireless_get_private_interface()
2412 *******************************************************************************
2416 * Returns the Linux Wireless Extensions' compatible private interface of
2421 * wrq - the wireless request buffer
2422 * lp - the device's private adapter structure
2427 * errno value otherwise
2429 ******************************************************************************/
2430 int wireless_get_private_interface( struct iwreq
*wrq
, struct wl_private
*lp
)
2433 /*------------------------------------------------------------------------*/
2436 DBG_FUNC( "wireless_get_private_interface" );
2437 DBG_ENTER( DbgInfo
);
2439 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
));
2459 DBG_LEAVE( DbgInfo
);
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
));
2469 DBG_LEAVE( DbgInfo
);
2471 } // wireless_get_private_interface
2472 /*============================================================================*/
2477 /*******************************************************************************
2478 * wireless_set_scan()
2479 *******************************************************************************
2483 * Instructs the driver to initiate a network scan.
2487 * wrq - the wireless request buffer
2488 * lp - the device's private adapter structure
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
;
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
) {
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" );
2533 /* Set the completion state to FALSE */
2534 lp
->probe_results
.scan_complete
= FALSE
;
2537 /* Channels to scan */
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 ); // ..
2546 lp
->ltvRecord
.len
= 2;
2547 lp
->ltvRecord
.typ
= CFG_SCAN_CHANNEL
;
2548 lp
->ltvRecord
.u
.u16
[0] = CNV_INT_TO_LITTLE( 0x7FFF );
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
) {
2563 DBG_TRACE( DbgInfo
, "Reset card to recover, attempt: %d\n", retries
);
2566 // Holding the lock too long, make a gap to allow other processes
2567 wl_unlock(lp
, &flags
);
2568 wl_lock( lp
, &flags
);
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" );
2597 DBG_TRACE( DbgInfo
, "INITIATE SCAN FAILED...\n" );
2600 wl_act_int_on( lp
);
2602 wl_unlock(lp
, &flags
);
2607 } // wireless_set_scan
2608 /*============================================================================*/
2613 /*******************************************************************************
2614 * wireless_get_scan()
2615 *******************************************************************************
2619 * Instructs the driver to gather and return the results of a network scan.
2623 * wrq - the wireless request buffer
2624 * lp - the device's private adapter structure
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
;
2640 struct iw_event iwe
;
2641 PROBE_RESP
*probe_resp
;
2645 /*------------------------------------------------------------------------*/
2648 DBG_FUNC( "wireless_get_scan" );
2649 DBG_ENTER( DbgInfo
);
2651 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
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
) {
2666 DBG_TRACE( DbgInfo
, "SCAN COMPLETE, Num of APs: %d\n",
2667 lp
->probe_results
.num_aps
);
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
;
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
));
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
;
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
);
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) */
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
;
2792 wl_act_int_on( lp
);
2794 wl_unlock(lp
, &flags
);
2797 DBG_LEAVE( DbgInfo
);
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
;
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
) {
2822 wl_lock( lp
, &flags
);
2824 wl_act_int_off( lp
);
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
)
2836 case IW_AUTH_WPA_ENABLED
:
2837 DBG_TRACE( DbgInfo
, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val
);
2839 lp
->EnableEncryption
= 2;
2841 lp
->EnableEncryption
= 0;
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
);
2851 hcf_cntl(&(lp
->hcfCtx
), HCF_CNTL_DISABLE
| HCF_PORT_0
);
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
2862 case IW_AUTH_CIPHER_PAIRWISE
:
2863 DBG_TRACE( DbgInfo
, "IW_AUTH_CIPHER_PAIRWISE\n");
2864 /* not implemented, return an error */
2868 case IW_AUTH_CIPHER_GROUP
:
2869 DBG_TRACE( DbgInfo
, "IW_AUTH_CIPHER_GROUP\n");
2870 /* not implemented, return an error */
2874 case IW_AUTH_KEY_MGMT
:
2875 DBG_TRACE( DbgInfo
, "IW_AUTH_KEY_MGMT\n");
2876 /* not implemented, return an error */
2880 case IW_AUTH_80211_AUTH_ALG
:
2881 DBG_TRACE( DbgInfo
, "IW_AUTH_80211_AUTH_ALG\n");
2882 /* not implemented, return an error */
2886 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
2887 DBG_TRACE( DbgInfo
, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2888 /* not implemented, return an error */
2892 case IW_AUTH_ROAMING_CONTROL
:
2893 DBG_TRACE( DbgInfo
, "IW_AUTH_ROAMING_CONTROL\n");
2894 /* not implemented, return an error */
2898 case IW_AUTH_PRIVACY_INVOKED
:
2899 DBG_TRACE( DbgInfo
, "IW_AUTH_PRIVACY_INVOKED\n");
2900 /* not implemented, return an error */
2905 DBG_TRACE( DbgInfo
, "IW_AUTH_?? (%d) unknown\n", iwa_idx
);
2906 /* return an error */
2911 wl_act_int_on( lp
);
2913 wl_unlock(lp
, &flags
);
2916 DBG_LEAVE( DbgInfo
);
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
)
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.
2943 case IW_ENCODE_ALG_TKIP
:
2944 DBG_TRACE( DbgInfo
, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx
);
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
++ )
2958 ltv
.typ
= 0xFD91; // This RID not defined in HCF yet!!!
2961 wl_get_info( sock
, <v
, ifname
);
2963 if( ltv
.u
.u16
[0] == 0 )
2971 wpa_printf( MSG_DEBUG
, "Timed out waiting for TxQ!" );
2978 ltv
->typ
= CFG_ADD_TKIP_MAPPED_KEY
;
2980 /* Load the BSSID */
2981 memcpy(<v
->u
.u8
[buf_idx
], addr
, ETH_ALEN
);
2982 buf_idx
+= ETH_ALEN
;
2984 /* Load the TKIP key */
2985 memcpy(<v
->u
.u8
[buf_idx
], &key
[0], 16);
2989 memcpy(<v
->u
.u8
[buf_idx
], tsc
, IW_ENCODE_SEQ_MAX_SIZE
);
2990 buf_idx
+= IW_ENCODE_SEQ_MAX_SIZE
;
2993 memcpy(<v
->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(<v
->u
.u8
[buf_idx
], &key
[16], 8);
3000 /* Load the RxMIC key */
3001 memcpy(<v
->u
.u8
[buf_idx
], &key
[24], 8);
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 */
3015 ltv
->u
.u16
[buf_idx
] |= 0x8000;
3019 memcpy(<v
->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(<v
->u
.u8
[buf_idx
], key
, key_len
);
3028 memcpy(<v
->u
.u8
[buf_idx
], tsc
, IW_ENCODE_SEQ_MAX_SIZE
);
3030 ltv
->u
.u16
[0] = CNV_INT_TO_LITTLE(ltv
->u
.u16
[0]);
3040 case IW_ENCODE_ALG_WEP
:
3041 DBG_TRACE( DbgInfo
, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx
);
3044 case IW_ENCODE_ALG_CCMP
:
3045 DBG_TRACE( DbgInfo
, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx
);
3048 case IW_ENCODE_ALG_NONE
:
3049 DBG_TRACE( DbgInfo
, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx
);
3052 if (memcmp(addr
, "\xff\xff\xff\xff\xff\xff", ETH_ALEN
) != 0) {
3053 //if (addr != NULL) {
3055 ltv
->typ
= CFG_REMOVE_TKIP_MAPPED_KEY
;
3056 memcpy(<v
->u
.u8
[0], addr
, ETH_ALEN
);
3063 /* Clear the Group TKIP keys by index */
3065 ltv
->typ
= CFG_REMOVE_TKIP_DEFAULT_KEY
;
3066 ltv
->u
.u16
[0] = key_idx
;
3075 DBG_TRACE( DbgInfo
, "IW_ENCODE_??: key(%d)\n", key_idx
);
3079 DBG_LEAVE( DbgInfo
);
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
;
3093 int key_idx
= (erq
->flags
&IW_ENCODE_INDEX
) - 1;
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
) {
3105 if (sizeof(ext
->rx_seq
) != 8) {
3106 DBG_TRACE(DbgInfo
, "rz_seq size mismatch\n");
3111 /* Handle WEP keys via the old set encode procedure */
3112 if(ext
->alg
== IW_ENCODE_ALG_WEP
) {
3113 struct iw_point wep_erq
;
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
);
3126 /* Proceed for extended encode functions for WAP and NONE */
3127 wl_lock( lp
, &flags
);
3129 wl_act_int_off( lp
);
3131 memset(<v
, 0, sizeof(ltv
));
3132 ret
= hermes_set_key(<v
, 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
);
3137 DBG_TRACE( DbgInfo
, "hermes_set_key returned != 0, key not set\n");
3141 /* Put the key in HCF */
3142 ret
= hcf_put_info(&(lp
->hcfCtx
), (LTVP
)<v
);
3145 if(ret
== HCF_SUCCESS
) {
3146 DBG_TRACE( DbgInfo
, "Put key info succes\n");
3148 DBG_TRACE( DbgInfo
, "Put key info failed, key not set\n");
3151 wl_act_int_on( lp
);
3153 wl_unlock(lp
, &flags
);
3156 DBG_LEAVE( DbgInfo
);
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
;
3173 DBG_FUNC( "wireless_get_genie" );
3174 DBG_ENTER( DbgInfo
);
3176 if(lp
->portState
== WVLAN_PORT_STATE_DISABLED
) {
3181 wl_lock( lp
, &flags
);
3183 wl_act_int_off( lp
);
3185 memset(<v
, 0, sizeof(ltv
));
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
)<v
);
3193 wl_act_int_on( lp
);
3195 wl_unlock(lp
, &flags
);
3198 DBG_LEAVE( DbgInfo
);
3201 /*============================================================================*/
3204 /*******************************************************************************
3205 * wl_wireless_stats()
3206 *******************************************************************************
3210 * Return the current device wireless statistics.
3214 * wrq - the wireless request buffer
3215 * lp - the device's private adapter structure
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" );
3232 DBG_PARAM(DbgInfo
, "dev", "%s (0x%p)", dev
->name
, dev
);
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
;
3246 /* Update driver status */
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
|
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
;
3285 memset( &( pStats
->discard
), 0, sizeof( pStats
->discard
));
3288 memset( &( pStats
->discard
), 0, sizeof( pStats
->discard
));
3292 DBG_LEAVE( DbgInfo
);
3294 } // wl_wireless_stats
3295 /*============================================================================*/
3300 /*******************************************************************************
3301 * wl_get_wireless_stats()
3302 *******************************************************************************
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.
3312 * wrq - the wireless request buffer
3313 * lp - the device's private adapter structure
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" );
3331 wl_lock( lp
, &flags
);
3333 wl_act_int_off( lp
);
3336 if( lp
->useRTS
== 1 ) {
3337 DBG_TRACE( DbgInfo
, "Skipping wireless stats, in RTS mode\n" );
3341 pStats
= wl_wireless_stats( dev
);
3343 wl_act_int_on( lp
);
3345 wl_unlock(lp
, &flags
);
3347 DBG_LEAVE( DbgInfo
);
3349 } // wl_get_wireless_stats
3352 /*******************************************************************************
3354 *******************************************************************************
3358 * Gather wireless spy statistics.
3362 * wrq - the wireless request buffer
3363 * lp - the device's private adapter structure
3368 * errno value otherwise
3370 ******************************************************************************/
3371 inline void wl_spy_gather( struct net_device
*dev
, u_char
*mac
)
3373 struct iw_quality wstats
;
3377 struct wl_private
*lp
= wl_priv(dev
);
3378 /*------------------------------------------------------------------------*/
3381 if (!lp
->spy_data
.spy_number
) {
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
|
3406 wireless_spy_update( dev
, mac
, &wstats
);
3409 /*============================================================================*/
3414 /*******************************************************************************
3415 * wl_wext_event_freq()
3416 *******************************************************************************
3420 * This function is used to send an event that the channel/freq
3421 * configuration for a specific device has changed.
3426 * dev - the network device for which this event is to be issued
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
;
3445 wireless_send_event( dev
, SIOCSIWFREQ
, &wrqu
, NULL
);
3448 } // wl_wext_event_freq
3449 /*============================================================================*/
3454 /*******************************************************************************
3455 * wl_wext_event_mode()
3456 *******************************************************************************
3460 * This function is used to send an event that the mode of operation
3461 * for a specific device has changed.
3466 * dev - the network device for which this event is to be issued
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
;
3485 wrqu
.mode
= IW_MODE_MASTER
;
3488 wireless_send_event( dev
, SIOCSIWMODE
, &wrqu
, NULL
);
3491 } // wl_wext_event_mode
3492 /*============================================================================*/
3497 /*******************************************************************************
3498 * wl_wext_event_essid()
3499 *******************************************************************************
3503 * This function is used to send an event that the ESSID configuration for
3504 * a specific device has changed.
3509 * dev - the network device for which this event is to be issued
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
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
);
3536 } // wl_wext_event_essid
3537 /*============================================================================*/
3542 /*******************************************************************************
3543 * wl_wext_event_encode()
3544 *******************************************************************************
3548 * This function is used to send an event that the encryption configuration
3549 * for a specific device has changed.
3554 * dev - the network device for which this event is to be issued
3560 ******************************************************************************/
3561 void wl_wext_event_encode( struct net_device
*dev
)
3563 union iwreq_data wrqu
;
3564 struct wl_private
*lp
= wl_priv(dev
);
3566 /*------------------------------------------------------------------------*/
3569 memset( &wrqu
, 0, sizeof( wrqu
));
3571 if( lp
->EnableEncryption
== 0 ) {
3572 wrqu
.encoding
.flags
= IW_ENCODE_DISABLED
;
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
;
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
;
3598 wrqu
.encoding
.flags
|= IW_ENCODE_NOKEY
;
3602 wireless_send_event( dev
, SIOCSIWENCODE
, &wrqu
,
3603 lp
->DefaultKeys
.key
[index
].key
);
3606 } // wl_wext_event_encode
3607 /*============================================================================*/
3612 /*******************************************************************************
3613 * wl_wext_event_ap()
3614 *******************************************************************************
3618 * This function is used to send an event that the device has been
3619 * associated to a new AP.
3624 * dev - the network device for which this event is to be issued
3630 ******************************************************************************/
3631 void wl_wext_event_ap( struct net_device
*dev
)
3633 union iwreq_data wrqu
;
3634 struct wl_private
*lp
= wl_priv(dev
);
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
);
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
);
3662 } // wl_wext_event_ap
3663 /*============================================================================*/
3667 /*******************************************************************************
3668 * wl_wext_event_scan_complete()
3669 *******************************************************************************
3673 * This function is used to send an event that a request for a network scan
3679 * dev - the network device for which this event is to be issued
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
);
3698 } // wl_wext_event_scan_complete
3699 /*============================================================================*/
3704 /*******************************************************************************
3705 * wl_wext_event_new_sta()
3706 *******************************************************************************
3710 * This function is used to send an event that an AP has registered a new
3716 * dev - the network device for which this event is to be issued
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
);
3737 } // wl_wext_event_new_sta
3738 /*============================================================================*/
3743 /*******************************************************************************
3744 * wl_wext_event_expired_sta()
3745 *******************************************************************************
3749 * This function is used to send an event that an AP has deregistered a
3755 * dev - the network device for which this event is to be issued
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
);
3775 } // wl_wext_event_expired_sta
3776 /*============================================================================*/
3781 /*******************************************************************************
3782 * wl_wext_event_mic_failed()
3783 *******************************************************************************
3787 * This function is used to send an event that MIC calculations failed.
3792 * dev - the network device for which this event is to be issued
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
;
3807 WVLAN_RX_WMP_HDR
*hdr
;
3808 /*------------------------------------------------------------------------*/
3811 key_idx
= lp
->lookAheadBuf
[HFS_STAT
+1] >> 3;
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
3819 addr1
= (char *)hdr
->address1
;
3820 addr2
= (char *)hdr
->address2
;
3822 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx
,
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
);
3838 } // wl_wext_event_mic_failed
3839 /*============================================================================*/
3844 /*******************************************************************************
3845 * wl_wext_event_assoc_ie()
3846 *******************************************************************************
3850 * This function is used to send an event containing the WPA-IE generated
3851 * by the firmware in an association request.
3856 * dev - the network device for which this event is to be issued
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
);
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
)
3884 memcpy( &data
.rawData
, &( lp
->ltvRecord
.u
.u8
[1] ), 88 );
3885 wpa_ie
= wl_parse_wpa_ie( &data
, &length
);
3889 wrqu
.data
.length
= wpa_ie
[1] + 2;
3890 wireless_send_event(dev
, IWEVASSOCREQIE
,
3893 /* This bit is a hack. We send the respie
3894 * event at the same time */
3895 wireless_send_event(dev
, IWEVASSOCRESPIE
,
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 */
3931 (iw_handler
) NULL
, /* SIOCGIWAP */
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 */
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" },
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
,