Staging: sep: Use kzalloc when needed
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / wlags49_h2 / wl_util.c
blob3b6f5a59b2bb9038604bab2057a08ce516bed877
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 /*******************************************************************************
319 * wl_has_wep()
320 *******************************************************************************
322 * DESCRIPTION:
324 * Checks to see if the device supports WEP
326 * PARAMETERS:
328 * ifbp - the IFB pointer of the device in question
330 * RETURNS:
332 * 1 if WEP is known enabled, else 0
334 ******************************************************************************/
335 int wl_has_wep (IFBP ifbp)
337 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
338 int rc, privacy;
339 /*------------------------------------------------------------------------*/
342 /* This function allows us to distiguish bronze cards from other types, to
343 know if WEP exists. Does not distinguish (because there's no way to)
344 between silver and gold cards. */
345 ltv.len = 2;
346 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
348 rc = hcf_get_info( ifbp, (LTVP) &ltv );
350 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
352 //return rc ? 0 : privacy;
353 return 1;
354 } // wl_has_wep
355 /*============================================================================*/
360 /*******************************************************************************
361 * wl_hcf_error()
362 *******************************************************************************
364 * DESCRIPTION:
366 * Report the type of HCF error message
368 * PARAMETERS:
370 * none
372 * RETURNS:
374 * A descriptive string indicating the error, quiet otherwise.
376 ******************************************************************************/
377 void wl_hcf_error( struct net_device *dev, int hcfStatus )
379 char buffer[64], *pMsg;
380 /*------------------------------------------------------------------------*/
383 if( hcfStatus != HCF_SUCCESS ) {
384 switch( hcfStatus ) {
386 case HCF_ERR_TIME_OUT:
388 pMsg = "Expected adapter event did not occur in expected time";
389 break;
392 case HCF_ERR_NO_NIC:
394 pMsg = "Card not found (ejected unexpectedly)";
395 break;
398 case HCF_ERR_LEN:
400 pMsg = "Command buffer size insufficient";
401 break;
404 case HCF_ERR_INCOMP_PRI:
406 pMsg = "Primary functions are not compatible";
407 break;
410 case HCF_ERR_INCOMP_FW:
412 pMsg = "Primary functions are compatible, "
413 "station/ap functions are not";
414 break;
417 case HCF_ERR_BUSY:
419 pMsg = "Inquire cmd while another Inquire in progress";
420 break;
423 //case HCF_ERR_SEQ_BUG:
425 // pMsg = "Unexpected command completed";
426 // break;
429 case HCF_ERR_DEFUNCT_AUX:
431 pMsg = "Timeout on ack for enable/disable of AUX registers";
432 break;
435 case HCF_ERR_DEFUNCT_TIMER:
436 pMsg = "Timeout on timer calibration during initialization process";
437 break;
440 case HCF_ERR_DEFUNCT_TIME_OUT:
441 pMsg = "Timeout on Busy bit drop during BAP setup";
442 break;
445 case HCF_ERR_DEFUNCT_CMD_SEQ:
446 pMsg = "Hermes and HCF are out of sync";
447 break;
450 default:
452 sprintf( buffer, "Error code %d", hcfStatus );
453 pMsg = buffer;
454 break;
457 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
458 dev->name, pMsg );
460 } // wl_hcf_error
461 /*============================================================================*/
466 /*******************************************************************************
467 * wl_endian_translate_event()
468 *******************************************************************************
470 * DESCRIPTION:
472 * Determines what type of data is in the mailbox and performs the proper
473 * endian translation.
475 * PARAMETERS:
477 * pLtv - an LTV pointer
479 * RETURNS:
481 * N/A
483 ******************************************************************************/
484 void wl_endian_translate_event( ltv_t *pLtv )
486 DBG_FUNC( "wl_endian_translate_event" );
487 DBG_ENTER( DbgInfo );
490 switch( pLtv->typ ) {
491 case CFG_TALLIES:
492 break;
495 case CFG_SCAN:
497 int numAPs;
498 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
500 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
501 (sizeof( SCAN_RS_STRCT )));
503 while( numAPs >= 1 ) {
504 numAPs--;
506 pAps[numAPs].channel_id =
507 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
509 pAps[numAPs].noise_level =
510 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
512 pAps[numAPs].signal_level =
513 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
515 pAps[numAPs].beacon_interval_time =
516 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
518 pAps[numAPs].capability =
519 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
521 pAps[numAPs].ssid_len =
522 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
524 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
528 break;
531 case CFG_ACS_SCAN:
533 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
535 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
536 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
537 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
538 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
540 #ifndef WARP
541 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
542 #endif // WARP
544 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
545 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
546 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
548 break;
551 case CFG_LINK_STAT:
552 #define ls ((LINK_STATUS_STRCT *)pLtv)
553 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
554 break;
555 #undef ls
557 case CFG_ASSOC_STAT:
559 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
561 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
563 break;
566 case CFG_SECURITY_STAT:
568 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
570 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
571 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
573 break;
576 case CFG_WMP:
577 break;
580 case CFG_NULL:
581 break;
584 default:
585 break;
588 DBG_LEAVE( DbgInfo );
589 return;
590 } // wl_endian_translate_event
591 /*============================================================================*/
594 /*******************************************************************************
595 * msf_assert()
596 *******************************************************************************
598 * DESCRIPTION:
600 * Print statement used to display asserts from within the HCF. Only called
601 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
603 * PARAMETERS:
605 * file_namep - the filename in which the assert occurred.
606 * line_number - the line number on which the assert occurred.
607 * trace - a comment associated with the assert.
608 * qual - return code or other value related to the assert
610 * RETURNS:
612 * N/A
614 ******************************************************************************/
615 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
617 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
618 } // msf_assert
619 /*============================================================================*/
624 /*******************************************************************************
625 * wl_parse_ds_ie()
626 *******************************************************************************
628 * DESCRIPTION:
630 * This function parses the Direct Sequence Parameter Set IE, used to
631 * determine channel/frequency information.
633 * PARAMETERS:
635 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
636 * response.
638 * RETURNS:
640 * The channel on which the BSS represented by this probe response is
641 * transmitting.
643 ******************************************************************************/
644 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
646 int i;
647 int ie_length = 0;
648 hcf_8 *buf;
649 hcf_8 buf_size;
650 /*------------------------------------------------------------------------*/
653 if( probe_rsp == NULL ) {
654 return 0;
657 buf = probe_rsp->rawData;
658 buf_size = sizeof( probe_rsp->rawData );
661 for( i = 0; i < buf_size; i++ ) {
662 if( buf[i] == DS_INFO_ELEM ) {
663 /* Increment by 1 to get the length, and test it; in a DS element,
664 length should always be 1 */
665 i++;
666 ie_length = buf[i];
668 if( buf[i] == 1 ) {
669 /* Get the channel information */
670 i++;
671 return buf[i];
676 /* If we get here, we didn't find a DS-IE, which is strange */
677 return 0;
678 } // wl_parse_ds_ie
681 /*******************************************************************************
682 * wl_parse_wpa_ie()
683 *******************************************************************************
685 * DESCRIPTION:
687 * This function parses the Probe Response for a valid WPA-IE.
689 * PARAMETERS:
691 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
692 * response
693 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
694 * be stored (if found).
696 * RETURNS:
698 * A pointer to the location in the probe response buffer where a valid
699 * WPA-IE lives. The length of this IE is written back to the 'length'
700 * argument passed to the function.
702 ******************************************************************************/
703 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
705 int i;
706 int ie_length = 0;
707 hcf_8 *buf;
708 hcf_8 buf_size;
709 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
710 /*------------------------------------------------------------------------*/
713 if( probe_rsp == NULL || length == NULL ) {
714 return NULL;
717 buf = probe_rsp->rawData;
718 buf_size = sizeof( probe_rsp->rawData );
719 *length = 0;
722 for( i = 0; i < buf_size; i++ ) {
723 if( buf[i] == GENERIC_INFO_ELEM ) {
724 /* Increment by one to get the IE length */
725 i++;
726 ie_length = probe_rsp->rawData[i];
728 /* Increment by one to point to the IE payload */
729 i++;
731 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
732 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
733 /* Pass back length and return a pointer to the WPA-IE */
734 /* NOTE: Length contained in the WPA-IE is only the length of
735 the payload. The entire WPA-IE, including the IE identifier
736 and the length, is 2 bytes larger */
737 *length = ie_length + 2;
739 /* Back up the pointer 2 bytes to include the IE identifier and
740 the length in the buffer returned */
741 i -= 2;
742 return &buf[i];
745 /* Increment past this non-WPA IE and continue looking */
746 i += ( ie_length - 1 );
750 /* If we're here, we didn't find a WPA-IE in the buffer */
751 return NULL;
752 } // wl_parse_wpa_ie
755 /*******************************************************************************
756 * wl_print_wpa_ie()
757 *******************************************************************************
759 * DESCRIPTION:
761 * Function used to take a WPA Information Element (WPA-IE) buffer and
762 * display it in a readable format.
764 * PARAMETERS:
766 * buffer - the byte buffer containing the WPA-IE
767 * length - the length of the above buffer
769 * RETURNS:
771 * A pointer to the formatted WPA-IE string. Note that the format used is
772 * byte-by-byte printing as %02x hex values with no spaces. This is
773 * required for proper operation with some WPA supplicants.
775 ******************************************************************************/
776 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
778 int count;
779 int rows;
780 int remainder;
781 int rowsize = 4;
782 hcf_8 row_buf[64];
783 static hcf_8 output[512];
784 /*------------------------------------------------------------------------*/
787 memset( output, 0, sizeof( output ));
788 memset( row_buf, 0, sizeof( row_buf ));
791 /* Determine how many rows will be needed, and the remainder */
792 rows = length / rowsize;
793 remainder = length % rowsize;
796 /* Format the rows */
797 for( count = 0; count < rows; count++ ) {
798 sprintf( row_buf, "%02x%02x%02x%02x",
799 buffer[count*rowsize], buffer[count*rowsize+1],
800 buffer[count*rowsize+2], buffer[count*rowsize+3]);
801 strcat( output, row_buf );
804 memset( row_buf, 0, sizeof( row_buf ));
807 /* Format the remainder */
808 for( count = 0; count < remainder; count++ ) {
809 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
810 strcat( output, row_buf );
813 return output;
814 } // wl_print_wpa_ie
815 /*============================================================================*/
820 /*******************************************************************************
821 * wl_is_a_valid_chan()
822 *******************************************************************************
824 * DESCRIPTION:
826 * Checks if a given channel is valid
828 * PARAMETERS:
830 * channel - the channel
832 * RETURNS:
834 * 1 if TRUE
835 * 0 if FALSE
837 ******************************************************************************/
838 int wl_is_a_valid_chan( int channel )
840 int i;
841 /*------------------------------------------------------------------------*/
844 /* Strip out the high bit set by the FW for 802.11a channels */
845 if( channel & 0x100 ) {
846 channel = channel & 0x0FF;
849 /* Iterate through the matrix and retrieve the frequency */
850 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
851 if( chan_freq_list[i][0] == channel ) {
852 return 1;
856 return 0;
857 } // wl_is_a_valid_chan
858 /*============================================================================*/
863 /*******************************************************************************
864 * wl_get_chan_from_freq()
865 *******************************************************************************
867 * DESCRIPTION:
869 * Checks if a given frequency is valid
871 * PARAMETERS:
873 * freq - the frequency
875 * RETURNS:
877 * 1 if TRUE
878 * 0 if FALSE
880 ******************************************************************************/
881 int wl_is_a_valid_freq( long frequency )
883 int i;
884 /*------------------------------------------------------------------------*/
887 /* Iterate through the matrix and retrieve the channel */
888 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
889 if( chan_freq_list[i][1] == frequency ) {
890 return 1;
894 return 0;
895 } // wl_is_a_valid_freq
896 /*============================================================================*/
901 /*******************************************************************************
902 * wl_get_freq_from_chan()
903 *******************************************************************************
905 * DESCRIPTION:
907 * Function used to look up the frequency for a given channel on which the
908 * adapter is Tx/Rx.
910 * PARAMETERS:
912 * channel - the channel
914 * RETURNS:
916 * The corresponding frequency
918 ******************************************************************************/
919 long wl_get_freq_from_chan( int channel )
921 int i;
922 /*------------------------------------------------------------------------*/
925 /* Strip out the high bit set by the FW for 802.11a channels */
926 if( channel & 0x100 ) {
927 channel = channel & 0x0FF;
930 /* Iterate through the matrix and retrieve the frequency */
931 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
932 if( chan_freq_list[i][0] == channel ) {
933 return chan_freq_list[i][1];
937 return 0;
938 } // wl_get_freq_from_chan
939 /*============================================================================*/
944 /*******************************************************************************
945 * wl_get_chan_from_freq()
946 *******************************************************************************
948 * DESCRIPTION:
950 * Function used to look up the channel for a given frequency on which the
951 * adapter is Tx/Rx.
953 * PARAMETERS:
955 * frequency - the frequency
957 * RETURNS:
959 * The corresponding channel
961 ******************************************************************************/
962 int wl_get_chan_from_freq( long frequency )
964 int i;
965 /*------------------------------------------------------------------------*/
968 /* Iterate through the matrix and retrieve the channel */
969 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
970 if( chan_freq_list[i][1] == frequency ) {
971 return chan_freq_list[i][0];
975 return 0;
976 } // wl_get_chan_from_freq
977 /*============================================================================*/
982 /*******************************************************************************
983 * wl_process_link_status()
984 *******************************************************************************
986 * DESCRIPTION:
988 * Process the link status message signaled by the device.
990 * PARAMETERS:
992 * lp - a pointer to the device's private structure
994 * RETURNS:
996 * N/A
998 ******************************************************************************/
999 void wl_process_link_status( struct wl_private *lp )
1001 hcf_16 link_stat;
1002 /*------------------------------------------------------------------------*/
1004 DBG_FUNC( "wl_process_link_status" );
1005 DBG_ENTER( DbgInfo );
1007 if( lp != NULL ) {
1008 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1009 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1010 switch( link_stat ) {
1011 case 1:
1012 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1013 wl_wext_event_ap( lp->dev );
1014 break;
1015 case 2:
1016 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1017 break;
1018 case 3:
1019 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1020 break;
1021 case 4:
1022 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1023 break;
1024 case 5:
1025 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1026 break;
1027 default:
1028 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1029 break;
1032 DBG_LEAVE( DbgInfo );
1033 return;
1034 } // wl_process_link_status
1035 /*============================================================================*/
1040 /*******************************************************************************
1041 * wl_process_probe_response()
1042 *******************************************************************************
1044 * DESCRIPTION:
1046 * Process the probe responses retunred by the device as a result of an
1047 * active scan.
1049 * PARAMETERS:
1051 * lp - a pointer to the device's private structure
1053 * RETURNS:
1055 * N/A
1057 ******************************************************************************/
1058 void wl_process_probe_response( struct wl_private *lp )
1060 PROBE_RESP *probe_rsp;
1061 hcf_8 *wpa_ie = NULL;
1062 hcf_16 wpa_ie_len = 0;
1063 /*------------------------------------------------------------------------*/
1066 DBG_FUNC( "wl_process_probe_response" );
1067 DBG_ENTER( DbgInfo );
1070 if( lp != NULL ) {
1071 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1073 wl_endian_translate_event( (ltv_t *)probe_rsp );
1075 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1076 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1077 probe_rsp->length );
1079 if( probe_rsp->length > 1 ) {
1080 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1081 probe_rsp->infoType );
1083 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1084 probe_rsp->signal );
1086 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1087 probe_rsp->silence );
1089 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1090 probe_rsp->rxFlow );
1092 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1093 probe_rsp->rate );
1095 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1096 probe_rsp->frameControl );
1098 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1099 probe_rsp->durID );
1101 DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name,
1102 probe_rsp->address1);
1104 DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name,
1105 probe_rsp->address2);
1107 DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name,
1108 probe_rsp->BSSID);
1110 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1111 probe_rsp->sequence );
1113 DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name,
1114 probe_rsp->address4);
1116 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1117 probe_rsp->dataLength );
1119 DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name,
1120 probe_rsp->DA);
1122 DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name,
1123 probe_rsp->SA);
1125 #ifdef WARP
1127 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1128 probe_rsp->channel );
1130 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1131 probe_rsp->band );
1132 #else
1133 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1134 probe_rsp->lenType );
1135 #endif // WARP
1137 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1138 lp->dev->name,
1139 probe_rsp->timeStamp[0],
1140 probe_rsp->timeStamp[1],
1141 probe_rsp->timeStamp[2],
1142 probe_rsp->timeStamp[3],
1143 probe_rsp->timeStamp[4],
1144 probe_rsp->timeStamp[5],
1145 probe_rsp->timeStamp[6],
1146 probe_rsp->timeStamp[7]);
1148 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1149 probe_rsp->beaconInterval );
1151 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1152 probe_rsp->capability );
1154 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1155 probe_rsp->rawData[1] );
1158 if( probe_rsp->rawData[1] > 0 ) {
1159 char ssid[HCF_MAX_NAME_LEN];
1161 memset( ssid, 0, sizeof( ssid ));
1162 strncpy( ssid, &probe_rsp->rawData[2],
1163 probe_rsp->rawData[1] );
1165 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1166 lp->dev->name, ssid );
1170 /* Parse out the WPA-IE, if one exists */
1171 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1172 if( wpa_ie != NULL ) {
1173 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1174 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1177 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1178 lp->dev->name, probe_rsp->flags );
1181 DBG_TRACE( DbgInfo, "\n" );
1184 /* If probe response length is 1, then the scan is complete */
1185 if( probe_rsp->length == 1 ) {
1186 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1187 lp->probe_results.num_aps = lp->probe_num_aps;
1188 lp->probe_results.scan_complete = TRUE;
1190 /* Reset the counter for the next scan request */
1191 lp->probe_num_aps = 0;
1193 /* Send a wireless extensions event that the scan completed */
1194 wl_wext_event_scan_complete( lp->dev );
1195 } else {
1196 /* Only copy to the table if the entry is unique; APs sometimes
1197 respond more than once to a probe */
1198 if( lp->probe_num_aps == 0 ) {
1199 /* Copy the info to the ScanResult structure in the private
1200 adapter struct */
1201 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1202 probe_rsp, sizeof( PROBE_RESP ));
1204 /* Increment the number of APs detected */
1205 lp->probe_num_aps++;
1206 } else {
1207 int count;
1208 int unique = 1;
1210 for( count = 0; count < lp->probe_num_aps; count++ ) {
1211 if( memcmp( &( probe_rsp->BSSID ),
1212 lp->probe_results.ProbeTable[count].BSSID,
1213 ETH_ALEN ) == 0 ) {
1214 unique = 0;
1218 if( unique ) {
1219 /* Copy the info to the ScanResult structure in the
1220 private adapter struct. Only copy if there's room in the
1221 table */
1222 if( lp->probe_num_aps < MAX_NAPS )
1224 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1225 probe_rsp, sizeof( PROBE_RESP ));
1227 else
1229 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1232 /* Increment the number of APs detected. Note I do this
1233 here even when I don't copy the probe response to the
1234 buffer in order to detect the overflow condition */
1235 lp->probe_num_aps++;
1241 DBG_LEAVE( DbgInfo );
1242 return;
1243 } // wl_process_probe_response
1244 /*============================================================================*/
1249 /*******************************************************************************
1250 * wl_process_updated_record()
1251 *******************************************************************************
1253 * DESCRIPTION:
1255 * Process the updated information record message signaled by the device.
1257 * PARAMETERS:
1259 * lp - a pointer to the device's private structure
1261 * RETURNS:
1263 * N/A
1265 ******************************************************************************/
1266 void wl_process_updated_record( struct wl_private *lp )
1268 DBG_FUNC( "wl_process_updated_record" );
1269 DBG_ENTER( DbgInfo );
1272 if( lp != NULL ) {
1273 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1275 switch( lp->updatedRecord.u.u16[0] ) {
1276 case CFG_CUR_COUNTRY_INFO:
1277 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1278 wl_connect( lp );
1279 break;
1281 case CFG_PORT_STAT:
1282 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1283 //wl_connect( lp );
1284 break;
1286 default:
1287 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1288 lp->updatedRecord.u.u16[0] );
1292 DBG_LEAVE( DbgInfo );
1293 return;
1294 } // wl_process_updated_record
1295 /*============================================================================*/
1300 /*******************************************************************************
1301 * wl_process_assoc_status()
1302 *******************************************************************************
1304 * DESCRIPTION:
1306 * Process the association status event signaled by the device.
1308 * PARAMETERS:
1310 * lp - a pointer to the device's private structure
1312 * RETURNS:
1314 * N/A
1316 ******************************************************************************/
1317 void wl_process_assoc_status( struct wl_private *lp )
1319 ASSOC_STATUS_STRCT *assoc_stat;
1320 /*------------------------------------------------------------------------*/
1323 DBG_FUNC( "wl_process_assoc_status" );
1324 DBG_ENTER( DbgInfo );
1327 if( lp != NULL ) {
1328 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1330 wl_endian_translate_event( (ltv_t *)assoc_stat );
1332 switch( assoc_stat->assocStatus ) {
1333 case 1:
1334 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1335 break;
1337 case 2:
1338 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1339 break;
1341 case 3:
1342 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1343 break;
1345 default:
1346 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1347 assoc_stat->assocStatus );
1348 break;
1351 DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr);
1353 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1354 DBG_TRACE(DbgInfo, "Old AP Address : %pM\n",
1355 assoc_stat->oldApAddr);
1359 DBG_LEAVE( DbgInfo );
1360 return;
1361 } // wl_process_assoc_status
1362 /*============================================================================*/
1367 /*******************************************************************************
1368 * wl_process_security_status()
1369 *******************************************************************************
1371 * DESCRIPTION:
1373 * Process the security status message signaled by the device.
1375 * PARAMETERS:
1377 * lp - a pointer to the device's private structure
1379 * RETURNS:
1381 * N/A
1383 ******************************************************************************/
1384 void wl_process_security_status( struct wl_private *lp )
1386 SECURITY_STATUS_STRCT *sec_stat;
1387 /*------------------------------------------------------------------------*/
1390 DBG_FUNC( "wl_process_security_status" );
1391 DBG_ENTER( DbgInfo );
1394 if( lp != NULL ) {
1395 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1397 wl_endian_translate_event( (ltv_t *)sec_stat );
1399 switch( sec_stat->securityStatus ) {
1400 case 1:
1401 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1402 break;
1404 case 2:
1405 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1406 break;
1408 case 3:
1409 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1410 break;
1412 case 4:
1413 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1414 break;
1416 case 5:
1417 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1418 break;
1420 default:
1421 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1422 sec_stat->securityStatus );
1423 break;
1426 DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr);
1427 DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason);
1431 DBG_LEAVE( DbgInfo );
1432 return;
1433 } // wl_process_security_status
1434 /*============================================================================*/
1436 int wl_get_tallies(struct wl_private *lp,
1437 CFG_HERMES_TALLIES_STRCT *tallies)
1439 int ret = 0;
1440 int status;
1441 CFG_HERMES_TALLIES_STRCT *pTallies;
1443 DBG_FUNC( "wl_get_tallies" );
1444 DBG_ENTER(DbgInfo);
1446 /* Get the current tallies from the adapter */
1447 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1448 lp->ltvRecord.typ = CFG_TALLIES;
1450 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1452 if( status == HCF_SUCCESS ) {
1453 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1454 memcpy(tallies, pTallies, sizeof(*tallies));
1455 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1456 } else {
1457 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1458 ret = -EFAULT;
1461 DBG_LEAVE( DbgInfo );
1463 return ret;