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] =
131 /*******************************************************************************
133 *******************************************************************************
137 * Return an energy value in dBm.
141 * value - the energy value to be converted
147 ******************************************************************************/
150 /* Truncate the value to be between min and max. */
151 if( value < HCF_MIN_SIGNAL_LEVEL )
152 value = HCF_MIN_SIGNAL_LEVEL;
154 if( value > HCF_MAX_SIGNAL_LEVEL )
155 value = HCF_MAX_SIGNAL_LEVEL;
157 /* Return the energy value in dBm. */
158 return ( value - HCF_0DBM_OFFSET );
160 /*============================================================================*/
165 /*******************************************************************************
167 *******************************************************************************
171 * Return a value as a percentage of min to max.
175 * value - the value in question
176 * min - the minimum range value
177 * max - the maximum range value
181 * the percentage value
183 ******************************************************************************/
184 int percent( int value, int min, int max )
186 /* Truncate the value to be between min and max. */
193 /* Return the value as a percentage of min to max. */
194 return ((( value - min ) * 100 ) / ( max - min ));
196 /*============================================================================*/
201 /*******************************************************************************
202 * is_valid_key_string()
203 *******************************************************************************
207 * Checks to determine if the WEP key string is valid
211 * s - the string in question
215 * non-zero if the string contains a valid key
217 ******************************************************************************/
218 int is_valid_key_string( char *s )
222 /*------------------------------------------------------------------------*/
227 /* 0x followed by 5 or 13 hexadecimal digit pairs is valid */
228 if( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' )) {
229 if( l == 12 || l == 28 ) {
230 for( i = 2; i < l; i++ ) {
231 if( !isxdigit( s[i] ))
241 /* string with 0, 5, or 13 characters is valid */
244 return( l == 0 || l == 5 || l == 13 );
246 } // is_valid_key_string
247 /*============================================================================*/
252 /*******************************************************************************
254 *******************************************************************************
258 * Converts a key_string to a key, Assumes the key_string is validated with
259 * is_valid_key_string().
263 * ks - the valid key string
264 * key - a pointer to a KEY_STRUCT where the converted key information will
271 ******************************************************************************/
272 void key_string2key( char *ks, KEY_STRCT *key )
276 /*------------------------------------------------------------------------*/
281 /* 0x followed by hexadecimal digit pairs */
282 if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
284 p = (char *)key->key;
286 for( i = 2; i < l; i+=2 ) {
287 *p++ = (hex_to_bin(ks[i]) << 4) + hex_to_bin(ks[i+1]);
291 /* Note that endian translation of the length field is not needed here
292 because it's performed in wl_put_ltv() */
295 /* character string */
298 strcpy( (char *)key->key, ks );
304 /*============================================================================*/
309 /*******************************************************************************
311 *******************************************************************************
315 * Checks to see if the device supports WEP
319 * ifbp - the IFB pointer of the device in question
323 * 1 if WEP is known enabled, else 0
325 ******************************************************************************/
326 int wl_has_wep (IFBP ifbp)
328 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
330 /*------------------------------------------------------------------------*/
333 /* This function allows us to distiguish bronze cards from other types, to
334 know if WEP exists. Does not distinguish (because there's no way to)
335 between silver and gold cards. */
337 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
339 rc = hcf_get_info( ifbp, (LTVP) <v );
341 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
343 //return rc ? 0 : privacy;
346 /*============================================================================*/
351 /*******************************************************************************
353 *******************************************************************************
357 * Report the type of HCF error message
365 * A descriptive string indicating the error, quiet otherwise.
367 ******************************************************************************/
368 void wl_hcf_error( struct net_device *dev, int hcfStatus )
370 char buffer[64], *pMsg;
371 /*------------------------------------------------------------------------*/
374 if( hcfStatus != HCF_SUCCESS ) {
375 switch( hcfStatus ) {
377 case HCF_ERR_TIME_OUT:
379 pMsg = "Expected adapter event did not occur in expected time";
385 pMsg = "Card not found (ejected unexpectedly)";
391 pMsg = "Command buffer size insufficient";
395 case HCF_ERR_INCOMP_PRI:
397 pMsg = "Primary functions are not compatible";
401 case HCF_ERR_INCOMP_FW:
403 pMsg = "Primary functions are compatible, "
404 "station/ap functions are not";
410 pMsg = "Inquire cmd while another Inquire in progress";
414 //case HCF_ERR_SEQ_BUG:
416 // pMsg = "Unexpected command completed";
420 case HCF_ERR_DEFUNCT_AUX:
422 pMsg = "Timeout on ack for enable/disable of AUX registers";
426 case HCF_ERR_DEFUNCT_TIMER:
427 pMsg = "Timeout on timer calibration during initialization process";
431 case HCF_ERR_DEFUNCT_TIME_OUT:
432 pMsg = "Timeout on Busy bit drop during BAP setup";
436 case HCF_ERR_DEFUNCT_CMD_SEQ:
437 pMsg = "Hermes and HCF are out of sync";
443 sprintf( buffer, "Error code %d", hcfStatus );
448 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
452 /*============================================================================*/
457 /*******************************************************************************
458 * wl_endian_translate_event()
459 *******************************************************************************
463 * Determines what type of data is in the mailbox and performs the proper
464 * endian translation.
468 * pLtv - an LTV pointer
474 ******************************************************************************/
475 void wl_endian_translate_event( ltv_t *pLtv )
477 switch( pLtv->typ ) {
485 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
487 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
488 (sizeof( SCAN_RS_STRCT )));
490 while( numAPs >= 1 ) {
493 pAps[numAPs].channel_id =
494 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
496 pAps[numAPs].noise_level =
497 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
499 pAps[numAPs].signal_level =
500 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
502 pAps[numAPs].beacon_interval_time =
503 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
505 pAps[numAPs].capability =
506 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
508 pAps[numAPs].ssid_len =
509 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
511 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
520 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
522 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
523 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
524 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
525 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
528 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
531 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
532 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
533 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
539 #define ls ((LINK_STATUS_STRCT *)pLtv)
540 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
546 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
548 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
553 case CFG_SECURITY_STAT:
555 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
557 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
558 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
574 } // wl_endian_translate_event
575 /*============================================================================*/
578 /*******************************************************************************
580 *******************************************************************************
584 * Print statement used to display asserts from within the HCF. Only called
585 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
589 * file_namep - the filename in which the assert occurred.
590 * line_number - the line number on which the assert occurred.
591 * trace - a comment associated with the assert.
592 * qual - return code or other value related to the assert
598 ******************************************************************************/
599 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
601 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
603 /*============================================================================*/
608 /*******************************************************************************
610 *******************************************************************************
614 * This function parses the Direct Sequence Parameter Set IE, used to
615 * determine channel/frequency information.
619 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
624 * The channel on which the BSS represented by this probe response is
627 ******************************************************************************/
628 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
634 /*------------------------------------------------------------------------*/
637 if( probe_rsp == NULL ) {
641 buf = probe_rsp->rawData;
642 buf_size = sizeof( probe_rsp->rawData );
645 for( i = 0; i < buf_size; i++ ) {
646 if( buf[i] == DS_INFO_ELEM ) {
647 /* Increment by 1 to get the length, and test it; in a DS element,
648 length should always be 1 */
653 /* Get the channel information */
660 /* If we get here, we didn't find a DS-IE, which is strange */
665 /*******************************************************************************
667 *******************************************************************************
671 * This function parses the Probe Response for a valid WPA-IE.
675 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
677 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
678 * be stored (if found).
682 * A pointer to the location in the probe response buffer where a valid
683 * WPA-IE lives. The length of this IE is written back to the 'length'
684 * argument passed to the function.
686 ******************************************************************************/
687 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
693 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
694 /*------------------------------------------------------------------------*/
697 if( probe_rsp == NULL || length == NULL ) {
701 buf = probe_rsp->rawData;
702 buf_size = sizeof( probe_rsp->rawData );
706 for( i = 0; i < buf_size; i++ ) {
707 if( buf[i] == GENERIC_INFO_ELEM ) {
708 /* Increment by one to get the IE length */
710 ie_length = probe_rsp->rawData[i];
712 /* Increment by one to point to the IE payload */
715 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
716 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
717 /* Pass back length and return a pointer to the WPA-IE */
718 /* NOTE: Length contained in the WPA-IE is only the length of
719 the payload. The entire WPA-IE, including the IE identifier
720 and the length, is 2 bytes larger */
721 *length = ie_length + 2;
723 /* Back up the pointer 2 bytes to include the IE identifier and
724 the length in the buffer returned */
729 /* Increment past this non-WPA IE and continue looking */
730 i += ( ie_length - 1 );
734 /* If we're here, we didn't find a WPA-IE in the buffer */
739 /*******************************************************************************
741 *******************************************************************************
745 * Function used to take a WPA Information Element (WPA-IE) buffer and
746 * display it in a readable format.
750 * buffer - the byte buffer containing the WPA-IE
751 * length - the length of the above buffer
755 * A pointer to the formatted WPA-IE string. Note that the format used is
756 * byte-by-byte printing as %02x hex values with no spaces. This is
757 * required for proper operation with some WPA supplicants.
759 ******************************************************************************/
760 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
767 static hcf_8 output[512];
768 /*------------------------------------------------------------------------*/
771 memset( output, 0, sizeof( output ));
772 memset( row_buf, 0, sizeof( row_buf ));
775 /* Determine how many rows will be needed, and the remainder */
776 rows = length / rowsize;
777 remainder = length % rowsize;
780 /* Format the rows */
781 for( count = 0; count < rows; count++ ) {
782 sprintf( row_buf, "%02x%02x%02x%02x",
783 buffer[count*rowsize], buffer[count*rowsize+1],
784 buffer[count*rowsize+2], buffer[count*rowsize+3]);
785 strcat( output, row_buf );
788 memset( row_buf, 0, sizeof( row_buf ));
791 /* Format the remainder */
792 for( count = 0; count < remainder; count++ ) {
793 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
794 strcat( output, row_buf );
799 /*============================================================================*/
804 /*******************************************************************************
805 * wl_is_a_valid_chan()
806 *******************************************************************************
810 * Checks if a given channel is valid
814 * channel - the channel
821 ******************************************************************************/
822 int wl_is_a_valid_chan( int channel )
825 /*------------------------------------------------------------------------*/
828 /* Strip out the high bit set by the FW for 802.11a channels */
829 if( channel & 0x100 ) {
830 channel = channel & 0x0FF;
833 /* Iterate through the matrix and retrieve the frequency */
834 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
835 if( chan_freq_list[i][0] == channel ) {
841 } // wl_is_a_valid_chan
842 /*============================================================================*/
847 /*******************************************************************************
848 * wl_get_chan_from_freq()
849 *******************************************************************************
853 * Checks if a given frequency is valid
857 * freq - the frequency
864 ******************************************************************************/
865 int wl_is_a_valid_freq( long frequency )
868 /*------------------------------------------------------------------------*/
871 /* Iterate through the matrix and retrieve the channel */
872 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
873 if( chan_freq_list[i][1] == frequency ) {
879 } // wl_is_a_valid_freq
880 /*============================================================================*/
885 /*******************************************************************************
886 * wl_get_freq_from_chan()
887 *******************************************************************************
891 * Function used to look up the frequency for a given channel on which the
896 * channel - the channel
900 * The corresponding frequency
902 ******************************************************************************/
903 long wl_get_freq_from_chan( int channel )
906 /*------------------------------------------------------------------------*/
909 /* Strip out the high bit set by the FW for 802.11a channels */
910 if( channel & 0x100 ) {
911 channel = channel & 0x0FF;
914 /* Iterate through the matrix and retrieve the frequency */
915 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
916 if( chan_freq_list[i][0] == channel ) {
917 return chan_freq_list[i][1];
922 } // wl_get_freq_from_chan
923 /*============================================================================*/
928 /*******************************************************************************
929 * wl_get_chan_from_freq()
930 *******************************************************************************
934 * Function used to look up the channel for a given frequency on which the
939 * frequency - the frequency
943 * The corresponding channel
945 ******************************************************************************/
946 int wl_get_chan_from_freq( long frequency )
949 /*------------------------------------------------------------------------*/
952 /* Iterate through the matrix and retrieve the channel */
953 for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
954 if( chan_freq_list[i][1] == frequency ) {
955 return chan_freq_list[i][0];
960 } // wl_get_chan_from_freq
961 /*============================================================================*/
966 /*******************************************************************************
967 * wl_process_link_status()
968 *******************************************************************************
972 * Process the link status message signaled by the device.
976 * lp - a pointer to the device's private structure
982 ******************************************************************************/
983 void wl_process_link_status( struct wl_private *lp )
988 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
989 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
990 switch( link_stat ) {
992 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
993 wl_wext_event_ap( lp->dev );
996 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
999 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1002 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1005 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1008 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1012 } // wl_process_link_status
1013 /*============================================================================*/
1018 /*******************************************************************************
1019 * wl_process_probe_response()
1020 *******************************************************************************
1024 * Process the probe responses retunred by the device as a result of an
1029 * lp - a pointer to the device's private structure
1035 ******************************************************************************/
1036 void wl_process_probe_response( struct wl_private *lp )
1038 PROBE_RESP *probe_rsp;
1039 hcf_8 *wpa_ie = NULL;
1040 hcf_16 wpa_ie_len = 0;
1043 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1045 wl_endian_translate_event( (ltv_t *)probe_rsp );
1047 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1048 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1049 probe_rsp->length );
1051 if( probe_rsp->length > 1 ) {
1052 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1053 probe_rsp->infoType );
1055 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1056 probe_rsp->signal );
1058 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1059 probe_rsp->silence );
1061 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1062 probe_rsp->rxFlow );
1064 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1067 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1068 probe_rsp->frameControl );
1070 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1073 DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name,
1074 probe_rsp->address1);
1076 DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name,
1077 probe_rsp->address2);
1079 DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name,
1082 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1083 probe_rsp->sequence );
1085 DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name,
1086 probe_rsp->address4);
1088 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1089 probe_rsp->dataLength );
1091 DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name,
1094 DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name,
1099 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1100 probe_rsp->channel );
1102 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1105 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1106 probe_rsp->lenType );
1109 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1111 probe_rsp->timeStamp[0],
1112 probe_rsp->timeStamp[1],
1113 probe_rsp->timeStamp[2],
1114 probe_rsp->timeStamp[3],
1115 probe_rsp->timeStamp[4],
1116 probe_rsp->timeStamp[5],
1117 probe_rsp->timeStamp[6],
1118 probe_rsp->timeStamp[7]);
1120 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1121 probe_rsp->beaconInterval );
1123 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1124 probe_rsp->capability );
1126 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1127 probe_rsp->rawData[1] );
1130 if( probe_rsp->rawData[1] > 0 ) {
1131 char ssid[HCF_MAX_NAME_LEN];
1133 memset( ssid, 0, sizeof( ssid ));
1134 strncpy( ssid, &probe_rsp->rawData[2],
1135 probe_rsp->rawData[1] );
1137 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1138 lp->dev->name, ssid );
1142 /* Parse out the WPA-IE, if one exists */
1143 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1144 if( wpa_ie != NULL ) {
1145 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1146 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1149 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1150 lp->dev->name, probe_rsp->flags );
1153 DBG_TRACE( DbgInfo, "\n" );
1156 /* If probe response length is 1, then the scan is complete */
1157 if( probe_rsp->length == 1 ) {
1158 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1159 lp->probe_results.num_aps = lp->probe_num_aps;
1160 lp->probe_results.scan_complete = TRUE;
1162 /* Reset the counter for the next scan request */
1163 lp->probe_num_aps = 0;
1165 /* Send a wireless extensions event that the scan completed */
1166 wl_wext_event_scan_complete( lp->dev );
1168 /* Only copy to the table if the entry is unique; APs sometimes
1169 respond more than once to a probe */
1170 if( lp->probe_num_aps == 0 ) {
1171 /* Copy the info to the ScanResult structure in the private
1173 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1174 probe_rsp, sizeof( PROBE_RESP ));
1176 /* Increment the number of APs detected */
1177 lp->probe_num_aps++;
1182 for( count = 0; count < lp->probe_num_aps; count++ ) {
1183 if( memcmp( &( probe_rsp->BSSID ),
1184 lp->probe_results.ProbeTable[count].BSSID,
1191 /* Copy the info to the ScanResult structure in the
1192 private adapter struct. Only copy if there's room in the
1194 if( lp->probe_num_aps < MAX_NAPS )
1196 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1197 probe_rsp, sizeof( PROBE_RESP ));
1201 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1204 /* Increment the number of APs detected. Note I do this
1205 here even when I don't copy the probe response to the
1206 buffer in order to detect the overflow condition */
1207 lp->probe_num_aps++;
1212 } // wl_process_probe_response
1213 /*============================================================================*/
1218 /*******************************************************************************
1219 * wl_process_updated_record()
1220 *******************************************************************************
1224 * Process the updated information record message signaled by the device.
1228 * lp - a pointer to the device's private structure
1234 ******************************************************************************/
1235 void wl_process_updated_record( struct wl_private *lp )
1238 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1240 switch( lp->updatedRecord.u.u16[0] ) {
1241 case CFG_CUR_COUNTRY_INFO:
1242 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1247 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1252 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1253 lp->updatedRecord.u.u16[0] );
1256 } // wl_process_updated_record
1257 /*============================================================================*/
1262 /*******************************************************************************
1263 * wl_process_assoc_status()
1264 *******************************************************************************
1268 * Process the association status event signaled by the device.
1272 * lp - a pointer to the device's private structure
1278 ******************************************************************************/
1279 void wl_process_assoc_status( struct wl_private *lp )
1281 ASSOC_STATUS_STRCT *assoc_stat;
1284 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1286 wl_endian_translate_event( (ltv_t *)assoc_stat );
1288 switch( assoc_stat->assocStatus ) {
1290 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1294 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1298 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1302 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1303 assoc_stat->assocStatus );
1307 DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr);
1309 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1310 DBG_TRACE(DbgInfo, "Old AP Address : %pM\n",
1311 assoc_stat->oldApAddr);
1314 } // wl_process_assoc_status
1315 /*============================================================================*/
1320 /*******************************************************************************
1321 * wl_process_security_status()
1322 *******************************************************************************
1326 * Process the security status message signaled by the device.
1330 * lp - a pointer to the device's private structure
1336 ******************************************************************************/
1337 void wl_process_security_status( struct wl_private *lp )
1339 SECURITY_STATUS_STRCT *sec_stat;
1342 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1344 wl_endian_translate_event( (ltv_t *)sec_stat );
1346 switch( sec_stat->securityStatus ) {
1348 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1352 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1356 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1360 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1364 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1368 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1369 sec_stat->securityStatus );
1373 DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr);
1374 DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason);
1377 } // wl_process_security_status
1378 /*============================================================================*/
1380 int wl_get_tallies(struct wl_private *lp,
1381 CFG_HERMES_TALLIES_STRCT *tallies)
1385 CFG_HERMES_TALLIES_STRCT *pTallies;
1387 /* Get the current tallies from the adapter */
1388 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1389 lp->ltvRecord.typ = CFG_TALLIES;
1391 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1393 if( status == HCF_SUCCESS ) {
1394 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1395 memcpy(tallies, pTallies, sizeof(*tallies));
1396 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1398 DBG_TRACE( DbgInfo, "Get tallies failed\n" );