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/bitops.h>
78 #include <linux/netdevice.h>
79 #include <linux/etherdevice.h>
80 // #include <linux/skbuff.h>
81 // #include <linux/if_arp.h>
82 // #include <linux/ioport.h>
86 // #include <hcfdef.h>
89 #include <wl_internal.h>
96 /*******************************************************************************
98 ******************************************************************************/
100 /* A matrix which maps channels to frequencies */
101 static const long chan_freq_list[][2] =
132 extern dbg_info_t *DbgInfo;
138 /*******************************************************************************
140 *******************************************************************************
144 * Return an energy value in dBm.
148 * value - the energy value to be converted
154 ******************************************************************************/
157 /* Truncate the value to be between min and max. */
158 if( value < HCF_MIN_SIGNAL_LEVEL )
159 value = HCF_MIN_SIGNAL_LEVEL;
161 if( value > HCF_MAX_SIGNAL_LEVEL )
162 value = HCF_MAX_SIGNAL_LEVEL;
164 /* Return the energy value in dBm. */
165 return ( value - HCF_0DBM_OFFSET );
167 /*============================================================================*/
172 /*******************************************************************************
174 *******************************************************************************
178 * Return a value as a percentage of min to max.
182 * value - the value in question
183 * min - the minimum range value
184 * max - the maximum range value
188 * the percentage value
190 ******************************************************************************/
191 int percent( int value, int min, int max )
193 /* Truncate the value to be between min and max. */
200 /* Return the value as a percentage of min to max. */
201 return ((( value - min ) * 100 ) / ( max - min ));
203 /*============================================================================*/
208 /*******************************************************************************
209 * is_valid_key_string()
210 *******************************************************************************
214 * Checks to determine if the WEP key string is valid
218 * s - the string in question
222 * non-zero if the string contains a valid key
224 ******************************************************************************/
225 int is_valid_key_string( char *s )
229 /*------------------------------------------------------------------------*/
234 /* 0x followed by 5 or 13 hexadecimal digit pairs is valid */
235 if( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' )) {
236 if( l == 12 || l == 28 ) {
237 for( i = 2; i < l; i++ ) {
238 if( !isxdigit( s[i] ))
248 /* string with 0, 5, or 13 characters is valid */
251 return( l == 0 || l == 5 || l == 13 );
253 } // is_valid_key_string
254 /*============================================================================*/
259 /*******************************************************************************
261 *******************************************************************************
265 * Converts a key_string to a key, Assumes the key_string is validated with
266 * is_valid_key_string().
270 * ks - the valid key string
271 * key - a pointer to a KEY_STRUCT where the converted key information will
278 ******************************************************************************/
279 void key_string2key( char *ks, KEY_STRCT *key )
283 /*------------------------------------------------------------------------*/
288 /* 0x followed by hexadecimal digit pairs */
289 if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
291 p = (char *)key->key;
293 for( i = 2; i < l; i+=2 ) {
294 *p++ = (hex_to_bin(ks[i]) << 4) + hex_to_bin(ks[i+1]);
298 /* Note that endian translation of the length field is not needed here
299 because it's performed in wl_put_ltv() */
302 /* character string */
305 strcpy( (char *)key->key, ks );
311 /*============================================================================*/
316 /*******************************************************************************
318 *******************************************************************************
322 * Checks to see if the device supports WEP
326 * ifbp - the IFB pointer of the device in question
330 * 1 if WEP is known enabled, else 0
332 ******************************************************************************/
333 int wl_has_wep (IFBP ifbp)
335 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
337 /*------------------------------------------------------------------------*/
340 /* This function allows us to distiguish bronze cards from other types, to
341 know if WEP exists. Does not distinguish (because there's no way to)
342 between silver and gold cards. */
344 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
346 rc = hcf_get_info( ifbp, (LTVP) <v );
348 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
350 //return rc ? 0 : privacy;
353 /*============================================================================*/
358 /*******************************************************************************
360 *******************************************************************************
364 * Report the type of HCF error message
372 * A descriptive string indicating the error, quiet otherwise.
374 ******************************************************************************/
375 void wl_hcf_error( struct net_device *dev, int hcfStatus )
377 char buffer[64], *pMsg;
378 /*------------------------------------------------------------------------*/
381 if( hcfStatus != HCF_SUCCESS ) {
382 switch( hcfStatus ) {
384 case HCF_ERR_TIME_OUT:
386 pMsg = "Expected adapter event did not occur in expected time";
392 pMsg = "Card not found (ejected unexpectedly)";
398 pMsg = "Command buffer size insufficient";
402 case HCF_ERR_INCOMP_PRI:
404 pMsg = "Primary functions are not compatible";
408 case HCF_ERR_INCOMP_FW:
410 pMsg = "Primary functions are compatible, "
411 "station/ap functions are not";
417 pMsg = "Inquire cmd while another Inquire in progress";
421 //case HCF_ERR_SEQ_BUG:
423 // pMsg = "Unexpected command completed";
427 case HCF_ERR_DEFUNCT_AUX:
429 pMsg = "Timeout on ack for enable/disable of AUX registers";
433 case HCF_ERR_DEFUNCT_TIMER:
434 pMsg = "Timeout on timer calibration during initialization process";
438 case HCF_ERR_DEFUNCT_TIME_OUT:
439 pMsg = "Timeout on Busy bit drop during BAP setup";
443 case HCF_ERR_DEFUNCT_CMD_SEQ:
444 pMsg = "Hermes and HCF are out of sync";
450 sprintf( buffer, "Error code %d", hcfStatus );
455 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
459 /*============================================================================*/
464 /*******************************************************************************
465 * wl_endian_translate_event()
466 *******************************************************************************
470 * Determines what type of data is in the mailbox and performs the proper
471 * endian translation.
475 * pLtv - an LTV pointer
481 ******************************************************************************/
482 void wl_endian_translate_event( ltv_t *pLtv )
484 switch( pLtv->typ ) {
492 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
494 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
495 (sizeof( SCAN_RS_STRCT )));
497 while( numAPs >= 1 ) {
500 pAps[numAPs].channel_id =
501 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
503 pAps[numAPs].noise_level =
504 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
506 pAps[numAPs].signal_level =
507 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
509 pAps[numAPs].beacon_interval_time =
510 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
512 pAps[numAPs].capability =
513 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
515 pAps[numAPs].ssid_len =
516 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
518 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
527 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
529 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
530 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
531 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
532 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
535 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
538 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
539 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
540 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
546 #define ls ((LINK_STATUS_STRCT *)pLtv)
547 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
553 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
555 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
560 case CFG_SECURITY_STAT:
562 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
564 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
565 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
582 DBG_LEAVE( DbgInfo );
584 } // wl_endian_translate_event
585 /*============================================================================*/
588 /*******************************************************************************
590 *******************************************************************************
594 * Print statement used to display asserts from within the HCF. Only called
595 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
599 * file_namep - the filename in which the assert occurred.
600 * line_number - the line number on which the assert occurred.
601 * trace - a comment associated with the assert.
602 * qual - return code or other value related to the assert
608 ******************************************************************************/
609 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
611 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
613 /*============================================================================*/
618 /*******************************************************************************
620 *******************************************************************************
624 * This function parses the Direct Sequence Parameter Set IE, used to
625 * determine channel/frequency information.
629 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
634 * The channel on which the BSS represented by this probe response is
637 ******************************************************************************/
638 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
644 /*------------------------------------------------------------------------*/
647 if( probe_rsp == NULL ) {
651 buf = probe_rsp->rawData;
652 buf_size = sizeof( probe_rsp->rawData );
655 for( i = 0; i < buf_size; i++ ) {
656 if( buf[i] == DS_INFO_ELEM ) {
657 /* Increment by 1 to get the length, and test it; in a DS element,
658 length should always be 1 */
663 /* Get the channel information */
670 /* If we get here, we didn't find a DS-IE, which is strange */
675 /*******************************************************************************
677 *******************************************************************************
681 * This function parses the Probe Response for a valid WPA-IE.
685 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
687 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
688 * be stored (if found).
692 * A pointer to the location in the probe response buffer where a valid
693 * WPA-IE lives. The length of this IE is written back to the 'length'
694 * argument passed to the function.
696 ******************************************************************************/
697 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
703 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
704 /*------------------------------------------------------------------------*/
707 if( probe_rsp == NULL || length == NULL ) {
711 buf = probe_rsp->rawData;
712 buf_size = sizeof( probe_rsp->rawData );
716 for( i = 0; i < buf_size; i++ ) {
717 if( buf[i] == GENERIC_INFO_ELEM ) {
718 /* Increment by one to get the IE length */
720 ie_length = probe_rsp->rawData[i];
722 /* Increment by one to point to the IE payload */
725 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
726 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
727 /* Pass back length and return a pointer to the WPA-IE */
728 /* NOTE: Length contained in the WPA-IE is only the length of
729 the payload. The entire WPA-IE, including the IE identifier
730 and the length, is 2 bytes larger */
731 *length = ie_length + 2;
733 /* Back up the pointer 2 bytes to include the IE identifier and
734 the length in the buffer returned */
739 /* Increment past this non-WPA IE and continue looking */
740 i += ( ie_length - 1 );
744 /* If we're here, we didn't find a WPA-IE in the buffer */
749 /*******************************************************************************
751 *******************************************************************************
755 * Function used to take a WPA Information Element (WPA-IE) buffer and
756 * display it in a readable format.
760 * buffer - the byte buffer containing the WPA-IE
761 * length - the length of the above buffer
765 * A pointer to the formatted WPA-IE string. Note that the format used is
766 * byte-by-byte printing as %02x hex values with no spaces. This is
767 * required for proper operation with some WPA supplicants.
769 ******************************************************************************/
770 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
777 static hcf_8 output[512];
778 /*------------------------------------------------------------------------*/
781 memset( output, 0, sizeof( output ));
782 memset( row_buf, 0, sizeof( row_buf ));
785 /* Determine how many rows will be needed, and the remainder */
786 rows = length / rowsize;
787 remainder = length % rowsize;
790 /* Format the rows */
791 for( count = 0; count < rows; count++ ) {
792 sprintf( row_buf, "%02x%02x%02x%02x",
793 buffer[count*rowsize], buffer[count*rowsize+1],
794 buffer[count*rowsize+2], buffer[count*rowsize+3]);
795 strcat( output, row_buf );
798 memset( row_buf, 0, sizeof( row_buf ));
801 /* Format the remainder */
802 for( count = 0; count < remainder; count++ ) {
803 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
804 strcat( output, row_buf );
809 /*============================================================================*/
814 /*******************************************************************************
815 * wl_is_a_valid_chan()
816 *******************************************************************************
820 * Checks if a given channel is valid
824 * channel - the channel
831 ******************************************************************************/
832 int wl_is_a_valid_chan( int channel )
835 /*------------------------------------------------------------------------*/
838 /* Strip out the high bit set by the FW for 802.11a channels */
839 if( channel & 0x100 ) {
840 channel = channel & 0x0FF;
843 /* Iterate through the matrix and retrieve the frequency */
844 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
845 if( chan_freq_list[i][0] == channel ) {
851 } // wl_is_a_valid_chan
852 /*============================================================================*/
857 /*******************************************************************************
858 * wl_get_chan_from_freq()
859 *******************************************************************************
863 * Checks if a given frequency is valid
867 * freq - the frequency
874 ******************************************************************************/
875 int wl_is_a_valid_freq( long frequency )
878 /*------------------------------------------------------------------------*/
881 /* Iterate through the matrix and retrieve the channel */
882 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
883 if( chan_freq_list[i][1] == frequency ) {
889 } // wl_is_a_valid_freq
890 /*============================================================================*/
895 /*******************************************************************************
896 * wl_get_freq_from_chan()
897 *******************************************************************************
901 * Function used to look up the frequency for a given channel on which the
906 * channel - the channel
910 * The corresponding frequency
912 ******************************************************************************/
913 long wl_get_freq_from_chan( int channel )
916 /*------------------------------------------------------------------------*/
919 /* Strip out the high bit set by the FW for 802.11a channels */
920 if( channel & 0x100 ) {
921 channel = channel & 0x0FF;
924 /* Iterate through the matrix and retrieve the frequency */
925 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
926 if( chan_freq_list[i][0] == channel ) {
927 return chan_freq_list[i][1];
932 } // wl_get_freq_from_chan
933 /*============================================================================*/
938 /*******************************************************************************
939 * wl_get_chan_from_freq()
940 *******************************************************************************
944 * Function used to look up the channel for a given frequency on which the
949 * frequency - the frequency
953 * The corresponding channel
955 ******************************************************************************/
956 int wl_get_chan_from_freq( long frequency )
959 /*------------------------------------------------------------------------*/
962 /* Iterate through the matrix and retrieve the channel */
963 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
964 if( chan_freq_list[i][1] == frequency ) {
965 return chan_freq_list[i][0];
970 } // wl_get_chan_from_freq
971 /*============================================================================*/
976 /*******************************************************************************
977 * wl_process_link_status()
978 *******************************************************************************
982 * Process the link status message signaled by the device.
986 * lp - a pointer to the device's private structure
992 ******************************************************************************/
993 void wl_process_link_status( struct wl_private *lp )
998 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
999 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1000 switch( link_stat ) {
1002 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1003 wl_wext_event_ap( lp->dev );
1006 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1009 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1012 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1015 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1018 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1022 DBG_LEAVE( DbgInfo );
1024 } // wl_process_link_status
1025 /*============================================================================*/
1030 /*******************************************************************************
1031 * wl_process_probe_response()
1032 *******************************************************************************
1036 * Process the probe responses retunred by the device as a result of an
1041 * lp - a pointer to the device's private structure
1047 ******************************************************************************/
1048 void wl_process_probe_response( struct wl_private *lp )
1050 PROBE_RESP *probe_rsp;
1051 hcf_8 *wpa_ie = NULL;
1052 hcf_16 wpa_ie_len = 0;
1055 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1057 wl_endian_translate_event( (ltv_t *)probe_rsp );
1059 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1060 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1061 probe_rsp->length );
1063 if( probe_rsp->length > 1 ) {
1064 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1065 probe_rsp->infoType );
1067 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1068 probe_rsp->signal );
1070 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1071 probe_rsp->silence );
1073 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1074 probe_rsp->rxFlow );
1076 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1079 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1080 probe_rsp->frameControl );
1082 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1085 DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name,
1086 probe_rsp->address1);
1088 DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name,
1089 probe_rsp->address2);
1091 DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name,
1094 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1095 probe_rsp->sequence );
1097 DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name,
1098 probe_rsp->address4);
1100 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1101 probe_rsp->dataLength );
1103 DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name,
1106 DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name,
1111 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1112 probe_rsp->channel );
1114 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1117 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1118 probe_rsp->lenType );
1121 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1123 probe_rsp->timeStamp[0],
1124 probe_rsp->timeStamp[1],
1125 probe_rsp->timeStamp[2],
1126 probe_rsp->timeStamp[3],
1127 probe_rsp->timeStamp[4],
1128 probe_rsp->timeStamp[5],
1129 probe_rsp->timeStamp[6],
1130 probe_rsp->timeStamp[7]);
1132 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1133 probe_rsp->beaconInterval );
1135 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1136 probe_rsp->capability );
1138 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1139 probe_rsp->rawData[1] );
1142 if( probe_rsp->rawData[1] > 0 ) {
1143 char ssid[HCF_MAX_NAME_LEN];
1145 memset( ssid, 0, sizeof( ssid ));
1146 strncpy( ssid, &probe_rsp->rawData[2],
1147 probe_rsp->rawData[1] );
1149 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1150 lp->dev->name, ssid );
1154 /* Parse out the WPA-IE, if one exists */
1155 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1156 if( wpa_ie != NULL ) {
1157 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1158 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1161 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1162 lp->dev->name, probe_rsp->flags );
1165 DBG_TRACE( DbgInfo, "\n" );
1168 /* If probe response length is 1, then the scan is complete */
1169 if( probe_rsp->length == 1 ) {
1170 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1171 lp->probe_results.num_aps = lp->probe_num_aps;
1172 lp->probe_results.scan_complete = TRUE;
1174 /* Reset the counter for the next scan request */
1175 lp->probe_num_aps = 0;
1177 /* Send a wireless extensions event that the scan completed */
1178 wl_wext_event_scan_complete( lp->dev );
1180 /* Only copy to the table if the entry is unique; APs sometimes
1181 respond more than once to a probe */
1182 if( lp->probe_num_aps == 0 ) {
1183 /* Copy the info to the ScanResult structure in the private
1185 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1186 probe_rsp, sizeof( PROBE_RESP ));
1188 /* Increment the number of APs detected */
1189 lp->probe_num_aps++;
1194 for( count = 0; count < lp->probe_num_aps; count++ ) {
1195 if( memcmp( &( probe_rsp->BSSID ),
1196 lp->probe_results.ProbeTable[count].BSSID,
1203 /* Copy the info to the ScanResult structure in the
1204 private adapter struct. Only copy if there's room in the
1206 if( lp->probe_num_aps < MAX_NAPS )
1208 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1209 probe_rsp, sizeof( PROBE_RESP ));
1213 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1216 /* Increment the number of APs detected. Note I do this
1217 here even when I don't copy the probe response to the
1218 buffer in order to detect the overflow condition */
1219 lp->probe_num_aps++;
1225 DBG_LEAVE( DbgInfo );
1227 } // wl_process_probe_response
1228 /*============================================================================*/
1233 /*******************************************************************************
1234 * wl_process_updated_record()
1235 *******************************************************************************
1239 * Process the updated information record message signaled by the device.
1243 * lp - a pointer to the device's private structure
1249 ******************************************************************************/
1250 void wl_process_updated_record( struct wl_private *lp )
1253 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1255 switch( lp->updatedRecord.u.u16[0] ) {
1256 case CFG_CUR_COUNTRY_INFO:
1257 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1262 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1267 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1268 lp->updatedRecord.u.u16[0] );
1272 DBG_LEAVE( DbgInfo );
1274 } // wl_process_updated_record
1275 /*============================================================================*/
1280 /*******************************************************************************
1281 * wl_process_assoc_status()
1282 *******************************************************************************
1286 * Process the association status event signaled by the device.
1290 * lp - a pointer to the device's private structure
1296 ******************************************************************************/
1297 void wl_process_assoc_status( struct wl_private *lp )
1299 ASSOC_STATUS_STRCT *assoc_stat;
1302 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1304 wl_endian_translate_event( (ltv_t *)assoc_stat );
1306 switch( assoc_stat->assocStatus ) {
1308 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1312 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1316 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1320 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1321 assoc_stat->assocStatus );
1325 DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr);
1327 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1328 DBG_TRACE(DbgInfo, "Old AP Address : %pM\n",
1329 assoc_stat->oldApAddr);
1333 DBG_LEAVE( DbgInfo );
1335 } // wl_process_assoc_status
1336 /*============================================================================*/
1341 /*******************************************************************************
1342 * wl_process_security_status()
1343 *******************************************************************************
1347 * Process the security status message signaled by the device.
1351 * lp - a pointer to the device's private structure
1357 ******************************************************************************/
1358 void wl_process_security_status( struct wl_private *lp )
1360 SECURITY_STATUS_STRCT *sec_stat;
1363 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1365 wl_endian_translate_event( (ltv_t *)sec_stat );
1367 switch( sec_stat->securityStatus ) {
1369 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1373 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1377 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1381 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1385 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1389 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1390 sec_stat->securityStatus );
1394 DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr);
1395 DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason);
1399 DBG_LEAVE( DbgInfo );
1401 } // wl_process_security_status
1402 /*============================================================================*/
1404 int wl_get_tallies(struct wl_private *lp,
1405 CFG_HERMES_TALLIES_STRCT *tallies)
1409 CFG_HERMES_TALLIES_STRCT *pTallies;
1411 /* Get the current tallies from the adapter */
1412 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1413 lp->ltvRecord.typ = CFG_TALLIES;
1415 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1417 if( status == HCF_SUCCESS ) {
1418 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1419 memcpy(tallies, pTallies, sizeof(*tallies));
1420 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1422 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1426 DBG_LEAVE( DbgInfo );