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 /*============================================================================*/
318 /*******************************************************************************
320 *******************************************************************************
324 * Checks to see if the device supports WEP
328 * ifbp - the IFB pointer of the device in question
332 * 1 if WEP is known enabled, else 0
334 ******************************************************************************/
335 int wl_has_wep (IFBP ifbp)
337 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
339 /*------------------------------------------------------------------------*/
342 /* This function allows us to distiguish bronze cards from other types, to
343 know if WEP exists. Does not distinguish (because there's no way to)
344 between silver and gold cards. */
346 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
348 rc = hcf_get_info( ifbp, (LTVP) <v );
350 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
352 //return rc ? 0 : privacy;
355 /*============================================================================*/
360 /*******************************************************************************
362 *******************************************************************************
366 * Report the type of HCF error message
374 * A descriptive string indicating the error, quiet otherwise.
376 ******************************************************************************/
377 void wl_hcf_error( struct net_device *dev, int hcfStatus )
379 char buffer[64], *pMsg;
380 /*------------------------------------------------------------------------*/
383 if( hcfStatus != HCF_SUCCESS ) {
384 switch( hcfStatus ) {
386 case HCF_ERR_TIME_OUT:
388 pMsg = "Expected adapter event did not occur in expected time";
394 pMsg = "Card not found (ejected unexpectedly)";
400 pMsg = "Command buffer size insufficient";
404 case HCF_ERR_INCOMP_PRI:
406 pMsg = "Primary functions are not compatible";
410 case HCF_ERR_INCOMP_FW:
412 pMsg = "Primary functions are compatible, "
413 "station/ap functions are not";
419 pMsg = "Inquire cmd while another Inquire in progress";
423 //case HCF_ERR_SEQ_BUG:
425 // pMsg = "Unexpected command completed";
429 case HCF_ERR_DEFUNCT_AUX:
431 pMsg = "Timeout on ack for enable/disable of AUX registers";
435 case HCF_ERR_DEFUNCT_TIMER:
436 pMsg = "Timeout on timer calibration during initialization process";
440 case HCF_ERR_DEFUNCT_TIME_OUT:
441 pMsg = "Timeout on Busy bit drop during BAP setup";
445 case HCF_ERR_DEFUNCT_CMD_SEQ:
446 pMsg = "Hermes and HCF are out of sync";
452 sprintf( buffer, "Error code %d", hcfStatus );
457 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
461 /*============================================================================*/
466 /*******************************************************************************
467 * wl_endian_translate_event()
468 *******************************************************************************
472 * Determines what type of data is in the mailbox and performs the proper
473 * endian translation.
477 * pLtv - an LTV pointer
483 ******************************************************************************/
484 void wl_endian_translate_event( ltv_t *pLtv )
486 DBG_FUNC( "wl_endian_translate_event" );
487 DBG_ENTER( DbgInfo );
490 switch( pLtv->typ ) {
498 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
500 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
501 (sizeof( SCAN_RS_STRCT )));
503 while( numAPs >= 1 ) {
506 pAps[numAPs].channel_id =
507 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
509 pAps[numAPs].noise_level =
510 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
512 pAps[numAPs].signal_level =
513 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
515 pAps[numAPs].beacon_interval_time =
516 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
518 pAps[numAPs].capability =
519 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
521 pAps[numAPs].ssid_len =
522 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
524 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
533 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
535 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
536 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
537 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
538 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
541 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
544 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
545 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
546 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
552 #define ls ((LINK_STATUS_STRCT *)pLtv)
553 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
559 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
561 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
566 case CFG_SECURITY_STAT:
568 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
570 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
571 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
588 DBG_LEAVE( DbgInfo );
590 } // wl_endian_translate_event
591 /*============================================================================*/
594 /*******************************************************************************
596 *******************************************************************************
600 * Print statement used to display asserts from within the HCF. Only called
601 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
605 * file_namep - the filename in which the assert occurred.
606 * line_number - the line number on which the assert occurred.
607 * trace - a comment associated with the assert.
608 * qual - return code or other value related to the assert
614 ******************************************************************************/
615 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
617 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
619 /*============================================================================*/
624 /*******************************************************************************
626 *******************************************************************************
630 * This function parses the Direct Sequence Parameter Set IE, used to
631 * determine channel/frequency information.
635 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
640 * The channel on which the BSS represented by this probe response is
643 ******************************************************************************/
644 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
650 /*------------------------------------------------------------------------*/
653 if( probe_rsp == NULL ) {
657 buf = probe_rsp->rawData;
658 buf_size = sizeof( probe_rsp->rawData );
661 for( i = 0; i < buf_size; i++ ) {
662 if( buf[i] == DS_INFO_ELEM ) {
663 /* Increment by 1 to get the length, and test it; in a DS element,
664 length should always be 1 */
669 /* Get the channel information */
676 /* If we get here, we didn't find a DS-IE, which is strange */
681 /*******************************************************************************
683 *******************************************************************************
687 * This function parses the Probe Response for a valid WPA-IE.
691 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
693 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
694 * be stored (if found).
698 * A pointer to the location in the probe response buffer where a valid
699 * WPA-IE lives. The length of this IE is written back to the 'length'
700 * argument passed to the function.
702 ******************************************************************************/
703 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
709 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
710 /*------------------------------------------------------------------------*/
713 if( probe_rsp == NULL || length == NULL ) {
717 buf = probe_rsp->rawData;
718 buf_size = sizeof( probe_rsp->rawData );
722 for( i = 0; i < buf_size; i++ ) {
723 if( buf[i] == GENERIC_INFO_ELEM ) {
724 /* Increment by one to get the IE length */
726 ie_length = probe_rsp->rawData[i];
728 /* Increment by one to point to the IE payload */
731 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
732 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
733 /* Pass back length and return a pointer to the WPA-IE */
734 /* NOTE: Length contained in the WPA-IE is only the length of
735 the payload. The entire WPA-IE, including the IE identifier
736 and the length, is 2 bytes larger */
737 *length = ie_length + 2;
739 /* Back up the pointer 2 bytes to include the IE identifier and
740 the length in the buffer returned */
745 /* Increment past this non-WPA IE and continue looking */
746 i += ( ie_length - 1 );
750 /* If we're here, we didn't find a WPA-IE in the buffer */
755 /*******************************************************************************
757 *******************************************************************************
761 * Function used to take a WPA Information Element (WPA-IE) buffer and
762 * display it in a readable format.
766 * buffer - the byte buffer containing the WPA-IE
767 * length - the length of the above buffer
771 * A pointer to the formatted WPA-IE string. Note that the format used is
772 * byte-by-byte printing as %02x hex values with no spaces. This is
773 * required for proper operation with some WPA supplicants.
775 ******************************************************************************/
776 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
783 static hcf_8 output[512];
784 /*------------------------------------------------------------------------*/
787 memset( output, 0, sizeof( output ));
788 memset( row_buf, 0, sizeof( row_buf ));
791 /* Determine how many rows will be needed, and the remainder */
792 rows = length / rowsize;
793 remainder = length % rowsize;
796 /* Format the rows */
797 for( count = 0; count < rows; count++ ) {
798 sprintf( row_buf, "%02x%02x%02x%02x",
799 buffer[count*rowsize], buffer[count*rowsize+1],
800 buffer[count*rowsize+2], buffer[count*rowsize+3]);
801 strcat( output, row_buf );
804 memset( row_buf, 0, sizeof( row_buf ));
807 /* Format the remainder */
808 for( count = 0; count < remainder; count++ ) {
809 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
810 strcat( output, row_buf );
815 /*============================================================================*/
820 /*******************************************************************************
821 * wl_is_a_valid_chan()
822 *******************************************************************************
826 * Checks if a given channel is valid
830 * channel - the channel
837 ******************************************************************************/
838 int wl_is_a_valid_chan( int channel )
841 /*------------------------------------------------------------------------*/
844 /* Strip out the high bit set by the FW for 802.11a channels */
845 if( channel & 0x100 ) {
846 channel = channel & 0x0FF;
849 /* Iterate through the matrix and retrieve the frequency */
850 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
851 if( chan_freq_list[i][0] == channel ) {
857 } // wl_is_a_valid_chan
858 /*============================================================================*/
863 /*******************************************************************************
864 * wl_get_chan_from_freq()
865 *******************************************************************************
869 * Checks if a given frequency is valid
873 * freq - the frequency
880 ******************************************************************************/
881 int wl_is_a_valid_freq( long frequency )
884 /*------------------------------------------------------------------------*/
887 /* Iterate through the matrix and retrieve the channel */
888 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
889 if( chan_freq_list[i][1] == frequency ) {
895 } // wl_is_a_valid_freq
896 /*============================================================================*/
901 /*******************************************************************************
902 * wl_get_freq_from_chan()
903 *******************************************************************************
907 * Function used to look up the frequency for a given channel on which the
912 * channel - the channel
916 * The corresponding frequency
918 ******************************************************************************/
919 long wl_get_freq_from_chan( int channel )
922 /*------------------------------------------------------------------------*/
925 /* Strip out the high bit set by the FW for 802.11a channels */
926 if( channel & 0x100 ) {
927 channel = channel & 0x0FF;
930 /* Iterate through the matrix and retrieve the frequency */
931 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
932 if( chan_freq_list[i][0] == channel ) {
933 return chan_freq_list[i][1];
938 } // wl_get_freq_from_chan
939 /*============================================================================*/
944 /*******************************************************************************
945 * wl_get_chan_from_freq()
946 *******************************************************************************
950 * Function used to look up the channel for a given frequency on which the
955 * frequency - the frequency
959 * The corresponding channel
961 ******************************************************************************/
962 int wl_get_chan_from_freq( long frequency )
965 /*------------------------------------------------------------------------*/
968 /* Iterate through the matrix and retrieve the channel */
969 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
970 if( chan_freq_list[i][1] == frequency ) {
971 return chan_freq_list[i][0];
976 } // wl_get_chan_from_freq
977 /*============================================================================*/
982 /*******************************************************************************
983 * wl_process_link_status()
984 *******************************************************************************
988 * Process the link status message signaled by the device.
992 * lp - a pointer to the device's private structure
998 ******************************************************************************/
999 void wl_process_link_status( struct wl_private *lp )
1002 /*------------------------------------------------------------------------*/
1004 DBG_FUNC( "wl_process_link_status" );
1005 DBG_ENTER( DbgInfo );
1008 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1009 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1010 switch( link_stat ) {
1012 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1013 wl_wext_event_ap( lp->dev );
1016 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1019 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1022 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1025 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1028 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1032 DBG_LEAVE( DbgInfo );
1034 } // wl_process_link_status
1035 /*============================================================================*/
1040 /*******************************************************************************
1041 * wl_process_probe_response()
1042 *******************************************************************************
1046 * Process the probe responses retunred by the device as a result of an
1051 * lp - a pointer to the device's private structure
1057 ******************************************************************************/
1058 void wl_process_probe_response( struct wl_private *lp )
1060 PROBE_RESP *probe_rsp;
1061 hcf_8 *wpa_ie = NULL;
1062 hcf_16 wpa_ie_len = 0;
1063 /*------------------------------------------------------------------------*/
1066 DBG_FUNC( "wl_process_probe_response" );
1067 DBG_ENTER( DbgInfo );
1071 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1073 wl_endian_translate_event( (ltv_t *)probe_rsp );
1075 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1076 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1077 probe_rsp->length );
1079 if( probe_rsp->length > 1 ) {
1080 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1081 probe_rsp->infoType );
1083 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1084 probe_rsp->signal );
1086 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1087 probe_rsp->silence );
1089 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1090 probe_rsp->rxFlow );
1092 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1095 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1096 probe_rsp->frameControl );
1098 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1101 DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name,
1102 probe_rsp->address1);
1104 DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name,
1105 probe_rsp->address2);
1107 DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name,
1110 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1111 probe_rsp->sequence );
1113 DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name,
1114 probe_rsp->address4);
1116 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1117 probe_rsp->dataLength );
1119 DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name,
1122 DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name,
1127 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1128 probe_rsp->channel );
1130 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1133 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1134 probe_rsp->lenType );
1137 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1139 probe_rsp->timeStamp[0],
1140 probe_rsp->timeStamp[1],
1141 probe_rsp->timeStamp[2],
1142 probe_rsp->timeStamp[3],
1143 probe_rsp->timeStamp[4],
1144 probe_rsp->timeStamp[5],
1145 probe_rsp->timeStamp[6],
1146 probe_rsp->timeStamp[7]);
1148 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1149 probe_rsp->beaconInterval );
1151 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1152 probe_rsp->capability );
1154 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1155 probe_rsp->rawData[1] );
1158 if( probe_rsp->rawData[1] > 0 ) {
1159 char ssid[HCF_MAX_NAME_LEN];
1161 memset( ssid, 0, sizeof( ssid ));
1162 strncpy( ssid, &probe_rsp->rawData[2],
1163 probe_rsp->rawData[1] );
1165 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1166 lp->dev->name, ssid );
1170 /* Parse out the WPA-IE, if one exists */
1171 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1172 if( wpa_ie != NULL ) {
1173 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1174 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1177 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1178 lp->dev->name, probe_rsp->flags );
1181 DBG_TRACE( DbgInfo, "\n" );
1184 /* If probe response length is 1, then the scan is complete */
1185 if( probe_rsp->length == 1 ) {
1186 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1187 lp->probe_results.num_aps = lp->probe_num_aps;
1188 lp->probe_results.scan_complete = TRUE;
1190 /* Reset the counter for the next scan request */
1191 lp->probe_num_aps = 0;
1193 /* Send a wireless extensions event that the scan completed */
1194 wl_wext_event_scan_complete( lp->dev );
1196 /* Only copy to the table if the entry is unique; APs sometimes
1197 respond more than once to a probe */
1198 if( lp->probe_num_aps == 0 ) {
1199 /* Copy the info to the ScanResult structure in the private
1201 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1202 probe_rsp, sizeof( PROBE_RESP ));
1204 /* Increment the number of APs detected */
1205 lp->probe_num_aps++;
1210 for( count = 0; count < lp->probe_num_aps; count++ ) {
1211 if( memcmp( &( probe_rsp->BSSID ),
1212 lp->probe_results.ProbeTable[count].BSSID,
1219 /* Copy the info to the ScanResult structure in the
1220 private adapter struct. Only copy if there's room in the
1222 if( lp->probe_num_aps < MAX_NAPS )
1224 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1225 probe_rsp, sizeof( PROBE_RESP ));
1229 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1232 /* Increment the number of APs detected. Note I do this
1233 here even when I don't copy the probe response to the
1234 buffer in order to detect the overflow condition */
1235 lp->probe_num_aps++;
1241 DBG_LEAVE( DbgInfo );
1243 } // wl_process_probe_response
1244 /*============================================================================*/
1249 /*******************************************************************************
1250 * wl_process_updated_record()
1251 *******************************************************************************
1255 * Process the updated information record message signaled by the device.
1259 * lp - a pointer to the device's private structure
1265 ******************************************************************************/
1266 void wl_process_updated_record( struct wl_private *lp )
1268 DBG_FUNC( "wl_process_updated_record" );
1269 DBG_ENTER( DbgInfo );
1273 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1275 switch( lp->updatedRecord.u.u16[0] ) {
1276 case CFG_CUR_COUNTRY_INFO:
1277 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1282 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1287 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1288 lp->updatedRecord.u.u16[0] );
1292 DBG_LEAVE( DbgInfo );
1294 } // wl_process_updated_record
1295 /*============================================================================*/
1300 /*******************************************************************************
1301 * wl_process_assoc_status()
1302 *******************************************************************************
1306 * Process the association status event signaled by the device.
1310 * lp - a pointer to the device's private structure
1316 ******************************************************************************/
1317 void wl_process_assoc_status( struct wl_private *lp )
1319 ASSOC_STATUS_STRCT *assoc_stat;
1320 /*------------------------------------------------------------------------*/
1323 DBG_FUNC( "wl_process_assoc_status" );
1324 DBG_ENTER( DbgInfo );
1328 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1330 wl_endian_translate_event( (ltv_t *)assoc_stat );
1332 switch( assoc_stat->assocStatus ) {
1334 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1338 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1342 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1346 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1347 assoc_stat->assocStatus );
1351 DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr);
1353 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1354 DBG_TRACE(DbgInfo, "Old AP Address : %pM\n",
1355 assoc_stat->oldApAddr);
1359 DBG_LEAVE( DbgInfo );
1361 } // wl_process_assoc_status
1362 /*============================================================================*/
1367 /*******************************************************************************
1368 * wl_process_security_status()
1369 *******************************************************************************
1373 * Process the security status message signaled by the device.
1377 * lp - a pointer to the device's private structure
1383 ******************************************************************************/
1384 void wl_process_security_status( struct wl_private *lp )
1386 SECURITY_STATUS_STRCT *sec_stat;
1387 /*------------------------------------------------------------------------*/
1390 DBG_FUNC( "wl_process_security_status" );
1391 DBG_ENTER( DbgInfo );
1395 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1397 wl_endian_translate_event( (ltv_t *)sec_stat );
1399 switch( sec_stat->securityStatus ) {
1401 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1405 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1409 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1413 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1417 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1421 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1422 sec_stat->securityStatus );
1426 DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr);
1427 DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason);
1431 DBG_LEAVE( DbgInfo );
1433 } // wl_process_security_status
1434 /*============================================================================*/
1436 int wl_get_tallies(struct wl_private *lp,
1437 CFG_HERMES_TALLIES_STRCT *tallies)
1441 CFG_HERMES_TALLIES_STRCT *pTallies;
1443 DBG_FUNC( "wl_get_tallies" );
1446 /* Get the current tallies from the adapter */
1447 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1448 lp->ltvRecord.typ = CFG_TALLIES;
1450 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1452 if( status == HCF_SUCCESS ) {
1453 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1454 memcpy(tallies, pTallies, sizeof(*tallies));
1455 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1457 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1461 DBG_LEAVE( DbgInfo );