Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wl_util.c
Go to the documentation of this file.
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  ******************************************************************************/
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  ******************************************************************************/
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 
434  pMsg = "Timeout on timer calibration during initialization process";
435  break;
436 
437 
439  pMsg = "Timeout on Busy bit drop during BAP setup";
440  break;
441 
442 
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  ******************************************************************************/
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  {
567 
568  pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
569  pSs->reason = CNV_LITTLE_TO_INT( pSs->reason );
570  }
571  break;
572 
573 
574  case CFG_WMP:
575  break;
576 
577 
578  case CFG_NULL:
579  break;
580 
581 
582  default:
583  break;
584  }
585 
586  DBG_LEAVE( DbgInfo );
587  return;
588 } // wl_endian_translate_event
589 /*============================================================================*/
590 
591 
592 /*******************************************************************************
593  * msf_assert()
594  *******************************************************************************
595  *
596  * DESCRIPTION:
597  *
598  * Print statement used to display asserts from within the HCF. Only called
599  * when asserts in the HCF are turned on. See hcfcfg.h for more information.
600  *
601  * PARAMETERS:
602  *
603  * file_namep - the filename in which the assert occurred.
604  * line_number - the line number on which the assert occurred.
605  * trace - a comment associated with the assert.
606  * qual - return code or other value related to the assert
607  *
608  * RETURNS:
609  *
610  * N/A
611  *
612  ******************************************************************************/
613 void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
614 {
615  DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
616 } // msf_assert
617 /*============================================================================*/
618 
619 
620 
621 
622 /*******************************************************************************
623  * wl_parse_ds_ie()
624  *******************************************************************************
625  *
626  * DESCRIPTION:
627  *
628  * This function parses the Direct Sequence Parameter Set IE, used to
629  * determine channel/frequency information.
630  *
631  * PARAMETERS:
632  *
633  * probe_rsp - a pointer to a PROBE_RESP structure containing the probe
634  * response.
635  *
636  * RETURNS:
637  *
638  * The channel on which the BSS represented by this probe response is
639  * transmitting.
640  *
641  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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" );
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 */
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 */
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  {
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  ******************************************************************************/
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  ******************************************************************************/
1316 {
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 
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  ******************************************************************************/
1383 {
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 
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 
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