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 *------------------------------------------------------------------------------
14 * This file defines misc utility functions.
16 *------------------------------------------------------------------------------
20 * This software is provided subject to the following terms and conditions,
21 * which you should read carefully before using the software. Using this
22 * software indicates your acceptance of these terms and conditions. If you do
23 * not agree with these terms and conditions, do not use the software.
25 * Copyright © 2003 Agere Systems Inc.
26 * All rights reserved.
28 * Redistribution and use in source or binary forms, with or without
29 * modifications, are permitted provided that the following conditions are met:
31 * . Redistributions of source code must retain the above copyright notice, this
32 * list of conditions and the following Disclaimer as comments in the code as
33 * well as in the documentation and/or other materials provided with the
36 * . Redistributions in binary form must reproduce the above copyright notice,
37 * this list of conditions and the following Disclaimer in the documentation
38 * and/or other materials provided with the distribution.
40 * . Neither the name of Agere Systems Inc. nor the names of the contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED
\93AS IS
\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
47 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
48 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
49 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
50 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
56 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
59 ******************************************************************************/
61 /*******************************************************************************
63 ******************************************************************************/
64 #include <wl_version.h>
66 #include <linux/kernel.h>
67 // #include <linux/sched.h>
68 // #include <linux/ptrace.h>
69 #include <linux/ctype.h>
70 // #include <linux/string.h>
71 // #include <linux/timer.h>
72 // #include <linux/interrupt.h>
73 // #include <linux/in.h>
74 // #include <linux/delay.h>
75 // #include <asm/io.h>
76 // #include <asm/system.h>
77 // #include <asm/bitops.h>
79 #include <linux/netdevice.h>
80 #include <linux/etherdevice.h>
81 // #include <linux/skbuff.h>
82 // #include <linux/if_arp.h>
83 // #include <linux/ioport.h>
87 // #include <hcfdef.h>
90 #include <wl_internal.h>
97 /*******************************************************************************
99 ******************************************************************************/
101 /* A matrix which maps channels to frequencies */
102 #define MAX_CHAN_FREQ_MAP_ENTRIES 50
103 static const long chan_freq_list[][MAX_CHAN_FREQ_MAP_ENTRIES] =
134 extern dbg_info_t *DbgInfo;
140 /*******************************************************************************
142 *******************************************************************************
146 * Return an energy value in dBm.
150 * value - the energy value to be converted
156 ******************************************************************************/
159 /* Truncate the value to be between min and max. */
160 if( value < HCF_MIN_SIGNAL_LEVEL )
161 value = HCF_MIN_SIGNAL_LEVEL;
163 if( value > HCF_MAX_SIGNAL_LEVEL )
164 value = HCF_MAX_SIGNAL_LEVEL;
166 /* Return the energy value in dBm. */
167 return ( value - HCF_0DBM_OFFSET );
169 /*============================================================================*/
174 /*******************************************************************************
176 *******************************************************************************
180 * Return a value as a percentage of min to max.
184 * value - the value in question
185 * min - the minimum range value
186 * max - the maximum range value
190 * the percentage value
192 ******************************************************************************/
193 int percent( int value, int min, int max )
195 /* Truncate the value to be between min and max. */
202 /* Return the value as a percentage of min to max. */
203 return ((( value - min ) * 100 ) / ( max - min ));
205 /*============================================================================*/
210 /*******************************************************************************
211 * is_valid_key_string()
212 *******************************************************************************
216 * Checks to determine if the WEP key string is valid
220 * s - the string in question
224 * non-zero if the string contains a valid key
226 ******************************************************************************/
227 int is_valid_key_string( char *s )
231 /*------------------------------------------------------------------------*/
236 /* 0x followed by 5 or 13 hexadecimal digit pairs is valid */
237 if( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' )) {
238 if( l == 12 || l == 28 ) {
239 for( i = 2; i < l; i++ ) {
240 if( !isxdigit( s[i] ))
250 /* string with 0, 5, or 13 characters is valid */
253 return( l == 0 || l == 5 || l == 13 );
255 } // is_valid_key_string
256 /*============================================================================*/
261 /*******************************************************************************
263 *******************************************************************************
267 * Converts a hexadecimal digit character to an integer
271 * c - the hexadecimal digit character
275 * the converted integer
277 ******************************************************************************/
278 int hexdigit2int( char c )
280 if( c >= '0' && c <= '9' )
283 if( c >= 'A' && c <= 'F' )
286 if( c >= 'a' && c <= 'f' )
291 /*============================================================================*/
296 /*******************************************************************************
298 *******************************************************************************
302 * Converts a key_string to a key, Assumes the key_string is validated with
303 * is_valid_key_string().
307 * ks - the valid key string
308 * key - a pointer to a KEY_STRUCT where the converted key information will
315 ******************************************************************************/
316 void key_string2key( char *ks, KEY_STRCT *key )
320 /*------------------------------------------------------------------------*/
325 /* 0x followed by hexadecimal digit pairs */
326 if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
328 p = (char *)key->key;
330 for( i = 2; i < l; i+=2 ) {
331 *p++ = ( hexdigit2int( ks[i] ) << 4 ) + hexdigit2int (ks[i+1] );
335 /* Note that endian translation of the length field is not needed here
336 because it's performed in wl_put_ltv() */
339 /* character string */
342 strcpy( (char *)key->key, ks );
348 /*============================================================================*/
354 /*******************************************************************************
356 *******************************************************************************
360 * Convert a hardware ethernet address to a character string
364 * hwAddr - an ethernet address
368 * a pointer to a string representing the ethernet address
370 ******************************************************************************/
371 const char *DbgHwAddr(unsigned char *hwAddr)
373 static char buffer[18];
374 /*------------------------------------------------------------------------*/
377 sprintf( buffer, "%02X:%02X:%02X:%02X:%02X:%02X",
378 hwAddr[0], hwAddr[1], hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5] );
382 /*============================================================================*/
389 /*******************************************************************************
391 *******************************************************************************
395 * Checks to see if the device supports WEP
399 * ifbp - the IFB pointer of the device in question
403 * 1 if WEP is known enabled, else 0
405 ******************************************************************************/
406 int wl_has_wep (IFBP ifbp)
408 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
410 /*------------------------------------------------------------------------*/
413 /* This function allows us to distiguish bronze cards from other types, to
414 know if WEP exists. Does not distinguish (because there's no way to)
415 between silver and gold cards. */
417 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
419 rc = hcf_get_info( ifbp, (LTVP) <v );
421 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
423 //return rc ? 0 : privacy;
426 /*============================================================================*/
431 /*******************************************************************************
433 *******************************************************************************
437 * Report the type of HCF error message
445 * A descriptive string indicating the error, quiet otherwise.
447 ******************************************************************************/
448 void wl_hcf_error( struct net_device *dev, int hcfStatus )
450 char buffer[64], *pMsg;
451 /*------------------------------------------------------------------------*/
454 if( hcfStatus != HCF_SUCCESS ) {
455 switch( hcfStatus ) {
457 case HCF_ERR_TIME_OUT:
459 pMsg = "Expected adapter event did not occur in expected time";
465 pMsg = "Card not found (ejected unexpectedly)";
471 pMsg = "Command buffer size insufficient";
475 case HCF_ERR_INCOMP_PRI:
477 pMsg = "Primary functions are not compatible";
481 case HCF_ERR_INCOMP_FW:
483 pMsg = "Primary functions are compatible, "
484 "station/ap functions are not";
490 pMsg = "Inquire cmd while another Inquire in progress";
494 //case HCF_ERR_SEQ_BUG:
496 // pMsg = "Unexpected command completed";
500 case HCF_ERR_DEFUNCT_AUX:
502 pMsg = "Timeout on ack for enable/disable of AUX registers";
506 case HCF_ERR_DEFUNCT_TIMER:
507 pMsg = "Timeout on timer calibration during initialization process";
511 case HCF_ERR_DEFUNCT_TIME_OUT:
512 pMsg = "Timeout on Busy bit drop during BAP setup";
516 case HCF_ERR_DEFUNCT_CMD_SEQ:
517 pMsg = "Hermes and HCF are out of sync";
523 sprintf( buffer, "Error code %d", hcfStatus );
528 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
532 /*============================================================================*/
537 /*******************************************************************************
538 * wl_endian_translate_event()
539 *******************************************************************************
543 * Determines what type of data is in the mailbox and performs the proper
544 * endian translation.
548 * pLtv - an LTV pointer
554 ******************************************************************************/
555 void wl_endian_translate_event( ltv_t *pLtv )
557 DBG_FUNC( "wl_endian_translate_event" );
558 DBG_ENTER( DbgInfo );
561 switch( pLtv->typ ) {
569 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
571 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
572 (sizeof( SCAN_RS_STRCT )));
574 while( numAPs >= 1 ) {
577 pAps[numAPs].channel_id =
578 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
580 pAps[numAPs].noise_level =
581 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
583 pAps[numAPs].signal_level =
584 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
586 pAps[numAPs].beacon_interval_time =
587 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
589 pAps[numAPs].capability =
590 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
592 pAps[numAPs].ssid_len =
593 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
595 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
604 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
606 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
607 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
608 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
609 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
612 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
615 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
616 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
617 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
623 #define ls ((LINK_STATUS_STRCT *)pLtv)
624 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
630 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
632 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
637 case CFG_SECURITY_STAT:
639 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
641 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
642 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
659 DBG_LEAVE( DbgInfo );
661 } // wl_endian_translate_event
662 /*============================================================================*/
665 /*******************************************************************************
667 *******************************************************************************
671 * Print statement used to display asserts from within the HCF. Only called
672 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
676 * file_namep - the filename in which the assert occurred.
677 * line_number - the line number on which the assert occurred.
678 * trace - a comment associated with the assert.
679 * qual - return code or other value related to the assert
685 ******************************************************************************/
686 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
688 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
690 /*============================================================================*/
695 /*******************************************************************************
697 *******************************************************************************
701 * This function parses the Direct Sequence Parameter Set IE, used to
702 * determine channel/frequency information.
706 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
711 * The channel on which the BSS represented by this probe response is
714 ******************************************************************************/
715 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
721 /*------------------------------------------------------------------------*/
724 if( probe_rsp == NULL ) {
728 buf = probe_rsp->rawData;
729 buf_size = sizeof( probe_rsp->rawData );
732 for( i = 0; i < buf_size; i++ ) {
733 if( buf[i] == DS_INFO_ELEM ) {
734 /* Increment by 1 to get the length, and test it; in a DS element,
735 length should always be 1 */
740 /* Get the channel information */
747 /* If we get here, we didn't find a DS-IE, which is strange */
752 /*******************************************************************************
754 *******************************************************************************
758 * This function parses the Probe Response for a valid WPA-IE.
762 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
764 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
765 * be stored (if found).
769 * A pointer to the location in the probe response buffer where a valid
770 * WPA-IE lives. The length of this IE is written back to the 'length'
771 * argument passed to the function.
773 ******************************************************************************/
774 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
780 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
781 /*------------------------------------------------------------------------*/
784 if( probe_rsp == NULL || length == NULL ) {
788 buf = probe_rsp->rawData;
789 buf_size = sizeof( probe_rsp->rawData );
793 for( i = 0; i < buf_size; i++ ) {
794 if( buf[i] == GENERIC_INFO_ELEM ) {
795 /* Increment by one to get the IE length */
797 ie_length = probe_rsp->rawData[i];
799 /* Increment by one to point to the IE payload */
802 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
803 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
804 /* Pass back length and return a pointer to the WPA-IE */
805 /* NOTE: Length contained in the WPA-IE is only the length of
806 the payload. The entire WPA-IE, including the IE identifier
807 and the length, is 2 bytes larger */
808 *length = ie_length + 2;
810 /* Back up the pointer 2 bytes to include the IE identifier and
811 the length in the buffer returned */
816 /* Increment past this non-WPA IE and continue looking */
817 i += ( ie_length - 1 );
821 /* If we're here, we didn't find a WPA-IE in the buffer */
826 /*******************************************************************************
828 *******************************************************************************
832 * Function used to take a WPA Information Element (WPA-IE) buffer and
833 * display it in a readable format.
837 * buffer - the byte buffer containing the WPA-IE
838 * length - the length of the above buffer
842 * A pointer to the formatted WPA-IE string. Note that the format used is
843 * byte-by-byte printing as %02x hex values with no spaces. This is
844 * required for proper operation with some WPA supplicants.
846 ******************************************************************************/
847 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
854 static hcf_8 output[512];
855 /*------------------------------------------------------------------------*/
858 memset( output, 0, sizeof( output ));
859 memset( row_buf, 0, sizeof( row_buf ));
862 /* Determine how many rows will be needed, and the remainder */
863 rows = length / rowsize;
864 remainder = length % rowsize;
867 /* Format the rows */
868 for( count = 0; count < rows; count++ ) {
869 sprintf( row_buf, "%02x%02x%02x%02x",
870 buffer[count*rowsize], buffer[count*rowsize+1],
871 buffer[count*rowsize+2], buffer[count*rowsize+3]);
872 strcat( output, row_buf );
875 memset( row_buf, 0, sizeof( row_buf ));
878 /* Format the remainder */
879 for( count = 0; count < remainder; count++ ) {
880 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
881 strcat( output, row_buf );
886 /*============================================================================*/
891 /*******************************************************************************
892 * wl_is_a_valid_chan()
893 *******************************************************************************
897 * Checks if a given channel is valid
901 * channel - the channel
908 ******************************************************************************/
909 int wl_is_a_valid_chan( int channel )
912 /*------------------------------------------------------------------------*/
915 /* Strip out the high bit set by the FW for 802.11a channels */
916 if( channel & 0x100 ) {
917 channel = channel & 0x0FF;
920 /* Iterate through the matrix and retrieve the frequency */
921 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
922 if( chan_freq_list[i][0] == channel ) {
928 } // wl_is_a_valid_chan
929 /*============================================================================*/
934 /*******************************************************************************
935 * wl_get_chan_from_freq()
936 *******************************************************************************
940 * Checks if a given frequency is valid
944 * freq - the frequency
951 ******************************************************************************/
952 int wl_is_a_valid_freq( long frequency )
955 /*------------------------------------------------------------------------*/
958 /* Iterate through the matrix and retrieve the channel */
959 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
960 if( chan_freq_list[i][1] == frequency ) {
966 } // wl_is_a_valid_freq
967 /*============================================================================*/
972 /*******************************************************************************
973 * wl_get_freq_from_chan()
974 *******************************************************************************
978 * Function used to look up the frequency for a given channel on which the
983 * channel - the channel
987 * The corresponding frequency
989 ******************************************************************************/
990 long wl_get_freq_from_chan( int channel )
993 /*------------------------------------------------------------------------*/
996 /* Strip out the high bit set by the FW for 802.11a channels */
997 if( channel & 0x100 ) {
998 channel = channel & 0x0FF;
1001 /* Iterate through the matrix and retrieve the frequency */
1002 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
1003 if( chan_freq_list[i][0] == channel ) {
1004 return chan_freq_list[i][1];
1009 } // wl_get_freq_from_chan
1010 /*============================================================================*/
1015 /*******************************************************************************
1016 * wl_get_chan_from_freq()
1017 *******************************************************************************
1021 * Function used to look up the channel for a given frequency on which the
1026 * frequency - the frequency
1030 * The corresponding channel
1032 ******************************************************************************/
1033 int wl_get_chan_from_freq( long frequency )
1036 /*------------------------------------------------------------------------*/
1039 /* Iterate through the matrix and retrieve the channel */
1040 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
1041 if( chan_freq_list[i][1] == frequency ) {
1042 return chan_freq_list[i][0];
1047 } // wl_get_chan_from_freq
1048 /*============================================================================*/
1053 /*******************************************************************************
1054 * wl_process_link_status()
1055 *******************************************************************************
1059 * Process the link status message signaled by the device.
1063 * lp - a pointer to the device's private structure
1069 ******************************************************************************/
1070 void wl_process_link_status( struct wl_private *lp )
1073 /*------------------------------------------------------------------------*/
1075 DBG_FUNC( "wl_process_link_status" );
1076 DBG_ENTER( DbgInfo );
1079 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1080 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1081 switch( link_stat ) {
1083 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1084 wl_wext_event_ap( lp->dev );
1087 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1090 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1093 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1096 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1099 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1103 DBG_LEAVE( DbgInfo );
1105 } // wl_process_link_status
1106 /*============================================================================*/
1111 /*******************************************************************************
1112 * wl_process_probe_response()
1113 *******************************************************************************
1117 * Process the probe responses retunred by the device as a result of an
1122 * lp - a pointer to the device's private structure
1128 ******************************************************************************/
1129 void wl_process_probe_response( struct wl_private *lp )
1131 PROBE_RESP *probe_rsp;
1132 hcf_8 *wpa_ie = NULL;
1133 hcf_16 wpa_ie_len = 0;
1134 /*------------------------------------------------------------------------*/
1137 DBG_FUNC( "wl_process_probe_response" );
1138 DBG_ENTER( DbgInfo );
1142 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1144 wl_endian_translate_event( (ltv_t *)probe_rsp );
1146 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1147 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1148 probe_rsp->length );
1150 if( probe_rsp->length > 1 ) {
1151 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1152 probe_rsp->infoType );
1154 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1155 probe_rsp->signal );
1157 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1158 probe_rsp->silence );
1160 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1161 probe_rsp->rxFlow );
1163 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1166 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1167 probe_rsp->frameControl );
1169 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1172 DBG_TRACE( DbgInfo, "(%s) address1 : %s\n", lp->dev->name,
1173 DbgHwAddr( probe_rsp->address1 ));
1175 DBG_TRACE( DbgInfo, "(%s) address2 : %s\n", lp->dev->name,
1176 DbgHwAddr( probe_rsp->address2 ));
1178 DBG_TRACE( DbgInfo, "(%s) BSSID : %s\n", lp->dev->name,
1179 DbgHwAddr( probe_rsp->BSSID ));
1181 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1182 probe_rsp->sequence );
1184 DBG_TRACE( DbgInfo, "(%s) address4 : %s\n", lp->dev->name,
1185 DbgHwAddr( probe_rsp->address4 ));
1187 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1188 probe_rsp->dataLength );
1190 DBG_TRACE( DbgInfo, "(%s) DA : %s\n", lp->dev->name,
1191 DbgHwAddr( probe_rsp->DA ));
1193 DBG_TRACE( DbgInfo, "(%s) SA : %s\n", lp->dev->name,
1194 DbgHwAddr( probe_rsp->SA ));
1198 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1199 probe_rsp->channel );
1201 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1204 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1205 probe_rsp->lenType );
1208 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1210 probe_rsp->timeStamp[0],
1211 probe_rsp->timeStamp[1],
1212 probe_rsp->timeStamp[2],
1213 probe_rsp->timeStamp[3],
1214 probe_rsp->timeStamp[4],
1215 probe_rsp->timeStamp[5],
1216 probe_rsp->timeStamp[6],
1217 probe_rsp->timeStamp[7]);
1219 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1220 probe_rsp->beaconInterval );
1222 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1223 probe_rsp->capability );
1225 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1226 probe_rsp->rawData[1] );
1229 if( probe_rsp->rawData[1] > 0 ) {
1230 char ssid[HCF_MAX_NAME_LEN];
1232 memset( ssid, 0, sizeof( ssid ));
1233 strncpy( ssid, &probe_rsp->rawData[2],
1234 probe_rsp->rawData[1] );
1236 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1237 lp->dev->name, ssid );
1241 /* Parse out the WPA-IE, if one exists */
1242 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1243 if( wpa_ie != NULL ) {
1244 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1245 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1248 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1249 lp->dev->name, probe_rsp->flags );
1252 DBG_TRACE( DbgInfo, "\n" );
1255 /* If probe response length is 1, then the scan is complete */
1256 if( probe_rsp->length == 1 ) {
1257 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1258 lp->probe_results.num_aps = lp->probe_num_aps;
1259 lp->probe_results.scan_complete = TRUE;
1261 /* Reset the counter for the next scan request */
1262 lp->probe_num_aps = 0;
1264 /* Send a wireless extensions event that the scan completed */
1265 wl_wext_event_scan_complete( lp->dev );
1267 /* Only copy to the table if the entry is unique; APs sometimes
1268 respond more than once to a probe */
1269 if( lp->probe_num_aps == 0 ) {
1270 /* Copy the info to the ScanResult structure in the private
1272 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1273 probe_rsp, sizeof( PROBE_RESP ));
1275 /* Increment the number of APs detected */
1276 lp->probe_num_aps++;
1281 for( count = 0; count < lp->probe_num_aps; count++ ) {
1282 if( memcmp( &( probe_rsp->BSSID ),
1283 lp->probe_results.ProbeTable[count].BSSID,
1290 /* Copy the info to the ScanResult structure in the
1291 private adapter struct. Only copy if there's room in the
1293 if( lp->probe_num_aps < MAX_NAPS )
1295 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1296 probe_rsp, sizeof( PROBE_RESP ));
1300 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1303 /* Increment the number of APs detected. Note I do this
1304 here even when I don't copy the probe response to the
1305 buffer in order to detect the overflow condition */
1306 lp->probe_num_aps++;
1312 DBG_LEAVE( DbgInfo );
1314 } // wl_process_probe_response
1315 /*============================================================================*/
1320 /*******************************************************************************
1321 * wl_process_updated_record()
1322 *******************************************************************************
1326 * Process the updated information record message signaled by the device.
1330 * lp - a pointer to the device's private structure
1336 ******************************************************************************/
1337 void wl_process_updated_record( struct wl_private *lp )
1339 DBG_FUNC( "wl_process_updated_record" );
1340 DBG_ENTER( DbgInfo );
1344 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1346 switch( lp->updatedRecord.u.u16[0] ) {
1347 case CFG_CUR_COUNTRY_INFO:
1348 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1353 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1358 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1359 lp->updatedRecord.u.u16[0] );
1363 DBG_LEAVE( DbgInfo );
1365 } // wl_process_updated_record
1366 /*============================================================================*/
1371 /*******************************************************************************
1372 * wl_process_assoc_status()
1373 *******************************************************************************
1377 * Process the association status event signaled by the device.
1381 * lp - a pointer to the device's private structure
1387 ******************************************************************************/
1388 void wl_process_assoc_status( struct wl_private *lp )
1390 ASSOC_STATUS_STRCT *assoc_stat;
1391 /*------------------------------------------------------------------------*/
1394 DBG_FUNC( "wl_process_assoc_status" );
1395 DBG_ENTER( DbgInfo );
1399 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1401 wl_endian_translate_event( (ltv_t *)assoc_stat );
1403 switch( assoc_stat->assocStatus ) {
1405 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1409 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1413 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1417 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1418 assoc_stat->assocStatus );
1422 DBG_TRACE( DbgInfo, "STA Address : %s\n",
1423 DbgHwAddr( assoc_stat->staAddr ));
1425 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1426 DBG_TRACE( DbgInfo, "Old AP Address : %s\n",
1427 DbgHwAddr( assoc_stat->oldApAddr ));
1431 DBG_LEAVE( DbgInfo );
1433 } // wl_process_assoc_status
1434 /*============================================================================*/
1439 /*******************************************************************************
1440 * wl_process_security_status()
1441 *******************************************************************************
1445 * Process the security status message signaled by the device.
1449 * lp - a pointer to the device's private structure
1455 ******************************************************************************/
1456 void wl_process_security_status( struct wl_private *lp )
1458 SECURITY_STATUS_STRCT *sec_stat;
1459 /*------------------------------------------------------------------------*/
1462 DBG_FUNC( "wl_process_security_status" );
1463 DBG_ENTER( DbgInfo );
1467 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1469 wl_endian_translate_event( (ltv_t *)sec_stat );
1471 switch( sec_stat->securityStatus ) {
1473 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1477 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1481 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1485 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1489 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1493 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1494 sec_stat->securityStatus );
1498 DBG_TRACE( DbgInfo, "STA Address : %s\n",
1499 DbgHwAddr( sec_stat->staAddr ));
1500 DBG_TRACE( DbgInfo, "Reason : 0x%04x \n", sec_stat->reason );
1504 DBG_LEAVE( DbgInfo );
1506 } // wl_process_security_status
1507 /*============================================================================*/
1509 int wl_get_tallies(struct wl_private *lp,
1510 CFG_HERMES_TALLIES_STRCT *tallies)
1514 CFG_HERMES_TALLIES_STRCT *pTallies;
1516 DBG_FUNC( "wl_get_tallies" );
1519 /* Get the current tallies from the adapter */
1520 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1521 lp->ltvRecord.typ = CFG_TALLIES;
1523 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1525 if( status == HCF_SUCCESS ) {
1526 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1527 memcpy(tallies, pTallies, sizeof(*tallies));
1528 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1530 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1534 DBG_LEAVE( DbgInfo );
1539 /*******************************************************************************
1541 *******************************************************************************
1545 * Believe it or not, we need our own implementation of atoi in the kernel.
1549 * string - the ASCII string to convert to an integer
1555 ******************************************************************************/
1556 unsigned int wl_atoi( char *string )
1558 unsigned int base = 10; //default to decimal
1559 unsigned int value = 0;
1561 int i = strlen( string );
1563 if ( i > 2 && string[0] == '0' && ( string[1] | ('X'^'x') ) == 'x' ) {
1567 while ( ( c = *string++ ) != '\0' ) {
1568 if ( value > UINT_MAX / base ) { //test for overrun
1569 DBG_FUNC( "wl_atoi" ); //don't overload the log file with good messages
1570 DBG_ENTER( DbgInfo );
1571 DBG_ERROR( DbgInfo, "string \"%s\", lenght exceeds expectations\n", string );
1572 printk( "<1>string \"%s\", lenght exceeds expectations\n", string );
1573 DBG_LEAVE( DbgInfo );
1577 if ( 0 <= c && c <= 9 ) value = base * value + c;
1578 else if ( base == 16 ) {
1582 if ( 10 <= c && c <= 15 ) value = base * value + c;