GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / wlags49_h2 / wl_util.c
blob7eff8cd0ce1b301b906ec128ad7d6f3c566744b7
1 /*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
14 * This file defines misc utility functions.
16 *------------------------------------------------------------------------------
18 * SOFTWARE LICENSE
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
34 * distribution.
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.
44 * Disclaimer
46 * THIS SOFTWARE IS PROVIDED “AS IS” 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
57 * DAMAGE.
59 ******************************************************************************/
61 /*******************************************************************************
62 * include files
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>
85 #include <debug.h>
86 #include <hcf.h>
87 // #include <hcfdef.h>
89 #include <wl_if.h>
90 #include <wl_internal.h>
91 #include <wl_util.h>
92 #include <wl_wext.h>
93 #include <wl_main.h>
97 /*******************************************************************************
98 * global variables
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] =
105 {1,2412},
106 {2,2417},
107 {3,2422},
108 {4,2427},
109 {5,2432},
110 {6,2437},
111 {7,2442},
112 {8,2447},
113 {9,2452},
114 {10,2457},
115 {11,2462},
116 {12,2467},
117 {13,2472},
118 {14,2484},
119 {36,5180},
120 {40,5200},
121 {44,5220},
122 {48,5240},
123 {52,5260},
124 {56,5280},
125 {60,5300},
126 {64,5320},
127 {149,5745},
128 {153,5765},
129 {157,5785},
130 {161,5805}
133 #if DBG
134 extern dbg_info_t *DbgInfo;
135 #endif /* DBG */
140 /*******************************************************************************
141 * dbm()
142 *******************************************************************************
144 * DESCRIPTION:
146 * Return an energy value in dBm.
148 * PARAMETERS:
150 * value - the energy value to be converted
152 * RETURNS:
154 * the value in dBm
156 ******************************************************************************/
157 int dbm( int value )
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 );
168 } // dbm
169 /*============================================================================*/
174 /*******************************************************************************
175 * percent()
176 *******************************************************************************
178 * DESCRIPTION:
180 * Return a value as a percentage of min to max.
182 * PARAMETERS:
184 * value - the value in question
185 * min - the minimum range value
186 * max - the maximum range value
188 * RETURNS:
190 * the percentage value
192 ******************************************************************************/
193 int percent( int value, int min, int max )
195 /* Truncate the value to be between min and max. */
196 if( value < min )
197 value = min;
199 if( value > max )
200 value = max;
202 /* Return the value as a percentage of min to max. */
203 return ((( value - min ) * 100 ) / ( max - min ));
204 } // percent
205 /*============================================================================*/
210 /*******************************************************************************
211 * is_valid_key_string()
212 *******************************************************************************
214 * DESCRIPTION:
216 * Checks to determine if the WEP key string is valid
218 * PARAMETERS:
220 * s - the string in question
222 * RETURNS:
224 * non-zero if the string contains a valid key
226 ******************************************************************************/
227 int is_valid_key_string( char *s )
229 int l;
230 int i;
231 /*------------------------------------------------------------------------*/
234 l = strlen( s );
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] ))
241 return 0;
244 return 1;
245 } else {
246 return 0;
250 /* string with 0, 5, or 13 characters is valid */
251 else
253 return( l == 0 || l == 5 || l == 13 );
255 } // is_valid_key_string
256 /*============================================================================*/
261 /*******************************************************************************
262 * key_string2key()
263 *******************************************************************************
265 * DESCRIPTION:
267 * Converts a key_string to a key, Assumes the key_string is validated with
268 * is_valid_key_string().
270 * PARAMETERS:
272 * ks - the valid key string
273 * key - a pointer to a KEY_STRUCT where the converted key information will
274 * be stored.
276 * RETURNS:
278 * N/A
280 ******************************************************************************/
281 void key_string2key( char *ks, KEY_STRCT *key )
283 int l,i,n;
284 char *p;
285 /*------------------------------------------------------------------------*/
288 l = strlen( ks );
290 /* 0x followed by hexadecimal digit pairs */
291 if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
292 n = 0;
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]);
297 n++;
300 /* Note that endian translation of the length field is not needed here
301 because it's performed in wl_put_ltv() */
302 key->len = n;
304 /* character string */
305 else
307 strcpy( (char *)key->key, ks );
308 key->len = l;
311 return;
312 } // key_string2key
313 /*============================================================================*/
318 #if DBG
319 /*******************************************************************************
320 * DbgHwAddr()
321 *******************************************************************************
323 * DESCRIPTION:
325 * Convert a hardware ethernet address to a character string
327 * PARAMETERS:
329 * hwAddr - an ethernet address
331 * RETURNS:
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] );
345 return buffer;
346 } // DbgHwAddr
347 /*============================================================================*/
349 #endif /* DBG */
354 /*******************************************************************************
355 * wl_has_wep()
356 *******************************************************************************
358 * DESCRIPTION:
360 * Checks to see if the device supports WEP
362 * PARAMETERS:
364 * ifbp - the IFB pointer of the device in question
366 * RETURNS:
368 * 1 if WEP is known enabled, else 0
370 ******************************************************************************/
371 int wl_has_wep (IFBP ifbp)
373 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
374 int rc, privacy;
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. */
381 ltv.len = 2;
382 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
384 rc = hcf_get_info( ifbp, (LTVP) &ltv );
386 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
388 //return rc ? 0 : privacy;
389 return 1;
390 } // wl_has_wep
391 /*============================================================================*/
396 /*******************************************************************************
397 * wl_hcf_error()
398 *******************************************************************************
400 * DESCRIPTION:
402 * Report the type of HCF error message
404 * PARAMETERS:
406 * none
408 * RETURNS:
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";
425 break;
428 case HCF_ERR_NO_NIC:
430 pMsg = "Card not found (ejected unexpectedly)";
431 break;
434 case HCF_ERR_LEN:
436 pMsg = "Command buffer size insufficient";
437 break;
440 case HCF_ERR_INCOMP_PRI:
442 pMsg = "Primary functions are not compatible";
443 break;
446 case HCF_ERR_INCOMP_FW:
448 pMsg = "Primary functions are compatible, "
449 "station/ap functions are not";
450 break;
453 case HCF_ERR_BUSY:
455 pMsg = "Inquire cmd while another Inquire in progress";
456 break;
459 //case HCF_ERR_SEQ_BUG:
461 // pMsg = "Unexpected command completed";
462 // break;
465 case HCF_ERR_DEFUNCT_AUX:
467 pMsg = "Timeout on ack for enable/disable of AUX registers";
468 break;
471 case HCF_ERR_DEFUNCT_TIMER:
472 pMsg = "Timeout on timer calibration during initialization process";
473 break;
476 case HCF_ERR_DEFUNCT_TIME_OUT:
477 pMsg = "Timeout on Busy bit drop during BAP setup";
478 break;
481 case HCF_ERR_DEFUNCT_CMD_SEQ:
482 pMsg = "Hermes and HCF are out of sync";
483 break;
486 default:
488 sprintf( buffer, "Error code %d", hcfStatus );
489 pMsg = buffer;
490 break;
493 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
494 dev->name, pMsg );
496 } // wl_hcf_error
497 /*============================================================================*/
502 /*******************************************************************************
503 * wl_endian_translate_event()
504 *******************************************************************************
506 * DESCRIPTION:
508 * Determines what type of data is in the mailbox and performs the proper
509 * endian translation.
511 * PARAMETERS:
513 * pLtv - an LTV pointer
515 * RETURNS:
517 * N/A
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 ) {
527 case CFG_TALLIES:
528 break;
531 case CFG_SCAN:
533 int numAPs;
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 ) {
540 numAPs--;
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;
564 break;
567 case CFG_ACS_SCAN:
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 );
576 #ifndef WARP
577 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
578 #endif // WARP
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 );
584 break;
587 case CFG_LINK_STAT:
588 #define ls ((LINK_STATUS_STRCT *)pLtv)
589 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
590 break;
591 #undef ls
593 case CFG_ASSOC_STAT:
595 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
597 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
599 break;
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 );
609 break;
612 case CFG_WMP:
613 break;
616 case CFG_NULL:
617 break;
620 default:
621 break;
624 DBG_LEAVE( DbgInfo );
625 return;
626 } // wl_endian_translate_event
627 /*============================================================================*/
630 /*******************************************************************************
631 * msf_assert()
632 *******************************************************************************
634 * DESCRIPTION:
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.
639 * PARAMETERS:
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
646 * RETURNS:
648 * N/A
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 );
654 } // msf_assert
655 /*============================================================================*/
660 /*******************************************************************************
661 * wl_parse_ds_ie()
662 *******************************************************************************
664 * DESCRIPTION:
666 * This function parses the Direct Sequence Parameter Set IE, used to
667 * determine channel/frequency information.
669 * PARAMETERS:
671 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
672 * response.
674 * RETURNS:
676 * The channel on which the BSS represented by this probe response is
677 * transmitting.
679 ******************************************************************************/
680 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
682 int i;
683 int ie_length = 0;
684 hcf_8 *buf;
685 hcf_8 buf_size;
686 /*------------------------------------------------------------------------*/
689 if( probe_rsp == NULL ) {
690 return 0;
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 */
701 i++;
702 ie_length = buf[i];
704 if( buf[i] == 1 ) {
705 /* Get the channel information */
706 i++;
707 return buf[i];
712 /* If we get here, we didn't find a DS-IE, which is strange */
713 return 0;
714 } // wl_parse_ds_ie
717 /*******************************************************************************
718 * wl_parse_wpa_ie()
719 *******************************************************************************
721 * DESCRIPTION:
723 * This function parses the Probe Response for a valid WPA-IE.
725 * PARAMETERS:
727 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
728 * response
729 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
730 * be stored (if found).
732 * RETURNS:
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 )
741 int i;
742 int ie_length = 0;
743 hcf_8 *buf;
744 hcf_8 buf_size;
745 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
746 /*------------------------------------------------------------------------*/
749 if( probe_rsp == NULL || length == NULL ) {
750 return NULL;
753 buf = probe_rsp->rawData;
754 buf_size = sizeof( probe_rsp->rawData );
755 *length = 0;
758 for( i = 0; i < buf_size; i++ ) {
759 if( buf[i] == GENERIC_INFO_ELEM ) {
760 /* Increment by one to get the IE length */
761 i++;
762 ie_length = probe_rsp->rawData[i];
764 /* Increment by one to point to the IE payload */
765 i++;
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 */
777 i -= 2;
778 return &buf[i];
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 */
787 return NULL;
788 } // wl_parse_wpa_ie
791 /*******************************************************************************
792 * wl_print_wpa_ie()
793 *******************************************************************************
795 * DESCRIPTION:
797 * Function used to take a WPA Information Element (WPA-IE) buffer and
798 * display it in a readable format.
800 * PARAMETERS:
802 * buffer - the byte buffer containing the WPA-IE
803 * length - the length of the above buffer
805 * RETURNS:
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 )
814 int count;
815 int rows;
816 int remainder;
817 int rowsize = 4;
818 hcf_8 row_buf[64];
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 );
849 return output;
850 } // wl_print_wpa_ie
851 /*============================================================================*/
856 /*******************************************************************************
857 * wl_is_a_valid_chan()
858 *******************************************************************************
860 * DESCRIPTION:
862 * Checks if a given channel is valid
864 * PARAMETERS:
866 * channel - the channel
868 * RETURNS:
870 * 1 if TRUE
871 * 0 if FALSE
873 ******************************************************************************/
874 int wl_is_a_valid_chan( int channel )
876 int i;
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 ) {
888 return 1;
892 return 0;
893 } // wl_is_a_valid_chan
894 /*============================================================================*/
899 /*******************************************************************************
900 * wl_get_chan_from_freq()
901 *******************************************************************************
903 * DESCRIPTION:
905 * Checks if a given frequency is valid
907 * PARAMETERS:
909 * freq - the frequency
911 * RETURNS:
913 * 1 if TRUE
914 * 0 if FALSE
916 ******************************************************************************/
917 int wl_is_a_valid_freq( long frequency )
919 int i;
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 ) {
926 return 1;
930 return 0;
931 } // wl_is_a_valid_freq
932 /*============================================================================*/
937 /*******************************************************************************
938 * wl_get_freq_from_chan()
939 *******************************************************************************
941 * DESCRIPTION:
943 * Function used to look up the frequency for a given channel on which the
944 * adapter is Tx/Rx.
946 * PARAMETERS:
948 * channel - the channel
950 * RETURNS:
952 * The corresponding frequency
954 ******************************************************************************/
955 long wl_get_freq_from_chan( int channel )
957 int i;
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];
973 return 0;
974 } // wl_get_freq_from_chan
975 /*============================================================================*/
980 /*******************************************************************************
981 * wl_get_chan_from_freq()
982 *******************************************************************************
984 * DESCRIPTION:
986 * Function used to look up the channel for a given frequency on which the
987 * adapter is Tx/Rx.
989 * PARAMETERS:
991 * frequency - the frequency
993 * RETURNS:
995 * The corresponding channel
997 ******************************************************************************/
998 int wl_get_chan_from_freq( long frequency )
1000 int i;
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];
1011 return 0;
1012 } // wl_get_chan_from_freq
1013 /*============================================================================*/
1018 /*******************************************************************************
1019 * wl_process_link_status()
1020 *******************************************************************************
1022 * DESCRIPTION:
1024 * Process the link status message signaled by the device.
1026 * PARAMETERS:
1028 * lp - a pointer to the device's private structure
1030 * RETURNS:
1032 * N/A
1034 ******************************************************************************/
1035 void wl_process_link_status( struct wl_private *lp )
1037 hcf_16 link_stat;
1038 /*------------------------------------------------------------------------*/
1040 DBG_FUNC( "wl_process_link_status" );
1041 DBG_ENTER( DbgInfo );
1043 if( lp != NULL ) {
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 ) {
1047 case 1:
1048 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1049 wl_wext_event_ap( lp->dev );
1050 break;
1051 case 2:
1052 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1053 break;
1054 case 3:
1055 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1056 break;
1057 case 4:
1058 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1059 break;
1060 case 5:
1061 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1062 break;
1063 default:
1064 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1065 break;
1068 DBG_LEAVE( DbgInfo );
1069 return;
1070 } // wl_process_link_status
1071 /*============================================================================*/
1076 /*******************************************************************************
1077 * wl_process_probe_response()
1078 *******************************************************************************
1080 * DESCRIPTION:
1082 * Process the probe responses retunred by the device as a result of an
1083 * active scan.
1085 * PARAMETERS:
1087 * lp - a pointer to the device's private structure
1089 * RETURNS:
1091 * N/A
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 );
1106 if( lp != NULL ) {
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,
1129 probe_rsp->rate );
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,
1135 probe_rsp->durID );
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 ));
1161 #ifdef WARP
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,
1167 probe_rsp->band );
1168 #else
1169 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1170 probe_rsp->lenType );
1171 #endif // WARP
1173 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1174 lp->dev->name,
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 );
1231 } else {
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
1236 adapter struct */
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++;
1242 } else {
1243 int count;
1244 int unique = 1;
1246 for( count = 0; count < lp->probe_num_aps; count++ ) {
1247 if( memcmp( &( probe_rsp->BSSID ),
1248 lp->probe_results.ProbeTable[count].BSSID,
1249 ETH_ALEN ) == 0 ) {
1250 unique = 0;
1254 if( unique ) {
1255 /* Copy the info to the ScanResult structure in the
1256 private adapter struct. Only copy if there's room in the
1257 table */
1258 if( lp->probe_num_aps < MAX_NAPS )
1260 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1261 probe_rsp, sizeof( PROBE_RESP ));
1263 else
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 );
1278 return;
1279 } // wl_process_probe_response
1280 /*============================================================================*/
1285 /*******************************************************************************
1286 * wl_process_updated_record()
1287 *******************************************************************************
1289 * DESCRIPTION:
1291 * Process the updated information record message signaled by the device.
1293 * PARAMETERS:
1295 * lp - a pointer to the device's private structure
1297 * RETURNS:
1299 * N/A
1301 ******************************************************************************/
1302 void wl_process_updated_record( struct wl_private *lp )
1304 DBG_FUNC( "wl_process_updated_record" );
1305 DBG_ENTER( DbgInfo );
1308 if( lp != NULL ) {
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" );
1314 wl_connect( lp );
1315 break;
1317 case CFG_PORT_STAT:
1318 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1319 //wl_connect( lp );
1320 break;
1322 default:
1323 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1324 lp->updatedRecord.u.u16[0] );
1328 DBG_LEAVE( DbgInfo );
1329 return;
1330 } // wl_process_updated_record
1331 /*============================================================================*/
1336 /*******************************************************************************
1337 * wl_process_assoc_status()
1338 *******************************************************************************
1340 * DESCRIPTION:
1342 * Process the association status event signaled by the device.
1344 * PARAMETERS:
1346 * lp - a pointer to the device's private structure
1348 * RETURNS:
1350 * N/A
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 );
1363 if( lp != NULL ) {
1364 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1366 wl_endian_translate_event( (ltv_t *)assoc_stat );
1368 switch( assoc_stat->assocStatus ) {
1369 case 1:
1370 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1371 break;
1373 case 2:
1374 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1375 break;
1377 case 3:
1378 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1379 break;
1381 default:
1382 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1383 assoc_stat->assocStatus );
1384 break;
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 );
1397 return;
1398 } // wl_process_assoc_status
1399 /*============================================================================*/
1404 /*******************************************************************************
1405 * wl_process_security_status()
1406 *******************************************************************************
1408 * DESCRIPTION:
1410 * Process the security status message signaled by the device.
1412 * PARAMETERS:
1414 * lp - a pointer to the device's private structure
1416 * RETURNS:
1418 * N/A
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 );
1431 if( lp != NULL ) {
1432 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1434 wl_endian_translate_event( (ltv_t *)sec_stat );
1436 switch( sec_stat->securityStatus ) {
1437 case 1:
1438 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1439 break;
1441 case 2:
1442 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1443 break;
1445 case 3:
1446 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1447 break;
1449 case 4:
1450 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1451 break;
1453 case 5:
1454 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1455 break;
1457 default:
1458 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1459 sec_stat->securityStatus );
1460 break;
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 );
1470 return;
1471 } // wl_process_security_status
1472 /*============================================================================*/
1474 int wl_get_tallies(struct wl_private *lp,
1475 CFG_HERMES_TALLIES_STRCT *tallies)
1477 int ret = 0;
1478 int status;
1479 CFG_HERMES_TALLIES_STRCT *pTallies;
1481 DBG_FUNC( "wl_get_tallies" );
1482 DBG_ENTER(DbgInfo);
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) );
1494 } else {
1495 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1496 ret = -EFAULT;
1499 DBG_LEAVE( DbgInfo );
1501 return ret;