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