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