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