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 DBG_FUNC( "wl_endian_translate_event" );
485 DBG_ENTER( DbgInfo );
488 switch( pLtv->typ ) {
496 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
498 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
499 (sizeof( SCAN_RS_STRCT )));
501 while( numAPs >= 1 ) {
504 pAps[numAPs].channel_id =
505 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
507 pAps[numAPs].noise_level =
508 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
510 pAps[numAPs].signal_level =
511 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
513 pAps[numAPs].beacon_interval_time =
514 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
516 pAps[numAPs].capability =
517 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
519 pAps[numAPs].ssid_len =
520 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
522 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
531 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
533 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
534 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
535 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
536 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
539 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
542 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
543 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
544 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
550 #define ls ((LINK_STATUS_STRCT *)pLtv)
551 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
557 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
559 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
564 case CFG_SECURITY_STAT:
566 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
568 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
569 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
586 DBG_LEAVE( DbgInfo );
588 } // wl_endian_translate_event
589 /*============================================================================*/
592 /*******************************************************************************
594 *******************************************************************************
598 * Print statement used to display asserts from within the HCF. Only called
599 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
603 * file_namep - the filename in which the assert occurred.
604 * line_number - the line number on which the assert occurred.
605 * trace - a comment associated with the assert.
606 * qual - return code or other value related to the assert
612 ******************************************************************************/
613 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
615 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
617 /*============================================================================*/
622 /*******************************************************************************
624 *******************************************************************************
628 * This function parses the Direct Sequence Parameter Set IE, used to
629 * determine channel/frequency information.
633 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
638 * The channel on which the BSS represented by this probe response is
641 ******************************************************************************/
642 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
648 /*------------------------------------------------------------------------*/
651 if( probe_rsp == NULL ) {
655 buf = probe_rsp->rawData;
656 buf_size = sizeof( probe_rsp->rawData );
659 for( i = 0; i < buf_size; i++ ) {
660 if( buf[i] == DS_INFO_ELEM ) {
661 /* Increment by 1 to get the length, and test it; in a DS element,
662 length should always be 1 */
667 /* Get the channel information */
674 /* If we get here, we didn't find a DS-IE, which is strange */
679 /*******************************************************************************
681 *******************************************************************************
685 * This function parses the Probe Response for a valid WPA-IE.
689 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
691 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
692 * be stored (if found).
696 * A pointer to the location in the probe response buffer where a valid
697 * WPA-IE lives. The length of this IE is written back to the 'length'
698 * argument passed to the function.
700 ******************************************************************************/
701 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
707 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
708 /*------------------------------------------------------------------------*/
711 if( probe_rsp == NULL || length == NULL ) {
715 buf = probe_rsp->rawData;
716 buf_size = sizeof( probe_rsp->rawData );
720 for( i = 0; i < buf_size; i++ ) {
721 if( buf[i] == GENERIC_INFO_ELEM ) {
722 /* Increment by one to get the IE length */
724 ie_length = probe_rsp->rawData[i];
726 /* Increment by one to point to the IE payload */
729 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
730 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
731 /* Pass back length and return a pointer to the WPA-IE */
732 /* NOTE: Length contained in the WPA-IE is only the length of
733 the payload. The entire WPA-IE, including the IE identifier
734 and the length, is 2 bytes larger */
735 *length = ie_length + 2;
737 /* Back up the pointer 2 bytes to include the IE identifier and
738 the length in the buffer returned */
743 /* Increment past this non-WPA IE and continue looking */
744 i += ( ie_length - 1 );
748 /* If we're here, we didn't find a WPA-IE in the buffer */
753 /*******************************************************************************
755 *******************************************************************************
759 * Function used to take a WPA Information Element (WPA-IE) buffer and
760 * display it in a readable format.
764 * buffer - the byte buffer containing the WPA-IE
765 * length - the length of the above buffer
769 * A pointer to the formatted WPA-IE string. Note that the format used is
770 * byte-by-byte printing as %02x hex values with no spaces. This is
771 * required for proper operation with some WPA supplicants.
773 ******************************************************************************/
774 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
781 static hcf_8 output[512];
782 /*------------------------------------------------------------------------*/
785 memset( output, 0, sizeof( output ));
786 memset( row_buf, 0, sizeof( row_buf ));
789 /* Determine how many rows will be needed, and the remainder */
790 rows = length / rowsize;
791 remainder = length % rowsize;
794 /* Format the rows */
795 for( count = 0; count < rows; count++ ) {
796 sprintf( row_buf, "%02x%02x%02x%02x",
797 buffer[count*rowsize], buffer[count*rowsize+1],
798 buffer[count*rowsize+2], buffer[count*rowsize+3]);
799 strcat( output, row_buf );
802 memset( row_buf, 0, sizeof( row_buf ));
805 /* Format the remainder */
806 for( count = 0; count < remainder; count++ ) {
807 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
808 strcat( output, row_buf );
813 /*============================================================================*/
818 /*******************************************************************************
819 * wl_is_a_valid_chan()
820 *******************************************************************************
824 * Checks if a given channel is valid
828 * channel - the channel
835 ******************************************************************************/
836 int wl_is_a_valid_chan( int channel )
839 /*------------------------------------------------------------------------*/
842 /* Strip out the high bit set by the FW for 802.11a channels */
843 if( channel & 0x100 ) {
844 channel = channel & 0x0FF;
847 /* Iterate through the matrix and retrieve the frequency */
848 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
849 if( chan_freq_list[i][0] == channel ) {
855 } // wl_is_a_valid_chan
856 /*============================================================================*/
861 /*******************************************************************************
862 * wl_get_chan_from_freq()
863 *******************************************************************************
867 * Checks if a given frequency is valid
871 * freq - the frequency
878 ******************************************************************************/
879 int wl_is_a_valid_freq( long frequency )
882 /*------------------------------------------------------------------------*/
885 /* Iterate through the matrix and retrieve the channel */
886 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
887 if( chan_freq_list[i][1] == frequency ) {
893 } // wl_is_a_valid_freq
894 /*============================================================================*/
899 /*******************************************************************************
900 * wl_get_freq_from_chan()
901 *******************************************************************************
905 * Function used to look up the frequency for a given channel on which the
910 * channel - the channel
914 * The corresponding frequency
916 ******************************************************************************/
917 long wl_get_freq_from_chan( int channel )
920 /*------------------------------------------------------------------------*/
923 /* Strip out the high bit set by the FW for 802.11a channels */
924 if( channel & 0x100 ) {
925 channel = channel & 0x0FF;
928 /* Iterate through the matrix and retrieve the frequency */
929 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
930 if( chan_freq_list[i][0] == channel ) {
931 return chan_freq_list[i][1];
936 } // wl_get_freq_from_chan
937 /*============================================================================*/
942 /*******************************************************************************
943 * wl_get_chan_from_freq()
944 *******************************************************************************
948 * Function used to look up the channel for a given frequency on which the
953 * frequency - the frequency
957 * The corresponding channel
959 ******************************************************************************/
960 int wl_get_chan_from_freq( long frequency )
963 /*------------------------------------------------------------------------*/
966 /* Iterate through the matrix and retrieve the channel */
967 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
968 if( chan_freq_list[i][1] == frequency ) {
969 return chan_freq_list[i][0];
974 } // wl_get_chan_from_freq
975 /*============================================================================*/
980 /*******************************************************************************
981 * wl_process_link_status()
982 *******************************************************************************
986 * Process the link status message signaled by the device.
990 * lp - a pointer to the device's private structure
996 ******************************************************************************/
997 void wl_process_link_status( struct wl_private *lp )
1000 /*------------------------------------------------------------------------*/
1002 DBG_FUNC( "wl_process_link_status" );
1003 DBG_ENTER( DbgInfo );
1006 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1007 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1008 switch( link_stat ) {
1010 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1011 wl_wext_event_ap( lp->dev );
1014 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1017 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1020 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1023 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1026 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1030 DBG_LEAVE( DbgInfo );
1032 } // wl_process_link_status
1033 /*============================================================================*/
1038 /*******************************************************************************
1039 * wl_process_probe_response()
1040 *******************************************************************************
1044 * Process the probe responses retunred by the device as a result of an
1049 * lp - a pointer to the device's private structure
1055 ******************************************************************************/
1056 void wl_process_probe_response( struct wl_private *lp )
1058 PROBE_RESP *probe_rsp;
1059 hcf_8 *wpa_ie = NULL;
1060 hcf_16 wpa_ie_len = 0;
1061 /*------------------------------------------------------------------------*/
1064 DBG_FUNC( "wl_process_probe_response" );
1065 DBG_ENTER( DbgInfo );
1069 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1071 wl_endian_translate_event( (ltv_t *)probe_rsp );
1073 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1074 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1075 probe_rsp->length );
1077 if( probe_rsp->length > 1 ) {
1078 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1079 probe_rsp->infoType );
1081 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1082 probe_rsp->signal );
1084 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1085 probe_rsp->silence );
1087 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1088 probe_rsp->rxFlow );
1090 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1093 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1094 probe_rsp->frameControl );
1096 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1099 DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name,
1100 probe_rsp->address1);
1102 DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name,
1103 probe_rsp->address2);
1105 DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name,
1108 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1109 probe_rsp->sequence );
1111 DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name,
1112 probe_rsp->address4);
1114 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1115 probe_rsp->dataLength );
1117 DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name,
1120 DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name,
1125 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1126 probe_rsp->channel );
1128 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1131 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1132 probe_rsp->lenType );
1135 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1137 probe_rsp->timeStamp[0],
1138 probe_rsp->timeStamp[1],
1139 probe_rsp->timeStamp[2],
1140 probe_rsp->timeStamp[3],
1141 probe_rsp->timeStamp[4],
1142 probe_rsp->timeStamp[5],
1143 probe_rsp->timeStamp[6],
1144 probe_rsp->timeStamp[7]);
1146 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1147 probe_rsp->beaconInterval );
1149 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1150 probe_rsp->capability );
1152 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1153 probe_rsp->rawData[1] );
1156 if( probe_rsp->rawData[1] > 0 ) {
1157 char ssid[HCF_MAX_NAME_LEN];
1159 memset( ssid, 0, sizeof( ssid ));
1160 strncpy( ssid, &probe_rsp->rawData[2],
1161 probe_rsp->rawData[1] );
1163 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1164 lp->dev->name, ssid );
1168 /* Parse out the WPA-IE, if one exists */
1169 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1170 if( wpa_ie != NULL ) {
1171 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1172 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1175 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1176 lp->dev->name, probe_rsp->flags );
1179 DBG_TRACE( DbgInfo, "\n" );
1182 /* If probe response length is 1, then the scan is complete */
1183 if( probe_rsp->length == 1 ) {
1184 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1185 lp->probe_results.num_aps = lp->probe_num_aps;
1186 lp->probe_results.scan_complete = TRUE;
1188 /* Reset the counter for the next scan request */
1189 lp->probe_num_aps = 0;
1191 /* Send a wireless extensions event that the scan completed */
1192 wl_wext_event_scan_complete( lp->dev );
1194 /* Only copy to the table if the entry is unique; APs sometimes
1195 respond more than once to a probe */
1196 if( lp->probe_num_aps == 0 ) {
1197 /* Copy the info to the ScanResult structure in the private
1199 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1200 probe_rsp, sizeof( PROBE_RESP ));
1202 /* Increment the number of APs detected */
1203 lp->probe_num_aps++;
1208 for( count = 0; count < lp->probe_num_aps; count++ ) {
1209 if( memcmp( &( probe_rsp->BSSID ),
1210 lp->probe_results.ProbeTable[count].BSSID,
1217 /* Copy the info to the ScanResult structure in the
1218 private adapter struct. Only copy if there's room in the
1220 if( lp->probe_num_aps < MAX_NAPS )
1222 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1223 probe_rsp, sizeof( PROBE_RESP ));
1227 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1230 /* Increment the number of APs detected. Note I do this
1231 here even when I don't copy the probe response to the
1232 buffer in order to detect the overflow condition */
1233 lp->probe_num_aps++;
1239 DBG_LEAVE( DbgInfo );
1241 } // wl_process_probe_response
1242 /*============================================================================*/
1247 /*******************************************************************************
1248 * wl_process_updated_record()
1249 *******************************************************************************
1253 * Process the updated information record message signaled by the device.
1257 * lp - a pointer to the device's private structure
1263 ******************************************************************************/
1264 void wl_process_updated_record( struct wl_private *lp )
1266 DBG_FUNC( "wl_process_updated_record" );
1267 DBG_ENTER( DbgInfo );
1271 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1273 switch( lp->updatedRecord.u.u16[0] ) {
1274 case CFG_CUR_COUNTRY_INFO:
1275 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1280 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1285 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1286 lp->updatedRecord.u.u16[0] );
1290 DBG_LEAVE( DbgInfo );
1292 } // wl_process_updated_record
1293 /*============================================================================*/
1298 /*******************************************************************************
1299 * wl_process_assoc_status()
1300 *******************************************************************************
1304 * Process the association status event signaled by the device.
1308 * lp - a pointer to the device's private structure
1314 ******************************************************************************/
1315 void wl_process_assoc_status( struct wl_private *lp )
1317 ASSOC_STATUS_STRCT *assoc_stat;
1318 /*------------------------------------------------------------------------*/
1321 DBG_FUNC( "wl_process_assoc_status" );
1322 DBG_ENTER( DbgInfo );
1326 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1328 wl_endian_translate_event( (ltv_t *)assoc_stat );
1330 switch( assoc_stat->assocStatus ) {
1332 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1336 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1340 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1344 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1345 assoc_stat->assocStatus );
1349 DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr);
1351 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1352 DBG_TRACE(DbgInfo, "Old AP Address : %pM\n",
1353 assoc_stat->oldApAddr);
1357 DBG_LEAVE( DbgInfo );
1359 } // wl_process_assoc_status
1360 /*============================================================================*/
1365 /*******************************************************************************
1366 * wl_process_security_status()
1367 *******************************************************************************
1371 * Process the security status message signaled by the device.
1375 * lp - a pointer to the device's private structure
1381 ******************************************************************************/
1382 void wl_process_security_status( struct wl_private *lp )
1384 SECURITY_STATUS_STRCT *sec_stat;
1385 /*------------------------------------------------------------------------*/
1388 DBG_FUNC( "wl_process_security_status" );
1389 DBG_ENTER( DbgInfo );
1393 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1395 wl_endian_translate_event( (ltv_t *)sec_stat );
1397 switch( sec_stat->securityStatus ) {
1399 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1403 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1407 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1411 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1415 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1419 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1420 sec_stat->securityStatus );
1424 DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr);
1425 DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason);
1429 DBG_LEAVE( DbgInfo );
1431 } // wl_process_security_status
1432 /*============================================================================*/
1434 int wl_get_tallies(struct wl_private *lp,
1435 CFG_HERMES_TALLIES_STRCT *tallies)
1439 CFG_HERMES_TALLIES_STRCT *pTallies;
1441 DBG_FUNC( "wl_get_tallies" );
1444 /* Get the current tallies from the adapter */
1445 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1446 lp->ltvRecord.typ = CFG_TALLIES;
1448 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1450 if( status == HCF_SUCCESS ) {
1451 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1452 memcpy(tallies, pTallies, sizeof(*tallies));
1453 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1455 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1459 DBG_LEAVE( DbgInfo );