1 /*******************************************************************************
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
14 * This file defines misc utility functions.
16 *------------------------------------------------------------------------------
20 * This software is provided subject to the following terms and conditions,
21 * which you should read carefully before using the software. Using this
22 * software indicates your acceptance of these terms and conditions. If you do
23 * not agree with these terms and conditions, do not use the software.
25 * Copyright © 2003 Agere Systems Inc.
26 * All rights reserved.
28 * Redistribution and use in source or binary forms, with or without
29 * modifications, are permitted provided that the following conditions are met:
31 * . Redistributions of source code must retain the above copyright notice, this
32 * list of conditions and the following Disclaimer as comments in the code as
33 * well as in the documentation and/or other materials provided with the
36 * . Redistributions in binary form must reproduce the above copyright notice,
37 * this list of conditions and the following Disclaimer in the documentation
38 * and/or other materials provided with the distribution.
40 * . Neither the name of Agere Systems Inc. nor the names of the contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED
\93AS IS
\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
47 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
48 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
49 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
50 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
56 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
59 ******************************************************************************/
61 /*******************************************************************************
63 ******************************************************************************/
64 #include <wl_version.h>
66 #include <linux/kernel.h>
67 // #include <linux/sched.h>
68 // #include <linux/ptrace.h>
69 #include <linux/ctype.h>
70 // #include <linux/string.h>
71 // #include <linux/timer.h>
72 // #include <linux/interrupt.h>
73 // #include <linux/in.h>
74 // #include <linux/delay.h>
75 // #include <asm/io.h>
76 // #include <asm/system.h>
77 // #include <asm/bitops.h>
79 #include <linux/netdevice.h>
80 #include <linux/etherdevice.h>
81 // #include <linux/skbuff.h>
82 // #include <linux/if_arp.h>
83 // #include <linux/ioport.h>
87 // #include <hcfdef.h>
90 #include <wl_internal.h>
97 /*******************************************************************************
99 ******************************************************************************/
101 /* A matrix which maps channels to frequencies */
102 #define MAX_CHAN_FREQ_MAP_ENTRIES 50
103 static const long chan_freq_list[][MAX_CHAN_FREQ_MAP_ENTRIES] =
134 extern dbg_info_t *DbgInfo;
140 /*******************************************************************************
142 *******************************************************************************
146 * Return an energy value in dBm.
150 * value - the energy value to be converted
156 ******************************************************************************/
159 /* Truncate the value to be between min and max. */
160 if( value < HCF_MIN_SIGNAL_LEVEL )
161 value = HCF_MIN_SIGNAL_LEVEL;
163 if( value > HCF_MAX_SIGNAL_LEVEL )
164 value = HCF_MAX_SIGNAL_LEVEL;
166 /* Return the energy value in dBm. */
167 return ( value - HCF_0DBM_OFFSET );
169 /*============================================================================*/
174 /*******************************************************************************
176 *******************************************************************************
180 * Return a value as a percentage of min to max.
184 * value - the value in question
185 * min - the minimum range value
186 * max - the maximum range value
190 * the percentage value
192 ******************************************************************************/
193 int percent( int value, int min, int max )
195 /* Truncate the value to be between min and max. */
202 /* Return the value as a percentage of min to max. */
203 return ((( value - min ) * 100 ) / ( max - min ));
205 /*============================================================================*/
210 /*******************************************************************************
211 * is_valid_key_string()
212 *******************************************************************************
216 * Checks to determine if the WEP key string is valid
220 * s - the string in question
224 * non-zero if the string contains a valid key
226 ******************************************************************************/
227 int is_valid_key_string( char *s )
231 /*------------------------------------------------------------------------*/
236 /* 0x followed by 5 or 13 hexadecimal digit pairs is valid */
237 if( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' )) {
238 if( l == 12 || l == 28 ) {
239 for( i = 2; i < l; i++ ) {
240 if( !isxdigit( s[i] ))
250 /* string with 0, 5, or 13 characters is valid */
253 return( l == 0 || l == 5 || l == 13 );
255 } // is_valid_key_string
256 /*============================================================================*/
261 /*******************************************************************************
263 *******************************************************************************
267 * Converts a key_string to a key, Assumes the key_string is validated with
268 * is_valid_key_string().
272 * ks - the valid key string
273 * key - a pointer to a KEY_STRUCT where the converted key information will
280 ******************************************************************************/
281 void key_string2key( char *ks, KEY_STRCT *key )
285 /*------------------------------------------------------------------------*/
290 /* 0x followed by hexadecimal digit pairs */
291 if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
293 p = (char *)key->key;
295 for( i = 2; i < l; i+=2 ) {
296 *p++ = (hex_to_bin(ks[i]) << 4) + hex_to_bin(ks[i+1]);
300 /* Note that endian translation of the length field is not needed here
301 because it's performed in wl_put_ltv() */
304 /* character string */
307 strcpy( (char *)key->key, ks );
313 /*============================================================================*/
319 /*******************************************************************************
321 *******************************************************************************
325 * Convert a hardware ethernet address to a character string
329 * hwAddr - an ethernet address
333 * a pointer to a string representing the ethernet address
335 ******************************************************************************/
336 const char *DbgHwAddr(unsigned char *hwAddr)
338 static char buffer[18];
339 /*------------------------------------------------------------------------*/
342 sprintf( buffer, "%02X:%02X:%02X:%02X:%02X:%02X",
343 hwAddr[0], hwAddr[1], hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5] );
347 /*============================================================================*/
354 /*******************************************************************************
356 *******************************************************************************
360 * Checks to see if the device supports WEP
364 * ifbp - the IFB pointer of the device in question
368 * 1 if WEP is known enabled, else 0
370 ******************************************************************************/
371 int wl_has_wep (IFBP ifbp)
373 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
375 /*------------------------------------------------------------------------*/
378 /* This function allows us to distiguish bronze cards from other types, to
379 know if WEP exists. Does not distinguish (because there's no way to)
380 between silver and gold cards. */
382 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
384 rc = hcf_get_info( ifbp, (LTVP) <v );
386 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
388 //return rc ? 0 : privacy;
391 /*============================================================================*/
396 /*******************************************************************************
398 *******************************************************************************
402 * Report the type of HCF error message
410 * A descriptive string indicating the error, quiet otherwise.
412 ******************************************************************************/
413 void wl_hcf_error( struct net_device *dev, int hcfStatus )
415 char buffer[64], *pMsg;
416 /*------------------------------------------------------------------------*/
419 if( hcfStatus != HCF_SUCCESS ) {
420 switch( hcfStatus ) {
422 case HCF_ERR_TIME_OUT:
424 pMsg = "Expected adapter event did not occur in expected time";
430 pMsg = "Card not found (ejected unexpectedly)";
436 pMsg = "Command buffer size insufficient";
440 case HCF_ERR_INCOMP_PRI:
442 pMsg = "Primary functions are not compatible";
446 case HCF_ERR_INCOMP_FW:
448 pMsg = "Primary functions are compatible, "
449 "station/ap functions are not";
455 pMsg = "Inquire cmd while another Inquire in progress";
459 //case HCF_ERR_SEQ_BUG:
461 // pMsg = "Unexpected command completed";
465 case HCF_ERR_DEFUNCT_AUX:
467 pMsg = "Timeout on ack for enable/disable of AUX registers";
471 case HCF_ERR_DEFUNCT_TIMER:
472 pMsg = "Timeout on timer calibration during initialization process";
476 case HCF_ERR_DEFUNCT_TIME_OUT:
477 pMsg = "Timeout on Busy bit drop during BAP setup";
481 case HCF_ERR_DEFUNCT_CMD_SEQ:
482 pMsg = "Hermes and HCF are out of sync";
488 sprintf( buffer, "Error code %d", hcfStatus );
493 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
497 /*============================================================================*/
502 /*******************************************************************************
503 * wl_endian_translate_event()
504 *******************************************************************************
508 * Determines what type of data is in the mailbox and performs the proper
509 * endian translation.
513 * pLtv - an LTV pointer
519 ******************************************************************************/
520 void wl_endian_translate_event( ltv_t *pLtv )
522 DBG_FUNC( "wl_endian_translate_event" );
523 DBG_ENTER( DbgInfo );
526 switch( pLtv->typ ) {
534 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
536 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
537 (sizeof( SCAN_RS_STRCT )));
539 while( numAPs >= 1 ) {
542 pAps[numAPs].channel_id =
543 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
545 pAps[numAPs].noise_level =
546 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
548 pAps[numAPs].signal_level =
549 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
551 pAps[numAPs].beacon_interval_time =
552 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
554 pAps[numAPs].capability =
555 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
557 pAps[numAPs].ssid_len =
558 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
560 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
569 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
571 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
572 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
573 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
574 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
577 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
580 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
581 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
582 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
588 #define ls ((LINK_STATUS_STRCT *)pLtv)
589 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
595 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
597 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
602 case CFG_SECURITY_STAT:
604 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
606 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
607 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
624 DBG_LEAVE( DbgInfo );
626 } // wl_endian_translate_event
627 /*============================================================================*/
630 /*******************************************************************************
632 *******************************************************************************
636 * Print statement used to display asserts from within the HCF. Only called
637 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
641 * file_namep - the filename in which the assert occurred.
642 * line_number - the line number on which the assert occurred.
643 * trace - a comment associated with the assert.
644 * qual - return code or other value related to the assert
650 ******************************************************************************/
651 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
653 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
655 /*============================================================================*/
660 /*******************************************************************************
662 *******************************************************************************
666 * This function parses the Direct Sequence Parameter Set IE, used to
667 * determine channel/frequency information.
671 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
676 * The channel on which the BSS represented by this probe response is
679 ******************************************************************************/
680 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
686 /*------------------------------------------------------------------------*/
689 if( probe_rsp == NULL ) {
693 buf = probe_rsp->rawData;
694 buf_size = sizeof( probe_rsp->rawData );
697 for( i = 0; i < buf_size; i++ ) {
698 if( buf[i] == DS_INFO_ELEM ) {
699 /* Increment by 1 to get the length, and test it; in a DS element,
700 length should always be 1 */
705 /* Get the channel information */
712 /* If we get here, we didn't find a DS-IE, which is strange */
717 /*******************************************************************************
719 *******************************************************************************
723 * This function parses the Probe Response for a valid WPA-IE.
727 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
729 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
730 * be stored (if found).
734 * A pointer to the location in the probe response buffer where a valid
735 * WPA-IE lives. The length of this IE is written back to the 'length'
736 * argument passed to the function.
738 ******************************************************************************/
739 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
745 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
746 /*------------------------------------------------------------------------*/
749 if( probe_rsp == NULL || length == NULL ) {
753 buf = probe_rsp->rawData;
754 buf_size = sizeof( probe_rsp->rawData );
758 for( i = 0; i < buf_size; i++ ) {
759 if( buf[i] == GENERIC_INFO_ELEM ) {
760 /* Increment by one to get the IE length */
762 ie_length = probe_rsp->rawData[i];
764 /* Increment by one to point to the IE payload */
767 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
768 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
769 /* Pass back length and return a pointer to the WPA-IE */
770 /* NOTE: Length contained in the WPA-IE is only the length of
771 the payload. The entire WPA-IE, including the IE identifier
772 and the length, is 2 bytes larger */
773 *length = ie_length + 2;
775 /* Back up the pointer 2 bytes to include the IE identifier and
776 the length in the buffer returned */
781 /* Increment past this non-WPA IE and continue looking */
782 i += ( ie_length - 1 );
786 /* If we're here, we didn't find a WPA-IE in the buffer */
791 /*******************************************************************************
793 *******************************************************************************
797 * Function used to take a WPA Information Element (WPA-IE) buffer and
798 * display it in a readable format.
802 * buffer - the byte buffer containing the WPA-IE
803 * length - the length of the above buffer
807 * A pointer to the formatted WPA-IE string. Note that the format used is
808 * byte-by-byte printing as %02x hex values with no spaces. This is
809 * required for proper operation with some WPA supplicants.
811 ******************************************************************************/
812 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
819 static hcf_8 output[512];
820 /*------------------------------------------------------------------------*/
823 memset( output, 0, sizeof( output ));
824 memset( row_buf, 0, sizeof( row_buf ));
827 /* Determine how many rows will be needed, and the remainder */
828 rows = length / rowsize;
829 remainder = length % rowsize;
832 /* Format the rows */
833 for( count = 0; count < rows; count++ ) {
834 sprintf( row_buf, "%02x%02x%02x%02x",
835 buffer[count*rowsize], buffer[count*rowsize+1],
836 buffer[count*rowsize+2], buffer[count*rowsize+3]);
837 strcat( output, row_buf );
840 memset( row_buf, 0, sizeof( row_buf ));
843 /* Format the remainder */
844 for( count = 0; count < remainder; count++ ) {
845 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
846 strcat( output, row_buf );
851 /*============================================================================*/
856 /*******************************************************************************
857 * wl_is_a_valid_chan()
858 *******************************************************************************
862 * Checks if a given channel is valid
866 * channel - the channel
873 ******************************************************************************/
874 int wl_is_a_valid_chan( int channel )
877 /*------------------------------------------------------------------------*/
880 /* Strip out the high bit set by the FW for 802.11a channels */
881 if( channel & 0x100 ) {
882 channel = channel & 0x0FF;
885 /* Iterate through the matrix and retrieve the frequency */
886 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
887 if( chan_freq_list[i][0] == channel ) {
893 } // wl_is_a_valid_chan
894 /*============================================================================*/
899 /*******************************************************************************
900 * wl_get_chan_from_freq()
901 *******************************************************************************
905 * Checks if a given frequency is valid
909 * freq - the frequency
916 ******************************************************************************/
917 int wl_is_a_valid_freq( long frequency )
920 /*------------------------------------------------------------------------*/
923 /* Iterate through the matrix and retrieve the channel */
924 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
925 if( chan_freq_list[i][1] == frequency ) {
931 } // wl_is_a_valid_freq
932 /*============================================================================*/
937 /*******************************************************************************
938 * wl_get_freq_from_chan()
939 *******************************************************************************
943 * Function used to look up the frequency for a given channel on which the
948 * channel - the channel
952 * The corresponding frequency
954 ******************************************************************************/
955 long wl_get_freq_from_chan( int channel )
958 /*------------------------------------------------------------------------*/
961 /* Strip out the high bit set by the FW for 802.11a channels */
962 if( channel & 0x100 ) {
963 channel = channel & 0x0FF;
966 /* Iterate through the matrix and retrieve the frequency */
967 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
968 if( chan_freq_list[i][0] == channel ) {
969 return chan_freq_list[i][1];
974 } // wl_get_freq_from_chan
975 /*============================================================================*/
980 /*******************************************************************************
981 * wl_get_chan_from_freq()
982 *******************************************************************************
986 * Function used to look up the channel for a given frequency on which the
991 * frequency - the frequency
995 * The corresponding channel
997 ******************************************************************************/
998 int wl_get_chan_from_freq( long frequency )
1001 /*------------------------------------------------------------------------*/
1004 /* Iterate through the matrix and retrieve the channel */
1005 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
1006 if( chan_freq_list[i][1] == frequency ) {
1007 return chan_freq_list[i][0];
1012 } // wl_get_chan_from_freq
1013 /*============================================================================*/
1018 /*******************************************************************************
1019 * wl_process_link_status()
1020 *******************************************************************************
1024 * Process the link status message signaled by the device.
1028 * lp - a pointer to the device's private structure
1034 ******************************************************************************/
1035 void wl_process_link_status( struct wl_private *lp )
1038 /*------------------------------------------------------------------------*/
1040 DBG_FUNC( "wl_process_link_status" );
1041 DBG_ENTER( DbgInfo );
1044 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1045 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1046 switch( link_stat ) {
1048 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1049 wl_wext_event_ap( lp->dev );
1052 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1055 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1058 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1061 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1064 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1068 DBG_LEAVE( DbgInfo );
1070 } // wl_process_link_status
1071 /*============================================================================*/
1076 /*******************************************************************************
1077 * wl_process_probe_response()
1078 *******************************************************************************
1082 * Process the probe responses retunred by the device as a result of an
1087 * lp - a pointer to the device's private structure
1093 ******************************************************************************/
1094 void wl_process_probe_response( struct wl_private *lp )
1096 PROBE_RESP *probe_rsp;
1097 hcf_8 *wpa_ie = NULL;
1098 hcf_16 wpa_ie_len = 0;
1099 /*------------------------------------------------------------------------*/
1102 DBG_FUNC( "wl_process_probe_response" );
1103 DBG_ENTER( DbgInfo );
1107 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1109 wl_endian_translate_event( (ltv_t *)probe_rsp );
1111 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1112 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1113 probe_rsp->length );
1115 if( probe_rsp->length > 1 ) {
1116 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1117 probe_rsp->infoType );
1119 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1120 probe_rsp->signal );
1122 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1123 probe_rsp->silence );
1125 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1126 probe_rsp->rxFlow );
1128 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1131 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1132 probe_rsp->frameControl );
1134 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1137 DBG_TRACE( DbgInfo, "(%s) address1 : %s\n", lp->dev->name,
1138 DbgHwAddr( probe_rsp->address1 ));
1140 DBG_TRACE( DbgInfo, "(%s) address2 : %s\n", lp->dev->name,
1141 DbgHwAddr( probe_rsp->address2 ));
1143 DBG_TRACE( DbgInfo, "(%s) BSSID : %s\n", lp->dev->name,
1144 DbgHwAddr( probe_rsp->BSSID ));
1146 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1147 probe_rsp->sequence );
1149 DBG_TRACE( DbgInfo, "(%s) address4 : %s\n", lp->dev->name,
1150 DbgHwAddr( probe_rsp->address4 ));
1152 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1153 probe_rsp->dataLength );
1155 DBG_TRACE( DbgInfo, "(%s) DA : %s\n", lp->dev->name,
1156 DbgHwAddr( probe_rsp->DA ));
1158 DBG_TRACE( DbgInfo, "(%s) SA : %s\n", lp->dev->name,
1159 DbgHwAddr( probe_rsp->SA ));
1163 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1164 probe_rsp->channel );
1166 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1169 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1170 probe_rsp->lenType );
1173 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1175 probe_rsp->timeStamp[0],
1176 probe_rsp->timeStamp[1],
1177 probe_rsp->timeStamp[2],
1178 probe_rsp->timeStamp[3],
1179 probe_rsp->timeStamp[4],
1180 probe_rsp->timeStamp[5],
1181 probe_rsp->timeStamp[6],
1182 probe_rsp->timeStamp[7]);
1184 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1185 probe_rsp->beaconInterval );
1187 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1188 probe_rsp->capability );
1190 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1191 probe_rsp->rawData[1] );
1194 if( probe_rsp->rawData[1] > 0 ) {
1195 char ssid[HCF_MAX_NAME_LEN];
1197 memset( ssid, 0, sizeof( ssid ));
1198 strncpy( ssid, &probe_rsp->rawData[2],
1199 probe_rsp->rawData[1] );
1201 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1202 lp->dev->name, ssid );
1206 /* Parse out the WPA-IE, if one exists */
1207 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1208 if( wpa_ie != NULL ) {
1209 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1210 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1213 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1214 lp->dev->name, probe_rsp->flags );
1217 DBG_TRACE( DbgInfo, "\n" );
1220 /* If probe response length is 1, then the scan is complete */
1221 if( probe_rsp->length == 1 ) {
1222 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1223 lp->probe_results.num_aps = lp->probe_num_aps;
1224 lp->probe_results.scan_complete = TRUE;
1226 /* Reset the counter for the next scan request */
1227 lp->probe_num_aps = 0;
1229 /* Send a wireless extensions event that the scan completed */
1230 wl_wext_event_scan_complete( lp->dev );
1232 /* Only copy to the table if the entry is unique; APs sometimes
1233 respond more than once to a probe */
1234 if( lp->probe_num_aps == 0 ) {
1235 /* Copy the info to the ScanResult structure in the private
1237 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1238 probe_rsp, sizeof( PROBE_RESP ));
1240 /* Increment the number of APs detected */
1241 lp->probe_num_aps++;
1246 for( count = 0; count < lp->probe_num_aps; count++ ) {
1247 if( memcmp( &( probe_rsp->BSSID ),
1248 lp->probe_results.ProbeTable[count].BSSID,
1255 /* Copy the info to the ScanResult structure in the
1256 private adapter struct. Only copy if there's room in the
1258 if( lp->probe_num_aps < MAX_NAPS )
1260 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1261 probe_rsp, sizeof( PROBE_RESP ));
1265 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1268 /* Increment the number of APs detected. Note I do this
1269 here even when I don't copy the probe response to the
1270 buffer in order to detect the overflow condition */
1271 lp->probe_num_aps++;
1277 DBG_LEAVE( DbgInfo );
1279 } // wl_process_probe_response
1280 /*============================================================================*/
1285 /*******************************************************************************
1286 * wl_process_updated_record()
1287 *******************************************************************************
1291 * Process the updated information record message signaled by the device.
1295 * lp - a pointer to the device's private structure
1301 ******************************************************************************/
1302 void wl_process_updated_record( struct wl_private *lp )
1304 DBG_FUNC( "wl_process_updated_record" );
1305 DBG_ENTER( DbgInfo );
1309 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1311 switch( lp->updatedRecord.u.u16[0] ) {
1312 case CFG_CUR_COUNTRY_INFO:
1313 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1318 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1323 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1324 lp->updatedRecord.u.u16[0] );
1328 DBG_LEAVE( DbgInfo );
1330 } // wl_process_updated_record
1331 /*============================================================================*/
1336 /*******************************************************************************
1337 * wl_process_assoc_status()
1338 *******************************************************************************
1342 * Process the association status event signaled by the device.
1346 * lp - a pointer to the device's private structure
1352 ******************************************************************************/
1353 void wl_process_assoc_status( struct wl_private *lp )
1355 ASSOC_STATUS_STRCT *assoc_stat;
1356 /*------------------------------------------------------------------------*/
1359 DBG_FUNC( "wl_process_assoc_status" );
1360 DBG_ENTER( DbgInfo );
1364 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1366 wl_endian_translate_event( (ltv_t *)assoc_stat );
1368 switch( assoc_stat->assocStatus ) {
1370 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1374 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1378 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1382 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1383 assoc_stat->assocStatus );
1387 DBG_TRACE( DbgInfo, "STA Address : %s\n",
1388 DbgHwAddr( assoc_stat->staAddr ));
1390 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1391 DBG_TRACE( DbgInfo, "Old AP Address : %s\n",
1392 DbgHwAddr( assoc_stat->oldApAddr ));
1396 DBG_LEAVE( DbgInfo );
1398 } // wl_process_assoc_status
1399 /*============================================================================*/
1404 /*******************************************************************************
1405 * wl_process_security_status()
1406 *******************************************************************************
1410 * Process the security status message signaled by the device.
1414 * lp - a pointer to the device's private structure
1420 ******************************************************************************/
1421 void wl_process_security_status( struct wl_private *lp )
1423 SECURITY_STATUS_STRCT *sec_stat;
1424 /*------------------------------------------------------------------------*/
1427 DBG_FUNC( "wl_process_security_status" );
1428 DBG_ENTER( DbgInfo );
1432 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1434 wl_endian_translate_event( (ltv_t *)sec_stat );
1436 switch( sec_stat->securityStatus ) {
1438 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1442 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1446 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1450 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1454 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1458 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1459 sec_stat->securityStatus );
1463 DBG_TRACE( DbgInfo, "STA Address : %s\n",
1464 DbgHwAddr( sec_stat->staAddr ));
1465 DBG_TRACE( DbgInfo, "Reason : 0x%04x \n", sec_stat->reason );
1469 DBG_LEAVE( DbgInfo );
1471 } // wl_process_security_status
1472 /*============================================================================*/
1474 int wl_get_tallies(struct wl_private *lp,
1475 CFG_HERMES_TALLIES_STRCT *tallies)
1479 CFG_HERMES_TALLIES_STRCT *pTallies;
1481 DBG_FUNC( "wl_get_tallies" );
1484 /* Get the current tallies from the adapter */
1485 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1486 lp->ltvRecord.typ = CFG_TALLIES;
1488 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1490 if( status == HCF_SUCCESS ) {
1491 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1492 memcpy(tallies, pTallies, sizeof(*tallies));
1493 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1495 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1499 DBG_LEAVE( DbgInfo );