Commit | Line | Data |
---|---|---|
68c0bdff HG |
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 | * | |
d36b6910 | 25 | * Copyright © 2003 Agere Systems Inc. |
68c0bdff HG |
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 | * | |
d36b6910 | 46 | * THIS SOFTWARE IS PROVIDED \93AS IS\94 AND ANY EXPRESS OR IMPLIED WARRANTIES, |
68c0bdff HG |
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 | ||
68c0bdff HG |
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> | |
9ffc93f2 | 76 | // // #include <asm/bitops.h> |
68c0bdff HG |
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 */ | |
fdf34800 | 101 | static const long chan_freq_list[][2] = |
68c0bdff HG |
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 | ||
68c0bdff HG |
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 ) { | |
ff290e23 | 294 | *p++ = (hex_to_bin(ks[i]) << 4) + hex_to_bin(ks[i+1]); |
68c0bdff HG |
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 | ||
68c0bdff HG |
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) <v ); | |
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 */ | |
fdf34800 | 848 | for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) { |
68c0bdff HG |
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 */ | |
fdf34800 | 886 | for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) { |
68c0bdff HG |
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 */ | |
fdf34800 | 929 | for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) { |
68c0bdff HG |
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 */ | |
fdf34800 | 967 | for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) { |
68c0bdff HG |
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 | ||
2b6d83d6 AS |
1099 | DBG_TRACE(DbgInfo, "(%s) address1 : %pM\n", lp->dev->name, |
1100 | probe_rsp->address1); | |
68c0bdff | 1101 | |
2b6d83d6 AS |
1102 | DBG_TRACE(DbgInfo, "(%s) address2 : %pM\n", lp->dev->name, |
1103 | probe_rsp->address2); | |
68c0bdff | 1104 | |
2b6d83d6 AS |
1105 | DBG_TRACE(DbgInfo, "(%s) BSSID : %pM\n", lp->dev->name, |
1106 | probe_rsp->BSSID); | |
68c0bdff HG |
1107 | |
1108 | DBG_TRACE( DbgInfo, "(%s) sequence : 0x%04x.\n", lp->dev->name, | |
1109 | probe_rsp->sequence ); | |
1110 | ||
2b6d83d6 AS |
1111 | DBG_TRACE(DbgInfo, "(%s) address4 : %pM\n", lp->dev->name, |
1112 | probe_rsp->address4); | |
68c0bdff HG |
1113 | |
1114 | DBG_TRACE( DbgInfo, "(%s) datalength : 0x%04x.\n", lp->dev->name, | |
1115 | probe_rsp->dataLength ); | |
1116 | ||
2b6d83d6 AS |
1117 | DBG_TRACE(DbgInfo, "(%s) DA : %pM\n", lp->dev->name, |
1118 | probe_rsp->DA); | |
68c0bdff | 1119 | |
2b6d83d6 AS |
1120 | DBG_TRACE(DbgInfo, "(%s) SA : %pM\n", lp->dev->name, |
1121 | probe_rsp->SA); | |
68c0bdff HG |
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 | ||
2b6d83d6 | 1349 | DBG_TRACE(DbgInfo, "STA Address : %pM\n", assoc_stat->staAddr); |
68c0bdff HG |
1350 | |
1351 | if(( assoc_stat->assocStatus == 2 ) && ( assoc_stat->len == 8 )) { | |
2b6d83d6 AS |
1352 | DBG_TRACE(DbgInfo, "Old AP Address : %pM\n", |
1353 | assoc_stat->oldApAddr); | |
68c0bdff HG |
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 | ||
2b6d83d6 AS |
1424 | DBG_TRACE(DbgInfo, "STA Address : %pM\n", sec_stat->staAddr); |
1425 | DBG_TRACE(DbgInfo, "Reason : 0x%04x\n", sec_stat->reason); | |
68c0bdff HG |
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 |