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