]> Pileus Git - ~andy/linux/blob - drivers/staging/wlags49_h2/wl_util.c
staging: wlags49_h2: remove empty DBG_FUNC()
[~andy/linux] / drivers / staging / wlags49_h2 / wl_util.c
1 /*******************************************************************************
2  * Agere Systems Inc.
3  * Wireless device driver for Linux (wlags49).
4  *
5  * Copyright (c) 1998-2003 Agere Systems Inc.
6  * All rights reserved.
7  *   http://www.agere.com
8  *
9  * Initially developed by TriplePoint, Inc.
10  *   http://www.triplepoint.com
11  *
12  *------------------------------------------------------------------------------
13  *
14  *   This file defines misc utility functions.
15  *
16  *------------------------------------------------------------------------------
17  *
18  * SOFTWARE LICENSE
19  *
20  * This software is provided subject to the following terms and conditions,
21  * which you should read carefully before using the software.  Using this
22  * software indicates your acceptance of these terms and conditions.  If you do
23  * not agree with these terms and conditions, do not use the software.
24  *
25  * Copyright © 2003 Agere Systems Inc.
26  * All rights reserved.
27  *
28  * Redistribution and use in source or binary forms, with or without
29  * modifications, are permitted provided that the following conditions are met:
30  *
31  * . Redistributions of source code must retain the above copyright notice, this
32  *    list of conditions and the following Disclaimer as comments in the code as
33  *    well as in the documentation and/or other materials provided with the
34  *    distribution.
35  *
36  * . Redistributions in binary form must reproduce the above copyright notice,
37  *    this list of conditions and the following Disclaimer in the documentation
38  *    and/or other materials provided with the distribution.
39  *
40  * . Neither the name of Agere Systems Inc. nor the names of the contributors
41  *    may be used to endorse or promote products derived from this software
42  *    without specific prior written permission.
43  *
44  * Disclaimer
45  *
46  * THIS SOFTWARE IS PROVIDED \93AS IS\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
47  * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
48  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
49  * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
50  * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
51  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54  * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
56  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
57  * DAMAGE.
58  *
59  ******************************************************************************/
60
61 /*******************************************************************************
62  *  include files
63  ******************************************************************************/
64 #include <wl_version.h>
65
66 #include <linux/kernel.h>
67 // #include <linux/sched.h>
68 // #include <linux/ptrace.h>
69 #include <linux/ctype.h>
70 // #include <linux/string.h>
71 // #include <linux/timer.h>
72 // #include <linux/interrupt.h>
73 // #include <linux/in.h>
74 // #include <linux/delay.h>
75 // #include <asm/io.h>
76 // // #include <asm/bitops.h>
77
78 #include <linux/netdevice.h>
79 #include <linux/etherdevice.h>
80 // #include <linux/skbuff.h>
81 // #include <linux/if_arp.h>
82 // #include <linux/ioport.h>
83
84 #include <debug.h>
85 #include <hcf.h>
86 // #include <hcfdef.h>
87
88 #include <wl_if.h>
89 #include <wl_internal.h>
90 #include <wl_util.h>
91 #include <wl_wext.h>
92 #include <wl_main.h>
93
94
95
96 /*******************************************************************************
97  * global variables
98  ******************************************************************************/
99
100 /* A matrix which maps channels to frequencies */
101 static const long chan_freq_list[][2] =
102 {
103     {1,2412},
104     {2,2417},
105     {3,2422},
106     {4,2427},
107     {5,2432},
108     {6,2437},
109     {7,2442},
110     {8,2447},
111     {9,2452},
112     {10,2457},
113     {11,2462},
114     {12,2467},
115     {13,2472},
116     {14,2484},
117     {36,5180},
118     {40,5200},
119     {44,5220},
120     {48,5240},
121     {52,5260},
122     {56,5280},
123     {60,5300},
124     {64,5320},
125     {149,5745},
126     {153,5765},
127     {157,5785},
128     {161,5805}
129 };
130
131 #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_ENTER( DbgInfo );
485
486
487     switch( pLtv->typ ) {
488     case CFG_TALLIES:
489         break;
490
491
492     case CFG_SCAN:
493         {
494             int numAPs;
495             SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
496
497             numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
498                                 (sizeof( SCAN_RS_STRCT )));
499
500             while( numAPs >= 1 ) {
501                 numAPs--;
502
503                 pAps[numAPs].channel_id           =
504                     CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
505
506                 pAps[numAPs].noise_level          =
507                     CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
508
509                 pAps[numAPs].signal_level         =
510                     CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
511
512                 pAps[numAPs].beacon_interval_time =
513                     CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
514
515                 pAps[numAPs].capability           =
516                     CNV_LITTLE_TO_INT( pAps[numAPs].capability );
517
518                 pAps[numAPs].ssid_len             =
519                     CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
520
521                 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
522
523             }
524         }
525         break;
526
527
528     case CFG_ACS_SCAN:
529         {
530             PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
531
532             probe_resp->frameControl   = CNV_LITTLE_TO_INT( probe_resp->frameControl );
533             probe_resp->durID          = CNV_LITTLE_TO_INT( probe_resp->durID );
534             probe_resp->sequence       = CNV_LITTLE_TO_INT( probe_resp->sequence );
535             probe_resp->dataLength     = CNV_LITTLE_TO_INT( probe_resp->dataLength );
536
537 #ifndef WARP
538             probe_resp->lenType        = CNV_LITTLE_TO_INT( probe_resp->lenType );
539 #endif // WARP
540
541             probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
542             probe_resp->capability     = CNV_LITTLE_TO_INT( probe_resp->capability );
543             probe_resp->flags          = CNV_LITTLE_TO_INT( probe_resp->flags );
544         }
545         break;
546
547
548     case CFG_LINK_STAT:
549 #define ls ((LINK_STATUS_STRCT *)pLtv)
550             ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
551         break;
552 #undef ls
553
554     case CFG_ASSOC_STAT:
555         {
556             ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
557
558             pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
559         }
560         break;
561
562
563     case CFG_SECURITY_STAT:
564         {
565             SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
566
567             pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
568             pSs->reason         = CNV_LITTLE_TO_INT( pSs->reason );
569         }
570         break;
571
572
573     case CFG_WMP:
574         break;
575
576
577     case CFG_NULL:
578         break;
579
580
581     default:
582         break;
583     }
584
585     DBG_LEAVE( DbgInfo );
586     return;
587 } // wl_endian_translate_event
588 /*============================================================================*/
589
590
591 /*******************************************************************************
592  *      msf_assert()
593  *******************************************************************************
594  *
595  *  DESCRIPTION:
596  *
597  *      Print statement used to display asserts from within the HCF. Only called
598  *  when asserts in the HCF are turned on. See hcfcfg.h for more information.
599  *
600  *  PARAMETERS:
601  *
602  *      file_namep  - the filename in which the assert occurred.
603  *      line_number - the line number on which the assert occurred.
604  *      trace       - a comment associated with the assert.
605  *      qual        - return code or other value related to the assert
606  *
607  *  RETURNS:
608  *
609  *      N/A
610  *
611  ******************************************************************************/
612 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
613 {
614     DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
615 } // msf_assert
616 /*============================================================================*/
617
618
619
620
621 /*******************************************************************************
622  *      wl_parse_ds_ie()
623  *******************************************************************************
624  *
625  *  DESCRIPTION:
626  *
627  *      This function parses the Direct Sequence Parameter Set IE, used to
628  *      determine channel/frequency information.
629  *
630  *  PARAMETERS:
631  *
632  *      probe_rsp - a pointer to a PROBE_RESP structure containing the probe
633  *                  response.
634  *
635  *  RETURNS:
636  *
637  *      The channel on which the BSS represented by this probe response is
638  *      transmitting.
639  *
640  ******************************************************************************/
641 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
642 {
643     int     i;
644     int     ie_length = 0;
645     hcf_8   *buf;
646     hcf_8   buf_size;
647     /*------------------------------------------------------------------------*/
648
649
650     if( probe_rsp == NULL ) {
651         return 0;
652     }
653
654     buf      = probe_rsp->rawData;
655     buf_size = sizeof( probe_rsp->rawData );
656
657
658     for( i = 0; i < buf_size; i++ ) {
659         if( buf[i] == DS_INFO_ELEM ) {
660             /* Increment by 1 to get the length, and test it; in a DS element,
661                length should always be 1 */
662             i++;
663             ie_length = buf[i];
664
665             if( buf[i] == 1 ) {
666                 /* Get the channel information */
667                 i++;
668                 return buf[i];
669             }
670         }
671     }
672
673     /* If we get here, we didn't find a DS-IE, which is strange */
674     return 0;
675 } // wl_parse_ds_ie
676
677
678 /*******************************************************************************
679  *      wl_parse_wpa_ie()
680  *******************************************************************************
681  *
682  *  DESCRIPTION:
683  *
684  *      This function parses the Probe Response for a valid WPA-IE.
685  *
686  *  PARAMETERS:
687  *
688  *      probe_rsp - a pointer to a PROBE_RESP structure containing the probe
689  *                  response
690  *      length    - a pointer to an hcf_16 in which the size of the WPA-IE will
691  *                  be stored (if found).
692  *
693  *  RETURNS:
694  *
695  *      A pointer to the location in the probe response buffer where a valid
696  *      WPA-IE lives. The length of this IE is written back to the 'length'
697  *      argument passed to the function.
698  *
699  ******************************************************************************/
700 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
701 {
702     int     i;
703     int     ie_length = 0;
704     hcf_8   *buf;
705     hcf_8   buf_size;
706     hcf_8   wpa_oui[] = WPA_OUI_TYPE;
707     /*------------------------------------------------------------------------*/
708
709
710     if( probe_rsp == NULL || length == NULL ) {
711         return NULL;
712     }
713
714     buf      = probe_rsp->rawData;
715     buf_size = sizeof( probe_rsp->rawData );
716     *length  = 0;
717
718
719     for( i = 0; i < buf_size; i++ ) {
720         if( buf[i] == GENERIC_INFO_ELEM ) {
721             /* Increment by one to get the IE length */
722             i++;
723             ie_length = probe_rsp->rawData[i];
724
725             /* Increment by one to point to the IE payload */
726             i++;
727
728             /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
729             if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
730                 /* Pass back length and return a pointer to the WPA-IE */
731                 /* NOTE: Length contained in the WPA-IE is only the length of
732                    the payload. The entire WPA-IE, including the IE identifier
733                    and the length, is 2 bytes larger */
734                 *length = ie_length + 2;
735
736                 /* Back up the pointer 2 bytes to include the IE identifier and
737                    the length in the buffer returned */
738                 i -= 2;
739                 return &buf[i];
740             }
741
742             /* Increment past this non-WPA IE and continue looking */
743             i += ( ie_length - 1 );
744         }
745     }
746
747     /* If we're here, we didn't find a WPA-IE in the buffer */
748     return NULL;
749 } // wl_parse_wpa_ie
750
751
752 /*******************************************************************************
753  *      wl_print_wpa_ie()
754  *******************************************************************************
755  *
756  *  DESCRIPTION:
757  *
758  *      Function used to take a WPA Information Element (WPA-IE) buffer and
759  *      display it in a readable format.
760  *
761  *  PARAMETERS:
762  *
763  *      buffer - the byte buffer containing the WPA-IE
764  *      length - the length of the above buffer
765  *
766  *  RETURNS:
767  *
768  *      A pointer to the formatted WPA-IE string. Note that the format used is
769  *      byte-by-byte printing as %02x hex values with no spaces. This is
770  *      required for proper operation with some WPA supplicants.
771  *
772  ******************************************************************************/
773 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
774 {
775     int count;
776     int rows;
777     int remainder;
778     int rowsize = 4;
779     hcf_8 row_buf[64];
780     static hcf_8 output[512];
781     /*------------------------------------------------------------------------*/
782
783
784     memset( output, 0, sizeof( output ));
785     memset( row_buf, 0, sizeof( row_buf ));
786
787
788     /* Determine how many rows will be needed, and the remainder */
789     rows = length / rowsize;
790     remainder = length % rowsize;
791
792
793     /* Format the rows */
794     for( count = 0; count < rows; count++ ) {
795         sprintf( row_buf, "%02x%02x%02x%02x",
796                  buffer[count*rowsize], buffer[count*rowsize+1],
797                  buffer[count*rowsize+2], buffer[count*rowsize+3]);
798         strcat( output, row_buf );
799     }
800
801     memset( row_buf, 0, sizeof( row_buf ));
802
803
804     /* Format the remainder */
805     for( count = 0; count < remainder; count++ ) {
806         sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
807         strcat( output, row_buf );
808     }
809
810     return output;
811 } // wl_print_wpa_ie
812 /*============================================================================*/
813
814
815
816
817 /*******************************************************************************
818  *      wl_is_a_valid_chan()
819  *******************************************************************************
820  *
821  *  DESCRIPTION:
822  *
823  *      Checks if a given channel is valid
824  *
825  *  PARAMETERS:
826  *
827  *      channel - the channel
828  *
829  *  RETURNS:
830  *
831  *      1 if TRUE
832  *      0 if FALSE
833  *
834  ******************************************************************************/
835 int wl_is_a_valid_chan( int channel )
836 {
837     int i;
838     /*------------------------------------------------------------------------*/
839
840
841     /* Strip out the high bit set by the FW for 802.11a channels */
842     if( channel & 0x100 ) {
843         channel = channel & 0x0FF;
844     }
845
846     /* Iterate through the matrix and retrieve the frequency */
847     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
848         if( chan_freq_list[i][0] == channel ) {
849             return 1;
850         }
851     }
852
853     return 0;
854 } // wl_is_a_valid_chan
855 /*============================================================================*/
856
857
858
859
860 /*******************************************************************************
861  *      wl_get_chan_from_freq()
862  *******************************************************************************
863  *
864  *  DESCRIPTION:
865  *
866  *      Checks if a given frequency is valid
867  *
868  *  PARAMETERS:
869  *
870  *      freq - the frequency
871  *
872  *  RETURNS:
873  *
874  *      1 if TRUE
875  *      0 if FALSE
876  *
877  ******************************************************************************/
878 int wl_is_a_valid_freq( long frequency )
879 {
880     int i;
881     /*------------------------------------------------------------------------*/
882
883
884     /* Iterate through the matrix and retrieve the channel */
885     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
886         if( chan_freq_list[i][1] == frequency ) {
887             return 1;
888         }
889     }
890
891     return 0;
892 } // wl_is_a_valid_freq
893 /*============================================================================*/
894
895
896
897
898 /*******************************************************************************
899  *      wl_get_freq_from_chan()
900  *******************************************************************************
901  *
902  *  DESCRIPTION:
903  *
904  *      Function used to look up the frequency for a given channel on which the
905  *      adapter is Tx/Rx.
906  *
907  *  PARAMETERS:
908  *
909  *      channel - the channel
910  *
911  *  RETURNS:
912  *
913  *      The corresponding frequency
914  *
915  ******************************************************************************/
916 long wl_get_freq_from_chan( int channel )
917 {
918     int i;
919     /*------------------------------------------------------------------------*/
920
921
922     /* Strip out the high bit set by the FW for 802.11a channels */
923     if( channel & 0x100 ) {
924         channel = channel & 0x0FF;
925     }
926
927     /* Iterate through the matrix and retrieve the frequency */
928     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
929         if( chan_freq_list[i][0] == channel ) {
930             return chan_freq_list[i][1];
931         }
932     }
933
934     return 0;
935 } // wl_get_freq_from_chan
936 /*============================================================================*/
937
938
939
940
941 /*******************************************************************************
942  *      wl_get_chan_from_freq()
943  *******************************************************************************
944  *
945  *  DESCRIPTION:
946  *
947  *      Function used to look up the channel for a given frequency on which the
948  *      adapter is Tx/Rx.
949  *
950  *  PARAMETERS:
951  *
952  *      frequency - the frequency
953  *
954  *  RETURNS:
955  *
956  *      The corresponding channel
957  *
958  ******************************************************************************/
959 int wl_get_chan_from_freq( long frequency )
960 {
961     int i;
962     /*------------------------------------------------------------------------*/
963
964
965     /* Iterate through the matrix and retrieve the channel */
966     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
967         if( chan_freq_list[i][1] == frequency ) {
968             return chan_freq_list[i][0];
969         }
970     }
971
972     return 0;
973 } // wl_get_chan_from_freq
974 /*============================================================================*/
975
976
977
978
979 /*******************************************************************************
980  *      wl_process_link_status()
981  *******************************************************************************
982  *
983  *  DESCRIPTION:
984  *
985  *      Process the link status message signaled by the device.
986  *
987  *  PARAMETERS:
988  *
989  *      lp - a pointer to the device's private structure
990  *
991  *  RETURNS:
992  *
993  *      N/A
994  *
995  ******************************************************************************/
996 void wl_process_link_status( struct wl_private *lp )
997 {
998     hcf_16 link_stat;
999     /*------------------------------------------------------------------------*/
1000
1001     DBG_ENTER( DbgInfo );
1002
1003     if( lp != NULL ) {
1004         //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1005         link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1006         switch( link_stat ) {
1007         case 1:
1008             DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1009             wl_wext_event_ap( lp->dev );
1010             break;
1011         case 2:
1012             DBG_TRACE( DbgInfo, "Link Status : Disconnected\n"  );
1013             break;
1014         case 3:
1015             DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1016             break;
1017         case 4:
1018             DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1019             break;
1020         case 5:
1021             DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1022             break;
1023         default:
1024             DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1025             break;
1026         }
1027     }
1028     DBG_LEAVE( DbgInfo );
1029     return;
1030 } // wl_process_link_status
1031 /*============================================================================*/
1032
1033
1034
1035
1036 /*******************************************************************************
1037  *      wl_process_probe_response()
1038  *******************************************************************************
1039  *
1040  *  DESCRIPTION:
1041  *
1042  *      Process the probe responses retunred by the device as a result of an
1043  *      active scan.
1044  *
1045  *  PARAMETERS:
1046  *
1047  *      lp - a pointer to the device's private structure
1048  *
1049  *  RETURNS:
1050  *
1051  *      N/A
1052  *
1053  ******************************************************************************/
1054 void wl_process_probe_response( struct wl_private *lp )
1055 {
1056     PROBE_RESP  *probe_rsp;
1057     hcf_8       *wpa_ie = NULL;
1058     hcf_16      wpa_ie_len = 0;
1059     /*------------------------------------------------------------------------*/
1060
1061
1062     DBG_ENTER( DbgInfo );
1063
1064
1065     if( lp != NULL ) {
1066         probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1067
1068         wl_endian_translate_event( (ltv_t *)probe_rsp );
1069
1070         DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1071         DBG_TRACE( DbgInfo, "(%s) length      : 0x%04x.\n",  lp->dev->name,
1072                 probe_rsp->length );
1073
1074         if( probe_rsp->length > 1 ) {
1075             DBG_TRACE( DbgInfo, "(%s) infoType    : 0x%04x.\n", lp->dev->name,
1076                     probe_rsp->infoType );
1077
1078             DBG_TRACE( DbgInfo, "(%s) signal      : 0x%02x.\n", lp->dev->name,
1079                     probe_rsp->signal );
1080
1081             DBG_TRACE( DbgInfo, "(%s) silence     : 0x%02x.\n", lp->dev->name,
1082                     probe_rsp->silence );
1083
1084             DBG_TRACE( DbgInfo, "(%s) rxFlow      : 0x%02x.\n", lp->dev->name,
1085                     probe_rsp->rxFlow );
1086
1087             DBG_TRACE( DbgInfo, "(%s) rate        : 0x%02x.\n", lp->dev->name,
1088                     probe_rsp->rate );
1089
1090             DBG_TRACE( DbgInfo, "(%s) frame cntl  : 0x%04x.\n", lp->dev->name,
1091                     probe_rsp->frameControl );
1092
1093             DBG_TRACE( DbgInfo, "(%s) durID       : 0x%04x.\n", lp->dev->name,
1094                     probe_rsp->durID );
1095
1096                 DBG_TRACE(DbgInfo, "(%s) address1    : %pM\n", lp->dev->name,
1097                         probe_rsp->address1);
1098
1099                 DBG_TRACE(DbgInfo, "(%s) address2    : %pM\n", lp->dev->name,
1100                         probe_rsp->address2);
1101
1102                 DBG_TRACE(DbgInfo, "(%s) BSSID       : %pM\n", lp->dev->name,
1103                         probe_rsp->BSSID);
1104
1105             DBG_TRACE( DbgInfo, "(%s) sequence    : 0x%04x.\n", lp->dev->name,
1106                     probe_rsp->sequence );
1107
1108                 DBG_TRACE(DbgInfo, "(%s) address4    : %pM\n", lp->dev->name,
1109                         probe_rsp->address4);
1110
1111             DBG_TRACE( DbgInfo, "(%s) datalength  : 0x%04x.\n", lp->dev->name,
1112                     probe_rsp->dataLength );
1113
1114                 DBG_TRACE(DbgInfo, "(%s) DA          : %pM\n", lp->dev->name,
1115                         probe_rsp->DA);
1116
1117                 DBG_TRACE(DbgInfo, "(%s) SA          : %pM\n", lp->dev->name,
1118                         probe_rsp->SA);
1119
1120 #ifdef WARP
1121
1122             DBG_TRACE( DbgInfo, "(%s) channel     : %d\n", lp->dev->name,
1123                     probe_rsp->channel );
1124
1125             DBG_TRACE( DbgInfo, "(%s) band        : %d\n", lp->dev->name,
1126                     probe_rsp->band );
1127 #else
1128             DBG_TRACE( DbgInfo, "(%s) lenType     : 0x%04x.\n", lp->dev->name,
1129                     probe_rsp->lenType );
1130 #endif  // WARP
1131
1132             DBG_TRACE( DbgInfo, "(%s) timeStamp   : %d.%d.%d.%d.%d.%d.%d.%d\n",
1133                     lp->dev->name,
1134                     probe_rsp->timeStamp[0],
1135                     probe_rsp->timeStamp[1],
1136                     probe_rsp->timeStamp[2],
1137                     probe_rsp->timeStamp[3],
1138                     probe_rsp->timeStamp[4],
1139                     probe_rsp->timeStamp[5],
1140                     probe_rsp->timeStamp[6],
1141                     probe_rsp->timeStamp[7]);
1142
1143             DBG_TRACE( DbgInfo, "(%s) beaconInt   : 0x%04x.\n", lp->dev->name,
1144                     probe_rsp->beaconInterval );
1145
1146             DBG_TRACE( DbgInfo, "(%s) capability  : 0x%04x.\n", lp->dev->name,
1147                     probe_rsp->capability );
1148
1149             DBG_TRACE( DbgInfo, "(%s) SSID len    : 0x%04x.\n", lp->dev->name,
1150                     probe_rsp->rawData[1] );
1151
1152
1153             if( probe_rsp->rawData[1] > 0 ) {
1154                 char ssid[HCF_MAX_NAME_LEN];
1155
1156                 memset( ssid, 0, sizeof( ssid ));
1157                 strncpy( ssid, &probe_rsp->rawData[2],
1158                             probe_rsp->rawData[1] );
1159
1160                 DBG_TRACE( DbgInfo, "(%s) SSID        : %s\n",
1161                             lp->dev->name, ssid );
1162             }
1163
1164
1165             /* Parse out the WPA-IE, if one exists */
1166             wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1167             if( wpa_ie != NULL ) {
1168                 DBG_TRACE( DbgInfo, "(%s) WPA-IE      : %s\n",
1169                 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1170             }
1171
1172             DBG_TRACE( DbgInfo, "(%s) flags       : 0x%04x.\n",
1173                         lp->dev->name, probe_rsp->flags );
1174         }
1175
1176         DBG_TRACE( DbgInfo, "\n" );
1177
1178
1179         /* If probe response length is 1, then the scan is complete */
1180         if( probe_rsp->length == 1 ) {
1181             DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1182             lp->probe_results.num_aps = lp->probe_num_aps;
1183             lp->probe_results.scan_complete = TRUE;
1184
1185             /* Reset the counter for the next scan request */
1186             lp->probe_num_aps = 0;
1187
1188             /* Send a wireless extensions event that the scan completed */
1189             wl_wext_event_scan_complete( lp->dev );
1190         } else {
1191             /* Only copy to the table if the entry is unique; APs sometimes
1192                 respond more than once to a probe */
1193             if( lp->probe_num_aps == 0 ) {
1194                 /* Copy the info to the ScanResult structure in the private
1195                 adapter struct */
1196                 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1197                         probe_rsp, sizeof( PROBE_RESP ));
1198
1199                 /* Increment the number of APs detected */
1200                 lp->probe_num_aps++;
1201             } else {
1202                 int count;
1203                 int unique = 1;
1204
1205                 for( count = 0; count < lp->probe_num_aps; count++ ) {
1206                     if( memcmp( &( probe_rsp->BSSID ),
1207                         lp->probe_results.ProbeTable[count].BSSID,
1208                         ETH_ALEN ) == 0 ) {
1209                         unique = 0;
1210                     }
1211                 }
1212
1213                 if( unique ) {
1214                     /* Copy the info to the ScanResult structure in the
1215                     private adapter struct. Only copy if there's room in the
1216                     table */
1217                     if( lp->probe_num_aps < MAX_NAPS )
1218                     {
1219                         memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1220                                 probe_rsp, sizeof( PROBE_RESP ));
1221                     }
1222                     else
1223                     {
1224                         DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1225                     }
1226
1227                     /* Increment the number of APs detected. Note I do this
1228                         here even when I don't copy the probe response to the
1229                         buffer in order to detect the overflow condition */
1230                     lp->probe_num_aps++;
1231                 }
1232             }
1233         }
1234     }
1235
1236     DBG_LEAVE( DbgInfo );
1237     return;
1238 } // wl_process_probe_response
1239 /*============================================================================*/
1240
1241
1242
1243
1244 /*******************************************************************************
1245  *      wl_process_updated_record()
1246  *******************************************************************************
1247  *
1248  *  DESCRIPTION:
1249  *
1250  *      Process the updated information record message signaled by the device.
1251  *
1252  *  PARAMETERS:
1253  *
1254  *      lp - a pointer to the device's private structure
1255  *
1256  *  RETURNS:
1257  *
1258  *      N/A
1259  *
1260  ******************************************************************************/
1261 void wl_process_updated_record( struct wl_private *lp )
1262 {
1263     DBG_ENTER( DbgInfo );
1264
1265
1266     if( lp != NULL ) {
1267         lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1268
1269         switch( lp->updatedRecord.u.u16[0] ) {
1270         case CFG_CUR_COUNTRY_INFO:
1271             DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1272             wl_connect( lp );
1273             break;
1274
1275         case CFG_PORT_STAT:
1276             DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1277             //wl_connect( lp );
1278             break;
1279
1280         default:
1281             DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1282                        lp->updatedRecord.u.u16[0] );
1283         }
1284     }
1285
1286     DBG_LEAVE( DbgInfo );
1287     return;
1288 } // wl_process_updated_record
1289 /*============================================================================*/
1290
1291
1292
1293
1294 /*******************************************************************************
1295  *      wl_process_assoc_status()
1296  *******************************************************************************
1297  *
1298  *  DESCRIPTION:
1299  *
1300  *      Process the association status event signaled by the device.
1301  *
1302  *  PARAMETERS:
1303  *
1304  *      lp - a pointer to the device's private structure
1305  *
1306  *  RETURNS:
1307  *
1308  *      N/A
1309  *
1310  ******************************************************************************/
1311 void wl_process_assoc_status( struct wl_private *lp )
1312 {
1313     ASSOC_STATUS_STRCT *assoc_stat;
1314     /*------------------------------------------------------------------------*/
1315
1316
1317     DBG_ENTER( DbgInfo );
1318
1319
1320     if( lp != NULL ) {
1321         assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1322
1323         wl_endian_translate_event( (ltv_t *)assoc_stat );
1324
1325         switch( assoc_stat->assocStatus ) {
1326         case 1:
1327             DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1328             break;
1329
1330         case 2:
1331             DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1332             break;
1333
1334         case 3:
1335             DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1336             break;
1337
1338         default:
1339             DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1340                         assoc_stat->assocStatus );
1341             break;
1342         }
1343
1344         DBG_TRACE(DbgInfo, "STA Address        : %pM\n", assoc_stat->staAddr);
1345
1346         if(( assoc_stat->assocStatus == 2 )  && ( assoc_stat->len == 8 )) {
1347                 DBG_TRACE(DbgInfo, "Old AP Address     : %pM\n",
1348                         assoc_stat->oldApAddr);
1349         }
1350     }
1351
1352     DBG_LEAVE( DbgInfo );
1353     return;
1354 } // wl_process_assoc_status
1355 /*============================================================================*/
1356
1357
1358
1359
1360 /*******************************************************************************
1361  *      wl_process_security_status()
1362  *******************************************************************************
1363  *
1364  *  DESCRIPTION:
1365  *
1366  *      Process the security status message signaled by the device.
1367  *
1368  *  PARAMETERS:
1369  *
1370  *      lp - a pointer to the device's private structure
1371  *
1372  *  RETURNS:
1373  *
1374  *      N/A
1375  *
1376  ******************************************************************************/
1377 void wl_process_security_status( struct wl_private *lp )
1378 {
1379     SECURITY_STATUS_STRCT *sec_stat;
1380     /*------------------------------------------------------------------------*/
1381
1382
1383     DBG_ENTER( DbgInfo );
1384
1385
1386     if( lp != NULL ) {
1387         sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1388
1389         wl_endian_translate_event( (ltv_t *)sec_stat );
1390
1391         switch( sec_stat->securityStatus ) {
1392         case 1:
1393             DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1394             break;
1395
1396         case 2:
1397             DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1398             break;
1399
1400         case 3:
1401             DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1402             break;
1403
1404         case 4:
1405             DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1406             break;
1407
1408         case 5:
1409             DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1410             break;
1411
1412         default:
1413             DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1414                         sec_stat->securityStatus );
1415             break;
1416         }
1417
1418         DBG_TRACE(DbgInfo, "STA Address     : %pM\n", sec_stat->staAddr);
1419         DBG_TRACE(DbgInfo, "Reason          : 0x%04x\n", sec_stat->reason);
1420
1421     }
1422
1423     DBG_LEAVE( DbgInfo );
1424     return;
1425 } // wl_process_security_status
1426 /*============================================================================*/
1427
1428 int wl_get_tallies(struct wl_private *lp,
1429                    CFG_HERMES_TALLIES_STRCT *tallies)
1430 {
1431     int ret = 0;
1432     int status;
1433     CFG_HERMES_TALLIES_STRCT *pTallies;
1434
1435     DBG_ENTER(DbgInfo);
1436
1437     /* Get the current tallies from the adapter */
1438     lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1439     lp->ltvRecord.typ = CFG_TALLIES;
1440
1441     status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1442
1443     if( status == HCF_SUCCESS ) {
1444         pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1445         memcpy(tallies, pTallies, sizeof(*tallies));
1446         DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1447     } else {
1448         DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1449         ret = -EFAULT;
1450     }
1451
1452     DBG_LEAVE( DbgInfo );
1453
1454     return ret;
1455 }
1456