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_ENTER( DbgInfo );
487 switch( pLtv->typ ) {
495 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
497 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
498 (sizeof( SCAN_RS_STRCT )));
500 while( numAPs >= 1 ) {
503 pAps[numAPs].channel_id =
504 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
506 pAps[numAPs].noise_level =
507 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
509 pAps[numAPs].signal_level =
510 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
512 pAps[numAPs].beacon_interval_time =
513 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
515 pAps[numAPs].capability =
516 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
518 pAps[numAPs].ssid_len =
519 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
521 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
530 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
532 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
533 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
534 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
535 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
538 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
541 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
542 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
543 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
549 #define ls ((LINK_STATUS_STRCT *)pLtv)
550 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
556 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
558 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
563 case CFG_SECURITY_STAT:
565 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
567 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
568 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
585 DBG_LEAVE( DbgInfo );
587 } // wl_endian_translate_event
588 /*============================================================================*/
591 /*******************************************************************************
593 *******************************************************************************
597 * Print statement used to display asserts from within the HCF. Only called
598 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
602 * file_namep - the filename in which the assert occurred.
603 * line_number - the line number on which the assert occurred.
604 * trace - a comment associated with the assert.
605 * qual - return code or other value related to the assert
611 ******************************************************************************/
612 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
614 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
616 /*============================================================================*/
621 /*******************************************************************************
623 *******************************************************************************
627 * This function parses the Direct Sequence Parameter Set IE, used to
628 * determine channel/frequency information.
632 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
637 * The channel on which the BSS represented by this probe response is
640 ******************************************************************************/
641 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
647 /*------------------------------------------------------------------------*/
650 if( probe_rsp == NULL ) {
654 buf = probe_rsp->rawData;
655 buf_size = sizeof( probe_rsp->rawData );
658 for( i = 0; i < buf_size; i++ ) {
659 if( buf[i] == DS_INFO_ELEM ) {
660 /* Increment by 1 to get the length, and test it; in a DS element,
661 length should always be 1 */
666 /* Get the channel information */
673 /* If we get here, we didn't find a DS-IE, which is strange */
678 /*******************************************************************************
680 *******************************************************************************
684 * This function parses the Probe Response for a valid WPA-IE.
688 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
690 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
691 * be stored (if found).
695 * A pointer to the location in the probe response buffer where a valid
696 * WPA-IE lives. The length of this IE is written back to the 'length'
697 * argument passed to the function.
699 ******************************************************************************/
700 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
706 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
707 /*------------------------------------------------------------------------*/
710 if( probe_rsp == NULL || length == NULL ) {
714 buf = probe_rsp->rawData;
715 buf_size = sizeof( probe_rsp->rawData );
719 for( i = 0; i < buf_size; i++ ) {
720 if( buf[i] == GENERIC_INFO_ELEM ) {
721 /* Increment by one to get the IE length */
723 ie_length = probe_rsp->rawData[i];
725 /* Increment by one to point to the IE payload */
728 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
729 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
730 /* Pass back length and return a pointer to the WPA-IE */
731 /* NOTE: Length contained in the WPA-IE is only the length of
732 the payload. The entire WPA-IE, including the IE identifier
733 and the length, is 2 bytes larger */
734 *length = ie_length + 2;
736 /* Back up the pointer 2 bytes to include the IE identifier and
737 the length in the buffer returned */
742 /* Increment past this non-WPA IE and continue looking */
743 i += ( ie_length - 1 );
747 /* If we're here, we didn't find a WPA-IE in the buffer */
752 /*******************************************************************************
754 *******************************************************************************
758 * Function used to take a WPA Information Element (WPA-IE) buffer and
759 * display it in a readable format.
763 * buffer - the byte buffer containing the WPA-IE
764 * length - the length of the above buffer
768 * A pointer to the formatted WPA-IE string. Note that the format used is
769 * byte-by-byte printing as %02x hex values with no spaces. This is
770 * required for proper operation with some WPA supplicants.
772 ******************************************************************************/
773 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
780 static hcf_8 output[512];
781 /*------------------------------------------------------------------------*/
784 memset( output, 0, sizeof( output ));
785 memset( row_buf, 0, sizeof( row_buf ));
788 /* Determine how many rows will be needed, and the remainder */
789 rows = length / rowsize;
790 remainder = length % rowsize;
793 /* Format the rows */
794 for( count = 0; count < rows; count++ ) {
795 sprintf( row_buf, "%02x%02x%02x%02x",
796 buffer[count*rowsize], buffer[count*rowsize+1],
797 buffer[count*rowsize+2], buffer[count*rowsize+3]);
798 strcat( output, row_buf );
801 memset( row_buf, 0, sizeof( row_buf ));
804 /* Format the remainder */
805 for( count = 0; count < remainder; count++ ) {
806 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
807 strcat( output, row_buf );
812 /*============================================================================*/
817 /*******************************************************************************
818 * wl_is_a_valid_chan()
819 *******************************************************************************
823 * Checks if a given channel is valid
827 * channel - the channel
834 ******************************************************************************/
835 int wl_is_a_valid_chan( int channel )
838 /*------------------------------------------------------------------------*/
841 /* Strip out the high bit set by the FW for 802.11a channels */
842 if( channel & 0x100 ) {
843 channel = channel & 0x0FF;
846 /* Iterate through the matrix and retrieve the frequency */
847 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
848 if( chan_freq_list[i][0] == channel ) {
854 } // wl_is_a_valid_chan
855 /*============================================================================*/
860 /*******************************************************************************
861 * wl_get_chan_from_freq()
862 *******************************************************************************
866 * Checks if a given frequency is valid
870 * freq - the frequency
877 ******************************************************************************/
878 int wl_is_a_valid_freq( long frequency )
881 /*------------------------------------------------------------------------*/
884 /* Iterate through the matrix and retrieve the channel */
885 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
886 if( chan_freq_list[i][1] == frequency ) {
892 } // wl_is_a_valid_freq
893 /*============================================================================*/
898 /*******************************************************************************
899 * wl_get_freq_from_chan()
900 *******************************************************************************
904 * Function used to look up the frequency for a given channel on which the
909 * channel - the channel
913 * The corresponding frequency
915 ******************************************************************************/
916 long wl_get_freq_from_chan( int channel )
919 /*------------------------------------------------------------------------*/
922 /* Strip out the high bit set by the FW for 802.11a channels */
923 if( channel & 0x100 ) {
924 channel = channel & 0x0FF;
927 /* Iterate through the matrix and retrieve the frequency */
928 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
929 if( chan_freq_list[i][0] == channel ) {
930 return chan_freq_list[i][1];
935 } // wl_get_freq_from_chan
936 /*============================================================================*/
941 /*******************************************************************************
942 * wl_get_chan_from_freq()
943 *******************************************************************************
947 * Function used to look up the channel for a given frequency on which the
952 * frequency - the frequency
956 * The corresponding channel
958 ******************************************************************************/
959 int wl_get_chan_from_freq( long frequency )
962 /*------------------------------------------------------------------------*/
965 /* Iterate through the matrix and retrieve the channel */
966 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
967 if( chan_freq_list[i][1] == frequency ) {
968 return chan_freq_list[i][0];
973 } // wl_get_chan_from_freq
974 /*============================================================================*/
979 /*******************************************************************************
980 * wl_process_link_status()
981 *******************************************************************************
985 * Process the link status message signaled by the device.
989 * lp - a pointer to the device's private structure
995 ******************************************************************************/
996 void wl_process_link_status( struct wl_private *lp )
999 /*------------------------------------------------------------------------*/
1001 DBG_ENTER( DbgInfo );
1004 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1005 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1006 switch( link_stat ) {
1008 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1009 wl_wext_event_ap( lp->dev );
1012 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1015 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1018 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1021 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1024 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1028 DBG_LEAVE( DbgInfo );
1030 } // wl_process_link_status
1031 /*============================================================================*/
1036 /*******************************************************************************
1037 * wl_process_probe_response()
1038 *******************************************************************************
1042 * Process the probe responses retunred by the device as a result of an
1047 * lp - a pointer to the device's private structure
1053 ******************************************************************************/
1054 void wl_process_probe_response( struct wl_private *lp )
1056 PROBE_RESP *probe_rsp;
1057 hcf_8 *wpa_ie = NULL;
1058 hcf_16 wpa_ie_len = 0;
1059 /*------------------------------------------------------------------------*/
1062 DBG_ENTER( DbgInfo );
1066 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1068 wl_endian_translate_event( (ltv_t *)probe_rsp );
1070 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1071 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1072 probe_rsp->length );
1074 if( probe_rsp->length > 1 ) {
1075 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1076 probe_rsp->infoType );
1078 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1079 probe_rsp->signal );
1081 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1082 probe_rsp->silence );
1084 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1085 probe_rsp->rxFlow );
1087 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1090 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1091 probe_rsp->frameControl );
1093 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1096 DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name,
1097 probe_rsp->address1);
1099 DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name,
1100 probe_rsp->address2);
1102 DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name,
1105 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1106 probe_rsp->sequence );
1108 DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name,
1109 probe_rsp->address4);
1111 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1112 probe_rsp->dataLength );
1114 DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name,
1117 DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name,
1122 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1123 probe_rsp->channel );
1125 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1128 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1129 probe_rsp->lenType );
1132 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1134 probe_rsp->timeStamp[0],
1135 probe_rsp->timeStamp[1],
1136 probe_rsp->timeStamp[2],
1137 probe_rsp->timeStamp[3],
1138 probe_rsp->timeStamp[4],
1139 probe_rsp->timeStamp[5],
1140 probe_rsp->timeStamp[6],
1141 probe_rsp->timeStamp[7]);
1143 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1144 probe_rsp->beaconInterval );
1146 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1147 probe_rsp->capability );
1149 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1150 probe_rsp->rawData[1] );
1153 if( probe_rsp->rawData[1] > 0 ) {
1154 char ssid[HCF_MAX_NAME_LEN];
1156 memset( ssid, 0, sizeof( ssid ));
1157 strncpy( ssid, &probe_rsp->rawData[2],
1158 probe_rsp->rawData[1] );
1160 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1161 lp->dev->name, ssid );
1165 /* Parse out the WPA-IE, if one exists */
1166 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1167 if( wpa_ie != NULL ) {
1168 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1169 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1172 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1173 lp->dev->name, probe_rsp->flags );
1176 DBG_TRACE( DbgInfo, "\n" );
1179 /* If probe response length is 1, then the scan is complete */
1180 if( probe_rsp->length == 1 ) {
1181 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1182 lp->probe_results.num_aps = lp->probe_num_aps;
1183 lp->probe_results.scan_complete = TRUE;
1185 /* Reset the counter for the next scan request */
1186 lp->probe_num_aps = 0;
1188 /* Send a wireless extensions event that the scan completed */
1189 wl_wext_event_scan_complete( lp->dev );
1191 /* Only copy to the table if the entry is unique; APs sometimes
1192 respond more than once to a probe */
1193 if( lp->probe_num_aps == 0 ) {
1194 /* Copy the info to the ScanResult structure in the private
1196 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1197 probe_rsp, sizeof( PROBE_RESP ));
1199 /* Increment the number of APs detected */
1200 lp->probe_num_aps++;
1205 for( count = 0; count < lp->probe_num_aps; count++ ) {
1206 if( memcmp( &( probe_rsp->BSSID ),
1207 lp->probe_results.ProbeTable[count].BSSID,
1214 /* Copy the info to the ScanResult structure in the
1215 private adapter struct. Only copy if there's room in the
1217 if( lp->probe_num_aps < MAX_NAPS )
1219 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1220 probe_rsp, sizeof( PROBE_RESP ));
1224 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1227 /* Increment the number of APs detected. Note I do this
1228 here even when I don't copy the probe response to the
1229 buffer in order to detect the overflow condition */
1230 lp->probe_num_aps++;
1236 DBG_LEAVE( DbgInfo );
1238 } // wl_process_probe_response
1239 /*============================================================================*/
1244 /*******************************************************************************
1245 * wl_process_updated_record()
1246 *******************************************************************************
1250 * Process the updated information record message signaled by the device.
1254 * lp - a pointer to the device's private structure
1260 ******************************************************************************/
1261 void wl_process_updated_record( struct wl_private *lp )
1263 DBG_ENTER( DbgInfo );
1267 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1269 switch( lp->updatedRecord.u.u16[0] ) {
1270 case CFG_CUR_COUNTRY_INFO:
1271 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1276 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1281 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1282 lp->updatedRecord.u.u16[0] );
1286 DBG_LEAVE( DbgInfo );
1288 } // wl_process_updated_record
1289 /*============================================================================*/
1294 /*******************************************************************************
1295 * wl_process_assoc_status()
1296 *******************************************************************************
1300 * Process the association status event signaled by the device.
1304 * lp - a pointer to the device's private structure
1310 ******************************************************************************/
1311 void wl_process_assoc_status( struct wl_private *lp )
1313 ASSOC_STATUS_STRCT *assoc_stat;
1314 /*------------------------------------------------------------------------*/
1317 DBG_ENTER( DbgInfo );
1321 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1323 wl_endian_translate_event( (ltv_t *)assoc_stat );
1325 switch( assoc_stat->assocStatus ) {
1327 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1331 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1335 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1339 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1340 assoc_stat->assocStatus );
1344 DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr);
1346 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1347 DBG_TRACE(DbgInfo, "Old AP Address : %pM\n",
1348 assoc_stat->oldApAddr);
1352 DBG_LEAVE( DbgInfo );
1354 } // wl_process_assoc_status
1355 /*============================================================================*/
1360 /*******************************************************************************
1361 * wl_process_security_status()
1362 *******************************************************************************
1366 * Process the security status message signaled by the device.
1370 * lp - a pointer to the device's private structure
1376 ******************************************************************************/
1377 void wl_process_security_status( struct wl_private *lp )
1379 SECURITY_STATUS_STRCT *sec_stat;
1380 /*------------------------------------------------------------------------*/
1383 DBG_ENTER( DbgInfo );
1387 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1389 wl_endian_translate_event( (ltv_t *)sec_stat );
1391 switch( sec_stat->securityStatus ) {
1393 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1397 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1401 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1405 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1409 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1413 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1414 sec_stat->securityStatus );
1418 DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr);
1419 DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason);
1423 DBG_LEAVE( DbgInfo );
1425 } // wl_process_security_status
1426 /*============================================================================*/
1428 int wl_get_tallies(struct wl_private *lp,
1429 CFG_HERMES_TALLIES_STRCT *tallies)
1433 CFG_HERMES_TALLIES_STRCT *pTallies;
1437 /* Get the current tallies from the adapter */
1438 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1439 lp->ltvRecord.typ = CFG_TALLIES;
1441 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1443 if( status == HCF_SUCCESS ) {
1444 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1445 memcpy(tallies, pTallies, sizeof(*tallies));
1446 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1448 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1452 DBG_LEAVE( DbgInfo );