Remove all #inclusions of asm/system.h
[linux-2.6.git] / drivers / staging / wlags49_h2 / wl_util.c
blobf104e6f1e980be07a974abaacdba66d9655e0c69
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/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>
84 #include <debug.h>
85 #include <hcf.h>
86 // #include <hcfdef.h>
88 #include <wl_if.h>
89 #include <wl_internal.h>
90 #include <wl_util.h>
91 #include <wl_wext.h>
92 #include <wl_main.h>
96 /*******************************************************************************
97 * global variables
98 ******************************************************************************/
100 /* A matrix which maps channels to frequencies */
101 #define MAX_CHAN_FREQ_MAP_ENTRIES 50
102 static const long chan_freq_list[][MAX_CHAN_FREQ_MAP_ENTRIES] =
104 {1,2412},
105 {2,2417},
106 {3,2422},
107 {4,2427},
108 {5,2432},
109 {6,2437},
110 {7,2442},
111 {8,2447},
112 {9,2452},
113 {10,2457},
114 {11,2462},
115 {12,2467},
116 {13,2472},
117 {14,2484},
118 {36,5180},
119 {40,5200},
120 {44,5220},
121 {48,5240},
122 {52,5260},
123 {56,5280},
124 {60,5300},
125 {64,5320},
126 {149,5745},
127 {153,5765},
128 {157,5785},
129 {161,5805}
132 #if DBG
133 extern dbg_info_t *DbgInfo;
134 #endif /* DBG */
139 /*******************************************************************************
140 * dbm()
141 *******************************************************************************
143 * DESCRIPTION:
145 * Return an energy value in dBm.
147 * PARAMETERS:
149 * value - the energy value to be converted
151 * RETURNS:
153 * the value in dBm
155 ******************************************************************************/
156 int dbm( int value )
158 /* Truncate the value to be between min and max. */
159 if( value < HCF_MIN_SIGNAL_LEVEL )
160 value = HCF_MIN_SIGNAL_LEVEL;
162 if( value > HCF_MAX_SIGNAL_LEVEL )
163 value = HCF_MAX_SIGNAL_LEVEL;
165 /* Return the energy value in dBm. */
166 return ( value - HCF_0DBM_OFFSET );
167 } // dbm
168 /*============================================================================*/
173 /*******************************************************************************
174 * percent()
175 *******************************************************************************
177 * DESCRIPTION:
179 * Return a value as a percentage of min to max.
181 * PARAMETERS:
183 * value - the value in question
184 * min - the minimum range value
185 * max - the maximum range value
187 * RETURNS:
189 * the percentage value
191 ******************************************************************************/
192 int percent( int value, int min, int max )
194 /* Truncate the value to be between min and max. */
195 if( value < min )
196 value = min;
198 if( value > max )
199 value = max;
201 /* Return the value as a percentage of min to max. */
202 return ((( value - min ) * 100 ) / ( max - min ));
203 } // percent
204 /*============================================================================*/
209 /*******************************************************************************
210 * is_valid_key_string()
211 *******************************************************************************
213 * DESCRIPTION:
215 * Checks to determine if the WEP key string is valid
217 * PARAMETERS:
219 * s - the string in question
221 * RETURNS:
223 * non-zero if the string contains a valid key
225 ******************************************************************************/
226 int is_valid_key_string( char *s )
228 int l;
229 int i;
230 /*------------------------------------------------------------------------*/
233 l = strlen( s );
235 /* 0x followed by 5 or 13 hexadecimal digit pairs is valid */
236 if( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' )) {
237 if( l == 12 || l == 28 ) {
238 for( i = 2; i < l; i++ ) {
239 if( !isxdigit( s[i] ))
240 return 0;
243 return 1;
244 } else {
245 return 0;
249 /* string with 0, 5, or 13 characters is valid */
250 else
252 return( l == 0 || l == 5 || l == 13 );
254 } // is_valid_key_string
255 /*============================================================================*/
260 /*******************************************************************************
261 * key_string2key()
262 *******************************************************************************
264 * DESCRIPTION:
266 * Converts a key_string to a key, Assumes the key_string is validated with
267 * is_valid_key_string().
269 * PARAMETERS:
271 * ks - the valid key string
272 * key - a pointer to a KEY_STRUCT where the converted key information will
273 * be stored.
275 * RETURNS:
277 * N/A
279 ******************************************************************************/
280 void key_string2key( char *ks, KEY_STRCT *key )
282 int l,i,n;
283 char *p;
284 /*------------------------------------------------------------------------*/
287 l = strlen( ks );
289 /* 0x followed by hexadecimal digit pairs */
290 if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
291 n = 0;
292 p = (char *)key->key;
294 for( i = 2; i < l; i+=2 ) {
295 *p++ = (hex_to_bin(ks[i]) << 4) + hex_to_bin(ks[i+1]);
296 n++;
299 /* Note that endian translation of the length field is not needed here
300 because it's performed in wl_put_ltv() */
301 key->len = n;
303 /* character string */
304 else
306 strcpy( (char *)key->key, ks );
307 key->len = l;
310 return;
311 } // key_string2key
312 /*============================================================================*/
317 /*******************************************************************************
318 * wl_has_wep()
319 *******************************************************************************
321 * DESCRIPTION:
323 * Checks to see if the device supports WEP
325 * PARAMETERS:
327 * ifbp - the IFB pointer of the device in question
329 * RETURNS:
331 * 1 if WEP is known enabled, else 0
333 ******************************************************************************/
334 int wl_has_wep (IFBP ifbp)
336 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
337 int rc, privacy;
338 /*------------------------------------------------------------------------*/
341 /* This function allows us to distiguish bronze cards from other types, to
342 know if WEP exists. Does not distinguish (because there's no way to)
343 between silver and gold cards. */
344 ltv.len = 2;
345 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
347 rc = hcf_get_info( ifbp, (LTVP) &ltv );
349 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
351 //return rc ? 0 : privacy;
352 return 1;
353 } // wl_has_wep
354 /*============================================================================*/
359 /*******************************************************************************
360 * wl_hcf_error()
361 *******************************************************************************
363 * DESCRIPTION:
365 * Report the type of HCF error message
367 * PARAMETERS:
369 * none
371 * RETURNS:
373 * A descriptive string indicating the error, quiet otherwise.
375 ******************************************************************************/
376 void wl_hcf_error( struct net_device *dev, int hcfStatus )
378 char buffer[64], *pMsg;
379 /*------------------------------------------------------------------------*/
382 if( hcfStatus != HCF_SUCCESS ) {
383 switch( hcfStatus ) {
385 case HCF_ERR_TIME_OUT:
387 pMsg = "Expected adapter event did not occur in expected time";
388 break;
391 case HCF_ERR_NO_NIC:
393 pMsg = "Card not found (ejected unexpectedly)";
394 break;
397 case HCF_ERR_LEN:
399 pMsg = "Command buffer size insufficient";
400 break;
403 case HCF_ERR_INCOMP_PRI:
405 pMsg = "Primary functions are not compatible";
406 break;
409 case HCF_ERR_INCOMP_FW:
411 pMsg = "Primary functions are compatible, "
412 "station/ap functions are not";
413 break;
416 case HCF_ERR_BUSY:
418 pMsg = "Inquire cmd while another Inquire in progress";
419 break;
422 //case HCF_ERR_SEQ_BUG:
424 // pMsg = "Unexpected command completed";
425 // break;
428 case HCF_ERR_DEFUNCT_AUX:
430 pMsg = "Timeout on ack for enable/disable of AUX registers";
431 break;
434 case HCF_ERR_DEFUNCT_TIMER:
435 pMsg = "Timeout on timer calibration during initialization process";
436 break;
439 case HCF_ERR_DEFUNCT_TIME_OUT:
440 pMsg = "Timeout on Busy bit drop during BAP setup";
441 break;
444 case HCF_ERR_DEFUNCT_CMD_SEQ:
445 pMsg = "Hermes and HCF are out of sync";
446 break;
449 default:
451 sprintf( buffer, "Error code %d", hcfStatus );
452 pMsg = buffer;
453 break;
456 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
457 dev->name, pMsg );
459 } // wl_hcf_error
460 /*============================================================================*/
465 /*******************************************************************************
466 * wl_endian_translate_event()
467 *******************************************************************************
469 * DESCRIPTION:
471 * Determines what type of data is in the mailbox and performs the proper
472 * endian translation.
474 * PARAMETERS:
476 * pLtv - an LTV pointer
478 * RETURNS:
480 * N/A
482 ******************************************************************************/
483 void wl_endian_translate_event( ltv_t *pLtv )
485 DBG_FUNC( "wl_endian_translate_event" );
486 DBG_ENTER( DbgInfo );
489 switch( pLtv->typ ) {
490 case CFG_TALLIES:
491 break;
494 case CFG_SCAN:
496 int numAPs;
497 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
499 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
500 (sizeof( SCAN_RS_STRCT )));
502 while( numAPs >= 1 ) {
503 numAPs--;
505 pAps[numAPs].channel_id =
506 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
508 pAps[numAPs].noise_level =
509 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
511 pAps[numAPs].signal_level =
512 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
514 pAps[numAPs].beacon_interval_time =
515 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
517 pAps[numAPs].capability =
518 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
520 pAps[numAPs].ssid_len =
521 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
523 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
527 break;
530 case CFG_ACS_SCAN:
532 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
534 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
535 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
536 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
537 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
539 #ifndef WARP
540 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
541 #endif // WARP
543 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
544 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
545 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
547 break;
550 case CFG_LINK_STAT:
551 #define ls ((LINK_STATUS_STRCT *)pLtv)
552 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
553 break;
554 #undef ls
556 case CFG_ASSOC_STAT:
558 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
560 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
562 break;
565 case CFG_SECURITY_STAT:
567 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
569 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
570 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
572 break;
575 case CFG_WMP:
576 break;
579 case CFG_NULL:
580 break;
583 default:
584 break;
587 DBG_LEAVE( DbgInfo );
588 return;
589 } // wl_endian_translate_event
590 /*============================================================================*/
593 /*******************************************************************************
594 * msf_assert()
595 *******************************************************************************
597 * DESCRIPTION:
599 * Print statement used to display asserts from within the HCF. Only called
600 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
602 * PARAMETERS:
604 * file_namep - the filename in which the assert occurred.
605 * line_number - the line number on which the assert occurred.
606 * trace - a comment associated with the assert.
607 * qual - return code or other value related to the assert
609 * RETURNS:
611 * N/A
613 ******************************************************************************/
614 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
616 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
617 } // msf_assert
618 /*============================================================================*/
623 /*******************************************************************************
624 * wl_parse_ds_ie()
625 *******************************************************************************
627 * DESCRIPTION:
629 * This function parses the Direct Sequence Parameter Set IE, used to
630 * determine channel/frequency information.
632 * PARAMETERS:
634 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
635 * response.
637 * RETURNS:
639 * The channel on which the BSS represented by this probe response is
640 * transmitting.
642 ******************************************************************************/
643 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
645 int i;
646 int ie_length = 0;
647 hcf_8 *buf;
648 hcf_8 buf_size;
649 /*------------------------------------------------------------------------*/
652 if( probe_rsp == NULL ) {
653 return 0;
656 buf = probe_rsp->rawData;
657 buf_size = sizeof( probe_rsp->rawData );
660 for( i = 0; i < buf_size; i++ ) {
661 if( buf[i] == DS_INFO_ELEM ) {
662 /* Increment by 1 to get the length, and test it; in a DS element,
663 length should always be 1 */
664 i++;
665 ie_length = buf[i];
667 if( buf[i] == 1 ) {
668 /* Get the channel information */
669 i++;
670 return buf[i];
675 /* If we get here, we didn't find a DS-IE, which is strange */
676 return 0;
677 } // wl_parse_ds_ie
680 /*******************************************************************************
681 * wl_parse_wpa_ie()
682 *******************************************************************************
684 * DESCRIPTION:
686 * This function parses the Probe Response for a valid WPA-IE.
688 * PARAMETERS:
690 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
691 * response
692 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
693 * be stored (if found).
695 * RETURNS:
697 * A pointer to the location in the probe response buffer where a valid
698 * WPA-IE lives. The length of this IE is written back to the 'length'
699 * argument passed to the function.
701 ******************************************************************************/
702 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
704 int i;
705 int ie_length = 0;
706 hcf_8 *buf;
707 hcf_8 buf_size;
708 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
709 /*------------------------------------------------------------------------*/
712 if( probe_rsp == NULL || length == NULL ) {
713 return NULL;
716 buf = probe_rsp->rawData;
717 buf_size = sizeof( probe_rsp->rawData );
718 *length = 0;
721 for( i = 0; i < buf_size; i++ ) {
722 if( buf[i] == GENERIC_INFO_ELEM ) {
723 /* Increment by one to get the IE length */
724 i++;
725 ie_length = probe_rsp->rawData[i];
727 /* Increment by one to point to the IE payload */
728 i++;
730 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
731 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
732 /* Pass back length and return a pointer to the WPA-IE */
733 /* NOTE: Length contained in the WPA-IE is only the length of
734 the payload. The entire WPA-IE, including the IE identifier
735 and the length, is 2 bytes larger */
736 *length = ie_length + 2;
738 /* Back up the pointer 2 bytes to include the IE identifier and
739 the length in the buffer returned */
740 i -= 2;
741 return &buf[i];
744 /* Increment past this non-WPA IE and continue looking */
745 i += ( ie_length - 1 );
749 /* If we're here, we didn't find a WPA-IE in the buffer */
750 return NULL;
751 } // wl_parse_wpa_ie
754 /*******************************************************************************
755 * wl_print_wpa_ie()
756 *******************************************************************************
758 * DESCRIPTION:
760 * Function used to take a WPA Information Element (WPA-IE) buffer and
761 * display it in a readable format.
763 * PARAMETERS:
765 * buffer - the byte buffer containing the WPA-IE
766 * length - the length of the above buffer
768 * RETURNS:
770 * A pointer to the formatted WPA-IE string. Note that the format used is
771 * byte-by-byte printing as %02x hex values with no spaces. This is
772 * required for proper operation with some WPA supplicants.
774 ******************************************************************************/
775 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
777 int count;
778 int rows;
779 int remainder;
780 int rowsize = 4;
781 hcf_8 row_buf[64];
782 static hcf_8 output[512];
783 /*------------------------------------------------------------------------*/
786 memset( output, 0, sizeof( output ));
787 memset( row_buf, 0, sizeof( row_buf ));
790 /* Determine how many rows will be needed, and the remainder */
791 rows = length / rowsize;
792 remainder = length % rowsize;
795 /* Format the rows */
796 for( count = 0; count < rows; count++ ) {
797 sprintf( row_buf, "%02x%02x%02x%02x",
798 buffer[count*rowsize], buffer[count*rowsize+1],
799 buffer[count*rowsize+2], buffer[count*rowsize+3]);
800 strcat( output, row_buf );
803 memset( row_buf, 0, sizeof( row_buf ));
806 /* Format the remainder */
807 for( count = 0; count < remainder; count++ ) {
808 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
809 strcat( output, row_buf );
812 return output;
813 } // wl_print_wpa_ie
814 /*============================================================================*/
819 /*******************************************************************************
820 * wl_is_a_valid_chan()
821 *******************************************************************************
823 * DESCRIPTION:
825 * Checks if a given channel is valid
827 * PARAMETERS:
829 * channel - the channel
831 * RETURNS:
833 * 1 if TRUE
834 * 0 if FALSE
836 ******************************************************************************/
837 int wl_is_a_valid_chan( int channel )
839 int i;
840 /*------------------------------------------------------------------------*/
843 /* Strip out the high bit set by the FW for 802.11a channels */
844 if( channel & 0x100 ) {
845 channel = channel & 0x0FF;
848 /* Iterate through the matrix and retrieve the frequency */
849 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
850 if( chan_freq_list[i][0] == channel ) {
851 return 1;
855 return 0;
856 } // wl_is_a_valid_chan
857 /*============================================================================*/
862 /*******************************************************************************
863 * wl_get_chan_from_freq()
864 *******************************************************************************
866 * DESCRIPTION:
868 * Checks if a given frequency is valid
870 * PARAMETERS:
872 * freq - the frequency
874 * RETURNS:
876 * 1 if TRUE
877 * 0 if FALSE
879 ******************************************************************************/
880 int wl_is_a_valid_freq( long frequency )
882 int i;
883 /*------------------------------------------------------------------------*/
886 /* Iterate through the matrix and retrieve the channel */
887 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
888 if( chan_freq_list[i][1] == frequency ) {
889 return 1;
893 return 0;
894 } // wl_is_a_valid_freq
895 /*============================================================================*/
900 /*******************************************************************************
901 * wl_get_freq_from_chan()
902 *******************************************************************************
904 * DESCRIPTION:
906 * Function used to look up the frequency for a given channel on which the
907 * adapter is Tx/Rx.
909 * PARAMETERS:
911 * channel - the channel
913 * RETURNS:
915 * The corresponding frequency
917 ******************************************************************************/
918 long wl_get_freq_from_chan( int channel )
920 int i;
921 /*------------------------------------------------------------------------*/
924 /* Strip out the high bit set by the FW for 802.11a channels */
925 if( channel & 0x100 ) {
926 channel = channel & 0x0FF;
929 /* Iterate through the matrix and retrieve the frequency */
930 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
931 if( chan_freq_list[i][0] == channel ) {
932 return chan_freq_list[i][1];
936 return 0;
937 } // wl_get_freq_from_chan
938 /*============================================================================*/
943 /*******************************************************************************
944 * wl_get_chan_from_freq()
945 *******************************************************************************
947 * DESCRIPTION:
949 * Function used to look up the channel for a given frequency on which the
950 * adapter is Tx/Rx.
952 * PARAMETERS:
954 * frequency - the frequency
956 * RETURNS:
958 * The corresponding channel
960 ******************************************************************************/
961 int wl_get_chan_from_freq( long frequency )
963 int i;
964 /*------------------------------------------------------------------------*/
967 /* Iterate through the matrix and retrieve the channel */
968 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
969 if( chan_freq_list[i][1] == frequency ) {
970 return chan_freq_list[i][0];
974 return 0;
975 } // wl_get_chan_from_freq
976 /*============================================================================*/
981 /*******************************************************************************
982 * wl_process_link_status()
983 *******************************************************************************
985 * DESCRIPTION:
987 * Process the link status message signaled by the device.
989 * PARAMETERS:
991 * lp - a pointer to the device's private structure
993 * RETURNS:
995 * N/A
997 ******************************************************************************/
998 void wl_process_link_status( struct wl_private *lp )
1000 hcf_16 link_stat;
1001 /*------------------------------------------------------------------------*/
1003 DBG_FUNC( "wl_process_link_status" );
1004 DBG_ENTER( DbgInfo );
1006 if( lp != NULL ) {
1007 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1008 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1009 switch( link_stat ) {
1010 case 1:
1011 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1012 wl_wext_event_ap( lp->dev );
1013 break;
1014 case 2:
1015 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1016 break;
1017 case 3:
1018 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1019 break;
1020 case 4:
1021 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1022 break;
1023 case 5:
1024 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1025 break;
1026 default:
1027 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1028 break;
1031 DBG_LEAVE( DbgInfo );
1032 return;
1033 } // wl_process_link_status
1034 /*============================================================================*/
1039 /*******************************************************************************
1040 * wl_process_probe_response()
1041 *******************************************************************************
1043 * DESCRIPTION:
1045 * Process the probe responses retunred by the device as a result of an
1046 * active scan.
1048 * PARAMETERS:
1050 * lp - a pointer to the device's private structure
1052 * RETURNS:
1054 * N/A
1056 ******************************************************************************/
1057 void wl_process_probe_response( struct wl_private *lp )
1059 PROBE_RESP *probe_rsp;
1060 hcf_8 *wpa_ie = NULL;
1061 hcf_16 wpa_ie_len = 0;
1062 /*------------------------------------------------------------------------*/
1065 DBG_FUNC( "wl_process_probe_response" );
1066 DBG_ENTER( DbgInfo );
1069 if( lp != NULL ) {
1070 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1072 wl_endian_translate_event( (ltv_t *)probe_rsp );
1074 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1075 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1076 probe_rsp->length );
1078 if( probe_rsp->length > 1 ) {
1079 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1080 probe_rsp->infoType );
1082 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1083 probe_rsp->signal );
1085 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1086 probe_rsp->silence );
1088 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1089 probe_rsp->rxFlow );
1091 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1092 probe_rsp->rate );
1094 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1095 probe_rsp->frameControl );
1097 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1098 probe_rsp->durID );
1100 DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name,
1101 probe_rsp->address1);
1103 DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name,
1104 probe_rsp->address2);
1106 DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name,
1107 probe_rsp->BSSID);
1109 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1110 probe_rsp->sequence );
1112 DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name,
1113 probe_rsp->address4);
1115 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1116 probe_rsp->dataLength );
1118 DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name,
1119 probe_rsp->DA);
1121 DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name,
1122 probe_rsp->SA);
1124 #ifdef WARP
1126 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1127 probe_rsp->channel );
1129 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1130 probe_rsp->band );
1131 #else
1132 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1133 probe_rsp->lenType );
1134 #endif // WARP
1136 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1137 lp->dev->name,
1138 probe_rsp->timeStamp[0],
1139 probe_rsp->timeStamp[1],
1140 probe_rsp->timeStamp[2],
1141 probe_rsp->timeStamp[3],
1142 probe_rsp->timeStamp[4],
1143 probe_rsp->timeStamp[5],
1144 probe_rsp->timeStamp[6],
1145 probe_rsp->timeStamp[7]);
1147 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1148 probe_rsp->beaconInterval );
1150 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1151 probe_rsp->capability );
1153 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1154 probe_rsp->rawData[1] );
1157 if( probe_rsp->rawData[1] > 0 ) {
1158 char ssid[HCF_MAX_NAME_LEN];
1160 memset( ssid, 0, sizeof( ssid ));
1161 strncpy( ssid, &probe_rsp->rawData[2],
1162 probe_rsp->rawData[1] );
1164 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1165 lp->dev->name, ssid );
1169 /* Parse out the WPA-IE, if one exists */
1170 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1171 if( wpa_ie != NULL ) {
1172 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1173 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1176 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1177 lp->dev->name, probe_rsp->flags );
1180 DBG_TRACE( DbgInfo, "\n" );
1183 /* If probe response length is 1, then the scan is complete */
1184 if( probe_rsp->length == 1 ) {
1185 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1186 lp->probe_results.num_aps = lp->probe_num_aps;
1187 lp->probe_results.scan_complete = TRUE;
1189 /* Reset the counter for the next scan request */
1190 lp->probe_num_aps = 0;
1192 /* Send a wireless extensions event that the scan completed */
1193 wl_wext_event_scan_complete( lp->dev );
1194 } else {
1195 /* Only copy to the table if the entry is unique; APs sometimes
1196 respond more than once to a probe */
1197 if( lp->probe_num_aps == 0 ) {
1198 /* Copy the info to the ScanResult structure in the private
1199 adapter struct */
1200 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1201 probe_rsp, sizeof( PROBE_RESP ));
1203 /* Increment the number of APs detected */
1204 lp->probe_num_aps++;
1205 } else {
1206 int count;
1207 int unique = 1;
1209 for( count = 0; count < lp->probe_num_aps; count++ ) {
1210 if( memcmp( &( probe_rsp->BSSID ),
1211 lp->probe_results.ProbeTable[count].BSSID,
1212 ETH_ALEN ) == 0 ) {
1213 unique = 0;
1217 if( unique ) {
1218 /* Copy the info to the ScanResult structure in the
1219 private adapter struct. Only copy if there's room in the
1220 table */
1221 if( lp->probe_num_aps < MAX_NAPS )
1223 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1224 probe_rsp, sizeof( PROBE_RESP ));
1226 else
1228 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1231 /* Increment the number of APs detected. Note I do this
1232 here even when I don't copy the probe response to the
1233 buffer in order to detect the overflow condition */
1234 lp->probe_num_aps++;
1240 DBG_LEAVE( DbgInfo );
1241 return;
1242 } // wl_process_probe_response
1243 /*============================================================================*/
1248 /*******************************************************************************
1249 * wl_process_updated_record()
1250 *******************************************************************************
1252 * DESCRIPTION:
1254 * Process the updated information record message signaled by the device.
1256 * PARAMETERS:
1258 * lp - a pointer to the device's private structure
1260 * RETURNS:
1262 * N/A
1264 ******************************************************************************/
1265 void wl_process_updated_record( struct wl_private *lp )
1267 DBG_FUNC( "wl_process_updated_record" );
1268 DBG_ENTER( DbgInfo );
1271 if( lp != NULL ) {
1272 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1274 switch( lp->updatedRecord.u.u16[0] ) {
1275 case CFG_CUR_COUNTRY_INFO:
1276 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1277 wl_connect( lp );
1278 break;
1280 case CFG_PORT_STAT:
1281 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1282 //wl_connect( lp );
1283 break;
1285 default:
1286 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1287 lp->updatedRecord.u.u16[0] );
1291 DBG_LEAVE( DbgInfo );
1292 return;
1293 } // wl_process_updated_record
1294 /*============================================================================*/
1299 /*******************************************************************************
1300 * wl_process_assoc_status()
1301 *******************************************************************************
1303 * DESCRIPTION:
1305 * Process the association status event signaled by the device.
1307 * PARAMETERS:
1309 * lp - a pointer to the device's private structure
1311 * RETURNS:
1313 * N/A
1315 ******************************************************************************/
1316 void wl_process_assoc_status( struct wl_private *lp )
1318 ASSOC_STATUS_STRCT *assoc_stat;
1319 /*------------------------------------------------------------------------*/
1322 DBG_FUNC( "wl_process_assoc_status" );
1323 DBG_ENTER( DbgInfo );
1326 if( lp != NULL ) {
1327 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1329 wl_endian_translate_event( (ltv_t *)assoc_stat );
1331 switch( assoc_stat->assocStatus ) {
1332 case 1:
1333 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1334 break;
1336 case 2:
1337 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1338 break;
1340 case 3:
1341 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1342 break;
1344 default:
1345 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1346 assoc_stat->assocStatus );
1347 break;
1350 DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr);
1352 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1353 DBG_TRACE(DbgInfo, "Old AP Address : %pM\n",
1354 assoc_stat->oldApAddr);
1358 DBG_LEAVE( DbgInfo );
1359 return;
1360 } // wl_process_assoc_status
1361 /*============================================================================*/
1366 /*******************************************************************************
1367 * wl_process_security_status()
1368 *******************************************************************************
1370 * DESCRIPTION:
1372 * Process the security status message signaled by the device.
1374 * PARAMETERS:
1376 * lp - a pointer to the device's private structure
1378 * RETURNS:
1380 * N/A
1382 ******************************************************************************/
1383 void wl_process_security_status( struct wl_private *lp )
1385 SECURITY_STATUS_STRCT *sec_stat;
1386 /*------------------------------------------------------------------------*/
1389 DBG_FUNC( "wl_process_security_status" );
1390 DBG_ENTER( DbgInfo );
1393 if( lp != NULL ) {
1394 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1396 wl_endian_translate_event( (ltv_t *)sec_stat );
1398 switch( sec_stat->securityStatus ) {
1399 case 1:
1400 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1401 break;
1403 case 2:
1404 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1405 break;
1407 case 3:
1408 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1409 break;
1411 case 4:
1412 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1413 break;
1415 case 5:
1416 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1417 break;
1419 default:
1420 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1421 sec_stat->securityStatus );
1422 break;
1425 DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr);
1426 DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason);
1430 DBG_LEAVE( DbgInfo );
1431 return;
1432 } // wl_process_security_status
1433 /*============================================================================*/
1435 int wl_get_tallies(struct wl_private *lp,
1436 CFG_HERMES_TALLIES_STRCT *tallies)
1438 int ret = 0;
1439 int status;
1440 CFG_HERMES_TALLIES_STRCT *pTallies;
1442 DBG_FUNC( "wl_get_tallies" );
1443 DBG_ENTER(DbgInfo);
1445 /* Get the current tallies from the adapter */
1446 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1447 lp->ltvRecord.typ = CFG_TALLIES;
1449 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1451 if( status == HCF_SUCCESS ) {
1452 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1453 memcpy(tallies, pTallies, sizeof(*tallies));
1454 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1455 } else {
1456 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1457 ret = -EFAULT;
1460 DBG_LEAVE( DbgInfo );
1462 return ret;