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