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