• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 “AS IS” 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  ******************************************************************************/
dbm(int value)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  ******************************************************************************/
percent(int value,int min,int max)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  ******************************************************************************/
is_valid_key_string(char * s)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  ******************************************************************************/
key_string2key(char * ks,KEY_STRCT * key)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  ******************************************************************************/
wl_has_wep(IFBP ifbp)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  ******************************************************************************/
wl_hcf_error(struct net_device * dev,int hcfStatus)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  ******************************************************************************/
wl_endian_translate_event(ltv_t * pLtv)482 void wl_endian_translate_event( ltv_t *pLtv )
483 {
484     DBG_FUNC( "wl_endian_translate_event" );
485     DBG_ENTER( DbgInfo );
486 
487 
488     switch( pLtv->typ ) {
489     case CFG_TALLIES:
490         break;
491 
492 
493     case CFG_SCAN:
494         {
495             int numAPs;
496             SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
497 
498             numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
499                                 (sizeof( SCAN_RS_STRCT )));
500 
501             while( numAPs >= 1 ) {
502                 numAPs--;
503 
504                 pAps[numAPs].channel_id           =
505                     CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
506 
507                 pAps[numAPs].noise_level          =
508                     CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
509 
510                 pAps[numAPs].signal_level         =
511                     CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
512 
513                 pAps[numAPs].beacon_interval_time =
514                     CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
515 
516                 pAps[numAPs].capability           =
517                     CNV_LITTLE_TO_INT( pAps[numAPs].capability );
518 
519                 pAps[numAPs].ssid_len             =
520                     CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
521 
522                 pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
523 
524             }
525         }
526         break;
527 
528 
529     case CFG_ACS_SCAN:
530         {
531             PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
532 
533             probe_resp->frameControl   = CNV_LITTLE_TO_INT( probe_resp->frameControl );
534             probe_resp->durID          = CNV_LITTLE_TO_INT( probe_resp->durID );
535             probe_resp->sequence       = CNV_LITTLE_TO_INT( probe_resp->sequence );
536             probe_resp->dataLength     = CNV_LITTLE_TO_INT( probe_resp->dataLength );
537 
538 #ifndef WARP
539             probe_resp->lenType        = CNV_LITTLE_TO_INT( probe_resp->lenType );
540 #endif // WARP
541 
542             probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
543             probe_resp->capability     = CNV_LITTLE_TO_INT( probe_resp->capability );
544             probe_resp->flags          = CNV_LITTLE_TO_INT( probe_resp->flags );
545         }
546         break;
547 
548 
549     case CFG_LINK_STAT:
550 #define ls ((LINK_STATUS_STRCT *)pLtv)
551             ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
552         break;
553 #undef ls
554 
555     case CFG_ASSOC_STAT:
556         {
557             ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
558 
559             pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
560         }
561         break;
562 
563 
564     case CFG_SECURITY_STAT:
565         {
566             SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
567 
568             pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
569             pSs->reason         = CNV_LITTLE_TO_INT( pSs->reason );
570         }
571         break;
572 
573 
574     case CFG_WMP:
575         break;
576 
577 
578     case CFG_NULL:
579         break;
580 
581 
582     default:
583         break;
584     }
585 
586     DBG_LEAVE( DbgInfo );
587     return;
588 } // wl_endian_translate_event
589 /*============================================================================*/
590 
591 
592 /*******************************************************************************
593  *	msf_assert()
594  *******************************************************************************
595  *
596  *  DESCRIPTION:
597  *
598  *      Print statement used to display asserts from within the HCF. Only called
599  *  when asserts in the HCF are turned on. See hcfcfg.h for more information.
600  *
601  *  PARAMETERS:
602  *
603  *      file_namep  - the filename in which the assert occurred.
604  *      line_number - the line number on which the assert occurred.
605  *      trace       - a comment associated with the assert.
606  *      qual        - return code or other value related to the assert
607  *
608  *  RETURNS:
609  *
610  *      N/A
611  *
612  ******************************************************************************/
msf_assert(unsigned int line_number,hcf_16 trace,hcf_32 qual)613 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
614 {
615     DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
616 } // msf_assert
617 /*============================================================================*/
618 
619 
620 
621 
622 /*******************************************************************************
623  *	wl_parse_ds_ie()
624  *******************************************************************************
625  *
626  *  DESCRIPTION:
627  *
628  *      This function parses the Direct Sequence Parameter Set IE, used to
629  *      determine channel/frequency information.
630  *
631  *  PARAMETERS:
632  *
633  *      probe_rsp - a pointer to a PROBE_RESP structure containing the probe
634  *                  response.
635  *
636  *  RETURNS:
637  *
638  *      The channel on which the BSS represented by this probe response is
639  *      transmitting.
640  *
641  ******************************************************************************/
wl_parse_ds_ie(PROBE_RESP * probe_rsp)642 hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
643 {
644     int     i;
645     int     ie_length = 0;
646     hcf_8   *buf;
647     hcf_8   buf_size;
648     /*------------------------------------------------------------------------*/
649 
650 
651     if( probe_rsp == NULL ) {
652         return 0;
653     }
654 
655     buf      = probe_rsp->rawData;
656     buf_size = sizeof( probe_rsp->rawData );
657 
658 
659     for( i = 0; i < buf_size; i++ ) {
660         if( buf[i] == DS_INFO_ELEM ) {
661             /* Increment by 1 to get the length, and test it; in a DS element,
662                length should always be 1 */
663             i++;
664             ie_length = buf[i];
665 
666             if( buf[i] == 1 ) {
667                 /* Get the channel information */
668                 i++;
669                 return buf[i];
670             }
671         }
672     }
673 
674     /* If we get here, we didn't find a DS-IE, which is strange */
675     return 0;
676 } // wl_parse_ds_ie
677 
678 
679 /*******************************************************************************
680  *	wl_parse_wpa_ie()
681  *******************************************************************************
682  *
683  *  DESCRIPTION:
684  *
685  *      This function parses the Probe Response for a valid WPA-IE.
686  *
687  *  PARAMETERS:
688  *
689  *      probe_rsp - a pointer to a PROBE_RESP structure containing the probe
690  *                  response
691  *      length    - a pointer to an hcf_16 in which the size of the WPA-IE will
692  *                  be stored (if found).
693  *
694  *  RETURNS:
695  *
696  *      A pointer to the location in the probe response buffer where a valid
697  *      WPA-IE lives. The length of this IE is written back to the 'length'
698  *      argument passed to the function.
699  *
700  ******************************************************************************/
wl_parse_wpa_ie(PROBE_RESP * probe_rsp,hcf_16 * length)701 hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
702 {
703     int     i;
704     int     ie_length = 0;
705     hcf_8   *buf;
706     hcf_8   buf_size;
707     hcf_8   wpa_oui[] = WPA_OUI_TYPE;
708     /*------------------------------------------------------------------------*/
709 
710 
711     if( probe_rsp == NULL || length == NULL ) {
712         return NULL;
713     }
714 
715     buf      = probe_rsp->rawData;
716     buf_size = sizeof( probe_rsp->rawData );
717     *length  = 0;
718 
719 
720     for( i = 0; i < buf_size; i++ ) {
721         if( buf[i] == GENERIC_INFO_ELEM ) {
722             /* Increment by one to get the IE length */
723             i++;
724             ie_length = probe_rsp->rawData[i];
725 
726             /* Increment by one to point to the IE payload */
727             i++;
728 
729             /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
730             if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
731                 /* Pass back length and return a pointer to the WPA-IE */
732                 /* NOTE: Length contained in the WPA-IE is only the length of
733                    the payload. The entire WPA-IE, including the IE identifier
734                    and the length, is 2 bytes larger */
735                 *length = ie_length + 2;
736 
737                 /* Back up the pointer 2 bytes to include the IE identifier and
738                    the length in the buffer returned */
739                 i -= 2;
740                 return &buf[i];
741             }
742 
743             /* Increment past this non-WPA IE and continue looking */
744             i += ( ie_length - 1 );
745         }
746     }
747 
748     /* If we're here, we didn't find a WPA-IE in the buffer */
749     return NULL;
750 } // wl_parse_wpa_ie
751 
752 
753 /*******************************************************************************
754  *	wl_print_wpa_ie()
755  *******************************************************************************
756  *
757  *  DESCRIPTION:
758  *
759  *      Function used to take a WPA Information Element (WPA-IE) buffer and
760  *      display it in a readable format.
761  *
762  *  PARAMETERS:
763  *
764  *      buffer - the byte buffer containing the WPA-IE
765  *      length - the length of the above buffer
766  *
767  *  RETURNS:
768  *
769  *      A pointer to the formatted WPA-IE string. Note that the format used is
770  *      byte-by-byte printing as %02x hex values with no spaces. This is
771  *      required for proper operation with some WPA supplicants.
772  *
773  ******************************************************************************/
wl_print_wpa_ie(hcf_8 * buffer,int length)774 hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
775 {
776     int count;
777     int rows;
778     int remainder;
779     int rowsize = 4;
780     hcf_8 row_buf[64];
781     static hcf_8 output[512];
782     /*------------------------------------------------------------------------*/
783 
784 
785     memset( output, 0, sizeof( output ));
786     memset( row_buf, 0, sizeof( row_buf ));
787 
788 
789     /* Determine how many rows will be needed, and the remainder */
790     rows = length / rowsize;
791     remainder = length % rowsize;
792 
793 
794     /* Format the rows */
795     for( count = 0; count < rows; count++ ) {
796         sprintf( row_buf, "%02x%02x%02x%02x",
797                  buffer[count*rowsize], buffer[count*rowsize+1],
798                  buffer[count*rowsize+2], buffer[count*rowsize+3]);
799         strcat( output, row_buf );
800     }
801 
802     memset( row_buf, 0, sizeof( row_buf ));
803 
804 
805     /* Format the remainder */
806     for( count = 0; count < remainder; count++ ) {
807         sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
808         strcat( output, row_buf );
809     }
810 
811     return output;
812 } // wl_print_wpa_ie
813 /*============================================================================*/
814 
815 
816 
817 
818 /*******************************************************************************
819  *	wl_is_a_valid_chan()
820  *******************************************************************************
821  *
822  *  DESCRIPTION:
823  *
824  *      Checks if a given channel is valid
825  *
826  *  PARAMETERS:
827  *
828  *      channel - the channel
829  *
830  *  RETURNS:
831  *
832  *      1 if TRUE
833  *      0 if FALSE
834  *
835  ******************************************************************************/
wl_is_a_valid_chan(int channel)836 int wl_is_a_valid_chan( int channel )
837 {
838     int i;
839     /*------------------------------------------------------------------------*/
840 
841 
842     /* Strip out the high bit set by the FW for 802.11a channels */
843     if( channel & 0x100 ) {
844         channel = channel & 0x0FF;
845     }
846 
847     /* Iterate through the matrix and retrieve the frequency */
848     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
849         if( chan_freq_list[i][0] == channel ) {
850             return 1;
851         }
852     }
853 
854     return 0;
855 } // wl_is_a_valid_chan
856 /*============================================================================*/
857 
858 
859 
860 
861 /*******************************************************************************
862  *	wl_get_chan_from_freq()
863  *******************************************************************************
864  *
865  *  DESCRIPTION:
866  *
867  *      Checks if a given frequency is valid
868  *
869  *  PARAMETERS:
870  *
871  *      freq - the frequency
872  *
873  *  RETURNS:
874  *
875  *      1 if TRUE
876  *      0 if FALSE
877  *
878  ******************************************************************************/
wl_is_a_valid_freq(long frequency)879 int wl_is_a_valid_freq( long frequency )
880 {
881     int i;
882     /*------------------------------------------------------------------------*/
883 
884 
885     /* Iterate through the matrix and retrieve the channel */
886     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
887         if( chan_freq_list[i][1] == frequency ) {
888             return 1;
889         }
890     }
891 
892     return 0;
893 } // wl_is_a_valid_freq
894 /*============================================================================*/
895 
896 
897 
898 
899 /*******************************************************************************
900  *	wl_get_freq_from_chan()
901  *******************************************************************************
902  *
903  *  DESCRIPTION:
904  *
905  *      Function used to look up the frequency for a given channel on which the
906  *      adapter is Tx/Rx.
907  *
908  *  PARAMETERS:
909  *
910  *      channel - the channel
911  *
912  *  RETURNS:
913  *
914  *      The corresponding frequency
915  *
916  ******************************************************************************/
wl_get_freq_from_chan(int channel)917 long wl_get_freq_from_chan( int channel )
918 {
919     int i;
920     /*------------------------------------------------------------------------*/
921 
922 
923     /* Strip out the high bit set by the FW for 802.11a channels */
924     if( channel & 0x100 ) {
925         channel = channel & 0x0FF;
926     }
927 
928     /* Iterate through the matrix and retrieve the frequency */
929     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
930         if( chan_freq_list[i][0] == channel ) {
931             return chan_freq_list[i][1];
932         }
933     }
934 
935     return 0;
936 } // wl_get_freq_from_chan
937 /*============================================================================*/
938 
939 
940 
941 
942 /*******************************************************************************
943  *	wl_get_chan_from_freq()
944  *******************************************************************************
945  *
946  *  DESCRIPTION:
947  *
948  *      Function used to look up the channel for a given frequency on which the
949  *      adapter is Tx/Rx.
950  *
951  *  PARAMETERS:
952  *
953  *      frequency - the frequency
954  *
955  *  RETURNS:
956  *
957  *      The corresponding channel
958  *
959  ******************************************************************************/
wl_get_chan_from_freq(long frequency)960 int wl_get_chan_from_freq( long frequency )
961 {
962     int i;
963     /*------------------------------------------------------------------------*/
964 
965 
966     /* Iterate through the matrix and retrieve the channel */
967     for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
968         if( chan_freq_list[i][1] == frequency ) {
969             return chan_freq_list[i][0];
970         }
971     }
972 
973     return 0;
974 } // wl_get_chan_from_freq
975 /*============================================================================*/
976 
977 
978 
979 
980 /*******************************************************************************
981  *	wl_process_link_status()
982  *******************************************************************************
983  *
984  *  DESCRIPTION:
985  *
986  *      Process the link status message signaled by the device.
987  *
988  *  PARAMETERS:
989  *
990  *      lp - a pointer to the device's private structure
991  *
992  *  RETURNS:
993  *
994  *      N/A
995  *
996  ******************************************************************************/
wl_process_link_status(struct wl_private * lp)997 void wl_process_link_status( struct wl_private *lp )
998 {
999     hcf_16 link_stat;
1000     /*------------------------------------------------------------------------*/
1001 
1002     DBG_FUNC( "wl_process_link_status" );
1003     DBG_ENTER( DbgInfo );
1004 
1005     if( lp != NULL ) {
1006         //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1007         link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1008         switch( link_stat ) {
1009         case 1:
1010             DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1011             wl_wext_event_ap( lp->dev );
1012             break;
1013         case 2:
1014             DBG_TRACE( DbgInfo, "Link Status : Disconnected\n"  );
1015             break;
1016         case 3:
1017             DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1018             break;
1019         case 4:
1020             DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1021             break;
1022         case 5:
1023             DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1024             break;
1025         default:
1026             DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1027             break;
1028         }
1029     }
1030     DBG_LEAVE( DbgInfo );
1031     return;
1032 } // wl_process_link_status
1033 /*============================================================================*/
1034 
1035 
1036 
1037 
1038 /*******************************************************************************
1039  *	wl_process_probe_response()
1040  *******************************************************************************
1041  *
1042  *  DESCRIPTION:
1043  *
1044  *      Process the probe responses retunred by the device as a result of an
1045  *      active scan.
1046  *
1047  *  PARAMETERS:
1048  *
1049  *      lp - a pointer to the device's private structure
1050  *
1051  *  RETURNS:
1052  *
1053  *      N/A
1054  *
1055  ******************************************************************************/
wl_process_probe_response(struct wl_private * lp)1056 void wl_process_probe_response( struct wl_private *lp )
1057 {
1058     PROBE_RESP  *probe_rsp;
1059     hcf_8       *wpa_ie = NULL;
1060     hcf_16      wpa_ie_len = 0;
1061     /*------------------------------------------------------------------------*/
1062 
1063 
1064     DBG_FUNC( "wl_process_probe_response" );
1065     DBG_ENTER( DbgInfo );
1066 
1067 
1068     if( lp != NULL ) {
1069         probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1070 
1071         wl_endian_translate_event( (ltv_t *)probe_rsp );
1072 
1073         DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1074         DBG_TRACE( DbgInfo, "(%s) length      : 0x%04x.\n",  lp->dev->name,
1075                 probe_rsp->length );
1076 
1077         if( probe_rsp->length > 1 ) {
1078             DBG_TRACE( DbgInfo, "(%s) infoType    : 0x%04x.\n", lp->dev->name,
1079                     probe_rsp->infoType );
1080 
1081             DBG_TRACE( DbgInfo, "(%s) signal      : 0x%02x.\n", lp->dev->name,
1082                     probe_rsp->signal );
1083 
1084             DBG_TRACE( DbgInfo, "(%s) silence     : 0x%02x.\n", lp->dev->name,
1085                     probe_rsp->silence );
1086 
1087             DBG_TRACE( DbgInfo, "(%s) rxFlow      : 0x%02x.\n", lp->dev->name,
1088                     probe_rsp->rxFlow );
1089 
1090             DBG_TRACE( DbgInfo, "(%s) rate        : 0x%02x.\n", lp->dev->name,
1091                     probe_rsp->rate );
1092 
1093             DBG_TRACE( DbgInfo, "(%s) frame cntl  : 0x%04x.\n", lp->dev->name,
1094                     probe_rsp->frameControl );
1095 
1096             DBG_TRACE( DbgInfo, "(%s) durID       : 0x%04x.\n", lp->dev->name,
1097                     probe_rsp->durID );
1098 
1099 		DBG_TRACE(DbgInfo, "(%s) address1    : %pM\n", lp->dev->name,
1100 			probe_rsp->address1);
1101 
1102 		DBG_TRACE(DbgInfo, "(%s) address2    : %pM\n", lp->dev->name,
1103 			probe_rsp->address2);
1104 
1105 		DBG_TRACE(DbgInfo, "(%s) BSSID       : %pM\n", lp->dev->name,
1106 			probe_rsp->BSSID);
1107 
1108             DBG_TRACE( DbgInfo, "(%s) sequence    : 0x%04x.\n", lp->dev->name,
1109                     probe_rsp->sequence );
1110 
1111 		DBG_TRACE(DbgInfo, "(%s) address4    : %pM\n", lp->dev->name,
1112 			probe_rsp->address4);
1113 
1114             DBG_TRACE( DbgInfo, "(%s) datalength  : 0x%04x.\n", lp->dev->name,
1115                     probe_rsp->dataLength );
1116 
1117 		DBG_TRACE(DbgInfo, "(%s) DA          : %pM\n", lp->dev->name,
1118 			probe_rsp->DA);
1119 
1120 		DBG_TRACE(DbgInfo, "(%s) SA          : %pM\n", lp->dev->name,
1121 			probe_rsp->SA);
1122 
1123 #ifdef WARP
1124 
1125             DBG_TRACE( DbgInfo, "(%s) channel     : %d\n", lp->dev->name,
1126                     probe_rsp->channel );
1127 
1128             DBG_TRACE( DbgInfo, "(%s) band        : %d\n", lp->dev->name,
1129                     probe_rsp->band );
1130 #else
1131             DBG_TRACE( DbgInfo, "(%s) lenType     : 0x%04x.\n", lp->dev->name,
1132                     probe_rsp->lenType );
1133 #endif  // WARP
1134 
1135             DBG_TRACE( DbgInfo, "(%s) timeStamp   : %d.%d.%d.%d.%d.%d.%d.%d\n",
1136                     lp->dev->name,
1137                     probe_rsp->timeStamp[0],
1138                     probe_rsp->timeStamp[1],
1139                     probe_rsp->timeStamp[2],
1140                     probe_rsp->timeStamp[3],
1141                     probe_rsp->timeStamp[4],
1142                     probe_rsp->timeStamp[5],
1143                     probe_rsp->timeStamp[6],
1144                     probe_rsp->timeStamp[7]);
1145 
1146             DBG_TRACE( DbgInfo, "(%s) beaconInt   : 0x%04x.\n", lp->dev->name,
1147                     probe_rsp->beaconInterval );
1148 
1149             DBG_TRACE( DbgInfo, "(%s) capability  : 0x%04x.\n", lp->dev->name,
1150                     probe_rsp->capability );
1151 
1152             DBG_TRACE( DbgInfo, "(%s) SSID len    : 0x%04x.\n", lp->dev->name,
1153                     probe_rsp->rawData[1] );
1154 
1155 
1156             if( probe_rsp->rawData[1] > 0 ) {
1157                 char ssid[HCF_MAX_NAME_LEN];
1158 
1159                 memset( ssid, 0, sizeof( ssid ));
1160                 strncpy( ssid, &probe_rsp->rawData[2],
1161                             probe_rsp->rawData[1] );
1162 
1163                 DBG_TRACE( DbgInfo, "(%s) SSID        : %s\n",
1164                             lp->dev->name, ssid );
1165             }
1166 
1167 
1168             /* Parse out the WPA-IE, if one exists */
1169             wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1170             if( wpa_ie != NULL ) {
1171                 DBG_TRACE( DbgInfo, "(%s) WPA-IE      : %s\n",
1172                 lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1173             }
1174 
1175             DBG_TRACE( DbgInfo, "(%s) flags       : 0x%04x.\n",
1176                         lp->dev->name, probe_rsp->flags );
1177         }
1178 
1179         DBG_TRACE( DbgInfo, "\n" );
1180 
1181 
1182         /* If probe response length is 1, then the scan is complete */
1183         if( probe_rsp->length == 1 ) {
1184             DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1185             lp->probe_results.num_aps = lp->probe_num_aps;
1186             lp->probe_results.scan_complete = TRUE;
1187 
1188             /* Reset the counter for the next scan request */
1189             lp->probe_num_aps = 0;
1190 
1191             /* Send a wireless extensions event that the scan completed */
1192             wl_wext_event_scan_complete( lp->dev );
1193         } else {
1194             /* Only copy to the table if the entry is unique; APs sometimes
1195                 respond more than once to a probe */
1196             if( lp->probe_num_aps == 0 ) {
1197                 /* Copy the info to the ScanResult structure in the private
1198                 adapter struct */
1199                 memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1200                         probe_rsp, sizeof( PROBE_RESP ));
1201 
1202                 /* Increment the number of APs detected */
1203                 lp->probe_num_aps++;
1204             } else {
1205                 int count;
1206                 int unique = 1;
1207 
1208                 for( count = 0; count < lp->probe_num_aps; count++ ) {
1209                     if( memcmp( &( probe_rsp->BSSID ),
1210                         lp->probe_results.ProbeTable[count].BSSID,
1211                         ETH_ALEN ) == 0 ) {
1212                         unique = 0;
1213                     }
1214                 }
1215 
1216                 if( unique ) {
1217                     /* Copy the info to the ScanResult structure in the
1218                     private adapter struct. Only copy if there's room in the
1219                     table */
1220                     if( lp->probe_num_aps < MAX_NAPS )
1221                     {
1222                         memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1223                                 probe_rsp, sizeof( PROBE_RESP ));
1224                     }
1225                     else
1226                     {
1227                         DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1228                     }
1229 
1230                     /* Increment the number of APs detected. Note I do this
1231                         here even when I don't copy the probe response to the
1232                         buffer in order to detect the overflow condition */
1233                     lp->probe_num_aps++;
1234                 }
1235             }
1236         }
1237     }
1238 
1239     DBG_LEAVE( DbgInfo );
1240     return;
1241 } // wl_process_probe_response
1242 /*============================================================================*/
1243 
1244 
1245 
1246 
1247 /*******************************************************************************
1248  *	wl_process_updated_record()
1249  *******************************************************************************
1250  *
1251  *  DESCRIPTION:
1252  *
1253  *      Process the updated information record message signaled by the device.
1254  *
1255  *  PARAMETERS:
1256  *
1257  *      lp - a pointer to the device's private structure
1258  *
1259  *  RETURNS:
1260  *
1261  *      N/A
1262  *
1263  ******************************************************************************/
wl_process_updated_record(struct wl_private * lp)1264 void wl_process_updated_record( struct wl_private *lp )
1265 {
1266     DBG_FUNC( "wl_process_updated_record" );
1267     DBG_ENTER( DbgInfo );
1268 
1269 
1270     if( lp != NULL ) {
1271         lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1272 
1273         switch( lp->updatedRecord.u.u16[0] ) {
1274         case CFG_CUR_COUNTRY_INFO:
1275             DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1276             wl_connect( lp );
1277             break;
1278 
1279         case CFG_PORT_STAT:
1280             DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1281             //wl_connect( lp );
1282             break;
1283 
1284         default:
1285             DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1286                        lp->updatedRecord.u.u16[0] );
1287         }
1288     }
1289 
1290     DBG_LEAVE( DbgInfo );
1291     return;
1292 } // wl_process_updated_record
1293 /*============================================================================*/
1294 
1295 
1296 
1297 
1298 /*******************************************************************************
1299  *	wl_process_assoc_status()
1300  *******************************************************************************
1301  *
1302  *  DESCRIPTION:
1303  *
1304  *      Process the association status event signaled by the device.
1305  *
1306  *  PARAMETERS:
1307  *
1308  *      lp - a pointer to the device's private structure
1309  *
1310  *  RETURNS:
1311  *
1312  *      N/A
1313  *
1314  ******************************************************************************/
wl_process_assoc_status(struct wl_private * lp)1315 void wl_process_assoc_status( struct wl_private *lp )
1316 {
1317     ASSOC_STATUS_STRCT *assoc_stat;
1318     /*------------------------------------------------------------------------*/
1319 
1320 
1321     DBG_FUNC( "wl_process_assoc_status" );
1322     DBG_ENTER( DbgInfo );
1323 
1324 
1325     if( lp != NULL ) {
1326         assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1327 
1328         wl_endian_translate_event( (ltv_t *)assoc_stat );
1329 
1330         switch( assoc_stat->assocStatus ) {
1331         case 1:
1332             DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1333             break;
1334 
1335         case 2:
1336             DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1337             break;
1338 
1339         case 3:
1340             DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1341             break;
1342 
1343         default:
1344             DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1345                         assoc_stat->assocStatus );
1346             break;
1347         }
1348 
1349 	DBG_TRACE(DbgInfo, "STA Address        : %pM\n", assoc_stat->staAddr);
1350 
1351         if(( assoc_stat->assocStatus == 2 )  && ( assoc_stat->len == 8 )) {
1352 		DBG_TRACE(DbgInfo, "Old AP Address     : %pM\n",
1353 			assoc_stat->oldApAddr);
1354         }
1355     }
1356 
1357     DBG_LEAVE( DbgInfo );
1358     return;
1359 } // wl_process_assoc_status
1360 /*============================================================================*/
1361 
1362 
1363 
1364 
1365 /*******************************************************************************
1366  *	wl_process_security_status()
1367  *******************************************************************************
1368  *
1369  *  DESCRIPTION:
1370  *
1371  *      Process the security status message signaled by the device.
1372  *
1373  *  PARAMETERS:
1374  *
1375  *      lp - a pointer to the device's private structure
1376  *
1377  *  RETURNS:
1378  *
1379  *      N/A
1380  *
1381  ******************************************************************************/
wl_process_security_status(struct wl_private * lp)1382 void wl_process_security_status( struct wl_private *lp )
1383 {
1384     SECURITY_STATUS_STRCT *sec_stat;
1385     /*------------------------------------------------------------------------*/
1386 
1387 
1388     DBG_FUNC( "wl_process_security_status" );
1389     DBG_ENTER( DbgInfo );
1390 
1391 
1392     if( lp != NULL ) {
1393         sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1394 
1395         wl_endian_translate_event( (ltv_t *)sec_stat );
1396 
1397         switch( sec_stat->securityStatus ) {
1398         case 1:
1399             DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1400             break;
1401 
1402         case 2:
1403             DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1404             break;
1405 
1406         case 3:
1407             DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1408             break;
1409 
1410         case 4:
1411             DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1412             break;
1413 
1414         case 5:
1415             DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1416             break;
1417 
1418         default:
1419             DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1420                         sec_stat->securityStatus );
1421             break;
1422         }
1423 
1424 	DBG_TRACE(DbgInfo, "STA Address     : %pM\n", sec_stat->staAddr);
1425 	DBG_TRACE(DbgInfo, "Reason          : 0x%04x\n", sec_stat->reason);
1426 
1427     }
1428 
1429     DBG_LEAVE( DbgInfo );
1430     return;
1431 } // wl_process_security_status
1432 /*============================================================================*/
1433 
wl_get_tallies(struct wl_private * lp,CFG_HERMES_TALLIES_STRCT * tallies)1434 int wl_get_tallies(struct wl_private *lp,
1435 		   CFG_HERMES_TALLIES_STRCT *tallies)
1436 {
1437     int ret = 0;
1438     int status;
1439     CFG_HERMES_TALLIES_STRCT *pTallies;
1440 
1441     DBG_FUNC( "wl_get_tallies" );
1442     DBG_ENTER(DbgInfo);
1443 
1444     /* Get the current tallies from the adapter */
1445     lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1446     lp->ltvRecord.typ = CFG_TALLIES;
1447 
1448     status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1449 
1450     if( status == HCF_SUCCESS ) {
1451 	pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1452 	memcpy(tallies, pTallies, sizeof(*tallies));
1453     	DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1454     } else {
1455     	DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1456 	ret = -EFAULT;
1457     }
1458 
1459     DBG_LEAVE( DbgInfo );
1460 
1461     return ret;
1462 }
1463 
1464