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