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
\93AS IS
\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
43 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
45 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
46 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
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 /* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS
81 #including linux/wireless.h), then these functions do not need to be included
85 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
86 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
87 iwe_stream_add_event(buf, end, iwe, len)
88 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
89 iwe_stream_add_point(buf, end, iwe, msg)
91 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
92 iwe_stream_add_event(info, buf, end, iwe, len)
93 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
94 iwe_stream_add_point(info, buf, end, iwe, msg)
99 /*******************************************************************************
101 ******************************************************************************/
103 extern dbg_info_t *DbgInfo;
109 /*******************************************************************************
111 *******************************************************************************
120 * wrq - the wireless request buffer
126 ******************************************************************************/
127 static int wireless_commit(struct net_device *dev,
128 struct iw_request_info *info,
129 union iwreq_data *rqu, char *extra)
131 struct wl_private *lp = wl_priv(dev);
134 /*------------------------------------------------------------------------*/
136 DBG_FUNC( "wireless_commit" );
139 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
144 wl_lock( lp, &flags );
146 wl_act_int_off( lp );
152 wl_unlock(lp, &flags);
155 DBG_LEAVE( DbgInfo );
158 /*============================================================================*/
163 /*******************************************************************************
164 * wireless_get_protocol()
165 *******************************************************************************
169 * Returns a vendor-defined string that should identify the wireless
174 * wrq - the wireless request buffer
180 ******************************************************************************/
181 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
183 DBG_FUNC( "wireless_get_protocol" );
184 DBG_ENTER( DbgInfo );
186 /* Originally, the driver was placing the string "Wireless" here. However,
187 the wireless extensions (/linux/wireless.h) indicate this string should
188 describe the wireless protocol. */
190 strcpy(name, "IEEE 802.11b");
194 } // wireless_get_protocol
195 /*============================================================================*/
200 /*******************************************************************************
201 * wireless_set_frequency()
202 *******************************************************************************
206 * Sets the frequency (channel) on which the card should Tx/Rx.
210 * wrq - the wireless request buffer
211 * lp - the device's private adapter structure
216 * errno value otherwise
218 ******************************************************************************/
219 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
221 struct wl_private *lp = wl_priv(dev);
225 /*------------------------------------------------------------------------*/
228 DBG_FUNC( "wireless_set_frequency" );
229 DBG_ENTER( DbgInfo );
231 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
236 if( !capable( CAP_NET_ADMIN )) {
238 DBG_LEAVE( DbgInfo );
243 /* If frequency specified, look up channel */
245 int f = freq->m / 100000;
246 channel = wl_get_chan_from_freq( f );
250 /* Channel specified */
256 /* If the channel is an 802.11a channel, set Bit 8 */
258 channel = channel | 0x100;
262 wl_lock( lp, &flags );
264 wl_act_int_off( lp );
266 lp->Channel = channel;
269 /* Commit the adapter parameters */
272 /* Send an event that channel/freq has been set */
273 wl_wext_event_freq( lp->dev );
277 wl_unlock(lp, &flags);
280 DBG_LEAVE( DbgInfo );
282 } // wireless_set_frequency
283 /*============================================================================*/
288 /*******************************************************************************
289 * wireless_get_frequency()
290 *******************************************************************************
294 * Gets the frequency (channel) on which the card is Tx/Rx.
298 * wrq - the wireless request buffer
299 * lp - the device's private adapter structure
305 ******************************************************************************/
306 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
309 struct wl_private *lp = wl_priv(dev);
312 /*------------------------------------------------------------------------*/
315 DBG_FUNC( "wireless_get_frequency" );
316 DBG_ENTER( DbgInfo );
318 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
323 wl_lock( lp, &flags );
325 wl_act_int_off( lp );
327 lp->ltvRecord.len = 2;
328 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
330 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
331 if( ret == HCF_SUCCESS ) {
332 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
336 freq->m = wl_get_freq_from_chan( channel ) * 100000;
343 #endif /* USE_FREQUENCY */
348 wl_unlock(lp, &flags);
350 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
353 DBG_LEAVE( DbgInfo );
355 } // wireless_get_frequency
356 /*============================================================================*/
361 /*******************************************************************************
362 * wireless_get_range()
363 *******************************************************************************
367 * This function is used to provide misc info and statistics about the
372 * wrq - the wireless request buffer
373 * lp - the device's private adapter structure
378 * errno value otherwise
380 ******************************************************************************/
381 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
383 struct wl_private *lp = wl_priv(dev);
385 struct iw_range *range = (struct iw_range *) extra;
391 /*------------------------------------------------------------------------*/
394 DBG_FUNC( "wireless_get_range" );
395 DBG_ENTER( DbgInfo );
397 /* Set range information */
398 data->length = sizeof(struct iw_range);
399 memset(range, 0, sizeof(struct iw_range));
401 wl_lock( lp, &flags );
403 wl_act_int_off( lp );
405 /* Set range information */
406 memset( range, 0, sizeof( struct iw_range ));
409 /* Get the current transmit rate from the adapter */
410 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
411 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
413 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
414 if( status != HCF_SUCCESS ) {
415 /* Recovery action: reset and retry up to 10 times */
416 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
421 /* Holding the lock too long, make a gap to allow other processes */
422 wl_unlock(lp, &flags);
423 wl_lock( lp, &flags );
425 status = wl_reset( dev );
426 if ( status != HCF_SUCCESS ) {
427 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
433 /* Holding the lock too long, make a gap to allow other processes */
434 wl_unlock(lp, &flags);
435 wl_lock( lp, &flags );
440 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
446 /* Holding the lock too long, make a gap to allow other processes */
447 wl_unlock(lp, &flags);
448 wl_lock( lp, &flags );
450 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
452 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
455 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
458 // NWID - NOT SUPPORTED
461 /* Channel/Frequency Info */
462 range->num_channels = RADIO_CHANNELS;
465 /* Signal Level Thresholds */
466 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
472 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
474 /* If the value returned in /proc/net/wireless is greater than the maximum range,
475 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
476 it requires a bit of contorsion... */
478 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
479 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
482 range->max_qual.qual = 100;
483 range->max_qual.level = 100;
484 range->max_qual.noise = 100;
489 /* Set available rates */
490 range->num_bitrates = 0;
492 lp->ltvRecord.len = 6;
493 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
495 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
496 if( status == HCF_SUCCESS ) {
497 for( count = 0; count < MAX_RATES; count++ )
498 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
499 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
500 range->num_bitrates++;
503 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
508 /* RTS Threshold info */
509 range->min_rts = MIN_RTS_BYTES;
510 range->max_rts = MAX_RTS_BYTES;
512 // Frag Threshold info - NOT SUPPORTED
514 // Power Management info - NOT SUPPORTED
520 /* Holding the lock too long, make a gap to allow other processes */
521 wl_unlock(lp, &flags);
522 wl_lock( lp, &flags );
524 /* Is WEP supported? */
526 if( wl_has_wep( &( lp->hcfCtx ))) {
527 /* WEP: RC4 40 bits */
528 range->encoding_size[0] = MIN_KEY_SIZE;
531 range->encoding_size[1] = MAX_KEY_SIZE;
532 range->num_encoding_sizes = 2;
533 range->max_encoding_tokens = MAX_KEYS;
536 #endif /* WIRELESS_EXT > 8 */
539 range->txpower_capa = IW_TXPOW_MWATT;
540 range->num_txpower = 1;
541 range->txpower[0] = RADIO_TX_POWER_MWATT;
543 #if WIRELESS_EXT > 10
545 /* Wireless Extension Info */
546 range->we_version_compiled = WIRELESS_EXT;
547 range->we_version_source = WIRELESS_SUPPORT;
549 // Retry Limits and Lifetime - NOT SUPPORTED
554 #if WIRELESS_EXT > 11
556 /* Holding the lock too long, make a gap to allow other processes */
557 wl_unlock(lp, &flags);
558 wl_lock( lp, &flags );
560 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
561 wl_wireless_stats( lp->dev );
562 range->avg_qual = lp->wstats.qual;
563 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
567 /* Event capability (kernel + driver) */
568 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
569 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
570 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
571 range->event_capa[1] = IW_EVENT_CAPA_K_1;
572 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
573 IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
574 IW_EVENT_CAPA_MASK(IWEVEXPIRED));
576 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
581 wl_unlock(lp, &flags);
585 } // wireless_get_range
586 /*============================================================================*/
589 /*******************************************************************************
590 * wireless_get_bssid()
591 *******************************************************************************
595 * Gets the BSSID the wireless device is currently associated with.
599 * wrq - the wireless request buffer
600 * lp - the device's private adapter structure
605 * errno value otherwise
607 ******************************************************************************/
608 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
610 struct wl_private *lp = wl_priv(dev);
613 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
615 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
616 /*------------------------------------------------------------------------*/
619 DBG_FUNC( "wireless_get_bssid" );
620 DBG_ENTER( DbgInfo );
622 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
627 wl_lock( lp, &flags );
629 wl_act_int_off( lp );
631 memset( &ap_addr->sa_data, 0, ETH_ALEN );
633 ap_addr->sa_family = ARPHRD_ETHER;
635 /* Assume AP mode here, which means the BSSID is our own MAC address. In
636 STA mode, this address will be overwritten with the actual BSSID using
638 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
641 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
642 //;?should we return an error status in AP mode
644 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
645 /* Get Current BSSID */
646 lp->ltvRecord.typ = CFG_CUR_BSSID;
647 lp->ltvRecord.len = 4;
648 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
650 if( status == HCF_SUCCESS ) {
651 /* Copy info into sockaddr struct */
652 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
658 #endif // (HCF_TYPE) & HCF_TYPE_STA
662 wl_unlock(lp, &flags);
667 } // wireless_get_bssid
668 /*============================================================================*/
673 /*******************************************************************************
674 * wireless_get_ap_list()
675 *******************************************************************************
679 * Gets the results of a network scan.
683 * wrq - the wireless request buffer
684 * lp - the device's private adapter structure
689 * errno value otherwise
691 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
692 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
693 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
695 ******************************************************************************/
696 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
698 struct wl_private *lp = wl_priv(dev);
704 struct sockaddr *hwa = NULL;
705 struct iw_quality *qual = NULL;
707 ScanResult *p = &lp->scan_results;
709 ProbeResult *p = &lp->probe_results;
711 /*------------------------------------------------------------------------*/
713 DBG_FUNC( "wireless_get_ap_list" );
714 DBG_ENTER( DbgInfo );
716 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
721 wl_lock( lp, &flags );
723 wl_act_int_off( lp );
725 /* Set the completion state to FALSE */
726 lp->scan_results.scan_complete = FALSE;
727 lp->probe_results.scan_complete = FALSE;
728 /* Channels to scan */
729 lp->ltvRecord.len = 2;
730 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
731 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
732 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
733 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
735 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
736 disassociate from the network we are currently on */
737 lp->ltvRecord.len = 2;
738 lp->ltvRecord.typ = CFG_SCAN_SSID;
739 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
740 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
741 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
743 /* Initiate the scan */
745 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
747 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
752 //;? unlock? what about the access to lp below? is it broken?
753 wl_unlock(lp, &flags);
755 if( ret == HCF_SUCCESS ) {
756 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
757 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
758 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
759 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
760 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
763 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
764 other things in the meantime, This prevents system lockups by
765 giving some time back to the kernel */
766 for( count = 0; count < 100; count ++ ) {
775 if ( ret != HCF_SUCCESS ) {
776 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
778 num_aps = (*p)/*lp->probe_results*/.num_aps;
779 if (num_aps > IW_MAX_AP) {
782 data->length = num_aps;
783 hwa = (struct sockaddr *)extra;
784 qual = (struct iw_quality *) extra +
785 ( sizeof( struct sockaddr ) * num_aps );
787 /* This flag is used to tell the user if we provide quality
788 information. Since we provide signal/noise levels but no
789 quality info on a scan, this is set to 0. Setting to 1 and
790 providing a quality of 0 produces weird results. If we ever
791 provide quality (or can calculate it), this can be changed */
794 for( count = 0; count < num_aps; count++ ) {
796 memcpy( hwa[count].sa_data,
797 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
798 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
799 DBG_PRINT( "BSSID: %s\n", DbgHwAddr( (*p)/*lp->probe_results*/.ProbeTable[count].BSSID ));
800 memcpy( hwa[count].sa_data,
801 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
804 /* Once the data is copied to the wireless struct, invalidate the
805 scan result to initiate a rescan on the next request */
806 (*p)/*lp->probe_results*/.scan_complete = FALSE;
807 /* Send the wireless event that the scan has completed, just in case
809 wl_wext_event_scan_complete( lp->dev );
813 DBG_LEAVE( DbgInfo );
815 } // wireless_get_ap_list
816 /*============================================================================*/
821 /*******************************************************************************
822 * wireless_set_sensitivity()
823 *******************************************************************************
827 * Sets the sensitivity (distance between APs) of the wireless card.
831 * wrq - the wireless request buffer
832 * lp - the device's private adapter structure
837 * errno value otherwise
839 ******************************************************************************/
840 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
842 struct wl_private *lp = wl_priv(dev);
845 int dens = sens->value;
846 /*------------------------------------------------------------------------*/
849 DBG_FUNC( "wireless_set_sensitivity" );
850 DBG_ENTER( DbgInfo );
852 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
857 if(( dens < 1 ) || ( dens > 3 )) {
862 wl_lock( lp, &flags );
864 wl_act_int_off( lp );
866 lp->DistanceBetweenAPs = dens;
871 wl_unlock(lp, &flags);
874 DBG_LEAVE( DbgInfo );
876 } // wireless_set_sensitivity
877 /*============================================================================*/
882 /*******************************************************************************
883 * wireless_get_sensitivity()
884 *******************************************************************************
888 * Gets the sensitivity (distance between APs) of the wireless card.
892 * wrq - the wireless request buffer
893 * lp - the device's private adapter structure
898 * errno value otherwise
900 ******************************************************************************/
901 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
903 struct wl_private *lp = wl_priv(dev);
905 /*------------------------------------------------------------------------*/
906 /*------------------------------------------------------------------------*/
909 DBG_FUNC( "wireless_get_sensitivity" );
910 DBG_ENTER( DbgInfo );
912 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
917 /* not worth locking ... */
918 sens->value = lp->DistanceBetweenAPs;
919 sens->fixed = 0; /* auto */
921 DBG_LEAVE( DbgInfo );
923 } // wireless_get_sensitivity
924 /*============================================================================*/
929 /*******************************************************************************
930 * wireless_set_essid()
931 *******************************************************************************
935 * Sets the ESSID (network name) that the wireless device should associate
940 * wrq - the wireless request buffer
941 * lp - the device's private adapter structure
946 * errno value otherwise
948 ******************************************************************************/
949 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
951 struct wl_private *lp = wl_priv(dev);
955 DBG_FUNC( "wireless_set_essid" );
956 DBG_ENTER( DbgInfo );
958 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
963 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
968 wl_lock( lp, &flags );
970 wl_act_int_off( lp );
972 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
974 /* data->flags is zero to ask for "any" */
975 if( data->flags == 0 ) {
976 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
977 * ;?but there ain't no STAP anymore*/
978 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
979 strcpy( lp->NetworkName, "ANY" );
981 //strcpy( lp->NetworkName, "ANY" );
982 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
985 memcpy( lp->NetworkName, ssid, data->length );
988 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
990 /* Commit the adapter parameters */
993 /* Send an event that ESSID has been set */
994 wl_wext_event_essid( lp->dev );
998 wl_unlock(lp, &flags);
1001 DBG_LEAVE( DbgInfo );
1003 } // wireless_set_essid
1004 /*============================================================================*/
1009 /*******************************************************************************
1010 * wireless_get_essid()
1011 *******************************************************************************
1015 * Gets the ESSID (network name) that the wireless device is associated
1020 * wrq - the wireless request buffer
1021 * lp - the device's private adapter structure
1026 * errno value otherwise
1028 ******************************************************************************/
1029 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1032 struct wl_private *lp = wl_priv(dev);
1033 unsigned long flags;
1037 /*------------------------------------------------------------------------*/
1040 DBG_FUNC( "wireless_get_essid" );
1041 DBG_ENTER( DbgInfo );
1043 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1048 wl_lock( lp, &flags );
1050 wl_act_int_off( lp );
1052 /* Get the desired network name */
1053 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1056 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1057 //;?should we return an error status in AP mode
1059 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1064 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1065 //;?should we restore this to allow smaller memory footprint
1067 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1068 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1074 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1075 if( status == HCF_SUCCESS ) {
1076 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1078 /* Endian translate the string length */
1079 pName->length = CNV_LITTLE_TO_INT( pName->length );
1081 /* Copy the information into the user buffer */
1082 data->length = pName->length;
1084 /* NOTE: Null terminating is necessary for proper display of the SSID in
1085 the wireless tools */
1086 data->length = pName->length + 1;
1087 if( pName->length < HCF_MAX_NAME_LEN ) {
1088 pName->name[pName->length] = '\0';
1094 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1095 //;?should we return an error status in AP mode
1096 #ifdef RETURN_CURRENT_NETWORKNAME
1098 /* if desired is null ("any"), return current or "any" */
1099 if( pName->name[0] == '\0' ) {
1100 /* Get the current network name */
1101 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1102 lp->ltvRecord.typ = CFG_CUR_SSID;
1104 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1106 if( status == HCF_SUCCESS ) {
1107 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1109 /* Endian translate the string length */
1110 pName->length = CNV_LITTLE_TO_INT( pName->length );
1112 /* Copy the information into the user buffer */
1113 data->length = pName->length + 1;
1114 if( pName->length < HCF_MAX_NAME_LEN ) {
1115 pName->name[pName->length] = '\0';
1125 #endif // RETURN_CURRENT_NETWORKNAME
1130 if (pName->length > IW_ESSID_MAX_SIZE) {
1135 memcpy(essid, pName->name, pName->length);
1142 wl_act_int_on( lp );
1144 wl_unlock(lp, &flags);
1147 DBG_LEAVE( DbgInfo );
1149 } // wireless_get_essid
1150 /*============================================================================*/
1155 /*******************************************************************************
1156 * wireless_set_encode()
1157 *******************************************************************************
1161 * Sets the encryption keys and status (enable or disable).
1165 * wrq - the wireless request buffer
1166 * lp - the device's private adapter structure
1171 * errno value otherwise
1173 ******************************************************************************/
1174 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1176 struct wl_private *lp = wl_priv(dev);
1177 unsigned long flags;
1180 #if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
1181 hcf_8 encryption_state;
1182 #endif // WIRELESS_EXT > 8
1183 /*------------------------------------------------------------------------*/
1186 DBG_FUNC( "wireless_set_encode" );
1187 DBG_ENTER( DbgInfo );
1189 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1194 wl_lock( lp, &flags );
1196 wl_act_int_off( lp );
1198 /* Is encryption supported? */
1199 if( !wl_has_wep( &( lp->hcfCtx ))) {
1200 DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1205 DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1206 keybuf, erq->length,
1209 /* Save state of Encryption switch */
1210 encryption_state = lp->EnableEncryption;
1212 /* Basic checking: do we have a key to set? */
1213 if((erq->length) != 0) {
1214 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1215 int tk = lp->TransmitKeyID - 1; // current key
1218 /* Check the size of the key */
1219 switch(erq->length) {
1226 /* Check the index */
1227 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1232 memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1234 /* Copy the key in the driver */
1235 memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1237 /* Set the length */
1238 lp->DefaultKeys.key[index].len = erq->length;
1240 DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1241 DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1242 lp->DefaultKeys.key[index].len, index );
1244 /* Enable WEP (if possible) */
1245 if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1246 lp->EnableEncryption = 1;
1252 DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1257 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1260 /* Do we want to just set the current transmit key? */
1261 if(( index >= 0 ) && ( index < MAX_KEYS )) {
1262 DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1263 lp->DefaultKeys.key[index].len );
1265 if( lp->DefaultKeys.key[index].len > 0 ) {
1266 lp->TransmitKeyID = index + 1;
1267 lp->EnableEncryption = 1;
1269 DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1270 DBG_LEAVE( DbgInfo );
1276 /* Read the flags */
1277 if( erq->flags & IW_ENCODE_DISABLED ) {
1278 lp->EnableEncryption = 0; // disable encryption
1280 lp->EnableEncryption = 1;
1283 if( erq->flags & IW_ENCODE_RESTRICTED ) {
1284 DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1285 ret = -EINVAL; // Invalid
1288 DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state );
1289 DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption );
1290 DBG_TRACE( DbgInfo, "erq->length : %d\n",
1292 DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n",
1295 /* Write the changes to the card */
1297 DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1298 lp->TransmitKeyID );
1300 if( lp->EnableEncryption == encryption_state ) {
1301 if( erq->length != 0 ) {
1302 /* Dynamic WEP key update */
1303 wl_set_wep_keys( lp );
1306 /* To switch encryption on/off, soft reset is required */
1311 /* Send an event that Encryption has been set */
1312 wl_wext_event_encode( dev );
1316 wl_act_int_on( lp );
1318 wl_unlock(lp, &flags);
1321 DBG_LEAVE( DbgInfo );
1323 } // wireless_set_encode
1324 /*============================================================================*/
1329 /*******************************************************************************
1330 * wireless_get_encode()
1331 *******************************************************************************
1335 * Gets the encryption keys and status.
1339 * wrq - the wireless request buffer
1340 * lp - the device's private adapter structure
1345 * errno value otherwise
1347 ******************************************************************************/
1348 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1351 struct wl_private *lp = wl_priv(dev);
1352 unsigned long flags;
1355 /*------------------------------------------------------------------------*/
1358 DBG_FUNC( "wireless_get_encode" );
1359 DBG_ENTER( DbgInfo );
1360 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1362 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1367 /* Only super-user can see WEP key */
1368 if( !capable( CAP_NET_ADMIN )) {
1370 DBG_LEAVE( DbgInfo );
1374 wl_lock( lp, &flags );
1376 wl_act_int_off( lp );
1378 /* Is it supported? */
1379 if( !wl_has_wep( &( lp->hcfCtx ))) {
1384 /* Basic checking */
1385 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1391 if( lp->EnableEncryption == 0 ) {
1392 erq->flags |= IW_ENCODE_DISABLED;
1395 /* Which key do we want */
1396 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1397 index = lp->TransmitKeyID - 1;
1400 erq->flags |= index + 1;
1402 /* Copy the key to the user buffer */
1403 erq->length = lp->DefaultKeys.key[index].len;
1405 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1409 wl_act_int_on( lp );
1411 wl_unlock(lp, &flags);
1414 DBG_LEAVE( DbgInfo );
1416 } // wireless_get_encode
1417 /*============================================================================*/
1422 /*******************************************************************************
1423 * wireless_set_nickname()
1424 *******************************************************************************
1428 * Sets the nickname, or station name, of the wireless device.
1432 * wrq - the wireless request buffer
1433 * lp - the device's private adapter structure
1438 * errno value otherwise
1440 ******************************************************************************/
1441 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1443 struct wl_private *lp = wl_priv(dev);
1444 unsigned long flags;
1446 /*------------------------------------------------------------------------*/
1449 DBG_FUNC( "wireless_set_nickname" );
1450 DBG_ENTER( DbgInfo );
1452 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1457 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1458 if( !capable(CAP_NET_ADMIN )) {
1460 DBG_LEAVE( DbgInfo );
1465 /* Validate the new value */
1466 if(data->length > HCF_MAX_NAME_LEN) {
1471 wl_lock( lp, &flags );
1473 wl_act_int_off( lp );
1475 memset( lp->StationName, 0, sizeof( lp->StationName ));
1477 memcpy( lp->StationName, nickname, data->length );
1479 /* Commit the adapter parameters */
1482 wl_act_int_on( lp );
1484 wl_unlock(lp, &flags);
1487 DBG_LEAVE( DbgInfo );
1489 } // wireless_set_nickname
1490 /*============================================================================*/
1495 /*******************************************************************************
1496 * wireless_get_nickname()
1497 *******************************************************************************
1501 * Gets the nickname, or station name, of the wireless device.
1505 * wrq - the wireless request buffer
1506 * lp - the device's private adapter structure
1511 * errno value otherwise
1513 ******************************************************************************/
1514 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1516 struct wl_private *lp = wl_priv(dev);
1517 unsigned long flags;
1521 /*------------------------------------------------------------------------*/
1524 DBG_FUNC( "wireless_get_nickname" );
1525 DBG_ENTER( DbgInfo );
1527 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1532 wl_lock( lp, &flags );
1534 wl_act_int_off( lp );
1536 /* Get the current station name */
1537 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1538 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1540 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1542 if( status == HCF_SUCCESS ) {
1543 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1545 /* Endian translate the length */
1546 pName->length = CNV_LITTLE_TO_INT( pName->length );
1548 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1551 /* Copy the information into the user buffer */
1552 data->length = pName->length;
1553 memcpy(nickname, pName->name, pName->length);
1559 wl_act_int_on( lp );
1561 wl_unlock(lp, &flags);
1566 } // wireless_get_nickname
1567 /*============================================================================*/
1572 /*******************************************************************************
1573 * wireless_set_porttype()
1574 *******************************************************************************
1578 * Sets the port type of the wireless device.
1582 * wrq - the wireless request buffer
1583 * lp - the device's private adapter structure
1588 * errno value otherwise
1590 ******************************************************************************/
1591 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1593 struct wl_private *lp = wl_priv(dev);
1594 unsigned long flags;
1598 /*------------------------------------------------------------------------*/
1600 DBG_FUNC( "wireless_set_porttype" );
1601 DBG_ENTER( DbgInfo );
1603 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1608 wl_lock( lp, &flags );
1610 wl_act_int_off( lp );
1612 /* Validate the new value */
1616 /* When user requests ad-hoc, set IBSS mode! */
1620 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1628 /* Both automatic and infrastructure set port to BSS/STA mode */
1632 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1637 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1639 case IW_MODE_MASTER:
1641 /* Set BSS/AP mode */
1645 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1649 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1659 if( portType != 0 ) {
1660 /* Only do something if there is a mode change */
1661 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1662 lp->PortType = portType;
1663 lp->CreateIBSS = createIBSS;
1665 /* Commit the adapter parameters */
1668 /* Send an event that mode has been set */
1669 wl_wext_event_mode( lp->dev );
1673 wl_act_int_on( lp );
1675 wl_unlock(lp, &flags);
1678 DBG_LEAVE( DbgInfo );
1680 } // wireless_set_porttype
1681 /*============================================================================*/
1686 /*******************************************************************************
1687 * wireless_get_porttype()
1688 *******************************************************************************
1692 * Gets the port type of the wireless device.
1696 * wrq - the wireless request buffer
1697 * lp - the device's private adapter structure
1702 * errno value otherwise
1704 ******************************************************************************/
1705 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1708 struct wl_private *lp = wl_priv(dev);
1709 unsigned long flags;
1713 /*------------------------------------------------------------------------*/
1716 DBG_FUNC( "wireless_get_porttype" );
1717 DBG_ENTER( DbgInfo );
1719 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1724 wl_lock( lp, &flags );
1726 wl_act_int_off( lp );
1728 /* Get the current port type */
1729 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1730 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1732 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1734 if( status == HCF_SUCCESS ) {
1735 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1737 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1739 switch( *pPortType ) {
1743 #if (HCF_TYPE) & HCF_TYPE_AP
1745 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1746 *mode = IW_MODE_MASTER;
1748 *mode = IW_MODE_INFRA;
1753 *mode = IW_MODE_INFRA;
1755 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1758 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1759 *mode = IW_MODE_MASTER;
1761 if( lp->CreateIBSS ) {
1762 *mode = IW_MODE_ADHOC;
1764 *mode = IW_MODE_INFRA;
1772 *mode = IW_MODE_ADHOC;
1783 wl_act_int_on( lp );
1785 wl_unlock(lp, &flags);
1788 DBG_LEAVE( DbgInfo );
1790 } // wireless_get_porttype
1791 /*============================================================================*/
1796 /*******************************************************************************
1797 * wireless_set_power()
1798 *******************************************************************************
1802 * Sets the power management settings of the wireless device.
1806 * wrq - the wireless request buffer
1807 * lp - the device's private adapter structure
1812 * errno value otherwise
1814 ******************************************************************************/
1815 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1817 struct wl_private *lp = wl_priv(dev);
1818 unsigned long flags;
1820 /*------------------------------------------------------------------------*/
1823 DBG_FUNC( "wireless_set_power" );
1824 DBG_ENTER( DbgInfo );
1826 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1831 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1833 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1834 if( !capable( CAP_NET_ADMIN )) {
1837 DBG_LEAVE( DbgInfo );
1842 wl_lock( lp, &flags );
1844 wl_act_int_off( lp );
1846 /* Set the power management state based on the 'disabled' value */
1847 if( wrq->disabled ) {
1853 /* Commit the adapter parameters */
1856 wl_act_int_on( lp );
1858 wl_unlock(lp, &flags);
1861 DBG_LEAVE( DbgInfo );
1863 } // wireless_set_power
1864 /*============================================================================*/
1869 /*******************************************************************************
1870 * wireless_get_power()
1871 *******************************************************************************
1875 * Gets the power management settings of the wireless device.
1879 * wrq - the wireless request buffer
1880 * lp - the device's private adapter structure
1885 * errno value otherwise
1887 ******************************************************************************/
1888 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1891 struct wl_private *lp = wl_priv(dev);
1892 unsigned long flags;
1894 /*------------------------------------------------------------------------*/
1895 DBG_FUNC( "wireless_get_power" );
1896 DBG_ENTER( DbgInfo );
1898 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1903 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1905 wl_lock( lp, &flags );
1907 wl_act_int_off( lp );
1912 if( lp->PMEnabled ) {
1918 wl_act_int_on( lp );
1920 wl_unlock(lp, &flags);
1923 DBG_LEAVE( DbgInfo );
1925 } // wireless_get_power
1926 /*============================================================================*/
1931 /*******************************************************************************
1932 * wireless_get_tx_power()
1933 *******************************************************************************
1937 * Gets the transmit power of the wireless device's radio.
1941 * wrq - the wireless request buffer
1942 * lp - the device's private adapter structure
1947 * errno value otherwise
1949 ******************************************************************************/
1950 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1952 struct wl_private *lp = wl_priv(dev);
1953 unsigned long flags;
1955 /*------------------------------------------------------------------------*/
1956 DBG_FUNC( "wireless_get_tx_power" );
1957 DBG_ENTER( DbgInfo );
1959 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1964 wl_lock( lp, &flags );
1966 wl_act_int_off( lp );
1968 #ifdef USE_POWER_DBM
1969 rrq->value = RADIO_TX_POWER_DBM;
1970 rrq->flags = IW_TXPOW_DBM;
1972 rrq->value = RADIO_TX_POWER_MWATT;
1973 rrq->flags = IW_TXPOW_MWATT;
1978 wl_act_int_on( lp );
1980 wl_unlock(lp, &flags);
1983 DBG_LEAVE( DbgInfo );
1985 } // wireless_get_tx_power
1986 /*============================================================================*/
1991 /*******************************************************************************
1992 * wireless_set_rts_threshold()
1993 *******************************************************************************
1997 * Sets the RTS threshold for the wireless card.
2001 * wrq - the wireless request buffer
2002 * lp - the device's private adapter structure
2007 * errno value otherwise
2009 ******************************************************************************/
2010 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2013 struct wl_private *lp = wl_priv(dev);
2014 unsigned long flags;
2015 int rthr = rts->value;
2016 /*------------------------------------------------------------------------*/
2019 DBG_FUNC( "wireless_set_rts_threshold" );
2020 DBG_ENTER( DbgInfo );
2022 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2027 if(rts->fixed == 0) {
2032 #if WIRELESS_EXT > 8
2033 if( rts->disabled ) {
2036 #endif /* WIRELESS_EXT > 8 */
2038 if(( rthr < 256 ) || ( rthr > 2347 )) {
2043 wl_lock( lp, &flags );
2045 wl_act_int_off( lp );
2047 lp->RTSThreshold = rthr;
2051 wl_act_int_on( lp );
2053 wl_unlock(lp, &flags);
2056 DBG_LEAVE( DbgInfo );
2058 } // wireless_set_rts_threshold
2059 /*============================================================================*/
2064 /*******************************************************************************
2065 * wireless_get_rts_threshold()
2066 *******************************************************************************
2070 * Gets the RTS threshold for the wireless card.
2074 * wrq - the wireless request buffer
2075 * lp - the device's private adapter structure
2080 * errno value otherwise
2082 ******************************************************************************/
2083 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2086 struct wl_private *lp = wl_priv(dev);
2087 unsigned long flags;
2088 /*------------------------------------------------------------------------*/
2090 DBG_FUNC( "wireless_get_rts_threshold" );
2091 DBG_ENTER( DbgInfo );
2093 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2098 wl_lock( lp, &flags );
2100 wl_act_int_off( lp );
2102 rts->value = lp->RTSThreshold;
2104 #if WIRELESS_EXT > 8
2106 rts->disabled = ( rts->value == 2347 );
2108 #endif /* WIRELESS_EXT > 8 */
2112 wl_act_int_on( lp );
2114 wl_unlock(lp, &flags);
2117 DBG_LEAVE( DbgInfo );
2119 } // wireless_get_rts_threshold
2120 /*============================================================================*/
2126 /*******************************************************************************
2127 * wireless_set_rate()
2128 *******************************************************************************
2132 * Set the default data rate setting used by the wireless device.
2136 * wrq - the wireless request buffer
2137 * lp - the device's private adapter structure
2142 * errno value otherwise
2144 ******************************************************************************/
2145 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2147 struct wl_private *lp = wl_priv(dev);
2148 unsigned long flags;
2154 /*------------------------------------------------------------------------*/
2157 DBG_FUNC( "wireless_set_rate" );
2158 DBG_ENTER( DbgInfo );
2160 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2165 wl_lock( lp, &flags );
2167 wl_act_int_off( lp );
2171 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2172 if Bit 9 is set in the current channel RID */
2173 lp->ltvRecord.len = 2;
2174 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2176 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2178 if( status == HCF_SUCCESS ) {
2179 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2181 DBG_PRINT( "Index: %d\n", index );
2183 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2184 DBG_LEAVE( DbgInfo );
2189 if( rrq->value > 0 &&
2190 rrq->value <= 1 * MEGABIT ) {
2191 lp->TxRateControl[index] = 0x0001;
2193 else if( rrq->value > 1 * MEGABIT &&
2194 rrq->value <= 2 * MEGABIT ) {
2195 if( rrq->fixed == 1 ) {
2196 lp->TxRateControl[index] = 0x0002;
2198 lp->TxRateControl[index] = 0x0003;
2201 else if( rrq->value > 2 * MEGABIT &&
2202 rrq->value <= 5 * MEGABIT ) {
2203 if( rrq->fixed == 1 ) {
2204 lp->TxRateControl[index] = 0x0004;
2206 lp->TxRateControl[index] = 0x0007;
2209 else if( rrq->value > 5 * MEGABIT &&
2210 rrq->value <= 6 * MEGABIT ) {
2211 if( rrq->fixed == 1 ) {
2212 lp->TxRateControl[index] = 0x0010;
2214 lp->TxRateControl[index] = 0x0017;
2217 else if( rrq->value > 6 * MEGABIT &&
2218 rrq->value <= 9 * MEGABIT ) {
2219 if( rrq->fixed == 1 ) {
2220 lp->TxRateControl[index] = 0x0020;
2222 lp->TxRateControl[index] = 0x0037;
2225 else if( rrq->value > 9 * MEGABIT &&
2226 rrq->value <= 11 * MEGABIT ) {
2227 if( rrq->fixed == 1 ) {
2228 lp->TxRateControl[index] = 0x0008;
2230 lp->TxRateControl[index] = 0x003F;
2233 else if( rrq->value > 11 * MEGABIT &&
2234 rrq->value <= 12 * MEGABIT ) {
2235 if( rrq->fixed == 1 ) {
2236 lp->TxRateControl[index] = 0x0040;
2238 lp->TxRateControl[index] = 0x007F;
2241 else if( rrq->value > 12 * MEGABIT &&
2242 rrq->value <= 18 * MEGABIT ) {
2243 if( rrq->fixed == 1 ) {
2244 lp->TxRateControl[index] = 0x0080;
2246 lp->TxRateControl[index] = 0x00FF;
2249 else if( rrq->value > 18 * MEGABIT &&
2250 rrq->value <= 24 * MEGABIT ) {
2251 if( rrq->fixed == 1 ) {
2252 lp->TxRateControl[index] = 0x0100;
2254 lp->TxRateControl[index] = 0x01FF;
2257 else if( rrq->value > 24 * MEGABIT &&
2258 rrq->value <= 36 * MEGABIT ) {
2259 if( rrq->fixed == 1 ) {
2260 lp->TxRateControl[index] = 0x0200;
2262 lp->TxRateControl[index] = 0x03FF;
2265 else if( rrq->value > 36 * MEGABIT &&
2266 rrq->value <= 48 * MEGABIT ) {
2267 if( rrq->fixed == 1 ) {
2268 lp->TxRateControl[index] = 0x0400;
2270 lp->TxRateControl[index] = 0x07FF;
2273 else if( rrq->value > 48 * MEGABIT &&
2274 rrq->value <= 54 * MEGABIT ) {
2275 if( rrq->fixed == 1 ) {
2276 lp->TxRateControl[index] = 0x0800;
2278 lp->TxRateControl[index] = 0x0FFF;
2281 else if( rrq->fixed == 0 ) {
2282 /* In this case, the user has not specified a bitrate, only the "auto"
2283 moniker. So, set to all supported rates */
2284 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2294 if( rrq->value > 0 &&
2295 rrq->value <= 1 * MEGABIT ) {
2296 lp->TxRateControl[0] = 1;
2298 else if( rrq->value > 1 * MEGABIT &&
2299 rrq->value <= 2 * MEGABIT ) {
2301 lp->TxRateControl[0] = 2;
2303 lp->TxRateControl[0] = 6;
2306 else if( rrq->value > 2 * MEGABIT &&
2307 rrq->value <= 5 * MEGABIT ) {
2309 lp->TxRateControl[0] = 4;
2311 lp->TxRateControl[0] = 7;
2314 else if( rrq->value > 5 * MEGABIT &&
2315 rrq->value <= 11 * MEGABIT ) {
2317 lp->TxRateControl[0] = 5;
2319 lp->TxRateControl[0] = 3;
2322 else if( rrq->fixed == 0 ) {
2323 /* In this case, the user has not specified a bitrate, only the "auto"
2324 moniker. So, set the rate to 11Mb auto */
2325 lp->TxRateControl[0] = 3;
2335 /* Commit the adapter parameters */
2340 wl_act_int_on( lp );
2342 wl_unlock(lp, &flags);
2345 DBG_LEAVE( DbgInfo );
2347 } // wireless_set_rate
2348 /*============================================================================*/
2353 /*******************************************************************************
2354 * wireless_get_rate()
2355 *******************************************************************************
2359 * Get the default data rate setting used by the wireless device.
2363 * wrq - the wireless request buffer
2364 * lp - the device's private adapter structure
2369 * errno value otherwise
2371 ******************************************************************************/
2372 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2375 struct wl_private *lp = wl_priv(dev);
2376 unsigned long flags;
2380 /*------------------------------------------------------------------------*/
2383 DBG_FUNC( "wireless_get_rate" );
2384 DBG_ENTER( DbgInfo );
2386 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2391 wl_lock( lp, &flags );
2393 wl_act_int_off( lp );
2395 /* Get the current transmit rate from the adapter */
2396 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2397 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2399 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2401 if( status == HCF_SUCCESS ) {
2404 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2406 if( txRate & 0x0001 ) {
2409 else if( txRate & 0x0002 ) {
2412 else if( txRate & 0x0004 ) {
2415 else if( txRate & 0x0008 ) {
2418 else if( txRate & 0x00010 ) {
2421 else if( txRate & 0x00020 ) {
2424 else if( txRate & 0x00040 ) {
2427 else if( txRate & 0x00080 ) {
2430 else if( txRate & 0x00100 ) {
2433 else if( txRate & 0x00200 ) {
2436 else if( txRate & 0x00400 ) {
2439 else if( txRate & 0x00800 ) {
2445 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2449 rrq->value = txRate * MEGABIT;
2455 wl_act_int_on( lp );
2457 wl_unlock(lp, &flags);
2460 DBG_LEAVE( DbgInfo );
2462 } // wireless_get_rate
2463 /*============================================================================*/
2468 #if 0 //;? Not used anymore
2469 /*******************************************************************************
2470 * wireless_get_private_interface()
2471 *******************************************************************************
2475 * Returns the Linux Wireless Extensions' compatible private interface of
2480 * wrq - the wireless request buffer
2481 * lp - the device's private adapter structure
2486 * errno value otherwise
2488 ******************************************************************************/
2489 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2492 /*------------------------------------------------------------------------*/
2495 DBG_FUNC( "wireless_get_private_interface" );
2496 DBG_ENTER( DbgInfo );
2498 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2503 if( wrq->u.data.pointer != NULL ) {
2504 struct iw_priv_args priv[] =
2506 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2507 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2508 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2509 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2510 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2511 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2514 /* Verify the user buffer */
2515 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2518 DBG_LEAVE( DbgInfo );
2522 /* Copy the data into the user's buffer */
2523 wrq->u.data.length = NELEM( priv );
2524 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2528 DBG_LEAVE( DbgInfo );
2530 } // wireless_get_private_interface
2531 /*============================================================================*/
2536 #if WIRELESS_EXT > 13
2538 /*******************************************************************************
2539 * wireless_set_scan()
2540 *******************************************************************************
2544 * Instructs the driver to initiate a network scan.
2548 * wrq - the wireless request buffer
2549 * lp - the device's private adapter structure
2554 * errno value otherwise
2556 ******************************************************************************/
2557 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2559 struct wl_private *lp = wl_priv(dev);
2560 unsigned long flags;
2564 /*------------------------------------------------------------------------*/
2566 //;? Note: shows results as trace, retruns always 0 unless BUSY
2568 DBG_FUNC( "wireless_set_scan" );
2569 DBG_ENTER( DbgInfo );
2571 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2576 wl_lock( lp, &flags );
2578 wl_act_int_off( lp );
2581 * This looks like a nice place to test if the HCF is still
2582 * communicating with the card. It seems that sometimes BAP_1
2583 * gets corrupted. By looking at the comments in HCF the
2584 * cause is still a mistery. Okay, the communication to the
2585 * card is dead, reset the card to revive.
2587 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2589 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2594 /* Set the completion state to FALSE */
2595 lp->probe_results.scan_complete = FALSE;
2598 /* Channels to scan */
2600 lp->ltvRecord.len = 5;
2601 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2602 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2603 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2604 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2605 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2607 lp->ltvRecord.len = 2;
2608 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2609 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2612 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2614 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2616 // Holding the lock too long, make a gap to allow other processes
2617 wl_unlock(lp, &flags);
2618 wl_lock( lp, &flags );
2620 if( status != HCF_SUCCESS ) {
2624 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2627 // Holding the lock too long, make a gap to allow other processes
2628 wl_unlock(lp, &flags);
2629 wl_lock( lp, &flags );
2635 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2636 disassociate from the network we are currently on */
2637 lp->ltvRecord.len = 18;
2638 lp->ltvRecord.typ = CFG_SCAN_SSID;
2639 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2640 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2642 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2644 // Holding the lock too long, make a gap to allow other processes
2645 wl_unlock(lp, &flags);
2646 wl_lock( lp, &flags );
2648 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2650 /* Initiate the scan */
2651 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2652 retrieve probe responses must always be used to support WPA */
2653 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2655 if( status == HCF_SUCCESS ) {
2656 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2658 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2661 wl_act_int_on( lp );
2663 wl_unlock(lp, &flags);
2668 } // wireless_set_scan
2669 /*============================================================================*/
2674 /*******************************************************************************
2675 * wireless_get_scan()
2676 *******************************************************************************
2680 * Instructs the driver to gather and return the results of a network scan.
2684 * wrq - the wireless request buffer
2685 * lp - the device's private adapter structure
2690 * errno value otherwise
2692 ******************************************************************************/
2693 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2695 struct wl_private *lp = wl_priv(dev);
2696 unsigned long flags;
2701 struct iw_event iwe;
2702 PROBE_RESP *probe_resp;
2706 /*------------------------------------------------------------------------*/
2709 DBG_FUNC( "wireless_get_scan" );
2710 DBG_ENTER( DbgInfo );
2712 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2717 wl_lock( lp, &flags );
2719 wl_act_int_off( lp );
2721 /* If the scan is not done, tell the calling process to try again later */
2722 if( !lp->probe_results.scan_complete ) {
2727 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2728 lp->probe_results.num_aps );
2731 buf_end = extra + IW_SCAN_MAX_DATA;
2733 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2734 /* Reference the probe response from the table */
2735 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2738 /* First entry MUST be the MAC address */
2739 memset( &iwe, 0, sizeof( iwe ));
2741 iwe.cmd = SIOCGIWAP;
2742 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2743 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2744 iwe.len = IW_EV_ADDR_LEN;
2746 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2749 /* Use the mode to indicate if it's a station or AP */
2750 /* Won't always be an AP if in IBSS mode */
2751 memset( &iwe, 0, sizeof( iwe ));
2753 iwe.cmd = SIOCGIWMODE;
2755 if( probe_resp->capability & CAPABILITY_IBSS ) {
2756 iwe.u.mode = IW_MODE_INFRA;
2758 iwe.u.mode = IW_MODE_MASTER;
2761 iwe.len = IW_EV_UINT_LEN;
2763 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2766 /* Any quality information */
2767 memset(&iwe, 0, sizeof(iwe));
2770 iwe.u.qual.level = dbm(probe_resp->signal);
2771 iwe.u.qual.noise = dbm(probe_resp->silence);
2772 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2773 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2774 iwe.len = IW_EV_QUAL_LEN;
2776 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2779 /* ESSID information */
2780 if( probe_resp->rawData[1] > 0 ) {
2781 memset( &iwe, 0, sizeof( iwe ));
2783 iwe.cmd = SIOCGIWESSID;
2784 iwe.u.data.length = probe_resp->rawData[1];
2785 iwe.u.data.flags = 1;
2787 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2791 /* Encryption Information */
2792 memset( &iwe, 0, sizeof( iwe ));
2794 iwe.cmd = SIOCGIWENCODE;
2795 iwe.u.data.length = 0;
2797 /* Check the capabilities field of the Probe Response to see if
2798 'privacy' is supported on the AP in question */
2799 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2800 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2802 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2805 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2808 /* Frequency Info */
2809 memset( &iwe, 0, sizeof( iwe ));
2811 iwe.cmd = SIOCGIWFREQ;
2812 iwe.len = IW_EV_FREQ_LEN;
2813 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2816 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2819 #if WIRELESS_EXT > 14
2820 /* Custom info (Beacon Interval) */
2821 memset( &iwe, 0, sizeof( iwe ));
2822 memset( msg, 0, sizeof( msg ));
2824 iwe.cmd = IWEVCUSTOM;
2825 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2826 iwe.u.data.length = strlen( msg );
2828 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2831 /* Custom info (WPA-IE) */
2835 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2836 if( wpa_ie != NULL ) {
2837 memset( &iwe, 0, sizeof( iwe ));
2838 memset( msg, 0, sizeof( msg ));
2840 iwe.cmd = IWEVCUSTOM;
2841 sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2842 iwe.u.data.length = strlen( msg );
2844 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2847 /* Add other custom info in formatted string format as needed... */
2851 data->length = buf - extra;
2855 wl_act_int_on( lp );
2857 wl_unlock(lp, &flags);
2860 DBG_LEAVE( DbgInfo );
2862 } // wireless_get_scan
2863 /*============================================================================*/
2865 #endif // WIRELESS_EXT > 13
2868 #if WIRELESS_EXT > 17
2870 static int wireless_set_auth(struct net_device *dev,
2871 struct iw_request_info *info,
2872 struct iw_param *data, char *extra)
2874 struct wl_private *lp = wl_priv(dev);
2875 unsigned long flags;
2877 int iwa_idx = data->flags & IW_AUTH_INDEX;
2878 int iwa_val = data->value;
2880 DBG_FUNC( "wireless_set_auth" );
2881 DBG_ENTER( DbgInfo );
2883 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2888 wl_lock( lp, &flags );
2890 wl_act_int_off( lp );
2893 case IW_AUTH_WPA_VERSION:
2894 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2895 /* We do support WPA only; how should DISABLED be treated? */
2896 if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2902 case IW_AUTH_WPA_ENABLED:
2903 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2905 lp->EnableEncryption = 2;
2907 lp->EnableEncryption = 0;
2911 case IW_AUTH_TKIP_COUNTERMEASURES:
2912 DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2913 lp->driverEnable = !iwa_val;
2914 if(lp->driverEnable)
2915 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2917 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2921 case IW_AUTH_DROP_UNENCRYPTED:
2922 DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2923 /* We do not actually do anything here, just to silence
2928 case IW_AUTH_CIPHER_PAIRWISE:
2929 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2930 /* not implemented, return an error */
2934 case IW_AUTH_CIPHER_GROUP:
2935 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2936 /* not implemented, return an error */
2940 case IW_AUTH_KEY_MGMT:
2941 DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2942 /* not implemented, return an error */
2946 case IW_AUTH_80211_AUTH_ALG:
2947 DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2948 /* not implemented, return an error */
2952 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2953 DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2954 /* not implemented, return an error */
2958 case IW_AUTH_ROAMING_CONTROL:
2959 DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2960 /* not implemented, return an error */
2964 case IW_AUTH_PRIVACY_INVOKED:
2965 DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2966 /* not implemented, return an error */
2971 DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2972 /* return an error */
2977 wl_act_int_on( lp );
2979 wl_unlock(lp, &flags);
2982 DBG_LEAVE( DbgInfo );
2984 } // wireless_set_auth
2985 /*============================================================================*/
2989 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
2990 int set_tx, u8 *seq, u8 *key, size_t key_len)
2995 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
2996 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
2998 DBG_FUNC( "hermes_set_key" );
2999 DBG_ENTER( DbgInfo );
3002 * Check the key index here; if 0, load as Pairwise Key, otherwise,
3003 * load as a group key. Note that for the Hermes, the RIDs for
3004 * group/pariwise keys are different from each other and different
3005 * than the default WEP keys as well.
3009 case IW_ENCODE_ALG_TKIP:
3010 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3013 * Make sure that there is no data queued up in the firmware
3014 * before setting the TKIP keys. If this check is not
3015 * performed, some data may be sent out with incorrect MIC
3016 * and cause synchronizarion errors with the AP
3018 /* Check every 1ms for 100ms */
3019 for( count = 0; count < 100; count++ )
3024 ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
3027 wl_get_info( sock, <v, ifname );
3029 if( ltv.u.u16[0] == 0 )
3037 wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
3044 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
3046 /* Load the BSSID */
3047 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
3048 buf_idx += ETH_ALEN;
3050 /* Load the TKIP key */
3051 memcpy(<v->u.u8[buf_idx], &key[0], 16);
3055 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3056 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3059 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3060 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3062 /* Load the TxMIC key */
3063 memcpy(<v->u.u8[buf_idx], &key[16], 8);
3066 /* Load the RxMIC key */
3067 memcpy(<v->u.u8[buf_idx], &key[24], 8);
3075 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3077 /* Load the key Index */
3078 ltv->u.u16[buf_idx] = key_idx;
3079 /* If this is a Tx Key, set bit 8000 */
3081 ltv->u.u16[buf_idx] |= 0x8000;
3085 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3086 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3088 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3089 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3090 memcpy(<v->u.u8[buf_idx], key, key_len);
3094 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3096 ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3106 case IW_ENCODE_ALG_WEP:
3107 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3110 case IW_ENCODE_ALG_CCMP:
3111 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3114 case IW_ENCODE_ALG_NONE:
3115 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3118 if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3119 //if (addr != NULL) {
3121 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3122 memcpy(<v->u.u8[0], addr, ETH_ALEN);
3129 /* Clear the Group TKIP keys by index */
3131 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3132 ltv->u.u16[0] = key_idx;
3141 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3145 DBG_LEAVE( DbgInfo );
3148 /*============================================================================*/
3152 static int wireless_set_encodeext (struct net_device *dev,
3153 struct iw_request_info *info,
3154 struct iw_point *erq, char *keybuf)
3156 struct wl_private *lp = wl_priv(dev);
3157 unsigned long flags;
3159 int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3161 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3163 DBG_FUNC( "wireless_set_encodeext" );
3164 DBG_ENTER( DbgInfo );
3166 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3171 if (sizeof(ext->rx_seq) != 8) {
3172 DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3177 /* Handle WEP keys via the old set encode procedure */
3178 if(ext->alg == IW_ENCODE_ALG_WEP) {
3179 struct iw_point wep_erq;
3182 /* Build request structure */
3183 wep_erq.flags = erq->flags; // take over flags with key index
3184 wep_erq.length = ext->key_len; // take length from extended key info
3185 wep_keybuf = ext->key; // pointer to the key text
3187 /* Call wireless_set_encode tot handle the WEP key */
3188 ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3192 /* Proceed for extended encode functions for WAP and NONE */
3193 wl_lock( lp, &flags );
3195 wl_act_int_off( lp );
3197 memset(<v, 0, sizeof(ltv));
3198 ret = hermes_set_key(<v, ext->alg, key_idx, ext->addr.sa_data,
3199 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3200 ext->rx_seq, ext->key, ext->key_len);
3203 DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3207 /* Put the key in HCF */
3208 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3211 if(ret == HCF_SUCCESS) {
3212 DBG_TRACE( DbgInfo, "Put key info succes\n");
3214 DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3217 wl_act_int_on( lp );
3219 wl_unlock(lp, &flags);
3222 DBG_LEAVE( DbgInfo );
3224 } // wireless_set_encodeext
3225 /*============================================================================*/
3229 static int wireless_get_genie(struct net_device *dev,
3230 struct iw_request_info *info,
3231 struct iw_point *data, char *extra)
3234 struct wl_private *lp = wl_priv(dev);
3235 unsigned long flags;
3239 DBG_FUNC( "wireless_get_genie" );
3240 DBG_ENTER( DbgInfo );
3242 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3247 wl_lock( lp, &flags );
3249 wl_act_int_off( lp );
3251 memset(<v, 0, sizeof(ltv));
3253 ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3254 lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3255 ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3257 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3259 wl_act_int_on( lp );
3261 wl_unlock(lp, &flags);
3264 DBG_LEAVE( DbgInfo );
3267 /*============================================================================*/
3270 #endif // WIRELESS_EXT > 17
3272 /*******************************************************************************
3273 * wl_wireless_stats()
3274 *******************************************************************************
3278 * Return the current device wireless statistics.
3282 * wrq - the wireless request buffer
3283 * lp - the device's private adapter structure
3288 * errno value otherwise
3290 ******************************************************************************/
3291 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3293 struct iw_statistics *pStats;
3294 struct wl_private *lp = wl_priv(dev);
3295 /*------------------------------------------------------------------------*/
3298 DBG_FUNC( "wl_wireless_stats" );
3300 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3304 /* Initialize the statistics */
3305 pStats = &( lp->wstats );
3306 pStats->qual.updated = 0x00;
3308 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3310 CFG_COMMS_QUALITY_STRCT *pQual;
3311 CFG_HERMES_TALLIES_STRCT tallies;
3314 /* Update driver status */
3317 /* Get the current link quality information */
3318 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3319 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3320 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3322 if( status == HCF_SUCCESS ) {
3323 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3326 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3327 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3328 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3330 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3331 IW_QUAL_LEVEL_UPDATED |
3332 IW_QUAL_NOISE_UPDATED |
3335 pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
3336 HCF_MIN_COMM_QUALITY,
3337 HCF_MAX_COMM_QUALITY );
3339 pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
3340 HCF_MIN_SIGNAL_LEVEL,
3341 HCF_MAX_SIGNAL_LEVEL );
3343 pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
3344 HCF_MIN_NOISE_LEVEL,
3345 HCF_MAX_NOISE_LEVEL );
3347 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3348 IW_QUAL_LEVEL_UPDATED |
3349 IW_QUAL_NOISE_UPDATED);
3350 #endif /* USE_DBM */
3352 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3355 /* Get the current tallies from the adapter */
3356 /* Only possible when the device is open */
3357 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3358 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3359 /* No endian translation is needed here, as CFG_TALLIES is an
3360 MSF RID; all processing is done on the host, not the card! */
3361 pStats->discard.nwid = 0L;
3362 pStats->discard.code = tallies.RxWEPUndecryptable;
3363 pStats->discard.misc = tallies.TxDiscards +
3364 tallies.RxFCSErrors +
3365 //tallies.RxDiscardsNoBuffer +
3366 tallies.TxDiscardsWrongSA;
3367 //;? Extra taken over from Linux driver based on 7.18 version
3368 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3369 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3371 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3374 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3378 DBG_LEAVE( DbgInfo );
3380 } // wl_wireless_stats
3381 /*============================================================================*/
3386 /*******************************************************************************
3387 * wl_get_wireless_stats()
3388 *******************************************************************************
3392 * Return the current device wireless statistics. This function calls
3393 * wl_wireless_stats, but acquires spinlocks first as it can be called
3394 * directly by the network layer.
3398 * wrq - the wireless request buffer
3399 * lp - the device's private adapter structure
3404 * errno value otherwise
3406 ******************************************************************************/
3407 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3409 unsigned long flags;
3410 struct wl_private *lp = wl_priv(dev);
3411 struct iw_statistics *pStats = NULL;
3412 /*------------------------------------------------------------------------*/
3414 DBG_FUNC( "wl_get_wireless_stats" );
3417 wl_lock( lp, &flags );
3419 wl_act_int_off( lp );
3422 if( lp->useRTS == 1 ) {
3423 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3427 pStats = wl_wireless_stats( dev );
3429 wl_act_int_on( lp );
3431 wl_unlock(lp, &flags);
3433 DBG_LEAVE( DbgInfo );
3435 } // wl_get_wireless_stats
3438 /*******************************************************************************
3440 *******************************************************************************
3444 * Gather wireless spy statistics.
3448 * wrq - the wireless request buffer
3449 * lp - the device's private adapter structure
3454 * errno value otherwise
3456 ******************************************************************************/
3457 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3459 struct iw_quality wstats;
3463 struct wl_private *lp = wl_priv(dev);
3464 /*------------------------------------------------------------------------*/
3467 if (!lp->spy_data.spy_number) {
3471 /* Gather wireless spy statistics: for each packet, compare the source
3472 address with out list, and if match, get the stats. */
3473 memset( stats, 0, sizeof(stats));
3474 memset( desc, 0, sizeof(DESC_STRCT));
3476 desc[0].buf_addr = stats;
3477 desc[0].BUF_SIZE = sizeof(stats);
3478 desc[0].next_desc_addr = 0; // terminate list
3480 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3482 if( status == HCF_SUCCESS ) {
3483 wstats.level = (u_char) dbm(stats[1]);
3484 wstats.noise = (u_char) dbm(stats[0]);
3485 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3487 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3488 IW_QUAL_LEVEL_UPDATED |
3489 IW_QUAL_NOISE_UPDATED |
3492 wireless_spy_update( dev, mac, &wstats );
3495 /*============================================================================*/
3500 /*******************************************************************************
3501 * wl_wext_event_freq()
3502 *******************************************************************************
3506 * This function is used to send an event that the channel/freq
3507 * configuration for a specific device has changed.
3512 * dev - the network device for which this event is to be issued
3518 ******************************************************************************/
3519 void wl_wext_event_freq( struct net_device *dev )
3521 #if WIRELESS_EXT > 13
3522 union iwreq_data wrqu;
3523 struct wl_private *lp = wl_priv(dev);
3524 /*------------------------------------------------------------------------*/
3527 memset( &wrqu, 0, sizeof( wrqu ));
3529 wrqu.freq.m = lp->Channel;
3532 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3533 #endif /* WIRELESS_EXT > 13 */
3536 } // wl_wext_event_freq
3537 /*============================================================================*/
3542 /*******************************************************************************
3543 * wl_wext_event_mode()
3544 *******************************************************************************
3548 * This function is used to send an event that the mode of operation
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_mode( struct net_device *dev )
3563 #if WIRELESS_EXT > 13
3564 union iwreq_data wrqu;
3565 struct wl_private *lp = wl_priv(dev);
3566 /*------------------------------------------------------------------------*/
3569 memset( &wrqu, 0, sizeof( wrqu ));
3571 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3572 wrqu.mode = IW_MODE_INFRA;
3574 wrqu.mode = IW_MODE_MASTER;
3577 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3578 #endif /* WIRELESS_EXT > 13 */
3581 } // wl_wext_event_mode
3582 /*============================================================================*/
3587 /*******************************************************************************
3588 * wl_wext_event_essid()
3589 *******************************************************************************
3593 * This function is used to send an event that the ESSID configuration for
3594 * a specific device has changed.
3599 * dev - the network device for which this event is to be issued
3605 ******************************************************************************/
3606 void wl_wext_event_essid( struct net_device *dev )
3608 #if WIRELESS_EXT > 13
3609 union iwreq_data wrqu;
3610 struct wl_private *lp = wl_priv(dev);
3611 /*------------------------------------------------------------------------*/
3614 memset( &wrqu, 0, sizeof( wrqu ));
3616 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3617 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3618 the call to wireless_send_event() must also point to where the ESSID
3620 wrqu.essid.length = strlen( lp->NetworkName );
3621 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3622 wrqu.essid.flags = 1;
3624 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3625 #endif /* WIRELESS_EXT > 13 */
3628 } // wl_wext_event_essid
3629 /*============================================================================*/
3634 /*******************************************************************************
3635 * wl_wext_event_encode()
3636 *******************************************************************************
3640 * This function is used to send an event that the encryption configuration
3641 * for a specific device has changed.
3646 * dev - the network device for which this event is to be issued
3652 ******************************************************************************/
3653 void wl_wext_event_encode( struct net_device *dev )
3655 #if WIRELESS_EXT > 13
3656 union iwreq_data wrqu;
3657 struct wl_private *lp = wl_priv(dev);
3659 /*------------------------------------------------------------------------*/
3662 memset( &wrqu, 0, sizeof( wrqu ));
3664 if( lp->EnableEncryption == 0 ) {
3665 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3667 wrqu.encoding.flags |= lp->TransmitKeyID;
3669 index = lp->TransmitKeyID - 1;
3671 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3672 if we're in AP mode */
3673 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3674 //;?should we restore this to allow smaller memory footprint
3676 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3677 if( lp->ExcludeUnencrypted ) {
3678 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3680 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3684 #endif // HCF_TYPE_AP
3686 /* Only provide the key if permissions allow */
3687 if( capable( CAP_NET_ADMIN )) {
3688 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3689 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3691 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3695 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3696 lp->DefaultKeys.key[index].key );
3697 #endif /* WIRELESS_EXT > 13 */
3700 } // wl_wext_event_encode
3701 /*============================================================================*/
3706 /*******************************************************************************
3707 * wl_wext_event_ap()
3708 *******************************************************************************
3712 * This function is used to send an event that the device has been
3713 * associated to a new AP.
3718 * dev - the network device for which this event is to be issued
3724 ******************************************************************************/
3725 void wl_wext_event_ap( struct net_device *dev )
3727 #if WIRELESS_EXT > 13
3728 union iwreq_data wrqu;
3729 struct wl_private *lp = wl_priv(dev);
3731 /*------------------------------------------------------------------------*/
3734 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3735 this event BEFORE sending the association event, as there are timing
3736 issues with the hostap supplicant. The supplicant will attempt to process
3737 an EAPOL-Key frame from an AP before receiving this information, which
3738 is required properly process the said frame. */
3739 wl_wext_event_assoc_ie( dev );
3742 lp->ltvRecord.typ = CFG_CUR_BSSID;
3743 lp->ltvRecord.len = 4;
3745 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3746 if( status == HCF_SUCCESS ) {
3747 memset( &wrqu, 0, sizeof( wrqu ));
3749 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3751 wrqu.addr.sa_family = ARPHRD_ETHER;
3753 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3756 #endif /* WIRELESS_EXT > 13 */
3759 } // wl_wext_event_ap
3760 /*============================================================================*/
3764 /*******************************************************************************
3765 * wl_wext_event_scan_complete()
3766 *******************************************************************************
3770 * This function is used to send an event that a request for a network scan
3776 * dev - the network device for which this event is to be issued
3782 ******************************************************************************/
3783 void wl_wext_event_scan_complete( struct net_device *dev )
3785 #if WIRELESS_EXT > 13
3786 union iwreq_data wrqu;
3787 /*------------------------------------------------------------------------*/
3790 memset( &wrqu, 0, sizeof( wrqu ));
3792 wrqu.addr.sa_family = ARPHRD_ETHER;
3793 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3794 #endif /* WIRELESS_EXT > 13 */
3797 } // wl_wext_event_scan_complete
3798 /*============================================================================*/
3803 /*******************************************************************************
3804 * wl_wext_event_new_sta()
3805 *******************************************************************************
3809 * This function is used to send an event that an AP has registered a new
3815 * dev - the network device for which this event is to be issued
3821 ******************************************************************************/
3822 void wl_wext_event_new_sta( struct net_device *dev )
3824 #if WIRELESS_EXT > 14
3825 union iwreq_data wrqu;
3826 /*------------------------------------------------------------------------*/
3829 memset( &wrqu, 0, sizeof( wrqu ));
3831 /* Send the station's mac address here */
3832 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3833 wrqu.addr.sa_family = ARPHRD_ETHER;
3834 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3835 #endif /* WIRELESS_EXT > 14 */
3838 } // wl_wext_event_new_sta
3839 /*============================================================================*/
3844 /*******************************************************************************
3845 * wl_wext_event_expired_sta()
3846 *******************************************************************************
3850 * This function is used to send an event that an AP has deregistered a
3856 * dev - the network device for which this event is to be issued
3862 ******************************************************************************/
3863 void wl_wext_event_expired_sta( struct net_device *dev )
3865 #if WIRELESS_EXT > 14
3866 union iwreq_data wrqu;
3867 /*------------------------------------------------------------------------*/
3870 memset( &wrqu, 0, sizeof( wrqu ));
3872 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3873 wrqu.addr.sa_family = ARPHRD_ETHER;
3874 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3875 #endif /* WIRELESS_EXT > 14 */
3878 } // wl_wext_event_expired_sta
3879 /*============================================================================*/
3884 /*******************************************************************************
3885 * wl_wext_event_mic_failed()
3886 *******************************************************************************
3890 * This function is used to send an event that MIC calculations failed.
3895 * dev - the network device for which this event is to be issued
3901 ******************************************************************************/
3902 void wl_wext_event_mic_failed( struct net_device *dev )
3904 #if WIRELESS_EXT > 14
3906 union iwreq_data wrqu;
3907 struct wl_private *lp = wl_priv(dev);
3911 WVLAN_RX_WMP_HDR *hdr;
3912 /*------------------------------------------------------------------------*/
3915 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3918 /* Cast the lookahead buffer into a RFS format */
3919 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3921 /* Cast the addresses to byte buffers, as in the above RFS they are word
3923 addr1 = (char *)hdr->address1;
3924 addr2 = (char *)hdr->address2;
3926 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3929 memset( &wrqu, 0, sizeof( wrqu ));
3930 memset( msg, 0, sizeof( msg ));
3933 /* Becuase MIC failures are not part of the Wireless Extensions yet, they
3934 must be passed as a string using an IWEVCUSTOM event. In order for the
3935 event to be effective, the string format must be known by both the
3936 driver and the supplicant. The following is the string format used by the
3937 hostap project's WPA supplicant, and will be used here until the Wireless
3938 Extensions interface adds this support:
3940 MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
3943 /* NOTE: Format of MAC address (using colons to seperate bytes) may cause
3944 a problem in future versions of the supplicant, if they ever
3945 actually parse these parameters */
3947 sprintf( msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
3948 "%s)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
3949 DbgHwAddr( addr2 ));
3951 wrqu.data.length = strlen( msg );
3952 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
3953 #endif /* WIRELESS_EXT > 14 */
3956 } // wl_wext_event_mic_failed
3957 /*============================================================================*/
3962 /*******************************************************************************
3963 * wl_wext_event_assoc_ie()
3964 *******************************************************************************
3968 * This function is used to send an event containing the WPA-IE generated
3969 * by the firmware in an association request.
3974 * dev - the network device for which this event is to be issued
3980 ******************************************************************************/
3981 void wl_wext_event_assoc_ie( struct net_device *dev )
3983 #if WIRELESS_EXT > 14
3985 union iwreq_data wrqu;
3986 struct wl_private *lp = wl_priv(dev);
3991 /*------------------------------------------------------------------------*/
3994 memset( &wrqu, 0, sizeof( wrqu ));
3995 memset( msg, 0, sizeof( msg ));
3997 /* Retrieve the Association Request IE */
3998 lp->ltvRecord.len = 45;
3999 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
4001 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
4002 if( status == HCF_SUCCESS )
4005 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
4006 wpa_ie = wl_parse_wpa_ie( &data, &length );
4008 /* Becuase this event (Association WPA-IE) is not part of the Wireless
4009 Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
4010 In order for the event to be effective, the string format must be known
4011 by both the driver and the supplicant. The following is the string format
4012 used by the hostap project's WPA supplicant, and will be used here until
4013 the Wireless Extensions interface adds this support:
4015 ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
4020 sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
4021 wrqu.data.length = strlen( msg );
4022 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
4025 #endif /* WIRELESS_EXT > 14 */
4028 } // wl_wext_event_assoc_ie
4029 /*============================================================================*/
4030 /* Structures to export the Wireless Handlers */
4032 static const iw_handler wl_handler[] =
4034 (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */
4035 (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */
4036 (iw_handler) NULL, /* SIOCSIWNWID */
4037 (iw_handler) NULL, /* SIOCGIWNWID */
4038 (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */
4039 (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */
4040 (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */
4041 (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */
4042 (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */
4043 (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */
4044 (iw_handler) NULL , /* SIOCSIWRANGE */
4045 (iw_handler) wireless_get_range, /* SIOCGIWRANGE */
4046 (iw_handler) NULL , /* SIOCSIWPRIV */
4047 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
4048 (iw_handler) NULL , /* SIOCSIWSTATS */
4049 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
4050 iw_handler_set_spy, /* SIOCSIWSPY */
4051 iw_handler_get_spy, /* SIOCGIWSPY */
4052 NULL, /* SIOCSIWTHRSPY */
4053 NULL, /* SIOCGIWTHRSPY */
4054 (iw_handler) NULL, /* SIOCSIWAP */
4055 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4056 (iw_handler) wireless_get_bssid, /* SIOCGIWAP */
4058 (iw_handler) NULL, /* SIOCGIWAP */
4060 (iw_handler) NULL, /* SIOCSIWMLME */
4061 (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */
4062 (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */
4063 (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */
4064 (iw_handler) wireless_set_essid, /* SIOCSIWESSID */
4065 (iw_handler) wireless_get_essid, /* SIOCGIWESSID */
4066 (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */
4067 (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */
4068 (iw_handler) NULL, /* -- hole -- */
4069 (iw_handler) NULL, /* -- hole -- */
4070 (iw_handler) wireless_set_rate, /* SIOCSIWRATE */
4071 (iw_handler) wireless_get_rate, /* SIOCGIWRATE */
4072 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
4073 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
4074 (iw_handler) NULL, /* SIOCSIWFRAG */
4075 (iw_handler) NULL, /* SIOCGIWFRAG */
4076 (iw_handler) NULL, /* SIOCSIWTXPOW */
4077 (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */
4078 (iw_handler) NULL, /* SIOCSIWRETRY */
4079 (iw_handler) NULL, /* SIOCGIWRETRY */
4080 (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */
4081 (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */
4082 (iw_handler) wireless_set_power, /* SIOCSIWPOWER */
4083 (iw_handler) wireless_get_power, /* SIOCGIWPOWER */
4084 (iw_handler) NULL, /* -- hole -- */
4085 (iw_handler) NULL, /* -- hole -- */
4086 (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */
4087 (iw_handler) NULL, /* SIOCGIWGENIE */
4088 (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */
4089 (iw_handler) NULL, /* SIOCGIWAUTH */
4090 (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */
4091 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
4092 (iw_handler) NULL, /* SIOCSIWPMKSA */
4093 (iw_handler) NULL, /* -- hole -- */
4096 static const iw_handler wl_private_handler[] =
4097 { /* SIOCIWFIRSTPRIV + */
4098 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
4099 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
4100 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
4101 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
4102 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4103 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
4104 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
4108 struct iw_priv_args wl_priv_args[] = {
4109 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
4110 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
4111 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
4112 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
4113 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
4114 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
4115 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
4119 const struct iw_handler_def wl_iw_handler_def =
4121 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
4122 .private = (iw_handler *) wl_private_handler,
4123 .private_args = (struct iw_priv_args *) wl_priv_args,
4124 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
4125 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
4126 .standard = (iw_handler *) wl_handler,
4127 .get_wireless_stats = wl_get_wireless_stats,
4130 #endif // WIRELESS_EXT