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