Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / wlags49_h2 / wl_util.c
1 /*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
4 *
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
8 *
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
11 *
12 *------------------------------------------------------------------------------
13 *
14 * This file defines misc utility functions.
15 *
16 *------------------------------------------------------------------------------
17 *
18 * SOFTWARE LICENSE
19 *
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.
24 *
25 * Copyright © 2003 Agere Systems Inc.
26 * All rights reserved.
27 *
28 * Redistribution and use in source or binary forms, with or without
29 * modifications, are permitted provided that the following conditions are met:
30 *
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.
35 *
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.
39 *
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.
43 *
44 * Disclaimer
45 *
46 * THIS SOFTWARE IS PROVIDED \93AS IS\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
47 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
48 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
49 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
50 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
56 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
57 * DAMAGE.
58 *
59 ******************************************************************************/
60
61 /*******************************************************************************
62 * include files
63 ******************************************************************************/
64 #include <wl_version.h>
65
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>
78
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>
84
85 #include <debug.h>
86 #include <hcf.h>
87 // #include <hcfdef.h>
88
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>
94
95
96
97 /*******************************************************************************
98 * global variables
99 ******************************************************************************/
100
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] =
104 {
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}
131 };
132
133 #if DBG
134 extern dbg_info_t *DbgInfo;
135 #endif /* DBG */
136
137
138
139
140 /*******************************************************************************
141 * dbm()
142 *******************************************************************************
143 *
144 * DESCRIPTION:
145 *
146 * Return an energy value in dBm.
147 *
148 * PARAMETERS:
149 *
150 * value - the energy value to be converted
151 *
152 * RETURNS:
153 *
154 * the value in dBm
155 *
156 ******************************************************************************/
157 int dbm( int value )
158 {
159 /* Truncate the value to be between min and max. */
160 if( value < HCF_MIN_SIGNAL_LEVEL )
161 value = HCF_MIN_SIGNAL_LEVEL;
162
163 if( value > HCF_MAX_SIGNAL_LEVEL )
164 value = HCF_MAX_SIGNAL_LEVEL;
165
166 /* Return the energy value in dBm. */
167 return ( value - HCF_0DBM_OFFSET );
168 } // dbm
169 /*============================================================================*/
170
171
172
173
174 /*******************************************************************************
175 * percent()
176 *******************************************************************************
177 *
178 * DESCRIPTION:
179 *
180 * Return a value as a percentage of min to max.
181 *
182 * PARAMETERS:
183 *
184 * value - the value in question
185 * min - the minimum range value
186 * max - the maximum range value
187 *
188 * RETURNS:
189 *
190 * the percentage value
191 *
192 ******************************************************************************/
193 int percent( int value, int min, int max )
194 {
195 /* Truncate the value to be between min and max. */
196 if( value < min )
197 value = min;
198
199 if( value > max )
200 value = max;
201
202 /* Return the value as a percentage of min to max. */
203 return ((( value - min ) * 100 ) / ( max - min ));
204 } // percent
205 /*============================================================================*/
206
207
208
209
210 /*******************************************************************************
211 * is_valid_key_string()
212 *******************************************************************************
213 *
214 * DESCRIPTION:
215 *
216 * Checks to determine if the WEP key string is valid
217 *
218 * PARAMETERS:
219 *
220 * s - the string in question
221 *
222 * RETURNS:
223 *
224 * non-zero if the string contains a valid key
225 *
226 ******************************************************************************/
227 int is_valid_key_string( char *s )
228 {
229 int l;
230 int i;
231 /*------------------------------------------------------------------------*/
232
233
234 l = strlen( s );
235
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;
242 }
243
244 return 1;
245 } else {
246 return 0;
247 }
248 }
249
250 /* string with 0, 5, or 13 characters is valid */
251 else
252 {
253 return( l == 0 || l == 5 || l == 13 );
254 }
255 } // is_valid_key_string
256 /*============================================================================*/
257
258
259
260
261 /*******************************************************************************
262 * hexdigit2int()
263 *******************************************************************************
264 *
265 * DESCRIPTION:
266 *
267 * Converts a hexadecimal digit character to an integer
268 *
269 * PARAMETERS:
270 *
271 * c - the hexadecimal digit character
272 *
273 * RETURNS:
274 *
275 * the converted integer
276 *
277 ******************************************************************************/
278 int hexdigit2int( char c )
279 {
280 if( c >= '0' && c <= '9' )
281 return c - '0';
282
283 if( c >= 'A' && c <= 'F' )
284 return c - 'A' + 10;
285
286 if( c >= 'a' && c <= 'f' )
287 return c - 'a' + 10;
288
289 return 0;
290 } // hexdigit2int
291 /*============================================================================*/
292
293
294
295
296 /*******************************************************************************
297 * key_string2key()
298 *******************************************************************************
299 *
300 * DESCRIPTION:
301 *
302 * Converts a key_string to a key, Assumes the key_string is validated with
303 * is_valid_key_string().
304 *
305 * PARAMETERS:
306 *
307 * ks - the valid key string
308 * key - a pointer to a KEY_STRUCT where the converted key information will
309 * be stored.
310 *
311 * RETURNS:
312 *
313 * N/A
314 *
315 ******************************************************************************/
316 void key_string2key( char *ks, KEY_STRCT *key )
317 {
318 int l,i,n;
319 char *p;
320 /*------------------------------------------------------------------------*/
321
322
323 l = strlen( ks );
324
325 /* 0x followed by hexadecimal digit pairs */
326 if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
327 n = 0;
328 p = (char *)key->key;
329
330 for( i = 2; i < l; i+=2 ) {
331 *p++ = ( hexdigit2int( ks[i] ) << 4 ) + hexdigit2int (ks[i+1] );
332 n++;
333 }
334
335 /* Note that endian translation of the length field is not needed here
336 because it's performed in wl_put_ltv() */
337 key->len = n;
338 }
339 /* character string */
340 else
341 {
342 strcpy( (char *)key->key, ks );
343 key->len = l;
344 }
345
346 return;
347 } // key_string2key
348 /*============================================================================*/
349
350
351
352
353 #if DBG
354 /*******************************************************************************
355 * DbgHwAddr()
356 *******************************************************************************
357 *
358 * DESCRIPTION:
359 *
360 * Convert a hardware ethernet address to a character string
361 *
362 * PARAMETERS:
363 *
364 * hwAddr - an ethernet address
365 *
366 * RETURNS:
367 *
368 * a pointer to a string representing the ethernet address
369 *
370 ******************************************************************************/
371 const char *DbgHwAddr(unsigned char *hwAddr)
372 {
373 static char buffer[18];
374 /*------------------------------------------------------------------------*/
375
376
377 sprintf( buffer, "%02X:%02X:%02X:%02X:%02X:%02X",
378 hwAddr[0], hwAddr[1], hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5] );
379
380 return buffer;
381 } // DbgHwAddr
382 /*============================================================================*/
383
384 #endif /* DBG */
385
386
387
388
389 /*******************************************************************************
390 * wl_has_wep()
391 *******************************************************************************
392 *
393 * DESCRIPTION:
394 *
395 * Checks to see if the device supports WEP
396 *
397 * PARAMETERS:
398 *
399 * ifbp - the IFB pointer of the device in question
400 *
401 * RETURNS:
402 *
403 * 1 if WEP is known enabled, else 0
404 *
405 ******************************************************************************/
406 int wl_has_wep (IFBP ifbp)
407 {
408 CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
409 int rc, privacy;
410 /*------------------------------------------------------------------------*/
411
412
413 /* This function allows us to distiguish bronze cards from other types, to
414 know if WEP exists. Does not distinguish (because there's no way to)
415 between silver and gold cards. */
416 ltv.len = 2;
417 ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
418
419 rc = hcf_get_info( ifbp, (LTVP) &ltv );
420
421 privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
422
423 //return rc ? 0 : privacy;
424 return 1;
425 } // wl_has_wep
426 /*============================================================================*/
427
428
429
430
431 /*******************************************************************************
432 * wl_hcf_error()
433 *******************************************************************************
434 *
435 * DESCRIPTION:
436 *
437 * Report the type of HCF error message
438 *
439 * PARAMETERS:
440 *
441 * none
442 *
443 * RETURNS:
444 *
445 * A descriptive string indicating the error, quiet otherwise.
446 *
447 ******************************************************************************/
448 void wl_hcf_error( struct net_device *dev, int hcfStatus )
449 {
450 char buffer[64], *pMsg;
451 /*------------------------------------------------------------------------*/
452
453
454 if( hcfStatus != HCF_SUCCESS ) {
455 switch( hcfStatus ) {
456
457 case HCF_ERR_TIME_OUT:
458
459 pMsg = "Expected adapter event did not occur in expected time";
460 break;
461
462
463 case HCF_ERR_NO_NIC:
464
465 pMsg = "Card not found (ejected unexpectedly)";
466 break;
467
468
469 case HCF_ERR_LEN:
470
471 pMsg = "Command buffer size insufficient";
472 break;
473
474
475 case HCF_ERR_INCOMP_PRI:
476
477 pMsg = "Primary functions are not compatible";
478 break;
479
480
481 case HCF_ERR_INCOMP_FW:
482
483 pMsg = "Primary functions are compatible, "
484 "station/ap functions are not";
485 break;
486
487
488 case HCF_ERR_BUSY:
489
490 pMsg = "Inquire cmd while another Inquire in progress";
491 break;
492
493
494 //case HCF_ERR_SEQ_BUG:
495
496 // pMsg = "Unexpected command completed";
497 // break;
498
499
500 case HCF_ERR_DEFUNCT_AUX:
501
502 pMsg = "Timeout on ack for enable/disable of AUX registers";
503 break;
504
505
506 case HCF_ERR_DEFUNCT_TIMER:
507 pMsg = "Timeout on timer calibration during initialization process";
508 break;
509
510
511 case HCF_ERR_DEFUNCT_TIME_OUT:
512 pMsg = "Timeout on Busy bit drop during BAP setup";
513 break;
514
515
516 case HCF_ERR_DEFUNCT_CMD_SEQ:
517 pMsg = "Hermes and HCF are out of sync";
518 break;
519
520
521 default:
522
523 sprintf( buffer, "Error code %d", hcfStatus );
524 pMsg = buffer;
525 break;
526 }
527
528 printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
529 dev->name, pMsg );
530 }
531 } // wl_hcf_error
532 /*============================================================================*/
533
534
535
536
537 /*******************************************************************************
538 * wl_endian_translate_event()
539 *******************************************************************************
540 *
541 * DESCRIPTION:
542 *
543 * Determines what type of data is in the mailbox and performs the proper
544 * endian translation.
545 *
546 * PARAMETERS:
547 *
548 * pLtv - an LTV pointer
549 *
550 * RETURNS:
551 *
552 * N/A
553 *
554 ******************************************************************************/
555 void wl_endian_translate_event( ltv_t *pLtv )
556 {
557 DBG_FUNC( "wl_endian_translate_event" );
558 DBG_ENTER( DbgInfo );
559
560
561 switch( pLtv->typ ) {
562 case CFG_TALLIES:
563 break;
564
565
566 case CFG_SCAN:
567 {
568 int numAPs;
569 SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
570
571 numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
572 (sizeof( SCAN_RS_STRCT )));
573
574 while( numAPs >= 1 ) {
575 numAPs--;
576
577 pAps[numAPs].channel_id =
578 CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
579
580 pAps[numAPs].noise_level =
581 CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
582
583 pAps[numAPs].signal_level =
584 CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
585
586 pAps[numAPs].beacon_interval_time =
587 CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
588
589 pAps[numAPs].capability =
590 CNV_LITTLE_TO_INT( pAps[numAPs].capability );
591
592 pAps[numAPs].ssid_len =
593 CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
594
595 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
596
597 }
598 }
599 break;
600
601
602 case CFG_ACS_SCAN:
603 {
604 PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
605
606 probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl );
607 probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID );
608 probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence );
609 probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength );
610
611 #ifndef WARP
612 probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType );
613 #endif // WARP
614
615 probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
616 probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability );
617 probe_resp->flags = CNV_LITTLE_TO_INT( probe_resp->flags );
618 }
619 break;
620
621
622 case CFG_LINK_STAT:
623 #define ls ((LINK_STATUS_STRCT *)pLtv)
624 ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
625 break;
626 #undef ls
627
628 case CFG_ASSOC_STAT:
629 {
630 ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
631
632 pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
633 }
634 break;
635
636
637 case CFG_SECURITY_STAT:
638 {
639 SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
640
641 pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
642 pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
643 }
644 break;
645
646
647 case CFG_WMP:
648 break;
649
650
651 case CFG_NULL:
652 break;
653
654
655 default:
656 break;
657 }
658
659 DBG_LEAVE( DbgInfo );
660 return;
661 } // wl_endian_translate_event
662 /*============================================================================*/
663
664
665 /*******************************************************************************
666 * msf_assert()
667 *******************************************************************************
668 *
669 * DESCRIPTION:
670 *
671 * Print statement used to display asserts from within the HCF. Only called
672 * when asserts in the HCF are turned on. See hcfcfg.h for more information.
673 *
674 * PARAMETERS:
675 *
676 * file_namep - the filename in which the assert occurred.
677 * line_number - the line number on which the assert occurred.
678 * trace - a comment associated with the assert.
679 * qual - return code or other value related to the assert
680 *
681 * RETURNS:
682 *
683 * N/A
684 *
685 ******************************************************************************/
686 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
687 {
688 DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
689 } // msf_assert
690 /*============================================================================*/
691
692
693
694
695 /*******************************************************************************
696 * wl_parse_ds_ie()
697 *******************************************************************************
698 *
699 * DESCRIPTION:
700 *
701 * This function parses the Direct Sequence Parameter Set IE, used to
702 * determine channel/frequency information.
703 *
704 * PARAMETERS:
705 *
706 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
707 * response.
708 *
709 * RETURNS:
710 *
711 * The channel on which the BSS represented by this probe response is
712 * transmitting.
713 *
714 ******************************************************************************/
715 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
716 {
717 int i;
718 int ie_length = 0;
719 hcf_8 *buf;
720 hcf_8 buf_size;
721 /*------------------------------------------------------------------------*/
722
723
724 if( probe_rsp == NULL ) {
725 return 0;
726 }
727
728 buf = probe_rsp->rawData;
729 buf_size = sizeof( probe_rsp->rawData );
730
731
732 for( i = 0; i < buf_size; i++ ) {
733 if( buf[i] == DS_INFO_ELEM ) {
734 /* Increment by 1 to get the length, and test it; in a DS element,
735 length should always be 1 */
736 i++;
737 ie_length = buf[i];
738
739 if( buf[i] == 1 ) {
740 /* Get the channel information */
741 i++;
742 return buf[i];
743 }
744 }
745 }
746
747 /* If we get here, we didn't find a DS-IE, which is strange */
748 return 0;
749 } // wl_parse_ds_ie
750
751
752 /*******************************************************************************
753 * wl_parse_wpa_ie()
754 *******************************************************************************
755 *
756 * DESCRIPTION:
757 *
758 * This function parses the Probe Response for a valid WPA-IE.
759 *
760 * PARAMETERS:
761 *
762 * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
763 * response
764 * length - a pointer to an hcf_16 in which the size of the WPA-IE will
765 * be stored (if found).
766 *
767 * RETURNS:
768 *
769 * A pointer to the location in the probe response buffer where a valid
770 * WPA-IE lives. The length of this IE is written back to the 'length'
771 * argument passed to the function.
772 *
773 ******************************************************************************/
774 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
775 {
776 int i;
777 int ie_length = 0;
778 hcf_8 *buf;
779 hcf_8 buf_size;
780 hcf_8 wpa_oui[] = WPA_OUI_TYPE;
781 /*------------------------------------------------------------------------*/
782
783
784 if( probe_rsp == NULL || length == NULL ) {
785 return NULL;
786 }
787
788 buf = probe_rsp->rawData;
789 buf_size = sizeof( probe_rsp->rawData );
790 *length = 0;
791
792
793 for( i = 0; i < buf_size; i++ ) {
794 if( buf[i] == GENERIC_INFO_ELEM ) {
795 /* Increment by one to get the IE length */
796 i++;
797 ie_length = probe_rsp->rawData[i];
798
799 /* Increment by one to point to the IE payload */
800 i++;
801
802 /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
803 if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
804 /* Pass back length and return a pointer to the WPA-IE */
805 /* NOTE: Length contained in the WPA-IE is only the length of
806 the payload. The entire WPA-IE, including the IE identifier
807 and the length, is 2 bytes larger */
808 *length = ie_length + 2;
809
810 /* Back up the pointer 2 bytes to include the IE identifier and
811 the length in the buffer returned */
812 i -= 2;
813 return &buf[i];
814 }
815
816 /* Increment past this non-WPA IE and continue looking */
817 i += ( ie_length - 1 );
818 }
819 }
820
821 /* If we're here, we didn't find a WPA-IE in the buffer */
822 return NULL;
823 } // wl_parse_wpa_ie
824
825
826 /*******************************************************************************
827 * wl_print_wpa_ie()
828 *******************************************************************************
829 *
830 * DESCRIPTION:
831 *
832 * Function used to take a WPA Information Element (WPA-IE) buffer and
833 * display it in a readable format.
834 *
835 * PARAMETERS:
836 *
837 * buffer - the byte buffer containing the WPA-IE
838 * length - the length of the above buffer
839 *
840 * RETURNS:
841 *
842 * A pointer to the formatted WPA-IE string. Note that the format used is
843 * byte-by-byte printing as %02x hex values with no spaces. This is
844 * required for proper operation with some WPA supplicants.
845 *
846 ******************************************************************************/
847 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
848 {
849 int count;
850 int rows;
851 int remainder;
852 int rowsize = 4;
853 hcf_8 row_buf[64];
854 static hcf_8 output[512];
855 /*------------------------------------------------------------------------*/
856
857
858 memset( output, 0, sizeof( output ));
859 memset( row_buf, 0, sizeof( row_buf ));
860
861
862 /* Determine how many rows will be needed, and the remainder */
863 rows = length / rowsize;
864 remainder = length % rowsize;
865
866
867 /* Format the rows */
868 for( count = 0; count < rows; count++ ) {
869 sprintf( row_buf, "%02x%02x%02x%02x",
870 buffer[count*rowsize], buffer[count*rowsize+1],
871 buffer[count*rowsize+2], buffer[count*rowsize+3]);
872 strcat( output, row_buf );
873 }
874
875 memset( row_buf, 0, sizeof( row_buf ));
876
877
878 /* Format the remainder */
879 for( count = 0; count < remainder; count++ ) {
880 sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
881 strcat( output, row_buf );
882 }
883
884 return output;
885 } // wl_print_wpa_ie
886 /*============================================================================*/
887
888
889
890
891 /*******************************************************************************
892 * wl_is_a_valid_chan()
893 *******************************************************************************
894 *
895 * DESCRIPTION:
896 *
897 * Checks if a given channel is valid
898 *
899 * PARAMETERS:
900 *
901 * channel - the channel
902 *
903 * RETURNS:
904 *
905 * 1 if TRUE
906 * 0 if FALSE
907 *
908 ******************************************************************************/
909 int wl_is_a_valid_chan( int channel )
910 {
911 int i;
912 /*------------------------------------------------------------------------*/
913
914
915 /* Strip out the high bit set by the FW for 802.11a channels */
916 if( channel & 0x100 ) {
917 channel = channel & 0x0FF;
918 }
919
920 /* Iterate through the matrix and retrieve the frequency */
921 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
922 if( chan_freq_list[i][0] == channel ) {
923 return 1;
924 }
925 }
926
927 return 0;
928 } // wl_is_a_valid_chan
929 /*============================================================================*/
930
931
932
933
934 /*******************************************************************************
935 * wl_get_chan_from_freq()
936 *******************************************************************************
937 *
938 * DESCRIPTION:
939 *
940 * Checks if a given frequency is valid
941 *
942 * PARAMETERS:
943 *
944 * freq - the frequency
945 *
946 * RETURNS:
947 *
948 * 1 if TRUE
949 * 0 if FALSE
950 *
951 ******************************************************************************/
952 int wl_is_a_valid_freq( long frequency )
953 {
954 int i;
955 /*------------------------------------------------------------------------*/
956
957
958 /* Iterate through the matrix and retrieve the channel */
959 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
960 if( chan_freq_list[i][1] == frequency ) {
961 return 1;
962 }
963 }
964
965 return 0;
966 } // wl_is_a_valid_freq
967 /*============================================================================*/
968
969
970
971
972 /*******************************************************************************
973 * wl_get_freq_from_chan()
974 *******************************************************************************
975 *
976 * DESCRIPTION:
977 *
978 * Function used to look up the frequency for a given channel on which the
979 * adapter is Tx/Rx.
980 *
981 * PARAMETERS:
982 *
983 * channel - the channel
984 *
985 * RETURNS:
986 *
987 * The corresponding frequency
988 *
989 ******************************************************************************/
990 long wl_get_freq_from_chan( int channel )
991 {
992 int i;
993 /*------------------------------------------------------------------------*/
994
995
996 /* Strip out the high bit set by the FW for 802.11a channels */
997 if( channel & 0x100 ) {
998 channel = channel & 0x0FF;
999 }
1000
1001 /* Iterate through the matrix and retrieve the frequency */
1002 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
1003 if( chan_freq_list[i][0] == channel ) {
1004 return chan_freq_list[i][1];
1005 }
1006 }
1007
1008 return 0;
1009 } // wl_get_freq_from_chan
1010 /*============================================================================*/
1011
1012
1013
1014
1015 /*******************************************************************************
1016 * wl_get_chan_from_freq()
1017 *******************************************************************************
1018 *
1019 * DESCRIPTION:
1020 *
1021 * Function used to look up the channel for a given frequency on which the
1022 * adapter is Tx/Rx.
1023 *
1024 * PARAMETERS:
1025 *
1026 * frequency - the frequency
1027 *
1028 * RETURNS:
1029 *
1030 * The corresponding channel
1031 *
1032 ******************************************************************************/
1033 int wl_get_chan_from_freq( long frequency )
1034 {
1035 int i;
1036 /*------------------------------------------------------------------------*/
1037
1038
1039 /* Iterate through the matrix and retrieve the channel */
1040 for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
1041 if( chan_freq_list[i][1] == frequency ) {
1042 return chan_freq_list[i][0];
1043 }
1044 }
1045
1046 return 0;
1047 } // wl_get_chan_from_freq
1048 /*============================================================================*/
1049
1050
1051
1052
1053 /*******************************************************************************
1054 * wl_process_link_status()
1055 *******************************************************************************
1056 *
1057 * DESCRIPTION:
1058 *
1059 * Process the link status message signaled by the device.
1060 *
1061 * PARAMETERS:
1062 *
1063 * lp - a pointer to the device's private structure
1064 *
1065 * RETURNS:
1066 *
1067 * N/A
1068 *
1069 ******************************************************************************/
1070 void wl_process_link_status( struct wl_private *lp )
1071 {
1072 hcf_16 link_stat;
1073 /*------------------------------------------------------------------------*/
1074
1075 DBG_FUNC( "wl_process_link_status" );
1076 DBG_ENTER( DbgInfo );
1077
1078 if( lp != NULL ) {
1079 //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1080 link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1081 switch( link_stat ) {
1082 case 1:
1083 DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1084 wl_wext_event_ap( lp->dev );
1085 break;
1086 case 2:
1087 DBG_TRACE( DbgInfo, "Link Status : Disconnected\n" );
1088 break;
1089 case 3:
1090 DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1091 break;
1092 case 4:
1093 DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1094 break;
1095 case 5:
1096 DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1097 break;
1098 default:
1099 DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1100 break;
1101 }
1102 }
1103 DBG_LEAVE( DbgInfo );
1104 return;
1105 } // wl_process_link_status
1106 /*============================================================================*/
1107
1108
1109
1110
1111 /*******************************************************************************
1112 * wl_process_probe_response()
1113 *******************************************************************************
1114 *
1115 * DESCRIPTION:
1116 *
1117 * Process the probe responses retunred by the device as a result of an
1118 * active scan.
1119 *
1120 * PARAMETERS:
1121 *
1122 * lp - a pointer to the device's private structure
1123 *
1124 * RETURNS:
1125 *
1126 * N/A
1127 *
1128 ******************************************************************************/
1129 void wl_process_probe_response( struct wl_private *lp )
1130 {
1131 PROBE_RESP *probe_rsp;
1132 hcf_8 *wpa_ie = NULL;
1133 hcf_16 wpa_ie_len = 0;
1134 /*------------------------------------------------------------------------*/
1135
1136
1137 DBG_FUNC( "wl_process_probe_response" );
1138 DBG_ENTER( DbgInfo );
1139
1140
1141 if( lp != NULL ) {
1142 probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1143
1144 wl_endian_translate_event( (ltv_t *)probe_rsp );
1145
1146 DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1147 DBG_TRACE( DbgInfo, "(%s) length : 0x%04x.\n", lp->dev->name,
1148 probe_rsp->length );
1149
1150 if( probe_rsp->length > 1 ) {
1151 DBG_TRACE( DbgInfo, "(%s) infoType : 0x%04x.\n", lp->dev->name,
1152 probe_rsp->infoType );
1153
1154 DBG_TRACE( DbgInfo, "(%s) signal : 0x%02x.\n", lp->dev->name,
1155 probe_rsp->signal );
1156
1157 DBG_TRACE( DbgInfo, "(%s) silence : 0x%02x.\n", lp->dev->name,
1158 probe_rsp->silence );
1159
1160 DBG_TRACE( DbgInfo, "(%s) rxFlow : 0x%02x.\n", lp->dev->name,
1161 probe_rsp->rxFlow );
1162
1163 DBG_TRACE( DbgInfo, "(%s) rate : 0x%02x.\n", lp->dev->name,
1164 probe_rsp->rate );
1165
1166 DBG_TRACE( DbgInfo, "(%s) frame cntl : 0x%04x.\n", lp->dev->name,
1167 probe_rsp->frameControl );
1168
1169 DBG_TRACE( DbgInfo, "(%s) durID : 0x%04x.\n", lp->dev->name,
1170 probe_rsp->durID );
1171
1172 DBG_TRACE( DbgInfo, "(%s) address1 : %s\n", lp->dev->name,
1173 DbgHwAddr( probe_rsp->address1 ));
1174
1175 DBG_TRACE( DbgInfo, "(%s) address2 : %s\n", lp->dev->name,
1176 DbgHwAddr( probe_rsp->address2 ));
1177
1178 DBG_TRACE( DbgInfo, "(%s) BSSID : %s\n", lp->dev->name,
1179 DbgHwAddr( probe_rsp->BSSID ));
1180
1181 DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name,
1182 probe_rsp->sequence );
1183
1184 DBG_TRACE( DbgInfo, "(%s) address4 : %s\n", lp->dev->name,
1185 DbgHwAddr( probe_rsp->address4 ));
1186
1187 DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name,
1188 probe_rsp->dataLength );
1189
1190 DBG_TRACE( DbgInfo, "(%s) DA : %s\n", lp->dev->name,
1191 DbgHwAddr( probe_rsp->DA ));
1192
1193 DBG_TRACE( DbgInfo, "(%s) SA : %s\n", lp->dev->name,
1194 DbgHwAddr( probe_rsp->SA ));
1195
1196 #ifdef WARP
1197
1198 DBG_TRACE( DbgInfo, "(%s) channel : %d\n", lp->dev->name,
1199 probe_rsp->channel );
1200
1201 DBG_TRACE( DbgInfo, "(%s) band : %d\n", lp->dev->name,
1202 probe_rsp->band );
1203 #else
1204 DBG_TRACE( DbgInfo, "(%s) lenType : 0x%04x.\n", lp->dev->name,
1205 probe_rsp->lenType );
1206 #endif // WARP
1207
1208 DBG_TRACE( DbgInfo, "(%s) timeStamp : %d.%d.%d.%d.%d.%d.%d.%d\n",
1209 lp->dev->name,
1210 probe_rsp->timeStamp[0],
1211 probe_rsp->timeStamp[1],
1212 probe_rsp->timeStamp[2],
1213 probe_rsp->timeStamp[3],
1214 probe_rsp->timeStamp[4],
1215 probe_rsp->timeStamp[5],
1216 probe_rsp->timeStamp[6],
1217 probe_rsp->timeStamp[7]);
1218
1219 DBG_TRACE( DbgInfo, "(%s) beaconInt : 0x%04x.\n", lp->dev->name,
1220 probe_rsp->beaconInterval );
1221
1222 DBG_TRACE( DbgInfo, "(%s) capability : 0x%04x.\n", lp->dev->name,
1223 probe_rsp->capability );
1224
1225 DBG_TRACE( DbgInfo, "(%s) SSID len : 0x%04x.\n", lp->dev->name,
1226 probe_rsp->rawData[1] );
1227
1228
1229 if( probe_rsp->rawData[1] > 0 ) {
1230 char ssid[HCF_MAX_NAME_LEN];
1231
1232 memset( ssid, 0, sizeof( ssid ));
1233 strncpy( ssid, &probe_rsp->rawData[2],
1234 probe_rsp->rawData[1] );
1235
1236 DBG_TRACE( DbgInfo, "(%s) SSID : %s\n",
1237 lp->dev->name, ssid );
1238 }
1239
1240
1241 /* Parse out the WPA-IE, if one exists */
1242 wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1243 if( wpa_ie != NULL ) {
1244 DBG_TRACE( DbgInfo, "(%s) WPA-IE : %s\n",
1245 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1246 }
1247
1248 DBG_TRACE( DbgInfo, "(%s) flags : 0x%04x.\n",
1249 lp->dev->name, probe_rsp->flags );
1250 }
1251
1252 DBG_TRACE( DbgInfo, "\n" );
1253
1254
1255 /* If probe response length is 1, then the scan is complete */
1256 if( probe_rsp->length == 1 ) {
1257 DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1258 lp->probe_results.num_aps = lp->probe_num_aps;
1259 lp->probe_results.scan_complete = TRUE;
1260
1261 /* Reset the counter for the next scan request */
1262 lp->probe_num_aps = 0;
1263
1264 /* Send a wireless extensions event that the scan completed */
1265 wl_wext_event_scan_complete( lp->dev );
1266 } else {
1267 /* Only copy to the table if the entry is unique; APs sometimes
1268 respond more than once to a probe */
1269 if( lp->probe_num_aps == 0 ) {
1270 /* Copy the info to the ScanResult structure in the private
1271 adapter struct */
1272 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1273 probe_rsp, sizeof( PROBE_RESP ));
1274
1275 /* Increment the number of APs detected */
1276 lp->probe_num_aps++;
1277 } else {
1278 int count;
1279 int unique = 1;
1280
1281 for( count = 0; count < lp->probe_num_aps; count++ ) {
1282 if( memcmp( &( probe_rsp->BSSID ),
1283 lp->probe_results.ProbeTable[count].BSSID,
1284 ETH_ALEN ) == 0 ) {
1285 unique = 0;
1286 }
1287 }
1288
1289 if( unique ) {
1290 /* Copy the info to the ScanResult structure in the
1291 private adapter struct. Only copy if there's room in the
1292 table */
1293 if( lp->probe_num_aps < MAX_NAPS )
1294 {
1295 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1296 probe_rsp, sizeof( PROBE_RESP ));
1297 }
1298 else
1299 {
1300 DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1301 }
1302
1303 /* Increment the number of APs detected. Note I do this
1304 here even when I don't copy the probe response to the
1305 buffer in order to detect the overflow condition */
1306 lp->probe_num_aps++;
1307 }
1308 }
1309 }
1310 }
1311
1312 DBG_LEAVE( DbgInfo );
1313 return;
1314 } // wl_process_probe_response
1315 /*============================================================================*/
1316
1317
1318
1319
1320 /*******************************************************************************
1321 * wl_process_updated_record()
1322 *******************************************************************************
1323 *
1324 * DESCRIPTION:
1325 *
1326 * Process the updated information record message signaled by the device.
1327 *
1328 * PARAMETERS:
1329 *
1330 * lp - a pointer to the device's private structure
1331 *
1332 * RETURNS:
1333 *
1334 * N/A
1335 *
1336 ******************************************************************************/
1337 void wl_process_updated_record( struct wl_private *lp )
1338 {
1339 DBG_FUNC( "wl_process_updated_record" );
1340 DBG_ENTER( DbgInfo );
1341
1342
1343 if( lp != NULL ) {
1344 lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1345
1346 switch( lp->updatedRecord.u.u16[0] ) {
1347 case CFG_CUR_COUNTRY_INFO:
1348 DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1349 wl_connect( lp );
1350 break;
1351
1352 case CFG_PORT_STAT:
1353 DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1354 //wl_connect( lp );
1355 break;
1356
1357 default:
1358 DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1359 lp->updatedRecord.u.u16[0] );
1360 }
1361 }
1362
1363 DBG_LEAVE( DbgInfo );
1364 return;
1365 } // wl_process_updated_record
1366 /*============================================================================*/
1367
1368
1369
1370
1371 /*******************************************************************************
1372 * wl_process_assoc_status()
1373 *******************************************************************************
1374 *
1375 * DESCRIPTION:
1376 *
1377 * Process the association status event signaled by the device.
1378 *
1379 * PARAMETERS:
1380 *
1381 * lp - a pointer to the device's private structure
1382 *
1383 * RETURNS:
1384 *
1385 * N/A
1386 *
1387 ******************************************************************************/
1388 void wl_process_assoc_status( struct wl_private *lp )
1389 {
1390 ASSOC_STATUS_STRCT *assoc_stat;
1391 /*------------------------------------------------------------------------*/
1392
1393
1394 DBG_FUNC( "wl_process_assoc_status" );
1395 DBG_ENTER( DbgInfo );
1396
1397
1398 if( lp != NULL ) {
1399 assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1400
1401 wl_endian_translate_event( (ltv_t *)assoc_stat );
1402
1403 switch( assoc_stat->assocStatus ) {
1404 case 1:
1405 DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1406 break;
1407
1408 case 2:
1409 DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1410 break;
1411
1412 case 3:
1413 DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1414 break;
1415
1416 default:
1417 DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1418 assoc_stat->assocStatus );
1419 break;
1420 }
1421
1422 DBG_TRACE( DbgInfo, "STA Address : %s\n",
1423 DbgHwAddr( assoc_stat->staAddr ));
1424
1425 if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) {
1426 DBG_TRACE( DbgInfo, "Old AP Address : %s\n",
1427 DbgHwAddr( assoc_stat->oldApAddr ));
1428 }
1429 }
1430
1431 DBG_LEAVE( DbgInfo );
1432 return;
1433 } // wl_process_assoc_status
1434 /*============================================================================*/
1435
1436
1437
1438
1439 /*******************************************************************************
1440 * wl_process_security_status()
1441 *******************************************************************************
1442 *
1443 * DESCRIPTION:
1444 *
1445 * Process the security status message signaled by the device.
1446 *
1447 * PARAMETERS:
1448 *
1449 * lp - a pointer to the device's private structure
1450 *
1451 * RETURNS:
1452 *
1453 * N/A
1454 *
1455 ******************************************************************************/
1456 void wl_process_security_status( struct wl_private *lp )
1457 {
1458 SECURITY_STATUS_STRCT *sec_stat;
1459 /*------------------------------------------------------------------------*/
1460
1461
1462 DBG_FUNC( "wl_process_security_status" );
1463 DBG_ENTER( DbgInfo );
1464
1465
1466 if( lp != NULL ) {
1467 sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1468
1469 wl_endian_translate_event( (ltv_t *)sec_stat );
1470
1471 switch( sec_stat->securityStatus ) {
1472 case 1:
1473 DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1474 break;
1475
1476 case 2:
1477 DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1478 break;
1479
1480 case 3:
1481 DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1482 break;
1483
1484 case 4:
1485 DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1486 break;
1487
1488 case 5:
1489 DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1490 break;
1491
1492 default:
1493 DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1494 sec_stat->securityStatus );
1495 break;
1496 }
1497
1498 DBG_TRACE( DbgInfo, "STA Address : %s\n",
1499 DbgHwAddr( sec_stat->staAddr ));
1500 DBG_TRACE( DbgInfo, "Reason : 0x%04x \n", sec_stat->reason );
1501
1502 }
1503
1504 DBG_LEAVE( DbgInfo );
1505 return;
1506 } // wl_process_security_status
1507 /*============================================================================*/
1508
1509 int wl_get_tallies(struct wl_private *lp,
1510 CFG_HERMES_TALLIES_STRCT *tallies)
1511 {
1512 int ret = 0;
1513 int status;
1514 CFG_HERMES_TALLIES_STRCT *pTallies;
1515
1516 DBG_FUNC( "wl_get_tallies" );
1517 DBG_ENTER(DbgInfo);
1518
1519 /* Get the current tallies from the adapter */
1520 lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1521 lp->ltvRecord.typ = CFG_TALLIES;
1522
1523 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1524
1525 if( status == HCF_SUCCESS ) {
1526 pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1527 memcpy(tallies, pTallies, sizeof(*tallies));
1528 DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1529 } else {
1530 DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1531 ret = -EFAULT;
1532 }
1533
1534 DBG_LEAVE( DbgInfo );
1535
1536 return ret;
1537 }
1538