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 ******************************************************************************/
60 /*******************************************************************************
61 * VERSION CONTROL INFORMATION
62 *******************************************************************************
65 * $Date: 2004/08/03 11:39:39 $
67 * $Source: /usr/local/cvs/wl_lkm/wireless/wl_wext.c,v $
69 ******************************************************************************/
74 /*******************************************************************************
76 ******************************************************************************/
77 #include <wl_version.h>
79 #include <linux/if_arp.h>
80 #include <linux/ioport.h>
81 #include <linux/delay.h>
82 #include <asm/uaccess.h>
89 #include <wl_internal.h>
97 /* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS
98 #including linux/wireless.h), then these functions do not need to be included
102 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
103 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
104 iwe_stream_add_event(buf, end, iwe, len)
105 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
106 iwe_stream_add_point(buf, end, iwe, msg)
108 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
109 iwe_stream_add_event(info, buf, end, iwe, len)
110 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
111 iwe_stream_add_point(info, buf, end, iwe, msg)
116 /*******************************************************************************
118 ******************************************************************************/
120 extern dbg_info_t *DbgInfo;
126 /*******************************************************************************
128 *******************************************************************************
137 * wrq - the wireless request buffer
143 ******************************************************************************/
144 static int wireless_commit(struct net_device *dev,
145 struct iw_request_info *info,
146 union iwreq_data *rqu, char *extra)
148 struct wl_private *lp = wl_priv(dev);
151 /*------------------------------------------------------------------------*/
153 DBG_FUNC( "wireless_commit" );
156 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
161 wl_lock( lp, &flags );
163 wl_act_int_off( lp );
169 wl_unlock(lp, &flags);
172 DBG_LEAVE( DbgInfo );
175 /*============================================================================*/
180 /*******************************************************************************
181 * wireless_get_protocol()
182 *******************************************************************************
186 * Returns a vendor-defined string that should identify the wireless
191 * wrq - the wireless request buffer
197 ******************************************************************************/
198 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
200 DBG_FUNC( "wireless_get_protocol" );
201 DBG_ENTER( DbgInfo );
203 /* Originally, the driver was placing the string "Wireless" here. However,
204 the wireless extensions (/linux/wireless.h) indicate this string should
205 describe the wireless protocol. */
207 strcpy(name, "IEEE 802.11b");
211 } // wireless_get_protocol
212 /*============================================================================*/
217 /*******************************************************************************
218 * wireless_set_frequency()
219 *******************************************************************************
223 * Sets the frequency (channel) on which the card should Tx/Rx.
227 * wrq - the wireless request buffer
228 * lp - the device's private adapter structure
233 * errno value otherwise
235 ******************************************************************************/
236 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
238 struct wl_private *lp = wl_priv(dev);
242 /*------------------------------------------------------------------------*/
245 DBG_FUNC( "wireless_set_frequency" );
246 DBG_ENTER( DbgInfo );
248 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
253 if( !capable( CAP_NET_ADMIN )) {
255 DBG_LEAVE( DbgInfo );
260 /* If frequency specified, look up channel */
262 int f = freq->m / 100000;
263 channel = wl_get_chan_from_freq( f );
267 /* Channel specified */
273 /* If the channel is an 802.11a channel, set Bit 8 */
275 channel = channel | 0x100;
279 wl_lock( lp, &flags );
281 wl_act_int_off( lp );
283 lp->Channel = channel;
286 /* Commit the adapter parameters */
289 /* Send an event that channel/freq has been set */
290 wl_wext_event_freq( lp->dev );
294 wl_unlock(lp, &flags);
297 DBG_LEAVE( DbgInfo );
299 } // wireless_set_frequency
300 /*============================================================================*/
305 /*******************************************************************************
306 * wireless_get_frequency()
307 *******************************************************************************
311 * Gets the frequency (channel) on which the card is Tx/Rx.
315 * wrq - the wireless request buffer
316 * lp - the device's private adapter structure
322 ******************************************************************************/
323 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
326 struct wl_private *lp = wl_priv(dev);
329 /*------------------------------------------------------------------------*/
332 DBG_FUNC( "wireless_get_frequency" );
333 DBG_ENTER( DbgInfo );
335 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
340 wl_lock( lp, &flags );
342 wl_act_int_off( lp );
344 lp->ltvRecord.len = 2;
345 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
347 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
348 if( ret == HCF_SUCCESS ) {
349 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
353 freq->m = wl_get_freq_from_chan( channel ) * 100000;
360 #endif /* USE_FREQUENCY */
365 wl_unlock(lp, &flags);
367 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
370 DBG_LEAVE( DbgInfo );
372 } // wireless_get_frequency
373 /*============================================================================*/
378 /*******************************************************************************
379 * wireless_get_range()
380 *******************************************************************************
384 * This function is used to provide misc info and statistics about the
389 * wrq - the wireless request buffer
390 * lp - the device's private adapter structure
395 * errno value otherwise
397 ******************************************************************************/
398 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
400 struct wl_private *lp = wl_priv(dev);
402 struct iw_range *range = (struct iw_range *) extra;
408 /*------------------------------------------------------------------------*/
411 DBG_FUNC( "wireless_get_range" );
412 DBG_ENTER( DbgInfo );
414 /* Set range information */
415 data->length = sizeof(struct iw_range);
416 memset(range, 0, sizeof(struct iw_range));
418 wl_lock( lp, &flags );
420 wl_act_int_off( lp );
422 /* Set range information */
423 memset( range, 0, sizeof( struct iw_range ));
426 /* Get the current transmit rate from the adapter */
427 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
428 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
430 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
431 if( status != HCF_SUCCESS ) {
432 /* Recovery action: reset and retry up to 10 times */
433 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
438 /* Holding the lock too long, make a gap to allow other processes */
439 wl_unlock(lp, &flags);
440 wl_lock( lp, &flags );
442 status = wl_reset( dev );
443 if ( status != HCF_SUCCESS ) {
444 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
450 /* Holding the lock too long, make a gap to allow other processes */
451 wl_unlock(lp, &flags);
452 wl_lock( lp, &flags );
457 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
463 /* Holding the lock too long, make a gap to allow other processes */
464 wl_unlock(lp, &flags);
465 wl_lock( lp, &flags );
467 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
469 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
472 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
475 // NWID - NOT SUPPORTED
478 /* Channel/Frequency Info */
479 range->num_channels = RADIO_CHANNELS;
482 /* Signal Level Thresholds */
483 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
489 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
491 /* If the value returned in /proc/net/wireless is greater than the maximum range,
492 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
493 it requires a bit of contorsion... */
495 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
496 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
499 range->max_qual.qual = 100;
500 range->max_qual.level = 100;
501 range->max_qual.noise = 100;
506 /* Set available rates */
507 range->num_bitrates = 0;
509 lp->ltvRecord.len = 6;
510 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
512 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
513 if( status == HCF_SUCCESS ) {
514 for( count = 0; count < MAX_RATES; count++ )
515 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
516 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
517 range->num_bitrates++;
520 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
525 /* RTS Threshold info */
526 range->min_rts = MIN_RTS_BYTES;
527 range->max_rts = MAX_RTS_BYTES;
529 // Frag Threshold info - NOT SUPPORTED
531 // Power Management info - NOT SUPPORTED
537 /* Holding the lock too long, make a gap to allow other processes */
538 wl_unlock(lp, &flags);
539 wl_lock( lp, &flags );
541 /* Is WEP supported? */
543 if( wl_has_wep( &( lp->hcfCtx ))) {
544 /* WEP: RC4 40 bits */
545 range->encoding_size[0] = MIN_KEY_SIZE;
548 range->encoding_size[1] = MAX_KEY_SIZE;
549 range->num_encoding_sizes = 2;
550 range->max_encoding_tokens = MAX_KEYS;
553 #endif /* WIRELESS_EXT > 8 */
556 range->txpower_capa = IW_TXPOW_MWATT;
557 range->num_txpower = 1;
558 range->txpower[0] = RADIO_TX_POWER_MWATT;
560 #if WIRELESS_EXT > 10
562 /* Wireless Extension Info */
563 range->we_version_compiled = WIRELESS_EXT;
564 range->we_version_source = WIRELESS_SUPPORT;
566 // Retry Limits and Lifetime - NOT SUPPORTED
571 #if WIRELESS_EXT > 11
573 /* Holding the lock too long, make a gap to allow other processes */
574 wl_unlock(lp, &flags);
575 wl_lock( lp, &flags );
577 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
578 wl_wireless_stats( lp->dev );
579 range->avg_qual = lp->wstats.qual;
580 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
584 /* Event capability (kernel + driver) */
585 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
586 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
587 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
588 range->event_capa[1] = IW_EVENT_CAPA_K_1;
589 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
590 IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
591 IW_EVENT_CAPA_MASK(IWEVEXPIRED));
593 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
598 wl_unlock(lp, &flags);
602 } // wireless_get_range
603 /*============================================================================*/
606 /*******************************************************************************
607 * wireless_get_bssid()
608 *******************************************************************************
612 * Gets the BSSID the wireless device is currently associated with.
616 * wrq - the wireless request buffer
617 * lp - the device's private adapter structure
622 * errno value otherwise
624 ******************************************************************************/
625 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
627 struct wl_private *lp = wl_priv(dev);
630 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
632 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
633 /*------------------------------------------------------------------------*/
636 DBG_FUNC( "wireless_get_bssid" );
637 DBG_ENTER( DbgInfo );
639 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
644 wl_lock( lp, &flags );
646 wl_act_int_off( lp );
648 memset( &ap_addr->sa_data, 0, ETH_ALEN );
650 ap_addr->sa_family = ARPHRD_ETHER;
652 /* Assume AP mode here, which means the BSSID is our own MAC address. In
653 STA mode, this address will be overwritten with the actual BSSID using
655 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
658 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
659 //;?should we return an error status in AP mode
661 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
662 /* Get Current BSSID */
663 lp->ltvRecord.typ = CFG_CUR_BSSID;
664 lp->ltvRecord.len = 4;
665 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
667 if( status == HCF_SUCCESS ) {
668 /* Copy info into sockaddr struct */
669 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
675 #endif // (HCF_TYPE) & HCF_TYPE_STA
679 wl_unlock(lp, &flags);
684 } // wireless_get_bssid
685 /*============================================================================*/
690 /*******************************************************************************
691 * wireless_get_ap_list()
692 *******************************************************************************
696 * Gets the results of a network scan.
700 * wrq - the wireless request buffer
701 * lp - the device's private adapter structure
706 * errno value otherwise
708 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
709 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
710 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
712 ******************************************************************************/
713 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
715 struct wl_private *lp = wl_priv(dev);
721 struct sockaddr *hwa = NULL;
722 struct iw_quality *qual = NULL;
724 ScanResult *p = &lp->scan_results;
726 ProbeResult *p = &lp->probe_results;
728 /*------------------------------------------------------------------------*/
730 DBG_FUNC( "wireless_get_ap_list" );
731 DBG_ENTER( DbgInfo );
733 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
738 wl_lock( lp, &flags );
740 wl_act_int_off( lp );
742 /* Set the completion state to FALSE */
743 lp->scan_results.scan_complete = FALSE;
744 lp->probe_results.scan_complete = FALSE;
745 /* Channels to scan */
746 lp->ltvRecord.len = 2;
747 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
748 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
749 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
750 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
752 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
753 disassociate from the network we are currently on */
754 lp->ltvRecord.len = 2;
755 lp->ltvRecord.typ = CFG_SCAN_SSID;
756 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
757 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
758 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
760 /* Initiate the scan */
762 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
764 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
769 //;? unlock? what about the access to lp below? is it broken?
770 wl_unlock(lp, &flags);
772 if( ret == HCF_SUCCESS ) {
773 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
774 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
775 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
776 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
777 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
780 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
781 other things in the meantime, This prevents system lockups by
782 giving some time back to the kernel */
783 for( count = 0; count < 100; count ++ ) {
792 if ( ret != HCF_SUCCESS ) {
793 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
795 num_aps = (*p)/*lp->probe_results*/.num_aps;
796 if (num_aps > IW_MAX_AP) {
799 data->length = num_aps;
800 hwa = (struct sockaddr *)extra;
801 qual = (struct iw_quality *) extra +
802 ( sizeof( struct sockaddr ) * num_aps );
804 /* This flag is used to tell the user if we provide quality
805 information. Since we provide signal/noise levels but no
806 quality info on a scan, this is set to 0. Setting to 1 and
807 providing a quality of 0 produces weird results. If we ever
808 provide quality (or can calculate it), this can be changed */
811 for( count = 0; count < num_aps; count++ ) {
813 memcpy( hwa[count].sa_data,
814 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
815 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
816 DBG_PRINT( "BSSID: %s\n", DbgHwAddr( (*p)/*lp->probe_results*/.ProbeTable[count].BSSID ));
817 memcpy( hwa[count].sa_data,
818 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
821 /* Once the data is copied to the wireless struct, invalidate the
822 scan result to initiate a rescan on the next request */
823 (*p)/*lp->probe_results*/.scan_complete = FALSE;
824 /* Send the wireless event that the scan has completed, just in case
826 wl_wext_event_scan_complete( lp->dev );
830 DBG_LEAVE( DbgInfo );
832 } // wireless_get_ap_list
833 /*============================================================================*/
838 /*******************************************************************************
839 * wireless_set_sensitivity()
840 *******************************************************************************
844 * Sets the sensitivity (distance between APs) of the wireless card.
848 * wrq - the wireless request buffer
849 * lp - the device's private adapter structure
854 * errno value otherwise
856 ******************************************************************************/
857 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
859 struct wl_private *lp = wl_priv(dev);
862 int dens = sens->value;
863 /*------------------------------------------------------------------------*/
866 DBG_FUNC( "wireless_set_sensitivity" );
867 DBG_ENTER( DbgInfo );
869 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
874 if(( dens < 1 ) || ( dens > 3 )) {
879 wl_lock( lp, &flags );
881 wl_act_int_off( lp );
883 lp->DistanceBetweenAPs = dens;
888 wl_unlock(lp, &flags);
891 DBG_LEAVE( DbgInfo );
893 } // wireless_set_sensitivity
894 /*============================================================================*/
899 /*******************************************************************************
900 * wireless_get_sensitivity()
901 *******************************************************************************
905 * Gets the sensitivity (distance between APs) of the wireless card.
909 * wrq - the wireless request buffer
910 * lp - the device's private adapter structure
915 * errno value otherwise
917 ******************************************************************************/
918 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
920 struct wl_private *lp = wl_priv(dev);
922 /*------------------------------------------------------------------------*/
923 /*------------------------------------------------------------------------*/
926 DBG_FUNC( "wireless_get_sensitivity" );
927 DBG_ENTER( DbgInfo );
929 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
934 /* not worth locking ... */
935 sens->value = lp->DistanceBetweenAPs;
936 sens->fixed = 0; /* auto */
938 DBG_LEAVE( DbgInfo );
940 } // wireless_get_sensitivity
941 /*============================================================================*/
946 /*******************************************************************************
947 * wireless_set_essid()
948 *******************************************************************************
952 * Sets the ESSID (network name) that the wireless device should associate
957 * wrq - the wireless request buffer
958 * lp - the device's private adapter structure
963 * errno value otherwise
965 ******************************************************************************/
966 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
968 struct wl_private *lp = wl_priv(dev);
972 DBG_FUNC( "wireless_set_essid" );
973 DBG_ENTER( DbgInfo );
975 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
980 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
985 wl_lock( lp, &flags );
987 wl_act_int_off( lp );
989 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
991 /* data->flags is zero to ask for "any" */
992 if( data->flags == 0 ) {
993 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
994 * ;?but there ain't no STAP anymore*/
995 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
996 strcpy( lp->NetworkName, "ANY" );
998 //strcpy( lp->NetworkName, "ANY" );
999 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
1002 memcpy( lp->NetworkName, ssid, data->length );
1005 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1007 /* Commit the adapter parameters */
1010 /* Send an event that ESSID has been set */
1011 wl_wext_event_essid( lp->dev );
1013 wl_act_int_on( lp );
1015 wl_unlock(lp, &flags);
1018 DBG_LEAVE( DbgInfo );
1020 } // wireless_set_essid
1021 /*============================================================================*/
1026 /*******************************************************************************
1027 * wireless_get_essid()
1028 *******************************************************************************
1032 * Gets the ESSID (network name) that the wireless device is associated
1037 * wrq - the wireless request buffer
1038 * lp - the device's private adapter structure
1043 * errno value otherwise
1045 ******************************************************************************/
1046 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1049 struct wl_private *lp = wl_priv(dev);
1050 unsigned long flags;
1054 /*------------------------------------------------------------------------*/
1057 DBG_FUNC( "wireless_get_essid" );
1058 DBG_ENTER( DbgInfo );
1060 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1065 wl_lock( lp, &flags );
1067 wl_act_int_off( lp );
1069 /* Get the desired network name */
1070 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1073 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1074 //;?should we return an error status in AP mode
1076 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1081 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1082 //;?should we restore this to allow smaller memory footprint
1084 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1085 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1091 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1092 if( status == HCF_SUCCESS ) {
1093 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1095 /* Endian translate the string length */
1096 pName->length = CNV_LITTLE_TO_INT( pName->length );
1098 /* Copy the information into the user buffer */
1099 data->length = pName->length;
1101 /* NOTE: Null terminating is necessary for proper display of the SSID in
1102 the wireless tools */
1103 data->length = pName->length + 1;
1104 if( pName->length < HCF_MAX_NAME_LEN ) {
1105 pName->name[pName->length] = '\0';
1111 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1112 //;?should we return an error status in AP mode
1113 #ifdef RETURN_CURRENT_NETWORKNAME
1115 /* if desired is null ("any"), return current or "any" */
1116 if( pName->name[0] == '\0' ) {
1117 /* Get the current network name */
1118 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1119 lp->ltvRecord.typ = CFG_CUR_SSID;
1121 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1123 if( status == HCF_SUCCESS ) {
1124 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1126 /* Endian translate the string length */
1127 pName->length = CNV_LITTLE_TO_INT( pName->length );
1129 /* Copy the information into the user buffer */
1130 data->length = pName->length + 1;
1131 if( pName->length < HCF_MAX_NAME_LEN ) {
1132 pName->name[pName->length] = '\0';
1142 #endif // RETURN_CURRENT_NETWORKNAME
1147 if (pName->length > IW_ESSID_MAX_SIZE) {
1152 memcpy(essid, pName->name, pName->length);
1159 wl_act_int_on( lp );
1161 wl_unlock(lp, &flags);
1164 DBG_LEAVE( DbgInfo );
1166 } // wireless_get_essid
1167 /*============================================================================*/
1172 /*******************************************************************************
1173 * wireless_set_encode()
1174 *******************************************************************************
1178 * Sets the encryption keys and status (enable or disable).
1182 * wrq - the wireless request buffer
1183 * lp - the device's private adapter structure
1188 * errno value otherwise
1190 ******************************************************************************/
1191 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1193 struct wl_private *lp = wl_priv(dev);
1194 unsigned long flags;
1197 #if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
1198 hcf_8 encryption_state;
1199 #endif // WIRELESS_EXT > 8
1200 /*------------------------------------------------------------------------*/
1203 DBG_FUNC( "wireless_set_encode" );
1204 DBG_ENTER( DbgInfo );
1206 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1211 wl_lock( lp, &flags );
1213 wl_act_int_off( lp );
1215 /* Is encryption supported? */
1216 if( !wl_has_wep( &( lp->hcfCtx ))) {
1217 DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1222 DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1223 keybuf, erq->length,
1226 /* Save state of Encryption switch */
1227 encryption_state = lp->EnableEncryption;
1229 /* Basic checking: do we have a key to set? */
1230 if((erq->length) != 0) {
1231 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1232 int tk = lp->TransmitKeyID - 1; // current key
1235 /* Check the size of the key */
1236 switch(erq->length) {
1243 /* Check the index */
1244 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1249 memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1251 /* Copy the key in the driver */
1252 memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1254 /* Set the length */
1255 lp->DefaultKeys.key[index].len = erq->length;
1257 DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1258 DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1259 lp->DefaultKeys.key[index].len, index );
1261 /* Enable WEP (if possible) */
1262 if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1263 lp->EnableEncryption = 1;
1269 DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1274 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1277 /* Do we want to just set the current transmit key? */
1278 if(( index >= 0 ) && ( index < MAX_KEYS )) {
1279 DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1280 lp->DefaultKeys.key[index].len );
1282 if( lp->DefaultKeys.key[index].len > 0 ) {
1283 lp->TransmitKeyID = index + 1;
1284 lp->EnableEncryption = 1;
1286 DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1287 DBG_LEAVE( DbgInfo );
1293 /* Read the flags */
1294 if( erq->flags & IW_ENCODE_DISABLED ) {
1295 lp->EnableEncryption = 0; // disable encryption
1297 lp->EnableEncryption = 1;
1300 if( erq->flags & IW_ENCODE_RESTRICTED ) {
1301 DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1302 ret = -EINVAL; // Invalid
1305 DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state );
1306 DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption );
1307 DBG_TRACE( DbgInfo, "erq->length : %d\n",
1309 DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n",
1312 /* Write the changes to the card */
1314 DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1315 lp->TransmitKeyID );
1317 if( lp->EnableEncryption == encryption_state ) {
1318 if( erq->length != 0 ) {
1319 /* Dynamic WEP key update */
1320 wl_set_wep_keys( lp );
1323 /* To switch encryption on/off, soft reset is required */
1328 /* Send an event that Encryption has been set */
1329 wl_wext_event_encode( dev );
1333 wl_act_int_on( lp );
1335 wl_unlock(lp, &flags);
1338 DBG_LEAVE( DbgInfo );
1340 } // wireless_set_encode
1341 /*============================================================================*/
1346 /*******************************************************************************
1347 * wireless_get_encode()
1348 *******************************************************************************
1352 * Gets the encryption keys and status.
1356 * wrq - the wireless request buffer
1357 * lp - the device's private adapter structure
1362 * errno value otherwise
1364 ******************************************************************************/
1365 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1368 struct wl_private *lp = wl_priv(dev);
1369 unsigned long flags;
1372 /*------------------------------------------------------------------------*/
1375 DBG_FUNC( "wireless_get_encode" );
1376 DBG_ENTER( DbgInfo );
1377 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1379 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1384 /* Only super-user can see WEP key */
1385 if( !capable( CAP_NET_ADMIN )) {
1387 DBG_LEAVE( DbgInfo );
1391 wl_lock( lp, &flags );
1393 wl_act_int_off( lp );
1395 /* Is it supported? */
1396 if( !wl_has_wep( &( lp->hcfCtx ))) {
1401 /* Basic checking */
1402 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1408 if( lp->EnableEncryption == 0 ) {
1409 erq->flags |= IW_ENCODE_DISABLED;
1412 /* Which key do we want */
1413 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1414 index = lp->TransmitKeyID - 1;
1417 erq->flags |= index + 1;
1419 /* Copy the key to the user buffer */
1420 erq->length = lp->DefaultKeys.key[index].len;
1422 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1426 wl_act_int_on( lp );
1428 wl_unlock(lp, &flags);
1431 DBG_LEAVE( DbgInfo );
1433 } // wireless_get_encode
1434 /*============================================================================*/
1439 /*******************************************************************************
1440 * wireless_set_nickname()
1441 *******************************************************************************
1445 * Sets the nickname, or station name, of the wireless device.
1449 * wrq - the wireless request buffer
1450 * lp - the device's private adapter structure
1455 * errno value otherwise
1457 ******************************************************************************/
1458 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1460 struct wl_private *lp = wl_priv(dev);
1461 unsigned long flags;
1463 /*------------------------------------------------------------------------*/
1466 DBG_FUNC( "wireless_set_nickname" );
1467 DBG_ENTER( DbgInfo );
1469 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1474 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1475 if( !capable(CAP_NET_ADMIN )) {
1477 DBG_LEAVE( DbgInfo );
1482 /* Validate the new value */
1483 if(data->length > HCF_MAX_NAME_LEN) {
1488 wl_lock( lp, &flags );
1490 wl_act_int_off( lp );
1492 memset( lp->StationName, 0, sizeof( lp->StationName ));
1494 memcpy( lp->StationName, nickname, data->length );
1496 /* Commit the adapter parameters */
1499 wl_act_int_on( lp );
1501 wl_unlock(lp, &flags);
1504 DBG_LEAVE( DbgInfo );
1506 } // wireless_set_nickname
1507 /*============================================================================*/
1512 /*******************************************************************************
1513 * wireless_get_nickname()
1514 *******************************************************************************
1518 * Gets the nickname, or station name, of the wireless device.
1522 * wrq - the wireless request buffer
1523 * lp - the device's private adapter structure
1528 * errno value otherwise
1530 ******************************************************************************/
1531 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1533 struct wl_private *lp = wl_priv(dev);
1534 unsigned long flags;
1538 /*------------------------------------------------------------------------*/
1541 DBG_FUNC( "wireless_get_nickname" );
1542 DBG_ENTER( DbgInfo );
1544 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1549 wl_lock( lp, &flags );
1551 wl_act_int_off( lp );
1553 /* Get the current station name */
1554 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1555 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1557 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1559 if( status == HCF_SUCCESS ) {
1560 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1562 /* Endian translate the length */
1563 pName->length = CNV_LITTLE_TO_INT( pName->length );
1565 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1568 /* Copy the information into the user buffer */
1569 data->length = pName->length;
1570 memcpy(nickname, pName->name, pName->length);
1576 wl_act_int_on( lp );
1578 wl_unlock(lp, &flags);
1583 } // wireless_get_nickname
1584 /*============================================================================*/
1589 /*******************************************************************************
1590 * wireless_set_porttype()
1591 *******************************************************************************
1595 * Sets the port type of the wireless device.
1599 * wrq - the wireless request buffer
1600 * lp - the device's private adapter structure
1605 * errno value otherwise
1607 ******************************************************************************/
1608 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1610 struct wl_private *lp = wl_priv(dev);
1611 unsigned long flags;
1615 /*------------------------------------------------------------------------*/
1617 DBG_FUNC( "wireless_set_porttype" );
1618 DBG_ENTER( DbgInfo );
1620 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1625 wl_lock( lp, &flags );
1627 wl_act_int_off( lp );
1629 /* Validate the new value */
1633 /* When user requests ad-hoc, set IBSS mode! */
1637 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1645 /* Both automatic and infrastructure set port to BSS/STA mode */
1649 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1654 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1656 case IW_MODE_MASTER:
1658 /* Set BSS/AP mode */
1662 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1666 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1676 if( portType != 0 ) {
1677 /* Only do something if there is a mode change */
1678 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1679 lp->PortType = portType;
1680 lp->CreateIBSS = createIBSS;
1682 /* Commit the adapter parameters */
1685 /* Send an event that mode has been set */
1686 wl_wext_event_mode( lp->dev );
1690 wl_act_int_on( lp );
1692 wl_unlock(lp, &flags);
1695 DBG_LEAVE( DbgInfo );
1697 } // wireless_set_porttype
1698 /*============================================================================*/
1703 /*******************************************************************************
1704 * wireless_get_porttype()
1705 *******************************************************************************
1709 * Gets the port type of the wireless device.
1713 * wrq - the wireless request buffer
1714 * lp - the device's private adapter structure
1719 * errno value otherwise
1721 ******************************************************************************/
1722 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1725 struct wl_private *lp = wl_priv(dev);
1726 unsigned long flags;
1730 /*------------------------------------------------------------------------*/
1733 DBG_FUNC( "wireless_get_porttype" );
1734 DBG_ENTER( DbgInfo );
1736 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1741 wl_lock( lp, &flags );
1743 wl_act_int_off( lp );
1745 /* Get the current port type */
1746 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1747 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1749 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1751 if( status == HCF_SUCCESS ) {
1752 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1754 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1756 switch( *pPortType ) {
1760 #if (HCF_TYPE) & HCF_TYPE_AP
1762 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1763 *mode = IW_MODE_MASTER;
1765 *mode = IW_MODE_INFRA;
1770 *mode = IW_MODE_INFRA;
1772 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1775 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1776 *mode = IW_MODE_MASTER;
1778 if( lp->CreateIBSS ) {
1779 *mode = IW_MODE_ADHOC;
1781 *mode = IW_MODE_INFRA;
1789 *mode = IW_MODE_ADHOC;
1800 wl_act_int_on( lp );
1802 wl_unlock(lp, &flags);
1805 DBG_LEAVE( DbgInfo );
1807 } // wireless_get_porttype
1808 /*============================================================================*/
1813 /*******************************************************************************
1814 * wireless_set_power()
1815 *******************************************************************************
1819 * Sets the power management settings of the wireless device.
1823 * wrq - the wireless request buffer
1824 * lp - the device's private adapter structure
1829 * errno value otherwise
1831 ******************************************************************************/
1832 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1834 struct wl_private *lp = wl_priv(dev);
1835 unsigned long flags;
1837 /*------------------------------------------------------------------------*/
1840 DBG_FUNC( "wireless_set_power" );
1841 DBG_ENTER( DbgInfo );
1843 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1848 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1850 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1851 if( !capable( CAP_NET_ADMIN )) {
1854 DBG_LEAVE( DbgInfo );
1859 wl_lock( lp, &flags );
1861 wl_act_int_off( lp );
1863 /* Set the power management state based on the 'disabled' value */
1864 if( wrq->disabled ) {
1870 /* Commit the adapter parameters */
1873 wl_act_int_on( lp );
1875 wl_unlock(lp, &flags);
1878 DBG_LEAVE( DbgInfo );
1880 } // wireless_set_power
1881 /*============================================================================*/
1886 /*******************************************************************************
1887 * wireless_get_power()
1888 *******************************************************************************
1892 * Gets the power management settings of the wireless device.
1896 * wrq - the wireless request buffer
1897 * lp - the device's private adapter structure
1902 * errno value otherwise
1904 ******************************************************************************/
1905 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1908 struct wl_private *lp = wl_priv(dev);
1909 unsigned long flags;
1911 /*------------------------------------------------------------------------*/
1912 DBG_FUNC( "wireless_get_power" );
1913 DBG_ENTER( DbgInfo );
1915 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1920 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1922 wl_lock( lp, &flags );
1924 wl_act_int_off( lp );
1929 if( lp->PMEnabled ) {
1935 wl_act_int_on( lp );
1937 wl_unlock(lp, &flags);
1940 DBG_LEAVE( DbgInfo );
1942 } // wireless_get_power
1943 /*============================================================================*/
1948 /*******************************************************************************
1949 * wireless_get_tx_power()
1950 *******************************************************************************
1954 * Gets the transmit power of the wireless device's radio.
1958 * wrq - the wireless request buffer
1959 * lp - the device's private adapter structure
1964 * errno value otherwise
1966 ******************************************************************************/
1967 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1969 struct wl_private *lp = wl_priv(dev);
1970 unsigned long flags;
1972 /*------------------------------------------------------------------------*/
1973 DBG_FUNC( "wireless_get_tx_power" );
1974 DBG_ENTER( DbgInfo );
1976 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1981 wl_lock( lp, &flags );
1983 wl_act_int_off( lp );
1985 #ifdef USE_POWER_DBM
1986 rrq->value = RADIO_TX_POWER_DBM;
1987 rrq->flags = IW_TXPOW_DBM;
1989 rrq->value = RADIO_TX_POWER_MWATT;
1990 rrq->flags = IW_TXPOW_MWATT;
1995 wl_act_int_on( lp );
1997 wl_unlock(lp, &flags);
2000 DBG_LEAVE( DbgInfo );
2002 } // wireless_get_tx_power
2003 /*============================================================================*/
2008 /*******************************************************************************
2009 * wireless_set_rts_threshold()
2010 *******************************************************************************
2014 * Sets the RTS threshold for the wireless card.
2018 * wrq - the wireless request buffer
2019 * lp - the device's private adapter structure
2024 * errno value otherwise
2026 ******************************************************************************/
2027 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2030 struct wl_private *lp = wl_priv(dev);
2031 unsigned long flags;
2032 int rthr = rts->value;
2033 /*------------------------------------------------------------------------*/
2036 DBG_FUNC( "wireless_set_rts_threshold" );
2037 DBG_ENTER( DbgInfo );
2039 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2044 if(rts->fixed == 0) {
2049 #if WIRELESS_EXT > 8
2050 if( rts->disabled ) {
2053 #endif /* WIRELESS_EXT > 8 */
2055 if(( rthr < 256 ) || ( rthr > 2347 )) {
2060 wl_lock( lp, &flags );
2062 wl_act_int_off( lp );
2064 lp->RTSThreshold = rthr;
2068 wl_act_int_on( lp );
2070 wl_unlock(lp, &flags);
2073 DBG_LEAVE( DbgInfo );
2075 } // wireless_set_rts_threshold
2076 /*============================================================================*/
2081 /*******************************************************************************
2082 * wireless_get_rts_threshold()
2083 *******************************************************************************
2087 * Gets the RTS threshold for the wireless card.
2091 * wrq - the wireless request buffer
2092 * lp - the device's private adapter structure
2097 * errno value otherwise
2099 ******************************************************************************/
2100 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2103 struct wl_private *lp = wl_priv(dev);
2104 unsigned long flags;
2105 /*------------------------------------------------------------------------*/
2107 DBG_FUNC( "wireless_get_rts_threshold" );
2108 DBG_ENTER( DbgInfo );
2110 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2115 wl_lock( lp, &flags );
2117 wl_act_int_off( lp );
2119 rts->value = lp->RTSThreshold;
2121 #if WIRELESS_EXT > 8
2123 rts->disabled = ( rts->value == 2347 );
2125 #endif /* WIRELESS_EXT > 8 */
2129 wl_act_int_on( lp );
2131 wl_unlock(lp, &flags);
2134 DBG_LEAVE( DbgInfo );
2136 } // wireless_get_rts_threshold
2137 /*============================================================================*/
2143 /*******************************************************************************
2144 * wireless_set_rate()
2145 *******************************************************************************
2149 * Set the default data rate setting used by the wireless device.
2153 * wrq - the wireless request buffer
2154 * lp - the device's private adapter structure
2159 * errno value otherwise
2161 ******************************************************************************/
2162 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2164 struct wl_private *lp = wl_priv(dev);
2165 unsigned long flags;
2171 /*------------------------------------------------------------------------*/
2174 DBG_FUNC( "wireless_set_rate" );
2175 DBG_ENTER( DbgInfo );
2177 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2182 wl_lock( lp, &flags );
2184 wl_act_int_off( lp );
2188 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2189 if Bit 9 is set in the current channel RID */
2190 lp->ltvRecord.len = 2;
2191 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2193 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2195 if( status == HCF_SUCCESS ) {
2196 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2198 DBG_PRINT( "Index: %d\n", index );
2200 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2201 DBG_LEAVE( DbgInfo );
2206 if( rrq->value > 0 &&
2207 rrq->value <= 1 * MEGABIT ) {
2208 lp->TxRateControl[index] = 0x0001;
2210 else if( rrq->value > 1 * MEGABIT &&
2211 rrq->value <= 2 * MEGABIT ) {
2212 if( rrq->fixed == 1 ) {
2213 lp->TxRateControl[index] = 0x0002;
2215 lp->TxRateControl[index] = 0x0003;
2218 else if( rrq->value > 2 * MEGABIT &&
2219 rrq->value <= 5 * MEGABIT ) {
2220 if( rrq->fixed == 1 ) {
2221 lp->TxRateControl[index] = 0x0004;
2223 lp->TxRateControl[index] = 0x0007;
2226 else if( rrq->value > 5 * MEGABIT &&
2227 rrq->value <= 6 * MEGABIT ) {
2228 if( rrq->fixed == 1 ) {
2229 lp->TxRateControl[index] = 0x0010;
2231 lp->TxRateControl[index] = 0x0017;
2234 else if( rrq->value > 6 * MEGABIT &&
2235 rrq->value <= 9 * MEGABIT ) {
2236 if( rrq->fixed == 1 ) {
2237 lp->TxRateControl[index] = 0x0020;
2239 lp->TxRateControl[index] = 0x0037;
2242 else if( rrq->value > 9 * MEGABIT &&
2243 rrq->value <= 11 * MEGABIT ) {
2244 if( rrq->fixed == 1 ) {
2245 lp->TxRateControl[index] = 0x0008;
2247 lp->TxRateControl[index] = 0x003F;
2250 else if( rrq->value > 11 * MEGABIT &&
2251 rrq->value <= 12 * MEGABIT ) {
2252 if( rrq->fixed == 1 ) {
2253 lp->TxRateControl[index] = 0x0040;
2255 lp->TxRateControl[index] = 0x007F;
2258 else if( rrq->value > 12 * MEGABIT &&
2259 rrq->value <= 18 * MEGABIT ) {
2260 if( rrq->fixed == 1 ) {
2261 lp->TxRateControl[index] = 0x0080;
2263 lp->TxRateControl[index] = 0x00FF;
2266 else if( rrq->value > 18 * MEGABIT &&
2267 rrq->value <= 24 * MEGABIT ) {
2268 if( rrq->fixed == 1 ) {
2269 lp->TxRateControl[index] = 0x0100;
2271 lp->TxRateControl[index] = 0x01FF;
2274 else if( rrq->value > 24 * MEGABIT &&
2275 rrq->value <= 36 * MEGABIT ) {
2276 if( rrq->fixed == 1 ) {
2277 lp->TxRateControl[index] = 0x0200;
2279 lp->TxRateControl[index] = 0x03FF;
2282 else if( rrq->value > 36 * MEGABIT &&
2283 rrq->value <= 48 * MEGABIT ) {
2284 if( rrq->fixed == 1 ) {
2285 lp->TxRateControl[index] = 0x0400;
2287 lp->TxRateControl[index] = 0x07FF;
2290 else if( rrq->value > 48 * MEGABIT &&
2291 rrq->value <= 54 * MEGABIT ) {
2292 if( rrq->fixed == 1 ) {
2293 lp->TxRateControl[index] = 0x0800;
2295 lp->TxRateControl[index] = 0x0FFF;
2298 else if( rrq->fixed == 0 ) {
2299 /* In this case, the user has not specified a bitrate, only the "auto"
2300 moniker. So, set to all supported rates */
2301 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2311 if( rrq->value > 0 &&
2312 rrq->value <= 1 * MEGABIT ) {
2313 lp->TxRateControl[0] = 1;
2315 else if( rrq->value > 1 * MEGABIT &&
2316 rrq->value <= 2 * MEGABIT ) {
2318 lp->TxRateControl[0] = 2;
2320 lp->TxRateControl[0] = 6;
2323 else if( rrq->value > 2 * MEGABIT &&
2324 rrq->value <= 5 * MEGABIT ) {
2326 lp->TxRateControl[0] = 4;
2328 lp->TxRateControl[0] = 7;
2331 else if( rrq->value > 5 * MEGABIT &&
2332 rrq->value <= 11 * MEGABIT ) {
2334 lp->TxRateControl[0] = 5;
2336 lp->TxRateControl[0] = 3;
2339 else if( rrq->fixed == 0 ) {
2340 /* In this case, the user has not specified a bitrate, only the "auto"
2341 moniker. So, set the rate to 11Mb auto */
2342 lp->TxRateControl[0] = 3;
2352 /* Commit the adapter parameters */
2357 wl_act_int_on( lp );
2359 wl_unlock(lp, &flags);
2362 DBG_LEAVE( DbgInfo );
2364 } // wireless_set_rate
2365 /*============================================================================*/
2370 /*******************************************************************************
2371 * wireless_get_rate()
2372 *******************************************************************************
2376 * Get the default data rate setting used by the wireless device.
2380 * wrq - the wireless request buffer
2381 * lp - the device's private adapter structure
2386 * errno value otherwise
2388 ******************************************************************************/
2389 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2392 struct wl_private *lp = wl_priv(dev);
2393 unsigned long flags;
2397 /*------------------------------------------------------------------------*/
2400 DBG_FUNC( "wireless_get_rate" );
2401 DBG_ENTER( DbgInfo );
2403 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2408 wl_lock( lp, &flags );
2410 wl_act_int_off( lp );
2412 /* Get the current transmit rate from the adapter */
2413 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2414 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2416 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2418 if( status == HCF_SUCCESS ) {
2421 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2423 if( txRate & 0x0001 ) {
2426 else if( txRate & 0x0002 ) {
2429 else if( txRate & 0x0004 ) {
2432 else if( txRate & 0x0008 ) {
2435 else if( txRate & 0x00010 ) {
2438 else if( txRate & 0x00020 ) {
2441 else if( txRate & 0x00040 ) {
2444 else if( txRate & 0x00080 ) {
2447 else if( txRate & 0x00100 ) {
2450 else if( txRate & 0x00200 ) {
2453 else if( txRate & 0x00400 ) {
2456 else if( txRate & 0x00800 ) {
2462 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2466 rrq->value = txRate * MEGABIT;
2472 wl_act_int_on( lp );
2474 wl_unlock(lp, &flags);
2477 DBG_LEAVE( DbgInfo );
2479 } // wireless_get_rate
2480 /*============================================================================*/
2485 #if 0 //;? Not used anymore
2486 /*******************************************************************************
2487 * wireless_get_private_interface()
2488 *******************************************************************************
2492 * Returns the Linux Wireless Extensions' compatible private interface of
2497 * wrq - the wireless request buffer
2498 * lp - the device's private adapter structure
2503 * errno value otherwise
2505 ******************************************************************************/
2506 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2509 /*------------------------------------------------------------------------*/
2512 DBG_FUNC( "wireless_get_private_interface" );
2513 DBG_ENTER( DbgInfo );
2515 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2520 if( wrq->u.data.pointer != NULL ) {
2521 struct iw_priv_args priv[] =
2523 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2524 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2525 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2526 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2527 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2528 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2531 /* Verify the user buffer */
2532 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2535 DBG_LEAVE( DbgInfo );
2539 /* Copy the data into the user's buffer */
2540 wrq->u.data.length = NELEM( priv );
2541 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2545 DBG_LEAVE( DbgInfo );
2547 } // wireless_get_private_interface
2548 /*============================================================================*/
2553 #if WIRELESS_EXT > 13
2555 /*******************************************************************************
2556 * wireless_set_scan()
2557 *******************************************************************************
2561 * Instructs the driver to initiate a network scan.
2565 * wrq - the wireless request buffer
2566 * lp - the device's private adapter structure
2571 * errno value otherwise
2573 ******************************************************************************/
2574 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2576 struct wl_private *lp = wl_priv(dev);
2577 unsigned long flags;
2581 /*------------------------------------------------------------------------*/
2583 //;? Note: shows results as trace, retruns always 0 unless BUSY
2585 DBG_FUNC( "wireless_set_scan" );
2586 DBG_ENTER( DbgInfo );
2588 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2593 wl_lock( lp, &flags );
2595 wl_act_int_off( lp );
2598 * This looks like a nice place to test if the HCF is still
2599 * communicating with the card. It seems that sometimes BAP_1
2600 * gets corrupted. By looking at the comments in HCF the
2601 * cause is still a mistery. Okay, the communication to the
2602 * card is dead, reset the card to revive.
2604 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2606 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2611 /* Set the completion state to FALSE */
2612 lp->probe_results.scan_complete = FALSE;
2615 /* Channels to scan */
2617 lp->ltvRecord.len = 5;
2618 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2619 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2620 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2621 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2622 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2624 lp->ltvRecord.len = 2;
2625 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2626 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2629 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2631 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2633 // Holding the lock too long, make a gap to allow other processes
2634 wl_unlock(lp, &flags);
2635 wl_lock( lp, &flags );
2637 if( status != HCF_SUCCESS ) {
2641 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2644 // Holding the lock too long, make a gap to allow other processes
2645 wl_unlock(lp, &flags);
2646 wl_lock( lp, &flags );
2652 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2653 disassociate from the network we are currently on */
2654 lp->ltvRecord.len = 18;
2655 lp->ltvRecord.typ = CFG_SCAN_SSID;
2656 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2657 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2659 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2661 // Holding the lock too long, make a gap to allow other processes
2662 wl_unlock(lp, &flags);
2663 wl_lock( lp, &flags );
2665 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2667 /* Initiate the scan */
2668 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2669 retrieve probe responses must always be used to support WPA */
2670 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2672 if( status == HCF_SUCCESS ) {
2673 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2675 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2678 wl_act_int_on( lp );
2680 wl_unlock(lp, &flags);
2685 } // wireless_set_scan
2686 /*============================================================================*/
2691 /*******************************************************************************
2692 * wireless_get_scan()
2693 *******************************************************************************
2697 * Instructs the driver to gather and return the results of a network scan.
2701 * wrq - the wireless request buffer
2702 * lp - the device's private adapter structure
2707 * errno value otherwise
2709 ******************************************************************************/
2710 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2712 struct wl_private *lp = wl_priv(dev);
2713 unsigned long flags;
2718 struct iw_event iwe;
2719 PROBE_RESP *probe_resp;
2723 /*------------------------------------------------------------------------*/
2726 DBG_FUNC( "wireless_get_scan" );
2727 DBG_ENTER( DbgInfo );
2729 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2734 wl_lock( lp, &flags );
2736 wl_act_int_off( lp );
2738 /* If the scan is not done, tell the calling process to try again later */
2739 if( !lp->probe_results.scan_complete ) {
2744 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2745 lp->probe_results.num_aps );
2748 buf_end = extra + IW_SCAN_MAX_DATA;
2750 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2751 /* Reference the probe response from the table */
2752 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2755 /* First entry MUST be the MAC address */
2756 memset( &iwe, 0, sizeof( iwe ));
2758 iwe.cmd = SIOCGIWAP;
2759 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2760 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2761 iwe.len = IW_EV_ADDR_LEN;
2763 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2766 /* Use the mode to indicate if it's a station or AP */
2767 /* Won't always be an AP if in IBSS mode */
2768 memset( &iwe, 0, sizeof( iwe ));
2770 iwe.cmd = SIOCGIWMODE;
2772 if( probe_resp->capability & CAPABILITY_IBSS ) {
2773 iwe.u.mode = IW_MODE_INFRA;
2775 iwe.u.mode = IW_MODE_MASTER;
2778 iwe.len = IW_EV_UINT_LEN;
2780 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2783 /* Any quality information */
2784 memset(&iwe, 0, sizeof(iwe));
2787 iwe.u.qual.level = dbm(probe_resp->signal);
2788 iwe.u.qual.noise = dbm(probe_resp->silence);
2789 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2790 iwe.u.qual.updated = lp->probe_results.scan_complete;
2791 iwe.len = IW_EV_QUAL_LEN;
2793 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2796 /* ESSID information */
2797 if( probe_resp->rawData[1] > 0 ) {
2798 memset( &iwe, 0, sizeof( iwe ));
2800 iwe.cmd = SIOCGIWESSID;
2801 iwe.u.data.length = probe_resp->rawData[1];
2802 iwe.u.data.flags = 1;
2804 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2808 /* Encryption Information */
2809 memset( &iwe, 0, sizeof( iwe ));
2811 iwe.cmd = SIOCGIWENCODE;
2812 iwe.u.data.length = 0;
2814 /* Check the capabilities field of the Probe Response to see if
2815 'privacy' is supported on the AP in question */
2816 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2817 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2819 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2822 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2825 /* Frequency Info */
2826 memset( &iwe, 0, sizeof( iwe ));
2828 iwe.cmd = SIOCGIWFREQ;
2829 iwe.len = IW_EV_FREQ_LEN;
2830 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2833 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2836 #if WIRELESS_EXT > 14
2837 /* Custom info (Beacon Interval) */
2838 memset( &iwe, 0, sizeof( iwe ));
2839 memset( msg, 0, sizeof( msg ));
2841 iwe.cmd = IWEVCUSTOM;
2842 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2843 iwe.u.data.length = strlen( msg );
2845 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2848 /* Custom info (WPA-IE) */
2852 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2853 if( wpa_ie != NULL ) {
2854 memset( &iwe, 0, sizeof( iwe ));
2855 memset( msg, 0, sizeof( msg ));
2857 iwe.cmd = IWEVCUSTOM;
2858 sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2859 iwe.u.data.length = strlen( msg );
2861 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2864 /* Add other custom info in formatted string format as needed... */
2868 data->length = buf - extra;
2872 wl_act_int_on( lp );
2874 wl_unlock(lp, &flags);
2877 DBG_LEAVE( DbgInfo );
2879 } // wireless_get_scan
2880 /*============================================================================*/
2882 #endif // WIRELESS_EXT > 13
2885 #if WIRELESS_EXT > 17
2887 static int wireless_set_auth(struct net_device *dev,
2888 struct iw_request_info *info,
2889 struct iw_param *data, char *extra)
2891 struct wl_private *lp = wl_priv(dev);
2892 unsigned long flags;
2894 int iwa_idx = data->flags & IW_AUTH_INDEX;
2895 int iwa_val = data->value;
2897 DBG_FUNC( "wireless_set_auth" );
2898 DBG_ENTER( DbgInfo );
2900 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2905 wl_lock( lp, &flags );
2907 wl_act_int_off( lp );
2910 case IW_AUTH_WPA_VERSION:
2911 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2912 /* We do support WPA only; how should DISABLED be treated? */
2913 if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2919 case IW_AUTH_WPA_ENABLED:
2920 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2922 lp->EnableEncryption = 2;
2924 lp->EnableEncryption = 0;
2928 case IW_AUTH_TKIP_COUNTERMEASURES:
2929 DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2930 lp->driverEnable = !iwa_val;
2931 if(lp->driverEnable)
2932 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2934 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2938 case IW_AUTH_DROP_UNENCRYPTED:
2939 DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2940 /* We do not actually do anything here, just to silence
2945 case IW_AUTH_CIPHER_PAIRWISE:
2946 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2947 /* not implemented, return an error */
2951 case IW_AUTH_CIPHER_GROUP:
2952 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2953 /* not implemented, return an error */
2957 case IW_AUTH_KEY_MGMT:
2958 DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2959 /* not implemented, return an error */
2963 case IW_AUTH_80211_AUTH_ALG:
2964 DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2965 /* not implemented, return an error */
2969 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2970 DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2971 /* not implemented, return an error */
2975 case IW_AUTH_ROAMING_CONTROL:
2976 DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2977 /* not implemented, return an error */
2981 case IW_AUTH_PRIVACY_INVOKED:
2982 DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2983 /* not implemented, return an error */
2988 DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2989 /* return an error */
2994 wl_act_int_on( lp );
2996 wl_unlock(lp, &flags);
2999 DBG_LEAVE( DbgInfo );
3001 } // wireless_set_auth
3002 /*============================================================================*/
3006 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
3007 int set_tx, u8 *seq, u8 *key, size_t key_len)
3012 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
3013 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
3015 DBG_FUNC( "hermes_set_key" );
3016 DBG_ENTER( DbgInfo );
3019 * Check the key index here; if 0, load as Pairwise Key, otherwise,
3020 * load as a group key. Note that for the Hermes, the RIDs for
3021 * group/pariwise keys are different from each other and different
3022 * than the default WEP keys as well.
3026 case IW_ENCODE_ALG_TKIP:
3027 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3030 * Make sure that there is no data queued up in the firmware
3031 * before setting the TKIP keys. If this check is not
3032 * performed, some data may be sent out with incorrect MIC
3033 * and cause synchronizarion errors with the AP
3035 /* Check every 1ms for 100ms */
3036 for( count = 0; count < 100; count++ )
3041 ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
3044 wl_get_info( sock, <v, ifname );
3046 if( ltv.u.u16[0] == 0 )
3054 wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
3061 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
3063 /* Load the BSSID */
3064 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
3065 buf_idx += ETH_ALEN;
3067 /* Load the TKIP key */
3068 memcpy(<v->u.u8[buf_idx], &key[0], 16);
3072 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3073 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3076 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3077 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3079 /* Load the TxMIC key */
3080 memcpy(<v->u.u8[buf_idx], &key[16], 8);
3083 /* Load the RxMIC key */
3084 memcpy(<v->u.u8[buf_idx], &key[24], 8);
3092 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3094 /* Load the key Index */
3095 ltv->u.u16[buf_idx] = key_idx;
3096 /* If this is a Tx Key, set bit 8000 */
3098 ltv->u.u16[buf_idx] |= 0x8000;
3102 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3103 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3105 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3106 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3107 memcpy(<v->u.u8[buf_idx], key, key_len);
3111 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3113 ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3123 case IW_ENCODE_ALG_WEP:
3124 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3127 case IW_ENCODE_ALG_CCMP:
3128 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3131 case IW_ENCODE_ALG_NONE:
3132 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3135 if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3136 //if (addr != NULL) {
3138 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3139 memcpy(<v->u.u8[0], addr, ETH_ALEN);
3146 /* Clear the Group TKIP keys by index */
3148 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3149 ltv->u.u16[0] = key_idx;
3158 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3162 DBG_LEAVE( DbgInfo );
3165 /*============================================================================*/
3169 static int wireless_set_encodeext (struct net_device *dev,
3170 struct iw_request_info *info,
3171 struct iw_point *erq, char *keybuf)
3173 struct wl_private *lp = wl_priv(dev);
3174 unsigned long flags;
3176 int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3178 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3180 DBG_FUNC( "wireless_set_encodeext" );
3181 DBG_ENTER( DbgInfo );
3183 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3188 if (sizeof(ext->rx_seq) != 8) {
3189 DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3194 /* Handle WEP keys via the old set encode procedure */
3195 if(ext->alg == IW_ENCODE_ALG_WEP) {
3196 struct iw_point wep_erq;
3199 /* Build request structure */
3200 wep_erq.flags = erq->flags; // take over flags with key index
3201 wep_erq.length = ext->key_len; // take length from extended key info
3202 wep_keybuf = ext->key; // pointer to the key text
3204 /* Call wireless_set_encode tot handle the WEP key */
3205 ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3209 /* Proceed for extended encode functions for WAP and NONE */
3210 wl_lock( lp, &flags );
3212 wl_act_int_off( lp );
3214 memset(<v, 0, sizeof(ltv));
3215 ret = hermes_set_key(<v, ext->alg, key_idx, ext->addr.sa_data,
3216 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3217 ext->rx_seq, ext->key, ext->key_len);
3220 DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3224 /* Put the key in HCF */
3225 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3228 if(ret == HCF_SUCCESS) {
3229 DBG_TRACE( DbgInfo, "Put key info succes\n");
3231 DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3234 wl_act_int_on( lp );
3236 wl_unlock(lp, &flags);
3239 DBG_LEAVE( DbgInfo );
3241 } // wireless_set_encodeext
3242 /*============================================================================*/
3246 static int wireless_get_genie(struct net_device *dev,
3247 struct iw_request_info *info,
3248 struct iw_point *data, char *extra)
3251 struct wl_private *lp = wl_priv(dev);
3252 unsigned long flags;
3256 DBG_FUNC( "wireless_get_genie" );
3257 DBG_ENTER( DbgInfo );
3259 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3264 wl_lock( lp, &flags );
3266 wl_act_int_off( lp );
3268 memset(<v, 0, sizeof(ltv));
3270 ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3271 lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3272 ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3274 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3276 wl_act_int_on( lp );
3278 wl_unlock(lp, &flags);
3281 DBG_LEAVE( DbgInfo );
3284 /*============================================================================*/
3287 #endif // WIRELESS_EXT > 17
3289 /*******************************************************************************
3290 * wl_wireless_stats()
3291 *******************************************************************************
3295 * Return the current device wireless statistics.
3299 * wrq - the wireless request buffer
3300 * lp - the device's private adapter structure
3305 * errno value otherwise
3307 ******************************************************************************/
3308 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3310 struct iw_statistics *pStats;
3311 struct wl_private *lp = wl_priv(dev);
3312 /*------------------------------------------------------------------------*/
3315 DBG_FUNC( "wl_wireless_stats" );
3317 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3321 /* Initialize the statistics */
3322 pStats = &( lp->wstats );
3323 pStats->qual.updated = 0x00;
3325 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3327 CFG_COMMS_QUALITY_STRCT *pQual;
3328 CFG_HERMES_TALLIES_STRCT tallies;
3331 /* Update driver status */
3334 /* Get the current link quality information */
3335 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3336 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3338 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3340 if( status == HCF_SUCCESS ) {
3341 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3344 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3345 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3346 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3348 pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
3349 HCF_MIN_COMM_QUALITY,
3350 HCF_MAX_COMM_QUALITY );
3352 pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
3353 HCF_MIN_SIGNAL_LEVEL,
3354 HCF_MAX_SIGNAL_LEVEL );
3356 pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
3357 HCF_MIN_NOISE_LEVEL,
3358 HCF_MAX_NOISE_LEVEL );
3359 #endif /* USE_DBM */
3361 pStats->qual.updated |= 0x07;
3363 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3366 /* Get the current tallies from the adapter */
3367 /* Only possible when the device is open */
3368 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3369 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3370 /* No endian translation is needed here, as CFG_TALLIES is an
3371 MSF RID; all processing is done on the host, not the card! */
3372 pStats->discard.nwid = 0L;
3373 pStats->discard.code = tallies.RxWEPUndecryptable;
3374 pStats->discard.misc = tallies.TxDiscards +
3375 tallies.RxFCSErrors +
3376 //tallies.RxDiscardsNoBuffer +
3377 tallies.TxDiscardsWrongSA;
3378 //;? Extra taken over from Linux driver based on 7.18 version
3379 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3380 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3382 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3385 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3389 DBG_LEAVE( DbgInfo );
3391 } // wl_wireless_stats
3392 /*============================================================================*/
3397 /*******************************************************************************
3398 * wl_get_wireless_stats()
3399 *******************************************************************************
3403 * Return the current device wireless statistics. This function calls
3404 * wl_wireless_stats, but acquires spinlocks first as it can be called
3405 * directly by the network layer.
3409 * wrq - the wireless request buffer
3410 * lp - the device's private adapter structure
3415 * errno value otherwise
3417 ******************************************************************************/
3418 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3420 unsigned long flags;
3421 struct wl_private *lp = wl_priv(dev);
3422 struct iw_statistics *pStats = NULL;
3423 /*------------------------------------------------------------------------*/
3425 DBG_FUNC( "wl_get_wireless_stats" );
3428 wl_lock( lp, &flags );
3430 wl_act_int_off( lp );
3433 if( lp->useRTS == 1 ) {
3434 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3438 pStats = wl_wireless_stats( dev );
3440 wl_act_int_on( lp );
3442 wl_unlock(lp, &flags);
3444 DBG_LEAVE( DbgInfo );
3446 } // wl_get_wireless_stats
3449 /*******************************************************************************
3451 *******************************************************************************
3455 * Gather wireless spy statistics.
3459 * wrq - the wireless request buffer
3460 * lp - the device's private adapter structure
3465 * errno value otherwise
3467 ******************************************************************************/
3468 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3470 struct iw_quality wstats;
3474 struct wl_private *lp = wl_priv(dev);
3475 /*------------------------------------------------------------------------*/
3478 if (!lp->spy_data.spy_number) {
3482 /* Gather wireless spy statistics: for each packet, compare the source
3483 address with out list, and if match, get the stats. */
3484 memset( stats, 0, sizeof(stats));
3485 memset( desc, 0, sizeof(DESC_STRCT));
3487 desc[0].buf_addr = stats;
3488 desc[0].BUF_SIZE = sizeof(stats);
3489 desc[0].next_desc_addr = 0; // terminate list
3491 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3493 if( status == HCF_SUCCESS ) {
3494 wstats.level = (u_char) dbm(stats[1]);
3495 wstats.noise = (u_char) dbm(stats[0]);
3496 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3500 wireless_spy_update( dev, mac, &wstats );
3503 /*============================================================================*/
3508 /*******************************************************************************
3509 * wl_wext_event_freq()
3510 *******************************************************************************
3514 * This function is used to send an event that the channel/freq
3515 * configuration for a specific device has changed.
3520 * dev - the network device for which this event is to be issued
3526 ******************************************************************************/
3527 void wl_wext_event_freq( struct net_device *dev )
3529 #if WIRELESS_EXT > 13
3530 union iwreq_data wrqu;
3531 struct wl_private *lp = wl_priv(dev);
3532 /*------------------------------------------------------------------------*/
3535 memset( &wrqu, 0, sizeof( wrqu ));
3537 wrqu.freq.m = lp->Channel;
3540 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3541 #endif /* WIRELESS_EXT > 13 */
3544 } // wl_wext_event_freq
3545 /*============================================================================*/
3550 /*******************************************************************************
3551 * wl_wext_event_mode()
3552 *******************************************************************************
3556 * This function is used to send an event that the mode of operation
3557 * for a specific device has changed.
3562 * dev - the network device for which this event is to be issued
3568 ******************************************************************************/
3569 void wl_wext_event_mode( struct net_device *dev )
3571 #if WIRELESS_EXT > 13
3572 union iwreq_data wrqu;
3573 struct wl_private *lp = wl_priv(dev);
3574 /*------------------------------------------------------------------------*/
3577 memset( &wrqu, 0, sizeof( wrqu ));
3579 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3580 wrqu.mode = IW_MODE_INFRA;
3582 wrqu.mode = IW_MODE_MASTER;
3585 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3586 #endif /* WIRELESS_EXT > 13 */
3589 } // wl_wext_event_mode
3590 /*============================================================================*/
3595 /*******************************************************************************
3596 * wl_wext_event_essid()
3597 *******************************************************************************
3601 * This function is used to send an event that the ESSID configuration for
3602 * a specific device has changed.
3607 * dev - the network device for which this event is to be issued
3613 ******************************************************************************/
3614 void wl_wext_event_essid( struct net_device *dev )
3616 #if WIRELESS_EXT > 13
3617 union iwreq_data wrqu;
3618 struct wl_private *lp = wl_priv(dev);
3619 /*------------------------------------------------------------------------*/
3622 memset( &wrqu, 0, sizeof( wrqu ));
3624 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3625 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3626 the call to wireless_send_event() must also point to where the ESSID
3628 wrqu.essid.length = strlen( lp->NetworkName );
3629 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3630 wrqu.essid.flags = 1;
3632 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3633 #endif /* WIRELESS_EXT > 13 */
3636 } // wl_wext_event_essid
3637 /*============================================================================*/
3642 /*******************************************************************************
3643 * wl_wext_event_encode()
3644 *******************************************************************************
3648 * This function is used to send an event that the encryption configuration
3649 * for a specific device has changed.
3654 * dev - the network device for which this event is to be issued
3660 ******************************************************************************/
3661 void wl_wext_event_encode( struct net_device *dev )
3663 #if WIRELESS_EXT > 13
3664 union iwreq_data wrqu;
3665 struct wl_private *lp = wl_priv(dev);
3667 /*------------------------------------------------------------------------*/
3670 memset( &wrqu, 0, sizeof( wrqu ));
3672 if( lp->EnableEncryption == 0 ) {
3673 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3675 wrqu.encoding.flags |= lp->TransmitKeyID;
3677 index = lp->TransmitKeyID - 1;
3679 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3680 if we're in AP mode */
3681 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3682 //;?should we restore this to allow smaller memory footprint
3684 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3685 if( lp->ExcludeUnencrypted ) {
3686 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3688 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3692 #endif // HCF_TYPE_AP
3694 /* Only provide the key if permissions allow */
3695 if( capable( CAP_NET_ADMIN )) {
3696 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3697 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3699 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3703 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3704 lp->DefaultKeys.key[index].key );
3705 #endif /* WIRELESS_EXT > 13 */
3708 } // wl_wext_event_encode
3709 /*============================================================================*/
3714 /*******************************************************************************
3715 * wl_wext_event_ap()
3716 *******************************************************************************
3720 * This function is used to send an event that the device has been
3721 * associated to a new AP.
3726 * dev - the network device for which this event is to be issued
3732 ******************************************************************************/
3733 void wl_wext_event_ap( struct net_device *dev )
3735 #if WIRELESS_EXT > 13
3736 union iwreq_data wrqu;
3737 struct wl_private *lp = wl_priv(dev);
3739 /*------------------------------------------------------------------------*/
3742 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3743 this event BEFORE sending the association event, as there are timing
3744 issues with the hostap supplicant. The supplicant will attempt to process
3745 an EAPOL-Key frame from an AP before receiving this information, which
3746 is required properly process the said frame. */
3747 wl_wext_event_assoc_ie( dev );
3750 lp->ltvRecord.typ = CFG_CUR_BSSID;
3751 lp->ltvRecord.len = 4;
3753 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3754 if( status == HCF_SUCCESS ) {
3755 memset( &wrqu, 0, sizeof( wrqu ));
3757 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3759 wrqu.addr.sa_family = ARPHRD_ETHER;
3761 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3764 #endif /* WIRELESS_EXT > 13 */
3767 } // wl_wext_event_ap
3768 /*============================================================================*/
3772 /*******************************************************************************
3773 * wl_wext_event_scan_complete()
3774 *******************************************************************************
3778 * This function is used to send an event that a request for a network scan
3784 * dev - the network device for which this event is to be issued
3790 ******************************************************************************/
3791 void wl_wext_event_scan_complete( struct net_device *dev )
3793 #if WIRELESS_EXT > 13
3794 union iwreq_data wrqu;
3795 /*------------------------------------------------------------------------*/
3798 memset( &wrqu, 0, sizeof( wrqu ));
3800 wrqu.addr.sa_family = ARPHRD_ETHER;
3801 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3802 #endif /* WIRELESS_EXT > 13 */
3805 } // wl_wext_event_scan_complete
3806 /*============================================================================*/
3811 /*******************************************************************************
3812 * wl_wext_event_new_sta()
3813 *******************************************************************************
3817 * This function is used to send an event that an AP has registered a new
3823 * dev - the network device for which this event is to be issued
3829 ******************************************************************************/
3830 void wl_wext_event_new_sta( struct net_device *dev )
3832 #if WIRELESS_EXT > 14
3833 union iwreq_data wrqu;
3834 /*------------------------------------------------------------------------*/
3837 memset( &wrqu, 0, sizeof( wrqu ));
3839 /* Send the station's mac address here */
3840 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3841 wrqu.addr.sa_family = ARPHRD_ETHER;
3842 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3843 #endif /* WIRELESS_EXT > 14 */
3846 } // wl_wext_event_new_sta
3847 /*============================================================================*/
3852 /*******************************************************************************
3853 * wl_wext_event_expired_sta()
3854 *******************************************************************************
3858 * This function is used to send an event that an AP has deregistered a
3864 * dev - the network device for which this event is to be issued
3870 ******************************************************************************/
3871 void wl_wext_event_expired_sta( struct net_device *dev )
3873 #if WIRELESS_EXT > 14
3874 union iwreq_data wrqu;
3875 /*------------------------------------------------------------------------*/
3878 memset( &wrqu, 0, sizeof( wrqu ));
3880 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3881 wrqu.addr.sa_family = ARPHRD_ETHER;
3882 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3883 #endif /* WIRELESS_EXT > 14 */
3886 } // wl_wext_event_expired_sta
3887 /*============================================================================*/
3892 /*******************************************************************************
3893 * wl_wext_event_mic_failed()
3894 *******************************************************************************
3898 * This function is used to send an event that MIC calculations failed.
3903 * dev - the network device for which this event is to be issued
3909 ******************************************************************************/
3910 void wl_wext_event_mic_failed( struct net_device *dev )
3912 #if WIRELESS_EXT > 14
3914 union iwreq_data wrqu;
3915 struct wl_private *lp = wl_priv(dev);
3919 WVLAN_RX_WMP_HDR *hdr;
3920 /*------------------------------------------------------------------------*/
3923 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3926 /* Cast the lookahead buffer into a RFS format */
3927 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3929 /* Cast the addresses to byte buffers, as in the above RFS they are word
3931 addr1 = (char *)hdr->address1;
3932 addr2 = (char *)hdr->address2;
3934 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3937 memset( &wrqu, 0, sizeof( wrqu ));
3938 memset( msg, 0, sizeof( msg ));
3941 /* Becuase MIC failures are not part of the Wireless Extensions yet, they
3942 must be passed as a string using an IWEVCUSTOM event. In order for the
3943 event to be effective, the string format must be known by both the
3944 driver and the supplicant. The following is the string format used by the
3945 hostap project's WPA supplicant, and will be used here until the Wireless
3946 Extensions interface adds this support:
3948 MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
3951 /* NOTE: Format of MAC address (using colons to seperate bytes) may cause
3952 a problem in future versions of the supplicant, if they ever
3953 actually parse these parameters */
3955 sprintf( msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
3956 "%s)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
3957 DbgHwAddr( addr2 ));
3959 wrqu.data.length = strlen( msg );
3960 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
3961 #endif /* WIRELESS_EXT > 14 */
3964 } // wl_wext_event_mic_failed
3965 /*============================================================================*/
3970 /*******************************************************************************
3971 * wl_wext_event_assoc_ie()
3972 *******************************************************************************
3976 * This function is used to send an event containing the WPA-IE generated
3977 * by the firmware in an association request.
3982 * dev - the network device for which this event is to be issued
3988 ******************************************************************************/
3989 void wl_wext_event_assoc_ie( struct net_device *dev )
3991 #if WIRELESS_EXT > 14
3993 union iwreq_data wrqu;
3994 struct wl_private *lp = wl_priv(dev);
3999 /*------------------------------------------------------------------------*/
4002 memset( &wrqu, 0, sizeof( wrqu ));
4003 memset( msg, 0, sizeof( msg ));
4005 /* Retrieve the Association Request IE */
4006 lp->ltvRecord.len = 45;
4007 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
4009 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
4010 if( status == HCF_SUCCESS )
4013 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
4014 wpa_ie = wl_parse_wpa_ie( &data, &length );
4016 /* Becuase this event (Association WPA-IE) is not part of the Wireless
4017 Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
4018 In order for the event to be effective, the string format must be known
4019 by both the driver and the supplicant. The following is the string format
4020 used by the hostap project's WPA supplicant, and will be used here until
4021 the Wireless Extensions interface adds this support:
4023 ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
4028 sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
4029 wrqu.data.length = strlen( msg );
4030 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
4033 #endif /* WIRELESS_EXT > 14 */
4036 } // wl_wext_event_assoc_ie
4037 /*============================================================================*/
4038 /* Structures to export the Wireless Handlers */
4040 static const iw_handler wl_handler[] =
4042 (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */
4043 (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */
4044 (iw_handler) NULL, /* SIOCSIWNWID */
4045 (iw_handler) NULL, /* SIOCGIWNWID */
4046 (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */
4047 (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */
4048 (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */
4049 (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */
4050 (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */
4051 (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */
4052 (iw_handler) NULL , /* SIOCSIWRANGE */
4053 (iw_handler) wireless_get_range, /* SIOCGIWRANGE */
4054 (iw_handler) NULL , /* SIOCSIWPRIV */
4055 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
4056 (iw_handler) NULL , /* SIOCSIWSTATS */
4057 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
4058 iw_handler_set_spy, /* SIOCSIWSPY */
4059 iw_handler_get_spy, /* SIOCGIWSPY */
4060 NULL, /* SIOCSIWTHRSPY */
4061 NULL, /* SIOCGIWTHRSPY */
4062 (iw_handler) NULL, /* SIOCSIWAP */
4063 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4064 (iw_handler) wireless_get_bssid, /* SIOCGIWAP */
4066 (iw_handler) NULL, /* SIOCGIWAP */
4068 (iw_handler) NULL, /* SIOCSIWMLME */
4069 (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */
4070 (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */
4071 (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */
4072 (iw_handler) wireless_set_essid, /* SIOCSIWESSID */
4073 (iw_handler) wireless_get_essid, /* SIOCGIWESSID */
4074 (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */
4075 (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */
4076 (iw_handler) NULL, /* -- hole -- */
4077 (iw_handler) NULL, /* -- hole -- */
4078 (iw_handler) wireless_set_rate, /* SIOCSIWRATE */
4079 (iw_handler) wireless_get_rate, /* SIOCGIWRATE */
4080 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
4081 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
4082 (iw_handler) NULL, /* SIOCSIWFRAG */
4083 (iw_handler) NULL, /* SIOCGIWFRAG */
4084 (iw_handler) NULL, /* SIOCSIWTXPOW */
4085 (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */
4086 (iw_handler) NULL, /* SIOCSIWRETRY */
4087 (iw_handler) NULL, /* SIOCGIWRETRY */
4088 (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */
4089 (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */
4090 (iw_handler) wireless_set_power, /* SIOCSIWPOWER */
4091 (iw_handler) wireless_get_power, /* SIOCGIWPOWER */
4092 (iw_handler) NULL, /* -- hole -- */
4093 (iw_handler) NULL, /* -- hole -- */
4094 (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */
4095 (iw_handler) NULL, /* SIOCGIWGENIE */
4096 (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */
4097 (iw_handler) NULL, /* SIOCGIWAUTH */
4098 (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */
4099 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
4100 (iw_handler) NULL, /* SIOCSIWPMKSA */
4101 (iw_handler) NULL, /* -- hole -- */
4104 static const iw_handler wl_private_handler[] =
4105 { /* SIOCIWFIRSTPRIV + */
4106 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
4107 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
4108 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
4109 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
4110 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4111 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
4112 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
4116 struct iw_priv_args wl_priv_args[] = {
4117 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
4118 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
4119 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
4120 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
4121 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
4122 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
4123 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
4127 const struct iw_handler_def wl_iw_handler_def =
4129 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
4130 .private = (iw_handler *) wl_private_handler,
4131 .private_args = (struct iw_priv_args *) wl_priv_args,
4132 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
4133 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
4134 .standard = (iw_handler *) wl_handler,
4135 .get_wireless_stats = wl_get_wireless_stats,
4138 #endif // WIRELESS_EXT