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