Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wl_wext.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  * SOFTWARE LICENSE
15  *
16  * This software is provided subject to the following terms and conditions,
17  * which you should read carefully before using the software. Using this
18  * software indicates your acceptance of these terms and conditions. If you do
19  * not agree with these terms and conditions, do not use the software.
20  *
21  * Copyright © 2003 Agere Systems Inc.
22  * All rights reserved.
23  *
24  * Redistribution and use in source or binary forms, with or without
25  * modifications, are permitted provided that the following conditions are met:
26  *
27  * . Redistributions of source code must retain the above copyright notice, this
28  * list of conditions and the following Disclaimer as comments in the code as
29  * well as in the documentation and/or other materials provided with the
30  * distribution.
31  *
32  * . Redistributions in binary form must reproduce the above copyright notice,
33  * this list of conditions and the following Disclaimer in the documentation
34  * and/or other materials provided with the distribution.
35  *
36  * . Neither the name of Agere Systems Inc. nor the names of the contributors
37  * may be used to endorse or promote products derived from this software
38  * without specific prior written permission.
39  *
40  * Disclaimer
41  *
42  * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
43  * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
44  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
45  * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
46  * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
47  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50  * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
51  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53  * DAMAGE.
54  *
55  ******************************************************************************/
56 
57 /*******************************************************************************
58  * include files
59  ******************************************************************************/
60 #include <wl_version.h>
61 
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <linux/etherdevice.h>
66 #include <asm/uaccess.h>
67 
68 #include <debug.h>
69 #include <hcf.h>
70 #include <hcfdef.h>
71 
72 #include <wl_if.h>
73 #include <wl_internal.h>
74 #include <wl_util.h>
75 #include <wl_main.h>
76 #include <wl_wext.h>
77 #include <wl_priv.h>
78 
79 /*******************************************************************************
80  * global definitions
81  ******************************************************************************/
82 #if DBG
83 extern dbg_info_t *DbgInfo;
84 #endif // DBG
85 
86 
87 /* Set up the LTV to program the appropriate key */
88 static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr,
89  int set_tx, u8 *seq, u8 *key, size_t key_len)
90 {
91  int ret = -EINVAL;
92  int buf_idx = 0;
94  { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
95 
96  DBG_ENTER(DbgInfo);
97 
98  /*
99  * Check the key index here; if 0, load as Pairwise Key, otherwise,
100  * load as a group key. Note that for the Hermes, the RIDs for
101  * group/pairwise keys are different from each other and different
102  * than the default WEP keys as well.
103  */
104  switch (key_idx) {
105  case 0:
106  ltv->len = 28;
108 
109  /* Load the BSSID */
110  memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
111  buf_idx += ETH_ALEN;
112 
113  /* Load the TKIP key */
114  memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
115  buf_idx += 16;
116 
117  /* Load the TSC */
118  memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
119  buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
120 
121  /* Load the RSC */
122  memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
123  buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
124 
125  /* Load the TxMIC key */
126  memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
127  buf_idx += 8;
128 
129  /* Load the RxMIC key */
130  memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
131 
132  ret = 0;
133  break;
134  case 1:
135  case 2:
136  case 3:
137  ltv->len = 26;
139 
140  /* Load the key Index */
141 
142  /* If this is a Tx Key, set bit 8000 */
143  if (set_tx)
144  key_idx |= 0x8000;
145  ltv->u.u16[buf_idx] = cpu_to_le16(key_idx);
146  buf_idx += 2;
147 
148  /* Load the RSC */
149  memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
150  buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
151 
152  /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
153  CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
154  memcpy(&ltv->u.u8[buf_idx], key, key_len);
155  buf_idx += key_len;
156 
157  /* Load the TSC */
158  memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
159 
160  ret = 0;
161  break;
162  default:
163  break;
164  }
165 
166  DBG_LEAVE(DbgInfo);
167  return ret;
168 }
169 
170 /* Set up the LTV to clear the appropriate key */
171 static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr)
172 {
173  int ret;
174 
175  switch (key_idx) {
176  case 0:
177  if (!is_broadcast_ether_addr(addr)) {
178  ltv->len = 7;
180  memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
181  ret = 0;
182  }
183  break;
184  case 1:
185  case 2:
186  case 3:
187  /* Clear the Group TKIP keys by index */
188  ltv->len = 2;
190  ltv->u.u16[0] = cpu_to_le16(key_idx);
191 
192  ret = 0;
193  break;
194  default:
195  break;
196  }
197 
198  return ret;
199 }
200 
201 /* Set the WEP keys in the wl_private structure */
202 static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
203  u8 *key, size_t key_len,
204  bool enable, bool set_tx)
205 {
206  hcf_8 encryption_state = lp->EnableEncryption;
207  int tk = lp->TransmitKeyID - 1; /* current key */
208  int ret = 0;
209 
210  /* Is encryption supported? */
211  if (!wl_has_wep(&(lp->hcfCtx))) {
212  DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
213  ret = -EOPNOTSUPP;
214  goto out;
215  }
216 
217  DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
218  key, key_len);
219 
220  /* Check the size of the key */
221  switch (key_len) {
222  case MIN_KEY_SIZE:
223  case MAX_KEY_SIZE:
224 
225  /* Check the index */
226  if ((key_idx < 0) || (key_idx >= MAX_KEYS))
227  key_idx = tk;
228 
229  /* Cleanup */
230  memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
231 
232  /* Copy the key in the driver */
233  memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
234 
235  /* Set the length */
236  lp->DefaultKeys.key[key_idx].len = key_len;
237 
238  DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
239  DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
240  lp->DefaultKeys.key[key_idx].key,
241  lp->DefaultKeys.key[key_idx].len, key_idx);
242 
243  /* Enable WEP (if possible) */
244  if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
245  lp->EnableEncryption = 1;
246 
247  break;
248 
249  case 0:
250  /* Do we want to just set the current transmit key? */
251  if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
252  DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
253  lp->DefaultKeys.key[key_idx].len);
254 
255  if (lp->DefaultKeys.key[key_idx].len > 0) {
256  lp->TransmitKeyID = key_idx + 1;
257  lp->EnableEncryption = 1;
258  } else {
259  DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
260  ret = -EINVAL;
261  }
262  }
263  break;
264 
265  default:
266  DBG_WARNING(DbgInfo, "Invalid Key length\n");
267  ret = -EINVAL;
268  goto out;
269  }
270 
271  /* Read the flags */
272  if (enable) {
273  lp->EnableEncryption = 1;
275  } else {
276  lp->EnableEncryption = 0; /* disable encryption */
278  }
279 
280  DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
281  DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
282  DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
283 
284  /* Write the changes to the card */
285  if (ret == 0) {
286  DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
287  lp->TransmitKeyID);
288 
289  if (lp->EnableEncryption == encryption_state) {
290  if (key_len != 0) {
291  /* Dynamic WEP key update */
292  wl_set_wep_keys(lp);
293  }
294  } else {
295  /* To switch encryption on/off, soft reset is
296  * required */
297  wl_apply(lp);
298  }
299  }
300 
301 out:
302  return ret;
303 }
304 
305 /*******************************************************************************
306  * wireless_commit()
307  *******************************************************************************
308  *
309  * DESCRIPTION:
310  *
311  * Commit
312  * protocol used.
313  *
314  * PARAMETERS:
315  *
316  * wrq - the wireless request buffer
317  *
318  * RETURNS:
319  *
320  * N/A
321  *
322  ******************************************************************************/
323 static int wireless_commit(struct net_device *dev,
324  struct iw_request_info *info,
325  union iwreq_data *rqu, char *extra)
326 {
327  struct wl_private *lp = wl_priv(dev);
328  unsigned long flags;
329  int ret = 0;
330  /*------------------------------------------------------------------------*/
331 
332  DBG_FUNC( "wireless_commit" );
333  DBG_ENTER(DbgInfo);
334 
336  ret = -EBUSY;
337  goto out;
338  }
339 
340  wl_lock( lp, &flags );
341 
342  wl_act_int_off( lp );
343 
344  wl_apply(lp);
345 
346  wl_act_int_on( lp );
347 
348  wl_unlock(lp, &flags);
349 
350 out:
351  DBG_LEAVE( DbgInfo );
352  return ret;
353 } // wireless_commit
354 /*============================================================================*/
355 
356 
357 
358 
359 /*******************************************************************************
360  * wireless_get_protocol()
361  *******************************************************************************
362  *
363  * DESCRIPTION:
364  *
365  * Returns a vendor-defined string that should identify the wireless
366  * protocol used.
367  *
368  * PARAMETERS:
369  *
370  * wrq - the wireless request buffer
371  *
372  * RETURNS:
373  *
374  * N/A
375  *
376  ******************************************************************************/
377 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
378 {
379  DBG_FUNC( "wireless_get_protocol" );
380  DBG_ENTER( DbgInfo );
381 
382  /* Originally, the driver was placing the string "Wireless" here. However,
383  the wireless extensions (/linux/wireless.h) indicate this string should
384  describe the wireless protocol. */
385 
386  strcpy(name, "IEEE 802.11b");
387 
388  DBG_LEAVE(DbgInfo);
389  return 0;
390 } // wireless_get_protocol
391 /*============================================================================*/
392 
393 
394 
395 
396 /*******************************************************************************
397  * wireless_set_frequency()
398  *******************************************************************************
399  *
400  * DESCRIPTION:
401  *
402  * Sets the frequency (channel) on which the card should Tx/Rx.
403  *
404  * PARAMETERS:
405  *
406  * wrq - the wireless request buffer
407  * lp - the device's private adapter structure
408  *
409  * RETURNS:
410  *
411  * 0 on success
412  * errno value otherwise
413  *
414  ******************************************************************************/
415 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
416 {
417  struct wl_private *lp = wl_priv(dev);
418  unsigned long flags;
419  int channel = 0;
420  int ret = 0;
421  /*------------------------------------------------------------------------*/
422 
423 
424  DBG_FUNC( "wireless_set_frequency" );
425  DBG_ENTER( DbgInfo );
426 
428  ret = -EBUSY;
429  goto out;
430  }
431 
432  if( !capable( CAP_NET_ADMIN )) {
433  ret = -EPERM;
434  DBG_LEAVE( DbgInfo );
435  return ret;
436  }
437 
438 
439  /* If frequency specified, look up channel */
440  if( freq->e == 1 ) {
441  int f = freq->m / 100000;
442  channel = wl_get_chan_from_freq( f );
443  }
444 
445 
446  /* Channel specified */
447  if( freq->e == 0 ) {
448  channel = freq->m;
449  }
450 
451 
452  /* If the channel is an 802.11a channel, set Bit 8 */
453  if( channel > 14 ) {
454  channel = channel | 0x100;
455  }
456 
457 
458  wl_lock( lp, &flags );
459 
460  wl_act_int_off( lp );
461 
462  lp->Channel = channel;
463 
464 
465  /* Commit the adapter parameters */
466  wl_apply( lp );
467 
468  /* Send an event that channel/freq has been set */
469  wl_wext_event_freq( lp->dev );
470 
471  wl_act_int_on( lp );
472 
473  wl_unlock(lp, &flags);
474 
475 out:
476  DBG_LEAVE( DbgInfo );
477  return ret;
478 } // wireless_set_frequency
479 /*============================================================================*/
480 
481 
482 
483 
484 /*******************************************************************************
485  * wireless_get_frequency()
486  *******************************************************************************
487  *
488  * DESCRIPTION:
489  *
490  * Gets the frequency (channel) on which the card is Tx/Rx.
491  *
492  * PARAMETERS:
493  *
494  * wrq - the wireless request buffer
495  * lp - the device's private adapter structure
496  *
497  * RETURNS:
498  *
499  * N/A
500  *
501  ******************************************************************************/
502 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
503 
504 {
505  struct wl_private *lp = wl_priv(dev);
506  unsigned long flags;
507  int ret = -1;
508  /*------------------------------------------------------------------------*/
509 
510 
511  DBG_FUNC( "wireless_get_frequency" );
512  DBG_ENTER( DbgInfo );
513 
515  ret = -EBUSY;
516  goto out;
517  }
518 
519  wl_lock( lp, &flags );
520 
521  wl_act_int_off( lp );
522 
523  lp->ltvRecord.len = 2;
525 
526  ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
527  if( ret == HCF_SUCCESS ) {
528  hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
529 
530  freq->m = wl_get_freq_from_chan( channel ) * 100000;
531  freq->e = 1;
532  }
533 
534  wl_act_int_on( lp );
535 
536  wl_unlock(lp, &flags);
537 
538  ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
539 
540 out:
541  DBG_LEAVE( DbgInfo );
542  return ret;
543 } // wireless_get_frequency
544 /*============================================================================*/
545 
546 
547 
548 
549 /*******************************************************************************
550  * wireless_get_range()
551  *******************************************************************************
552  *
553  * DESCRIPTION:
554  *
555  * This function is used to provide misc info and statistics about the
556  * wireless device.
557  *
558  * PARAMETERS:
559  *
560  * wrq - the wireless request buffer
561  * lp - the device's private adapter structure
562  *
563  * RETURNS:
564  *
565  * 0 on success
566  * errno value otherwise
567  *
568  ******************************************************************************/
569 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
570 {
571  struct wl_private *lp = wl_priv(dev);
572  unsigned long flags;
573  struct iw_range *range = (struct iw_range *) extra;
574  int ret = 0;
575  int status = -1;
576  int count;
577  __u16 *pTxRate;
578  int retries = 0;
579  /*------------------------------------------------------------------------*/
580 
581 
582  DBG_FUNC( "wireless_get_range" );
583  DBG_ENTER( DbgInfo );
584 
585  /* Set range information */
586  data->length = sizeof(struct iw_range);
587  memset(range, 0, sizeof(struct iw_range));
588 
589  wl_lock( lp, &flags );
590 
591  wl_act_int_off( lp );
592 
593  /* Set range information */
594  memset( range, 0, sizeof( struct iw_range ));
595 
596 retry:
597  /* Get the current transmit rate from the adapter */
598  lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
600 
601  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
602  if( status != HCF_SUCCESS ) {
603  /* Recovery action: reset and retry up to 10 times */
604  DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
605 
606  if (retries < 10) {
607  retries++;
608 
609  /* Holding the lock too long, makes a gap to allow other processes */
610  wl_unlock(lp, &flags);
611  wl_lock( lp, &flags );
612 
613  status = wl_reset( dev );
614  if ( status != HCF_SUCCESS ) {
615  DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
616 
617  ret = -EFAULT;
618  goto out_unlock;
619  }
620 
621  /* Holding the lock too long, makes a gap to allow other processes */
622  wl_unlock(lp, &flags);
623  wl_lock( lp, &flags );
624 
625  goto retry;
626 
627  } else {
628  DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
629  ret = -EFAULT;
630  goto out_unlock;
631  }
632  }
633 
634  /* Holding the lock too long, makes a gap to allow other processes */
635  wl_unlock(lp, &flags);
636  wl_lock( lp, &flags );
637 
638  pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
639 
640  range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
641 
642  if (retries > 0) {
643  DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
644  }
645 
646  // NWID - NOT SUPPORTED
647 
648 
649  /* Channel/Frequency Info */
650  range->num_channels = RADIO_CHANNELS;
651 
652 
653  /* Signal Level Thresholds */
655 
656 
657  /* Link quality */
658  range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
659 
660  /* If the value returned in /proc/net/wireless is greater than the maximum range,
661  iwconfig assumes that the value is in dBm. Because an unsigned char is used,
662  it requires a bit of contorsion... */
663 
664  range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
665  range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
666 
667 
668  /* Set available rates */
669  range->num_bitrates = 0;
670 
671  lp->ltvRecord.len = 6;
673 
674  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
675  if( status == HCF_SUCCESS ) {
676  for( count = 0; count < MAX_RATES; count++ )
677  if( lp->ltvRecord.u.u8[count+2] != 0 ) {
678  range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
679  range->num_bitrates++;
680  }
681  } else {
682  DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
683  ret = -EFAULT;
684  goto out_unlock;
685  }
686 
687  /* RTS Threshold info */
688  range->min_rts = MIN_RTS_BYTES;
689  range->max_rts = MAX_RTS_BYTES;
690 
691  // Frag Threshold info - NOT SUPPORTED
692 
693  // Power Management info - NOT SUPPORTED
694 
695  /* Encryption */
696 
697  /* Holding the lock too long, makes a gap to allow other processes */
698  wl_unlock(lp, &flags);
699  wl_lock( lp, &flags );
700 
701  /* Is WEP supported? */
702 
703  if( wl_has_wep( &( lp->hcfCtx ))) {
704  /* WEP: RC4 40 bits */
705  range->encoding_size[0] = MIN_KEY_SIZE;
706 
707  /* RC4 ~128 bits */
708  range->encoding_size[1] = MAX_KEY_SIZE;
709  range->num_encoding_sizes = 2;
710  range->max_encoding_tokens = MAX_KEYS;
711  }
712 
713  /* Tx Power Info */
714  range->txpower_capa = IW_TXPOW_MWATT;
715  range->num_txpower = 1;
716  range->txpower[0] = RADIO_TX_POWER_MWATT;
717 
718  /* Wireless Extension Info */
721 
722  // Retry Limits and Lifetime - NOT SUPPORTED
723 
724  /* Holding the lock too long, makes a gap to allow other processes */
725  wl_unlock(lp, &flags);
726  wl_lock( lp, &flags );
727 
728  DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
729  wl_wireless_stats( lp->dev );
730  range->avg_qual = lp->wstats.qual;
731  DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
732 
733  /* Event capability (kernel + driver) */
742 
744  range->scan_capa = IW_SCAN_CAPA_NONE;
745 
746 out_unlock:
747  wl_act_int_on( lp );
748 
749  wl_unlock(lp, &flags);
750 
751  DBG_LEAVE(DbgInfo);
752  return ret;
753 } // wireless_get_range
754 /*============================================================================*/
755 
756 
757 /*******************************************************************************
758  * wireless_get_bssid()
759  *******************************************************************************
760  *
761  * DESCRIPTION:
762  *
763  * Gets the BSSID the wireless device is currently associated with.
764  *
765  * PARAMETERS:
766  *
767  * wrq - the wireless request buffer
768  * lp - the device's private adapter structure
769  *
770  * RETURNS:
771  *
772  * 0 on success
773  * errno value otherwise
774  *
775  ******************************************************************************/
776 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
777 {
778  struct wl_private *lp = wl_priv(dev);
779  unsigned long flags;
780  int ret = 0;
781 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
782  int status = -1;
783 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
784  /*------------------------------------------------------------------------*/
785 
786 
787  DBG_FUNC( "wireless_get_bssid" );
788  DBG_ENTER( DbgInfo );
789 
791  ret = -EBUSY;
792  goto out;
793  }
794 
795  wl_lock( lp, &flags );
796 
797  wl_act_int_off( lp );
798 
799  memset( &ap_addr->sa_data, 0, ETH_ALEN );
800 
801  ap_addr->sa_family = ARPHRD_ETHER;
802 
803  /* Assume AP mode here, which means the BSSID is our own MAC address. In
804  STA mode, this address will be overwritten with the actual BSSID using
805  the code below. */
806  memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
807 
808 
809 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
810  //;?should we return an error status in AP mode
811 
812  if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
813  /* Get Current BSSID */
815  lp->ltvRecord.len = 4;
816  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
817 
818  if( status == HCF_SUCCESS ) {
819  /* Copy info into sockaddr struct */
820  memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
821  } else {
822  ret = -EFAULT;
823  }
824  }
825 
826 #endif // (HCF_TYPE) & HCF_TYPE_STA
827 
828  wl_act_int_on( lp );
829 
830  wl_unlock(lp, &flags);
831 
832 out:
833  DBG_LEAVE(DbgInfo);
834  return ret;
835 } // wireless_get_bssid
836 /*============================================================================*/
837 
838 
839 
840 
841 /*******************************************************************************
842  * wireless_get_ap_list()
843  *******************************************************************************
844  *
845  * DESCRIPTION:
846  *
847  * Gets the results of a network scan.
848  *
849  * PARAMETERS:
850  *
851  * wrq - the wireless request buffer
852  * lp - the device's private adapter structure
853  *
854  * RETURNS:
855  *
856  * 0 on success
857  * errno value otherwise
858  *
859  * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
860  * implements SIOCGIWAPLIST only to provide backwards compatibility. For
861  * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
862  *
863  ******************************************************************************/
864 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
865 {
866  struct wl_private *lp = wl_priv(dev);
867  unsigned long flags;
868  int ret;
869  int num_aps = -1;
870  int sec_count = 0;
871  hcf_32 count;
872  struct sockaddr *hwa = NULL;
873  struct iw_quality *qual = NULL;
874 #ifdef WARP
875  ScanResult *p = &lp->scan_results;
876 #else
877  ProbeResult *p = &lp->probe_results;
878 #endif // WARP
879  /*------------------------------------------------------------------------*/
880 
881  DBG_FUNC( "wireless_get_ap_list" );
882  DBG_ENTER( DbgInfo );
883 
885  ret = -EBUSY;
886  goto out;
887  }
888 
889  wl_lock( lp, &flags );
890 
891  wl_act_int_off( lp );
892 
893  /* Set the completion state to FALSE */
896  /* Channels to scan */
897  lp->ltvRecord.len = 2;
898  lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
899  lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
900  ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
901  DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
902 
903  /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
904  disassociate from the network we are currently on */
905  lp->ltvRecord.len = 2;
907  lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
908  ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
909  DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
910 
911  /* Initiate the scan */
912 #ifdef WARP
913  ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
914 #else
915  ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
916 #endif // WARP
917 
918  wl_act_int_on( lp );
919 
920  //;? unlock? what about the access to lp below? is it broken?
921  wl_unlock(lp, &flags);
922 
923  if( ret == HCF_SUCCESS ) {
924  DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
925  while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
926  DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
927  /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
928  if( sec_count++ > MAX_SCAN_TIME_SEC ) {
929  ret = -EIO;
930  } else {
931  /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
932  other things in the meantime, This prevents system lockups by
933  giving some time back to the kernel */
934  for( count = 0; count < 100; count ++ ) {
935  mdelay( 10 );
936  schedule( );
937  }
938  }
939  }
940 
941  rmb();
942 
943  if ( ret != HCF_SUCCESS ) {
944  DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
945  } else {
946  num_aps = (*p)/*lp->probe_results*/.num_aps;
947  if (num_aps > IW_MAX_AP) {
948  num_aps = IW_MAX_AP;
949  }
950  data->length = num_aps;
951  hwa = (struct sockaddr *)extra;
952  qual = (struct iw_quality *) extra +
953  ( sizeof( struct sockaddr ) * num_aps );
954 
955  /* This flag is used to tell the user if we provide quality
956  information. Since we provide signal/noise levels but no
957  quality info on a scan, this is set to 0. Setting to 1 and
958  providing a quality of 0 produces weird results. If we ever
959  provide quality (or can calculate it), this can be changed */
960  data->flags = 0;
961 
962  for( count = 0; count < num_aps; count++ ) {
963 #ifdef WARP
964  memcpy( hwa[count].sa_data,
965  (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
966 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
967  DBG_PRINT("BSSID: %pM\n",
968  (*p).ProbeTable[count].BSSID);
969  memcpy( hwa[count].sa_data,
970  (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
971 #endif // WARP
972  }
973  /* Once the data is copied to the wireless struct, invalidate the
974  scan result to initiate a rescan on the next request */
975  (*p)/*lp->probe_results*/.scan_complete = FALSE;
976  /* Send the wireless event that the scan has completed, just in case
977  it's needed */
979  }
980  }
981 out:
982  DBG_LEAVE( DbgInfo );
983  return ret;
984 } // wireless_get_ap_list
985 /*============================================================================*/
986 
987 
988 
989 
990 /*******************************************************************************
991  * wireless_set_sensitivity()
992  *******************************************************************************
993  *
994  * DESCRIPTION:
995  *
996  * Sets the sensitivity (distance between APs) of the wireless card.
997  *
998  * PARAMETERS:
999  *
1000  * wrq - the wireless request buffer
1001  * lp - the device's private adapter structure
1002  *
1003  * RETURNS:
1004  *
1005  * 0 on success
1006  * errno value otherwise
1007  *
1008  ******************************************************************************/
1009 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1010 {
1011  struct wl_private *lp = wl_priv(dev);
1012  unsigned long flags;
1013  int ret = 0;
1014  int dens = sens->value;
1015  /*------------------------------------------------------------------------*/
1016 
1017 
1018  DBG_FUNC( "wireless_set_sensitivity" );
1019  DBG_ENTER( DbgInfo );
1020 
1022  ret = -EBUSY;
1023  goto out;
1024  }
1025 
1026  if(( dens < 1 ) || ( dens > 3 )) {
1027  ret = -EINVAL;
1028  goto out;
1029  }
1030 
1031  wl_lock( lp, &flags );
1032 
1033  wl_act_int_off( lp );
1034 
1035  lp->DistanceBetweenAPs = dens;
1036  wl_apply( lp );
1037 
1038  wl_act_int_on( lp );
1039 
1040  wl_unlock(lp, &flags);
1041 
1042 out:
1043  DBG_LEAVE( DbgInfo );
1044  return ret;
1045 } // wireless_set_sensitivity
1046 /*============================================================================*/
1047 
1048 
1049 
1050 
1051 /*******************************************************************************
1052  * wireless_get_sensitivity()
1053  *******************************************************************************
1054  *
1055  * DESCRIPTION:
1056  *
1057  * Gets the sensitivity (distance between APs) of the wireless card.
1058  *
1059  * PARAMETERS:
1060  *
1061  * wrq - the wireless request buffer
1062  * lp - the device's private adapter structure
1063  *
1064  * RETURNS:
1065  *
1066  * 0 on success
1067  * errno value otherwise
1068  *
1069  ******************************************************************************/
1070 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1071 {
1072  struct wl_private *lp = wl_priv(dev);
1073  int ret = 0;
1074  /*------------------------------------------------------------------------*/
1075  /*------------------------------------------------------------------------*/
1076 
1077 
1078  DBG_FUNC( "wireless_get_sensitivity" );
1079  DBG_ENTER( DbgInfo );
1080 
1082  ret = -EBUSY;
1083  goto out;
1084  }
1085 
1086  /* not worth locking ... */
1087  sens->value = lp->DistanceBetweenAPs;
1088  sens->fixed = 0; /* auto */
1089 out:
1090  DBG_LEAVE( DbgInfo );
1091  return ret;
1092 } // wireless_get_sensitivity
1093 /*============================================================================*/
1094 
1095 
1096 
1097 
1098 /*******************************************************************************
1099  * wireless_set_essid()
1100  *******************************************************************************
1101  *
1102  * DESCRIPTION:
1103  *
1104  * Sets the ESSID (network name) that the wireless device should associate
1105  * with.
1106  *
1107  * PARAMETERS:
1108  *
1109  * wrq - the wireless request buffer
1110  * lp - the device's private adapter structure
1111  *
1112  * RETURNS:
1113  *
1114  * 0 on success
1115  * errno value otherwise
1116  *
1117  ******************************************************************************/
1118 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
1119 {
1120  struct wl_private *lp = wl_priv(dev);
1121  unsigned long flags;
1122  int ret = 0;
1123 
1124  DBG_FUNC( "wireless_set_essid" );
1125  DBG_ENTER( DbgInfo );
1126 
1128  ret = -EBUSY;
1129  goto out;
1130  }
1131 
1132  if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
1133  ret = -EINVAL;
1134  goto out;
1135  }
1136 
1137  wl_lock( lp, &flags );
1138 
1139  wl_act_int_off( lp );
1140 
1141  memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
1142 
1143  /* data->flags is zero to ask for "any" */
1144  if( data->flags == 0 ) {
1145  /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
1146  * ;?but there ain't no STAP anymore*/
1147  if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
1148  strcpy( lp->NetworkName, "ANY" );
1149  } else {
1150  //strcpy( lp->NetworkName, "ANY" );
1152  }
1153  } else {
1154  memcpy( lp->NetworkName, ssid, data->length );
1155  }
1156 
1157  DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1158 
1159  /* Commit the adapter parameters */
1160  wl_apply( lp );
1161 
1162  /* Send an event that ESSID has been set */
1163  wl_wext_event_essid( lp->dev );
1164 
1165  wl_act_int_on( lp );
1166 
1167  wl_unlock(lp, &flags);
1168 
1169 out:
1170  DBG_LEAVE( DbgInfo );
1171  return ret;
1172 } // wireless_set_essid
1173 /*============================================================================*/
1174 
1175 
1176 
1177 
1178 /*******************************************************************************
1179  * wireless_get_essid()
1180  *******************************************************************************
1181  *
1182  * DESCRIPTION:
1183  *
1184  * Gets the ESSID (network name) that the wireless device is associated
1185  * with.
1186  *
1187  * PARAMETERS:
1188  *
1189  * wrq - the wireless request buffer
1190  * lp - the device's private adapter structure
1191  *
1192  * RETURNS:
1193  *
1194  * 0 on success
1195  * errno value otherwise
1196  *
1197  ******************************************************************************/
1198 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1199 
1200 {
1201  struct wl_private *lp = wl_priv(dev);
1202  unsigned long flags;
1203  int ret = 0;
1204  int status = -1;
1205  wvName_t *pName;
1206  /*------------------------------------------------------------------------*/
1207 
1208 
1209  DBG_FUNC( "wireless_get_essid" );
1210  DBG_ENTER( DbgInfo );
1211 
1213  ret = -EBUSY;
1214  goto out;
1215  }
1216 
1217  wl_lock( lp, &flags );
1218 
1219  wl_act_int_off( lp );
1220 
1221  /* Get the desired network name */
1222  lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1223 
1224 
1225 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1226  //;?should we return an error status in AP mode
1227 
1229 
1230 #endif
1231 
1232 
1233 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1234  //;?should we restore this to allow smaller memory footprint
1235 
1236  if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1238  }
1239 
1240 #endif // HCF_AP
1241 
1242 
1243  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1244  if( status == HCF_SUCCESS ) {
1245  pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1246 
1247  /* Endian translate the string length */
1248  pName->length = CNV_LITTLE_TO_INT( pName->length );
1249 
1250  /* Copy the information into the user buffer */
1251  data->length = pName->length;
1252 
1253  if( pName->length < HCF_MAX_NAME_LEN ) {
1254  pName->name[pName->length] = '\0';
1255  }
1256 
1257  data->flags = 1;
1258 
1259 
1260 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1261  //;?should we return an error status in AP mode
1262 
1263  /* if desired is null ("any"), return current or "any" */
1264  if( pName->name[0] == '\0' ) {
1265  /* Get the current network name */
1266  lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1267  lp->ltvRecord.typ = CFG_CUR_SSID;
1268 
1269  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1270 
1271  if( status == HCF_SUCCESS ) {
1272  pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1273 
1274  /* Endian translate the string length */
1275  pName->length = CNV_LITTLE_TO_INT( pName->length );
1276 
1277  /* Copy the information into the user buffer */
1278  data->length = pName->length;
1279  data->flags = 1;
1280  } else {
1281  ret = -EFAULT;
1282  goto out_unlock;
1283  }
1284  }
1285 
1286 #endif // HCF_STA
1287 
1288  if (pName->length > IW_ESSID_MAX_SIZE) {
1289  ret = -EFAULT;
1290  goto out_unlock;
1291  }
1292 
1293  memcpy(essid, pName->name, pName->length);
1294  } else {
1295  ret = -EFAULT;
1296  goto out_unlock;
1297  }
1298 
1299 out_unlock:
1300  wl_act_int_on( lp );
1301 
1302  wl_unlock(lp, &flags);
1303 
1304 out:
1305  DBG_LEAVE( DbgInfo );
1306  return ret;
1307 } // wireless_get_essid
1308 /*============================================================================*/
1309 
1310 
1311 
1312 
1313 /*******************************************************************************
1314  * wireless_set_encode()
1315  *******************************************************************************
1316  *
1317  * DESCRIPTION:
1318  *
1319  * Sets the encryption keys and status (enable or disable).
1320  *
1321  * PARAMETERS:
1322  *
1323  * wrq - the wireless request buffer
1324  * lp - the device's private adapter structure
1325  *
1326  * RETURNS:
1327  *
1328  * 0 on success
1329  * errno value otherwise
1330  *
1331  ******************************************************************************/
1332 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1333 {
1334  struct wl_private *lp = wl_priv(dev);
1335  unsigned long flags;
1336  int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1337  int ret = 0;
1338  bool enable = true;
1339 
1340  DBG_ENTER(DbgInfo);
1341 
1342  if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
1343  ret = -EBUSY;
1344  goto out;
1345  }
1346 
1347  if (erq->flags & IW_ENCODE_DISABLED)
1348  enable = false;
1349 
1350  wl_lock(lp, &flags);
1351 
1352  wl_act_int_off(lp);
1353 
1354  ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1355  enable, true);
1356 
1357  /* Send an event that Encryption has been set */
1358  if (ret == 0)
1359  wl_wext_event_encode(dev);
1360 
1361  wl_act_int_on(lp);
1362 
1363  wl_unlock(lp, &flags);
1364 
1365 out:
1366  DBG_LEAVE(DbgInfo);
1367  return ret;
1368 }
1369 
1370 /*******************************************************************************
1371  * wireless_get_encode()
1372  *******************************************************************************
1373  *
1374  * DESCRIPTION:
1375  *
1376  * Gets the encryption keys and status.
1377  *
1378  * PARAMETERS:
1379  *
1380  * wrq - the wireless request buffer
1381  * lp - the device's private adapter structure
1382  *
1383  * RETURNS:
1384  *
1385  * 0 on success
1386  * errno value otherwise
1387  *
1388  ******************************************************************************/
1389 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1390 
1391 {
1392  struct wl_private *lp = wl_priv(dev);
1393  unsigned long flags;
1394  int ret = 0;
1395  int index;
1396  /*------------------------------------------------------------------------*/
1397 
1398 
1399  DBG_FUNC( "wireless_get_encode" );
1400  DBG_ENTER( DbgInfo );
1401  DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1402 
1404  ret = -EBUSY;
1405  goto out;
1406  }
1407 
1408  /* Only super-user can see WEP key */
1409  if( !capable( CAP_NET_ADMIN )) {
1410  ret = -EPERM;
1411  DBG_LEAVE( DbgInfo );
1412  return ret;
1413  }
1414 
1415  wl_lock( lp, &flags );
1416 
1417  wl_act_int_off( lp );
1418 
1419  /* Is it supported? */
1420  if( !wl_has_wep( &( lp->hcfCtx ))) {
1421  ret = -EOPNOTSUPP;
1422  goto out_unlock;
1423  }
1424 
1425  /* Basic checking */
1426  index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1427 
1428 
1429  /* Set the flags */
1430  erq->flags = 0;
1431 
1432  if( lp->EnableEncryption == 0 ) {
1433  erq->flags |= IW_ENCODE_DISABLED;
1434  }
1435 
1436  /* Which key do we want */
1437  if(( index < 0 ) || ( index >= MAX_KEYS )) {
1438  index = lp->TransmitKeyID - 1;
1439  }
1440 
1441  erq->flags |= index + 1;
1442 
1443  /* Copy the key to the user buffer */
1444  erq->length = lp->DefaultKeys.key[index].len;
1445 
1446  memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1447 
1448 out_unlock:
1449 
1450  wl_act_int_on( lp );
1451 
1452  wl_unlock(lp, &flags);
1453 
1454 out:
1455  DBG_LEAVE( DbgInfo );
1456  return ret;
1457 } // wireless_get_encode
1458 /*============================================================================*/
1459 
1460 
1461 
1462 
1463 /*******************************************************************************
1464  * wireless_set_nickname()
1465  *******************************************************************************
1466  *
1467  * DESCRIPTION:
1468  *
1469  * Sets the nickname, or station name, of the wireless device.
1470  *
1471  * PARAMETERS:
1472  *
1473  * wrq - the wireless request buffer
1474  * lp - the device's private adapter structure
1475  *
1476  * RETURNS:
1477  *
1478  * 0 on success
1479  * errno value otherwise
1480  *
1481  ******************************************************************************/
1482 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1483 {
1484  struct wl_private *lp = wl_priv(dev);
1485  unsigned long flags;
1486  int ret = 0;
1487  /*------------------------------------------------------------------------*/
1488 
1489 
1490  DBG_FUNC( "wireless_set_nickname" );
1491  DBG_ENTER( DbgInfo );
1492 
1494  ret = -EBUSY;
1495  goto out;
1496  }
1497 
1498 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1499  if( !capable(CAP_NET_ADMIN )) {
1500  ret = -EPERM;
1501  DBG_LEAVE( DbgInfo );
1502  return ret;
1503  }
1504 #endif
1505 
1506  /* Validate the new value */
1507  if(data->length > HCF_MAX_NAME_LEN) {
1508  ret = -EINVAL;
1509  goto out;
1510  }
1511 
1512  wl_lock( lp, &flags );
1513 
1514  wl_act_int_off( lp );
1515 
1516  memset( lp->StationName, 0, sizeof( lp->StationName ));
1517 
1518  memcpy( lp->StationName, nickname, data->length );
1519 
1520  /* Commit the adapter parameters */
1521  wl_apply( lp );
1522 
1523  wl_act_int_on( lp );
1524 
1525  wl_unlock(lp, &flags);
1526 
1527 out:
1528  DBG_LEAVE( DbgInfo );
1529  return ret;
1530 } // wireless_set_nickname
1531 /*============================================================================*/
1532 
1533 
1534 
1535 
1536 /*******************************************************************************
1537  * wireless_get_nickname()
1538  *******************************************************************************
1539  *
1540  * DESCRIPTION:
1541  *
1542  * Gets the nickname, or station name, of the wireless device.
1543  *
1544  * PARAMETERS:
1545  *
1546  * wrq - the wireless request buffer
1547  * lp - the device's private adapter structure
1548  *
1549  * RETURNS:
1550  *
1551  * 0 on success
1552  * errno value otherwise
1553  *
1554  ******************************************************************************/
1555 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1556 {
1557  struct wl_private *lp = wl_priv(dev);
1558  unsigned long flags;
1559  int ret = 0;
1560  int status = -1;
1561  wvName_t *pName;
1562  /*------------------------------------------------------------------------*/
1563 
1564 
1565  DBG_FUNC( "wireless_get_nickname" );
1566  DBG_ENTER( DbgInfo );
1567 
1569  ret = -EBUSY;
1570  goto out;
1571  }
1572 
1573  wl_lock( lp, &flags );
1574 
1575  wl_act_int_off( lp );
1576 
1577  /* Get the current station name */
1578  lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1580 
1581  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1582 
1583  if( status == HCF_SUCCESS ) {
1584  pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1585 
1586  /* Endian translate the length */
1587  pName->length = CNV_LITTLE_TO_INT( pName->length );
1588 
1589  if ( pName->length > IW_ESSID_MAX_SIZE ) {
1590  ret = -EFAULT;
1591  } else {
1592  /* Copy the information into the user buffer */
1593  data->length = pName->length;
1594  memcpy(nickname, pName->name, pName->length);
1595  }
1596  } else {
1597  ret = -EFAULT;
1598  }
1599 
1600  wl_act_int_on( lp );
1601 
1602  wl_unlock(lp, &flags);
1603 
1604 out:
1605  DBG_LEAVE(DbgInfo);
1606  return ret;
1607 } // wireless_get_nickname
1608 /*============================================================================*/
1609 
1610 
1611 
1612 
1613 /*******************************************************************************
1614  * wireless_set_porttype()
1615  *******************************************************************************
1616  *
1617  * DESCRIPTION:
1618  *
1619  * Sets the port type of the wireless device.
1620  *
1621  * PARAMETERS:
1622  *
1623  * wrq - the wireless request buffer
1624  * lp - the device's private adapter structure
1625  *
1626  * RETURNS:
1627  *
1628  * 0 on success
1629  * errno value otherwise
1630  *
1631  ******************************************************************************/
1632 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1633 {
1634  struct wl_private *lp = wl_priv(dev);
1635  unsigned long flags;
1636  int ret = 0;
1637  hcf_16 portType;
1638  hcf_16 createIBSS;
1639  /*------------------------------------------------------------------------*/
1640 
1641  DBG_FUNC( "wireless_set_porttype" );
1642  DBG_ENTER( DbgInfo );
1643 
1645  ret = -EBUSY;
1646  goto out;
1647  }
1648 
1649  wl_lock( lp, &flags );
1650 
1651  wl_act_int_off( lp );
1652 
1653  /* Validate the new value */
1654  switch( *mode ) {
1655  case IW_MODE_ADHOC:
1656 
1657  /* When user requests ad-hoc, set IBSS mode! */
1658  portType = 1;
1659  createIBSS = 1;
1660 
1662 
1663  break;
1664 
1665 
1666  case IW_MODE_AUTO:
1667  case IW_MODE_INFRA:
1668 
1669  /* Both automatic and infrastructure set port to BSS/STA mode */
1670  portType = 1;
1671  createIBSS = 0;
1672 
1674 
1675  break;
1676 
1677 
1678 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1679 
1680  case IW_MODE_MASTER:
1681 
1682  /* Set BSS/AP mode */
1683  portType = 1;
1684 
1685  lp->CreateIBSS = 0;
1687 
1688  break;
1689 
1690 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1691 
1692 
1693  default:
1694 
1695  portType = 0;
1696  createIBSS = 0;
1697  ret = -EINVAL;
1698  }
1699 
1700  if( portType != 0 ) {
1701  /* Only do something if there is a mode change */
1702  if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1703  lp->PortType = portType;
1704  lp->CreateIBSS = createIBSS;
1705 
1706  /* Commit the adapter parameters */
1707  wl_go( lp );
1708 
1709  /* Send an event that mode has been set */
1710  wl_wext_event_mode( lp->dev );
1711  }
1712  }
1713 
1714  wl_act_int_on( lp );
1715 
1716  wl_unlock(lp, &flags);
1717 
1718 out:
1719  DBG_LEAVE( DbgInfo );
1720  return ret;
1721 } // wireless_set_porttype
1722 /*============================================================================*/
1723 
1724 
1725 
1726 
1727 /*******************************************************************************
1728  * wireless_get_porttype()
1729  *******************************************************************************
1730  *
1731  * DESCRIPTION:
1732  *
1733  * Gets the port type of the wireless device.
1734  *
1735  * PARAMETERS:
1736  *
1737  * wrq - the wireless request buffer
1738  * lp - the device's private adapter structure
1739  *
1740  * RETURNS:
1741  *
1742  * 0 on success
1743  * errno value otherwise
1744  *
1745  ******************************************************************************/
1746 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1747 
1748 {
1749  struct wl_private *lp = wl_priv(dev);
1750  unsigned long flags;
1751  int ret = 0;
1752  int status = -1;
1753  hcf_16 *pPortType;
1754  /*------------------------------------------------------------------------*/
1755 
1756 
1757  DBG_FUNC( "wireless_get_porttype" );
1758  DBG_ENTER( DbgInfo );
1759 
1761  ret = -EBUSY;
1762  goto out;
1763  }
1764 
1765  wl_lock( lp, &flags );
1766 
1767  wl_act_int_off( lp );
1768 
1769  /* Get the current port type */
1770  lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1772 
1773  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1774 
1775  if( status == HCF_SUCCESS ) {
1776  pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1777 
1778  *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1779 
1780  switch( *pPortType ) {
1781  case 1:
1782 
1783 #if 0
1784 #if (HCF_TYPE) & HCF_TYPE_AP
1785 
1786  if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1787  *mode = IW_MODE_MASTER;
1788  } else {
1789  *mode = IW_MODE_INFRA;
1790  }
1791 
1792 #else
1793 
1794  *mode = IW_MODE_INFRA;
1795 
1796 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1797 #endif
1798 
1799  if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1800  *mode = IW_MODE_MASTER;
1801  } else {
1802  if( lp->CreateIBSS ) {
1803  *mode = IW_MODE_ADHOC;
1804  } else {
1805  *mode = IW_MODE_INFRA;
1806  }
1807  }
1808 
1809  break;
1810 
1811 
1812  case 3:
1813  *mode = IW_MODE_ADHOC;
1814  break;
1815 
1816  default:
1817  ret = -EFAULT;
1818  break;
1819  }
1820  } else {
1821  ret = -EFAULT;
1822  }
1823 
1824  wl_act_int_on( lp );
1825 
1826  wl_unlock(lp, &flags);
1827 
1828 out:
1829  DBG_LEAVE( DbgInfo );
1830  return ret;
1831 } // wireless_get_porttype
1832 /*============================================================================*/
1833 
1834 
1835 
1836 
1837 /*******************************************************************************
1838  * wireless_set_power()
1839  *******************************************************************************
1840  *
1841  * DESCRIPTION:
1842  *
1843  * Sets the power management settings of the wireless device.
1844  *
1845  * PARAMETERS:
1846  *
1847  * wrq - the wireless request buffer
1848  * lp - the device's private adapter structure
1849  *
1850  * RETURNS:
1851  *
1852  * 0 on success
1853  * errno value otherwise
1854  *
1855  ******************************************************************************/
1856 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1857 {
1858  struct wl_private *lp = wl_priv(dev);
1859  unsigned long flags;
1860  int ret = 0;
1861  /*------------------------------------------------------------------------*/
1862 
1863 
1864  DBG_FUNC( "wireless_set_power" );
1865  DBG_ENTER( DbgInfo );
1866 
1868  ret = -EBUSY;
1869  goto out;
1870  }
1871 
1872  DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1873 
1874 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1875  if( !capable( CAP_NET_ADMIN )) {
1876  ret = -EPERM;
1877 
1878  DBG_LEAVE( DbgInfo );
1879  return ret;
1880  }
1881 #endif
1882 
1883  wl_lock( lp, &flags );
1884 
1885  wl_act_int_off( lp );
1886 
1887  /* Set the power management state based on the 'disabled' value */
1888  if( wrq->disabled ) {
1889  lp->PMEnabled = 0;
1890  } else {
1891  lp->PMEnabled = 1;
1892  }
1893 
1894  /* Commit the adapter parameters */
1895  wl_apply( lp );
1896 
1897  wl_act_int_on( lp );
1898 
1899  wl_unlock(lp, &flags);
1900 
1901 out:
1902  DBG_LEAVE( DbgInfo );
1903  return ret;
1904 } // wireless_set_power
1905 /*============================================================================*/
1906 
1907 
1908 
1909 
1910 /*******************************************************************************
1911  * wireless_get_power()
1912  *******************************************************************************
1913  *
1914  * DESCRIPTION:
1915  *
1916  * Gets the power management settings of the wireless device.
1917  *
1918  * PARAMETERS:
1919  *
1920  * wrq - the wireless request buffer
1921  * lp - the device's private adapter structure
1922  *
1923  * RETURNS:
1924  *
1925  * 0 on success
1926  * errno value otherwise
1927  *
1928  ******************************************************************************/
1929 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1930 
1931 {
1932  struct wl_private *lp = wl_priv(dev);
1933  unsigned long flags;
1934  int ret = 0;
1935  /*------------------------------------------------------------------------*/
1936  DBG_FUNC( "wireless_get_power" );
1937  DBG_ENTER( DbgInfo );
1938 
1940  ret = -EBUSY;
1941  goto out;
1942  }
1943 
1944  DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1945 
1946  wl_lock( lp, &flags );
1947 
1948  wl_act_int_off( lp );
1949 
1950  rrq->flags = 0;
1951  rrq->value = 0;
1952 
1953  if( lp->PMEnabled ) {
1954  rrq->disabled = 0;
1955  } else {
1956  rrq->disabled = 1;
1957  }
1958 
1959  wl_act_int_on( lp );
1960 
1961  wl_unlock(lp, &flags);
1962 
1963 out:
1964  DBG_LEAVE( DbgInfo );
1965  return ret;
1966 } // wireless_get_power
1967 /*============================================================================*/
1968 
1969 
1970 
1971 
1972 /*******************************************************************************
1973  * wireless_get_tx_power()
1974  *******************************************************************************
1975  *
1976  * DESCRIPTION:
1977  *
1978  * Gets the transmit power of the wireless device's radio.
1979  *
1980  * PARAMETERS:
1981  *
1982  * wrq - the wireless request buffer
1983  * lp - the device's private adapter structure
1984  *
1985  * RETURNS:
1986  *
1987  * 0 on success
1988  * errno value otherwise
1989  *
1990  ******************************************************************************/
1991 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1992 {
1993  struct wl_private *lp = wl_priv(dev);
1994  unsigned long flags;
1995  int ret = 0;
1996  /*------------------------------------------------------------------------*/
1997  DBG_FUNC( "wireless_get_tx_power" );
1998  DBG_ENTER( DbgInfo );
1999 
2001  ret = -EBUSY;
2002  goto out;
2003  }
2004 
2005  wl_lock( lp, &flags );
2006 
2007  wl_act_int_off( lp );
2008 
2009 #ifdef USE_POWER_DBM
2010  rrq->value = RADIO_TX_POWER_DBM;
2011  rrq->flags = IW_TXPOW_DBM;
2012 #else
2013  rrq->value = RADIO_TX_POWER_MWATT;
2014  rrq->flags = IW_TXPOW_MWATT;
2015 #endif
2016  rrq->fixed = 1;
2017  rrq->disabled = 0;
2018 
2019  wl_act_int_on( lp );
2020 
2021  wl_unlock(lp, &flags);
2022 
2023 out:
2024  DBG_LEAVE( DbgInfo );
2025  return ret;
2026 } // wireless_get_tx_power
2027 /*============================================================================*/
2028 
2029 
2030 
2031 
2032 /*******************************************************************************
2033  * wireless_set_rts_threshold()
2034  *******************************************************************************
2035  *
2036  * DESCRIPTION:
2037  *
2038  * Sets the RTS threshold for the wireless card.
2039  *
2040  * PARAMETERS:
2041  *
2042  * wrq - the wireless request buffer
2043  * lp - the device's private adapter structure
2044  *
2045  * RETURNS:
2046  *
2047  * 0 on success
2048  * errno value otherwise
2049  *
2050  ******************************************************************************/
2051 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2052 {
2053  int ret = 0;
2054  struct wl_private *lp = wl_priv(dev);
2055  unsigned long flags;
2056  int rthr = rts->value;
2057  /*------------------------------------------------------------------------*/
2058 
2059 
2060  DBG_FUNC( "wireless_set_rts_threshold" );
2061  DBG_ENTER( DbgInfo );
2062 
2064  ret = -EBUSY;
2065  goto out;
2066  }
2067 
2068  if(rts->fixed == 0) {
2069  ret = -EINVAL;
2070  goto out;
2071  }
2072 
2073  if( rts->disabled ) {
2074  rthr = 2347;
2075  }
2076 
2077  if(( rthr < 256 ) || ( rthr > 2347 )) {
2078  ret = -EINVAL;
2079  goto out;
2080  }
2081 
2082  wl_lock( lp, &flags );
2083 
2084  wl_act_int_off( lp );
2085 
2086  lp->RTSThreshold = rthr;
2087 
2088  wl_apply( lp );
2089 
2090  wl_act_int_on( lp );
2091 
2092  wl_unlock(lp, &flags);
2093 
2094 out:
2095  DBG_LEAVE( DbgInfo );
2096  return ret;
2097 } // wireless_set_rts_threshold
2098 /*============================================================================*/
2099 
2100 
2101 
2102 
2103 /*******************************************************************************
2104  * wireless_get_rts_threshold()
2105  *******************************************************************************
2106  *
2107  * DESCRIPTION:
2108  *
2109  * Gets the RTS threshold for the wireless card.
2110  *
2111  * PARAMETERS:
2112  *
2113  * wrq - the wireless request buffer
2114  * lp - the device's private adapter structure
2115  *
2116  * RETURNS:
2117  *
2118  * 0 on success
2119  * errno value otherwise
2120  *
2121  ******************************************************************************/
2122 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2123 {
2124  int ret = 0;
2125  struct wl_private *lp = wl_priv(dev);
2126  unsigned long flags;
2127  /*------------------------------------------------------------------------*/
2128 
2129  DBG_FUNC( "wireless_get_rts_threshold" );
2130  DBG_ENTER( DbgInfo );
2131 
2133  ret = -EBUSY;
2134  goto out;
2135  }
2136 
2137  wl_lock( lp, &flags );
2138 
2139  wl_act_int_off( lp );
2140 
2141  rts->value = lp->RTSThreshold;
2142 
2143  rts->disabled = ( rts->value == 2347 );
2144 
2145  rts->fixed = 1;
2146 
2147  wl_act_int_on( lp );
2148 
2149  wl_unlock(lp, &flags);
2150 
2151 out:
2152  DBG_LEAVE( DbgInfo );
2153  return ret;
2154 } // wireless_get_rts_threshold
2155 /*============================================================================*/
2156 
2157 
2158 
2159 
2160 
2161 /*******************************************************************************
2162  * wireless_set_rate()
2163  *******************************************************************************
2164  *
2165  * DESCRIPTION:
2166  *
2167  * Set the default data rate setting used by the wireless device.
2168  *
2169  * PARAMETERS:
2170  *
2171  * wrq - the wireless request buffer
2172  * lp - the device's private adapter structure
2173  *
2174  * RETURNS:
2175  *
2176  * 0 on success
2177  * errno value otherwise
2178  *
2179  ******************************************************************************/
2180 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2181 {
2182  struct wl_private *lp = wl_priv(dev);
2183  unsigned long flags;
2184  int ret = 0;
2185 #ifdef WARP
2186  int status = -1;
2187  int index = 0;
2188 #endif // WARP
2189  /*------------------------------------------------------------------------*/
2190 
2191 
2192  DBG_FUNC( "wireless_set_rate" );
2193  DBG_ENTER( DbgInfo );
2194 
2196  ret = -EBUSY;
2197  goto out;
2198  }
2199 
2200  wl_lock( lp, &flags );
2201 
2202  wl_act_int_off( lp );
2203 
2204 #ifdef WARP
2205 
2206  /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2207  if Bit 9 is set in the current channel RID */
2208  lp->ltvRecord.len = 2;
2210 
2211  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2212 
2213  if( status == HCF_SUCCESS ) {
2214  index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2215 
2216  DBG_PRINT( "Index: %d\n", index );
2217  } else {
2218  DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2219  DBG_LEAVE( DbgInfo );
2220  ret = -EINVAL;
2221  goto out_unlock;
2222  }
2223 
2224  if( rrq->value > 0 &&
2225  rrq->value <= 1 * MEGABIT ) {
2226  lp->TxRateControl[index] = 0x0001;
2227  }
2228  else if( rrq->value > 1 * MEGABIT &&
2229  rrq->value <= 2 * MEGABIT ) {
2230  if( rrq->fixed == 1 ) {
2231  lp->TxRateControl[index] = 0x0002;
2232  } else {
2233  lp->TxRateControl[index] = 0x0003;
2234  }
2235  }
2236  else if( rrq->value > 2 * MEGABIT &&
2237  rrq->value <= 5 * MEGABIT ) {
2238  if( rrq->fixed == 1 ) {
2239  lp->TxRateControl[index] = 0x0004;
2240  } else {
2241  lp->TxRateControl[index] = 0x0007;
2242  }
2243  }
2244  else if( rrq->value > 5 * MEGABIT &&
2245  rrq->value <= 6 * MEGABIT ) {
2246  if( rrq->fixed == 1 ) {
2247  lp->TxRateControl[index] = 0x0010;
2248  } else {
2249  lp->TxRateControl[index] = 0x0017;
2250  }
2251  }
2252  else if( rrq->value > 6 * MEGABIT &&
2253  rrq->value <= 9 * MEGABIT ) {
2254  if( rrq->fixed == 1 ) {
2255  lp->TxRateControl[index] = 0x0020;
2256  } else {
2257  lp->TxRateControl[index] = 0x0037;
2258  }
2259  }
2260  else if( rrq->value > 9 * MEGABIT &&
2261  rrq->value <= 11 * MEGABIT ) {
2262  if( rrq->fixed == 1 ) {
2263  lp->TxRateControl[index] = 0x0008;
2264  } else {
2265  lp->TxRateControl[index] = 0x003F;
2266  }
2267  }
2268  else if( rrq->value > 11 * MEGABIT &&
2269  rrq->value <= 12 * MEGABIT ) {
2270  if( rrq->fixed == 1 ) {
2271  lp->TxRateControl[index] = 0x0040;
2272  } else {
2273  lp->TxRateControl[index] = 0x007F;
2274  }
2275  }
2276  else if( rrq->value > 12 * MEGABIT &&
2277  rrq->value <= 18 * MEGABIT ) {
2278  if( rrq->fixed == 1 ) {
2279  lp->TxRateControl[index] = 0x0080;
2280  } else {
2281  lp->TxRateControl[index] = 0x00FF;
2282  }
2283  }
2284  else if( rrq->value > 18 * MEGABIT &&
2285  rrq->value <= 24 * MEGABIT ) {
2286  if( rrq->fixed == 1 ) {
2287  lp->TxRateControl[index] = 0x0100;
2288  } else {
2289  lp->TxRateControl[index] = 0x01FF;
2290  }
2291  }
2292  else if( rrq->value > 24 * MEGABIT &&
2293  rrq->value <= 36 * MEGABIT ) {
2294  if( rrq->fixed == 1 ) {
2295  lp->TxRateControl[index] = 0x0200;
2296  } else {
2297  lp->TxRateControl[index] = 0x03FF;
2298  }
2299  }
2300  else if( rrq->value > 36 * MEGABIT &&
2301  rrq->value <= 48 * MEGABIT ) {
2302  if( rrq->fixed == 1 ) {
2303  lp->TxRateControl[index] = 0x0400;
2304  } else {
2305  lp->TxRateControl[index] = 0x07FF;
2306  }
2307  }
2308  else if( rrq->value > 48 * MEGABIT &&
2309  rrq->value <= 54 * MEGABIT ) {
2310  if( rrq->fixed == 1 ) {
2311  lp->TxRateControl[index] = 0x0800;
2312  } else {
2313  lp->TxRateControl[index] = 0x0FFF;
2314  }
2315  }
2316  else if( rrq->fixed == 0 ) {
2317  /* In this case, the user has not specified a bitrate, only the "auto"
2318  moniker. So, set to all supported rates */
2320  } else {
2321  rrq->value = 0;
2322  ret = -EINVAL;
2323  goto out_unlock;
2324  }
2325 
2326 
2327 #else
2328 
2329  if( rrq->value > 0 &&
2330  rrq->value <= 1 * MEGABIT ) {
2331  lp->TxRateControl[0] = 1;
2332  }
2333  else if( rrq->value > 1 * MEGABIT &&
2334  rrq->value <= 2 * MEGABIT ) {
2335  if( rrq->fixed ) {
2336  lp->TxRateControl[0] = 2;
2337  } else {
2338  lp->TxRateControl[0] = 6;
2339  }
2340  }
2341  else if( rrq->value > 2 * MEGABIT &&
2342  rrq->value <= 5 * MEGABIT ) {
2343  if( rrq->fixed ) {
2344  lp->TxRateControl[0] = 4;
2345  } else {
2346  lp->TxRateControl[0] = 7;
2347  }
2348  }
2349  else if( rrq->value > 5 * MEGABIT &&
2350  rrq->value <= 11 * MEGABIT ) {
2351  if( rrq->fixed) {
2352  lp->TxRateControl[0] = 5;
2353  } else {
2354  lp->TxRateControl[0] = 3;
2355  }
2356  }
2357  else if( rrq->fixed == 0 ) {
2358  /* In this case, the user has not specified a bitrate, only the "auto"
2359  moniker. So, set the rate to 11Mb auto */
2360  lp->TxRateControl[0] = 3;
2361  } else {
2362  rrq->value = 0;
2363  ret = -EINVAL;
2364  goto out_unlock;
2365  }
2366 
2367 #endif // WARP
2368 
2369 
2370  /* Commit the adapter parameters */
2371  wl_apply( lp );
2372 
2373 out_unlock:
2374 
2375  wl_act_int_on( lp );
2376 
2377  wl_unlock(lp, &flags);
2378 
2379 out:
2380  DBG_LEAVE( DbgInfo );
2381  return ret;
2382 } // wireless_set_rate
2383 /*============================================================================*/
2384 
2385 
2386 
2387 
2388 /*******************************************************************************
2389  * wireless_get_rate()
2390  *******************************************************************************
2391  *
2392  * DESCRIPTION:
2393  *
2394  * Get the default data rate setting used by the wireless device.
2395  *
2396  * PARAMETERS:
2397  *
2398  * wrq - the wireless request buffer
2399  * lp - the device's private adapter structure
2400  *
2401  * RETURNS:
2402  *
2403  * 0 on success
2404  * errno value otherwise
2405  *
2406  ******************************************************************************/
2407 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2408 
2409 {
2410  struct wl_private *lp = wl_priv(dev);
2411  unsigned long flags;
2412  int ret = 0;
2413  int status = -1;
2414  hcf_16 txRate;
2415  /*------------------------------------------------------------------------*/
2416 
2417 
2418  DBG_FUNC( "wireless_get_rate" );
2419  DBG_ENTER( DbgInfo );
2420 
2422  ret = -EBUSY;
2423  goto out;
2424  }
2425 
2426  wl_lock( lp, &flags );
2427 
2428  wl_act_int_off( lp );
2429 
2430  /* Get the current transmit rate from the adapter */
2431  lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2433 
2434  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2435 
2436  if( status == HCF_SUCCESS ) {
2437 #ifdef WARP
2438 
2439  txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2440 
2441  if( txRate & 0x0001 ) {
2442  txRate = 1;
2443  }
2444  else if( txRate & 0x0002 ) {
2445  txRate = 2;
2446  }
2447  else if( txRate & 0x0004 ) {
2448  txRate = 5;
2449  }
2450  else if( txRate & 0x0008 ) {
2451  txRate = 11;
2452  }
2453  else if( txRate & 0x00010 ) {
2454  txRate = 6;
2455  }
2456  else if( txRate & 0x00020 ) {
2457  txRate = 9;
2458  }
2459  else if( txRate & 0x00040 ) {
2460  txRate = 12;
2461  }
2462  else if( txRate & 0x00080 ) {
2463  txRate = 18;
2464  }
2465  else if( txRate & 0x00100 ) {
2466  txRate = 24;
2467  }
2468  else if( txRate & 0x00200 ) {
2469  txRate = 36;
2470  }
2471  else if( txRate & 0x00400 ) {
2472  txRate = 48;
2473  }
2474  else if( txRate & 0x00800 ) {
2475  txRate = 54;
2476  }
2477 
2478 #else
2479 
2480  txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2481 
2482 #endif // WARP
2483 
2484  rrq->value = txRate * MEGABIT;
2485  } else {
2486  rrq->value = 0;
2487  ret = -EFAULT;
2488  }
2489 
2490  wl_act_int_on( lp );
2491 
2492  wl_unlock(lp, &flags);
2493 
2494 out:
2495  DBG_LEAVE( DbgInfo );
2496  return ret;
2497 } // wireless_get_rate
2498 /*============================================================================*/
2499 
2500 
2501 
2502 
2503 #if 0 //;? Not used anymore
2504 /*******************************************************************************
2505  * wireless_get_private_interface()
2506  *******************************************************************************
2507  *
2508  * DESCRIPTION:
2509  *
2510  * Returns the Linux Wireless Extensions' compatible private interface of
2511  * the driver.
2512  *
2513  * PARAMETERS:
2514  *
2515  * wrq - the wireless request buffer
2516  * lp - the device's private adapter structure
2517  *
2518  * RETURNS:
2519  *
2520  * 0 on success
2521  * errno value otherwise
2522  *
2523  ******************************************************************************/
2524 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2525 {
2526  int ret = 0;
2527  /*------------------------------------------------------------------------*/
2528 
2529 
2530  DBG_FUNC( "wireless_get_private_interface" );
2531  DBG_ENTER( DbgInfo );
2532 
2534  ret = -EBUSY;
2535  goto out;
2536  }
2537 
2538  if( wrq->u.data.pointer != NULL ) {
2539  struct iw_priv_args priv[] =
2540  {
2541  { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2542  { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2543  { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2544  { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2545  { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2546  { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2547  };
2548 
2549  /* Verify the user buffer */
2550  ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2551 
2552  if( ret != 0 ) {
2553  DBG_LEAVE( DbgInfo );
2554  return ret;
2555  }
2556 
2557  /* Copy the data into the user's buffer */
2558  wrq->u.data.length = NELEM( priv );
2559  copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2560  }
2561 
2562 out:
2563  DBG_LEAVE( DbgInfo );
2564  return ret;
2565 } // wireless_get_private_interface
2566 /*============================================================================*/
2567 #endif
2568 
2569 
2570 
2571 /*******************************************************************************
2572  * wireless_set_scan()
2573  *******************************************************************************
2574  *
2575  * DESCRIPTION:
2576  *
2577  * Instructs the driver to initiate a network scan.
2578  *
2579  * PARAMETERS:
2580  *
2581  * wrq - the wireless request buffer
2582  * lp - the device's private adapter structure
2583  *
2584  * RETURNS:
2585  *
2586  * 0 on success
2587  * errno value otherwise
2588  *
2589  ******************************************************************************/
2590 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2591 {
2592  struct wl_private *lp = wl_priv(dev);
2593  unsigned long flags;
2594  int ret = 0;
2595  int status = -1;
2596  int retries = 0;
2597  /*------------------------------------------------------------------------*/
2598 
2599  //;? Note: shows results as trace, returns always 0 unless BUSY
2600 
2601  DBG_FUNC( "wireless_set_scan" );
2602  DBG_ENTER( DbgInfo );
2603 
2605  ret = -EBUSY;
2606  goto out;
2607  }
2608 
2609  wl_lock( lp, &flags );
2610 
2611  wl_act_int_off( lp );
2612 
2613  /*
2614  * This looks like a nice place to test if the HCF is still
2615  * communicating with the card. It seems that sometimes BAP_1
2616  * gets corrupted. By looking at the comments in HCF the
2617  * cause is still a mystery. Okay, the communication to the
2618  * card is dead, reset the card to revive.
2619  */
2620  if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2621  {
2622  DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2623  wl_reset( dev );
2624  }
2625 
2626 retry:
2627  /* Set the completion state to FALSE */
2629 
2630 
2631  /* Channels to scan */
2632 #ifdef WARP
2633  lp->ltvRecord.len = 5;
2635  lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2636  lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2637  lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2638  lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2639 #else
2640  lp->ltvRecord.len = 2;
2642  lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2643 #endif // WARP
2644 
2645  status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2646 
2647  DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2648 
2649  // Holding the lock too long, makes a gap to allow other processes
2650  wl_unlock(lp, &flags);
2651  wl_lock( lp, &flags );
2652 
2653  if( status != HCF_SUCCESS ) {
2654  //Recovery
2655  retries++;
2656  if(retries <= 10) {
2657  DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2658  wl_reset( dev );
2659 
2660  // Holding the lock too long, makes a gap to allow other processes
2661  wl_unlock(lp, &flags);
2662  wl_lock( lp, &flags );
2663 
2664  goto retry;
2665  }
2666  }
2667 
2668  /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2669  disassociate from the network we are currently on */
2670  lp->ltvRecord.len = 18;
2671  lp->ltvRecord.typ = CFG_SCAN_SSID;
2672  lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2673  lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2674 
2675  status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2676 
2677  // Holding the lock too long, makes a gap to allow other processes
2678  wl_unlock(lp, &flags);
2679  wl_lock( lp, &flags );
2680 
2681  DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2682 
2683  /* Initiate the scan */
2684  /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2685  retrieve probe response must always be used to support WPA */
2686  status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2687 
2688  if( status == HCF_SUCCESS ) {
2689  DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2690  } else {
2691  DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2692  }
2693 
2694  wl_act_int_on( lp );
2695 
2696  wl_unlock(lp, &flags);
2697 
2698 out:
2699  DBG_LEAVE(DbgInfo);
2700  return ret;
2701 } // wireless_set_scan
2702 /*============================================================================*/
2703 
2704 
2705 
2706 
2707 /*******************************************************************************
2708  * wireless_get_scan()
2709  *******************************************************************************
2710  *
2711  * DESCRIPTION:
2712  *
2713  * Instructs the driver to gather and return the results of a network scan.
2714  *
2715  * PARAMETERS:
2716  *
2717  * wrq - the wireless request buffer
2718  * lp - the device's private adapter structure
2719  *
2720  * RETURNS:
2721  *
2722  * 0 on success
2723  * errno value otherwise
2724  *
2725  ******************************************************************************/
2726 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2727 {
2728  struct wl_private *lp = wl_priv(dev);
2729  unsigned long flags;
2730  int ret = 0;
2731  int count;
2732  char *buf;
2733  char *buf_end;
2734  struct iw_event iwe;
2736  hcf_8 msg[512];
2737  hcf_8 *wpa_ie;
2738  hcf_16 wpa_ie_len;
2739  /*------------------------------------------------------------------------*/
2740 
2741 
2742  DBG_FUNC( "wireless_get_scan" );
2743  DBG_ENTER( DbgInfo );
2744 
2746  ret = -EBUSY;
2747  goto out;
2748  }
2749 
2750  wl_lock( lp, &flags );
2751 
2752  wl_act_int_off( lp );
2753 
2754  /* If the scan is not done, tell the calling process to try again later */
2755  if( !lp->probe_results.scan_complete ) {
2756  ret = -EAGAIN;
2757  goto out_unlock;
2758  }
2759 
2760  DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2761  lp->probe_results.num_aps );
2762 
2763  buf = extra;
2764  buf_end = extra + IW_SCAN_MAX_DATA;
2765 
2766  for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2767  /* Reference the probe response from the table */
2768  probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2769 
2770 
2771  /* First entry MUST be the MAC address */
2772  memset( &iwe, 0, sizeof( iwe ));
2773 
2774  iwe.cmd = SIOCGIWAP;
2775  iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2776  memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2777  iwe.len = IW_EV_ADDR_LEN;
2778 
2779  buf = iwe_stream_add_event(info, buf, buf_end,
2780  &iwe, IW_EV_ADDR_LEN);
2781 
2782  /* Use the mode to indicate if it's a station or AP */
2783  /* Won't always be an AP if in IBSS mode */
2784  memset( &iwe, 0, sizeof( iwe ));
2785 
2786  iwe.cmd = SIOCGIWMODE;
2787 
2788  if( probe_resp->capability & CAPABILITY_IBSS ) {
2789  iwe.u.mode = IW_MODE_INFRA;
2790  } else {
2791  iwe.u.mode = IW_MODE_MASTER;
2792  }
2793 
2794  iwe.len = IW_EV_UINT_LEN;
2795 
2796  buf = iwe_stream_add_event(info, buf, buf_end,
2797  &iwe, IW_EV_UINT_LEN);
2798 
2799  /* Any quality information */
2800  memset(&iwe, 0, sizeof(iwe));
2801 
2802  iwe.cmd = IWEVQUAL;
2803  iwe.u.qual.level = dbm(probe_resp->signal);
2804  iwe.u.qual.noise = dbm(probe_resp->silence);
2805  iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2806  iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2807  iwe.len = IW_EV_QUAL_LEN;
2808 
2809  buf = iwe_stream_add_event(info, buf, buf_end,
2810  &iwe, IW_EV_QUAL_LEN);
2811 
2812 
2813  /* ESSID information */
2814  if( probe_resp->rawData[1] > 0 ) {
2815  memset( &iwe, 0, sizeof( iwe ));
2816 
2817  iwe.cmd = SIOCGIWESSID;
2818  iwe.u.data.length = probe_resp->rawData[1];
2819  iwe.u.data.flags = 1;
2820 
2821  buf = iwe_stream_add_point(info, buf, buf_end,
2822  &iwe, &probe_resp->rawData[2]);
2823  }
2824 
2825 
2826  /* Encryption Information */
2827  memset( &iwe, 0, sizeof( iwe ));
2828 
2829  iwe.cmd = SIOCGIWENCODE;
2830  iwe.u.data.length = 0;
2831 
2832  /* Check the capabilities field of the Probe Response to see if
2833  'privacy' is supported on the AP in question */
2834  if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2835  iwe.u.data.flags |= IW_ENCODE_ENABLED;
2836  } else {
2837  iwe.u.data.flags |= IW_ENCODE_DISABLED;
2838  }
2839 
2840  buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
2841 
2842 
2843  /* Frequency Info */
2844  memset( &iwe, 0, sizeof( iwe ));
2845 
2846  iwe.cmd = SIOCGIWFREQ;
2847  iwe.len = IW_EV_FREQ_LEN;
2848  iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2849  iwe.u.freq.e = 0;
2850 
2851  buf = iwe_stream_add_event(info, buf, buf_end,
2852  &iwe, IW_EV_FREQ_LEN);
2853 
2854 
2855  /* Custom info (Beacon Interval) */
2856  memset( &iwe, 0, sizeof( iwe ));
2857  memset( msg, 0, sizeof( msg ));
2858 
2859  iwe.cmd = IWEVCUSTOM;
2860  sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2861  iwe.u.data.length = strlen( msg );
2862 
2863  buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
2864 
2865 
2866  /* WPA-IE */
2867  wpa_ie = NULL;
2868  wpa_ie_len = 0;
2869 
2870  wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2871  if( wpa_ie != NULL ) {
2872  memset(&iwe, 0, sizeof(iwe));
2873 
2874  iwe.cmd = IWEVGENIE;
2875  iwe.u.data.length = wpa_ie_len;
2876 
2877  buf = iwe_stream_add_point(info, buf, buf_end,
2878  &iwe, wpa_ie);
2879  }
2880 
2881  /* Add other custom info in formatted string format as needed... */
2882  }
2883 
2884  data->length = buf - extra;
2885 
2886 out_unlock:
2887 
2888  wl_act_int_on( lp );
2889 
2890  wl_unlock(lp, &flags);
2891 
2892 out:
2893  DBG_LEAVE( DbgInfo );
2894  return ret;
2895 } // wireless_get_scan
2896 /*============================================================================*/
2897 
2898 #if DBG
2899 static const char * const auth_names[] = {
2900  "IW_AUTH_WPA_VERSION",
2901  "IW_AUTH_CIPHER_PAIRWISE",
2902  "IW_AUTH_CIPHER_GROUP",
2903  "IW_AUTH_KEY_MGMT",
2904  "IW_AUTH_TKIP_COUNTERMEASURES",
2905  "IW_AUTH_DROP_UNENCRYPTED",
2906  "IW_AUTH_80211_AUTH_ALG",
2907  "IW_AUTH_WPA_ENABLED",
2908  "IW_AUTH_RX_UNENCRYPTED_EAPOL",
2909  "IW_AUTH_ROAMING_CONTROL",
2910  "IW_AUTH_PRIVACY_INVOKED",
2911  "IW_AUTH_CIPHER_GROUP_MGMT",
2912  "IW_AUTH_MFP",
2913  "Unsupported"
2914 };
2915 #endif
2916 
2917 static int wireless_set_auth(struct net_device *dev,
2918  struct iw_request_info *info,
2919  struct iw_param *data, char *extra)
2920 {
2921  struct wl_private *lp = wl_priv(dev);
2922  unsigned long flags;
2923  ltv_t ltv;
2924  int ret;
2925  int iwa_idx = data->flags & IW_AUTH_INDEX;
2926  int iwa_val = data->value;
2927 
2928  DBG_FUNC( "wireless_set_auth" );
2929  DBG_ENTER( DbgInfo );
2930 
2931  if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2932  ret = -EBUSY;
2933  goto out;
2934  }
2935 
2936  wl_lock( lp, &flags );
2937 
2938  wl_act_int_off( lp );
2939 
2940  if (iwa_idx > IW_AUTH_MFP)
2941  iwa_idx = IW_AUTH_MFP + 1;
2942  DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
2943  switch (iwa_idx) {
2944  case IW_AUTH_WPA_VERSION:
2945  /* We do support WPA */
2946  if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
2947  (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
2948  ret = 0;
2949  else
2950  ret = -EINVAL;
2951  break;
2952 
2953  case IW_AUTH_WPA_ENABLED:
2954  DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
2955  if (iwa_val)
2956  lp->EnableEncryption = 2;
2957  else
2958  lp->EnableEncryption = 0;
2959 
2960  /* Write straight to the card */
2961  ltv.len = 2;
2962  ltv.typ = CFG_CNF_ENCRYPTION;
2963  ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
2964  ret = hcf_put_info(&lp->hcfCtx, (LTVP)&ltv);
2965 
2966  break;
2967 
2969 
2970  /* Immediately disable card */
2971  lp->driverEnable = !iwa_val;
2972  if (lp->driverEnable)
2973  hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2974  else
2975  hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2976  ret = 0;
2977  break;
2978 
2979  case IW_AUTH_MFP:
2980  /* Management Frame Protection not supported.
2981  * Only fail if set to required.
2982  */
2983  if (iwa_val == IW_AUTH_MFP_REQUIRED)
2984  ret = -EINVAL;
2985  else
2986  ret = 0;
2987  break;
2988 
2989  case IW_AUTH_KEY_MGMT:
2990 
2991  /* Record required management suite.
2992  * Will take effect on next commit */
2993  if (iwa_val != 0)
2994  lp->AuthKeyMgmtSuite = 4;
2995  else
2996  lp->AuthKeyMgmtSuite = 0;
2997 
2998  ret = -EINPROGRESS;
2999  break;
3000 
3002 
3003  /* Just record whether open or shared is required.
3004  * Will take effect on next commit */
3005  ret = -EINPROGRESS;
3006 
3007  if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
3008  lp->authentication = 1;
3009  else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
3010  lp->authentication = 0;
3011  else
3012  ret = -EINVAL;
3013  break;
3014 
3016  /* Only needed for AP */
3017  lp->ExcludeUnencrypted = iwa_val;
3018  ret = -EINPROGRESS;
3019  break;
3020 
3022  case IW_AUTH_CIPHER_GROUP:
3026  /* Not used. May need to do something with
3027  * CIPHER_PAIRWISE and CIPHER_GROUP*/
3028  ret = -EINPROGRESS;
3029  break;
3030 
3031  default:
3032  DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
3033  /* return an error */
3034  ret = -EOPNOTSUPP;
3035  break;
3036  }
3037 
3038  wl_act_int_on( lp );
3039 
3040  wl_unlock(lp, &flags);
3041 
3042 out:
3043  DBG_LEAVE( DbgInfo );
3044  return ret;
3045 } // wireless_set_auth
3046 /*============================================================================*/
3047 
3048 
3049 static void flush_tx(struct wl_private *lp)
3050 {
3051  ltv_t ltv;
3052  int count;
3053 
3054  /*
3055  * Make sure that there is no data queued up in the firmware
3056  * before setting the TKIP keys. If this check is not
3057  * performed, some data may be sent out with incorrect MIC
3058  * and cause synchronization errors with the AP
3059  */
3060  /* Check every 1ms for 100ms */
3061  for (count = 0; count < 100; count++) {
3062  udelay(1000);
3063 
3064  ltv.len = 2;
3065  ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
3066  ltv.u.u16[0] = 0;
3067 
3068  hcf_get_info(&(lp->hcfCtx), (LTVP)&ltv);
3069 
3070  if (ltv.u.u16[0] == 0)
3071  break;
3072  }
3073 
3074  if (count >= 100)
3075  DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
3076 
3077 }
3078 
3079 static int wireless_set_encodeext(struct net_device *dev,
3080  struct iw_request_info *info,
3081  struct iw_point *erq, char *keybuf)
3082 {
3083  struct wl_private *lp = wl_priv(dev);
3084  unsigned long flags;
3085  int ret;
3086  int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
3087  ltv_t ltv;
3088  struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3089  bool enable = true;
3090  bool set_tx = false;
3091 
3092  DBG_ENTER(DbgInfo);
3093 
3094  if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
3095  ret = -EBUSY;
3096  goto out;
3097  }
3098 
3099  if (erq->flags & IW_ENCODE_DISABLED) {
3100  ext->alg = IW_ENCODE_ALG_NONE;
3101  enable = false;
3102  }
3103 
3105  set_tx = true;
3106 
3107  wl_lock(lp, &flags);
3108 
3109  wl_act_int_off(lp);
3110 
3111  memset(&ltv, 0, sizeof(ltv));
3112 
3113  switch (ext->alg) {
3114  case IW_ENCODE_ALG_TKIP:
3115  DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3116 
3117  if (sizeof(ext->rx_seq) != 8) {
3118  DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
3119  DBG_LEAVE(DbgInfo);
3120  ret = -EINVAL;
3121  goto out_unlock;
3122  }
3123 
3124  ret = hermes_set_tkip_keys(&ltv, key_idx, ext->addr.sa_data,
3125  set_tx,
3126  ext->rx_seq, ext->key, ext->key_len);
3127 
3128  if (ret != 0) {
3129  DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
3130  goto out_unlock;
3131  }
3132 
3133  flush_tx(lp);
3134 
3136 
3137  /* Write the key */
3138  ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3139  break;
3140 
3141  case IW_ENCODE_ALG_WEP:
3142  DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3143 
3144  if (erq->flags & IW_ENCODE_RESTRICTED) {
3145  DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
3146  ret = -EINVAL;
3147  goto out_unlock;
3148  }
3149 
3150  ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
3151  enable, set_tx);
3152 
3153  break;
3154 
3155  case IW_ENCODE_ALG_CCMP:
3156  DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3157  ret = -EOPNOTSUPP;
3158  break;
3159 
3160  case IW_ENCODE_ALG_NONE:
3161  DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3162 
3163  if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
3164  ret = hermes_clear_tkip_keys(&ltv, key_idx,
3165  ext->addr.sa_data);
3166  flush_tx(lp);
3168  ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3169 
3170  } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
3171  ret = hermes_set_wep_keys(lp, key_idx,
3172  ext->key, ext->key_len,
3173  false, false);
3174  } else {
3175  ret = 0;
3176  }
3177 
3178  break;
3179 
3180  default:
3181  DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3182  ret = -EOPNOTSUPP;
3183  break;
3184  }
3185 
3186 out_unlock:
3187 
3188  wl_act_int_on(lp);
3189 
3190  wl_unlock(lp, &flags);
3191 
3192 out:
3193  DBG_LEAVE(DbgInfo);
3194  return ret;
3195 }
3196 /*============================================================================*/
3197 
3198 
3199 
3200 static int wireless_set_genie(struct net_device *dev,
3201  struct iw_request_info *info,
3202  struct iw_point *data, char *extra)
3203 
3204 {
3205  int ret = 0;
3206 
3207  DBG_ENTER(DbgInfo);
3208 
3209  /* We can't write this to the card, but apparently this
3210  * operation needs to succeed */
3211  ret = 0;
3212 
3213  DBG_LEAVE(DbgInfo);
3214  return ret;
3215 }
3216 /*============================================================================*/
3217 
3218 
3219 /*******************************************************************************
3220  * wl_wireless_stats()
3221  *******************************************************************************
3222  *
3223  * DESCRIPTION:
3224  *
3225  * Return the current device wireless statistics.
3226  *
3227  * PARAMETERS:
3228  *
3229  * wrq - the wireless request buffer
3230  * lp - the device's private adapter structure
3231  *
3232  * RETURNS:
3233  *
3234  * 0 on success
3235  * errno value otherwise
3236  *
3237  ******************************************************************************/
3239 {
3240  struct iw_statistics *pStats;
3241  struct wl_private *lp = wl_priv(dev);
3242  /*------------------------------------------------------------------------*/
3243 
3244 
3245  DBG_FUNC( "wl_wireless_stats" );
3246  DBG_ENTER(DbgInfo);
3247  DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3248 
3249  pStats = NULL;
3250 
3251  /* Initialize the statistics */
3252  pStats = &( lp->wstats );
3253  pStats->qual.updated = 0x00;
3254 
3255  if( !( lp->flags & WVLAN2_UIL_BUSY ))
3256  {
3257  CFG_COMMS_QUALITY_STRCT *pQual;
3258  CFG_HERMES_TALLIES_STRCT tallies;
3259  int status;
3260 
3261  /* Update driver status */
3262  pStats->status = 0;
3263 
3264  /* Get the current link quality information */
3265  lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3267  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3268 
3269  if( status == HCF_SUCCESS ) {
3270  pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3271 
3272  pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3273  pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3274  pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3275 
3276  pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3279  IW_QUAL_DBM);
3280  } else {
3281  memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3282  }
3283 
3284  /* Get the current tallies from the adapter */
3285  /* Only possible when the device is open */
3287  if( wl_get_tallies( lp, &tallies ) == 0 ) {
3288  /* No endian translation is needed here, as CFG_TALLIES is an
3289  MSF RID; all processing is done on the host, not the card! */
3290  pStats->discard.nwid = 0L;
3291  pStats->discard.code = tallies.RxWEPUndecryptable;
3292  pStats->discard.misc = tallies.TxDiscards +
3293  tallies.RxFCSErrors +
3294  //tallies.RxDiscardsNoBuffer +
3295  tallies.TxDiscardsWrongSA;
3296  //;? Extra taken over from Linux driver based on 7.18 version
3297  pStats->discard.retries = tallies.TxRetryLimitExceeded;
3298  pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3299  } else {
3300  memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3301  }
3302  } else {
3303  memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3304  }
3305  }
3306 
3307  DBG_LEAVE( DbgInfo );
3308  return pStats;
3309 } // wl_wireless_stats
3310 /*============================================================================*/
3311 
3312 
3313 
3314 
3315 /*******************************************************************************
3316  * wl_get_wireless_stats()
3317  *******************************************************************************
3318  *
3319  * DESCRIPTION:
3320  *
3321  * Return the current device wireless statistics. This function calls
3322  * wl_wireless_stats, but acquires spinlocks first as it can be called
3323  * directly by the network layer.
3324  *
3325  * PARAMETERS:
3326  *
3327  * wrq - the wireless request buffer
3328  * lp - the device's private adapter structure
3329  *
3330  * RETURNS:
3331  *
3332  * 0 on success
3333  * errno value otherwise
3334  *
3335  ******************************************************************************/
3337 {
3338  unsigned long flags;
3339  struct wl_private *lp = wl_priv(dev);
3340  struct iw_statistics *pStats = NULL;
3341  /*------------------------------------------------------------------------*/
3342 
3343  DBG_FUNC( "wl_get_wireless_stats" );
3344  DBG_ENTER(DbgInfo);
3345 
3346  wl_lock( lp, &flags );
3347 
3348  wl_act_int_off( lp );
3349 
3350 #ifdef USE_RTS
3351  if( lp->useRTS == 1 ) {
3352  DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3353  } else
3354 #endif
3355  {
3356  pStats = wl_wireless_stats( dev );
3357  }
3358  wl_act_int_on( lp );
3359 
3360  wl_unlock(lp, &flags);
3361 
3362  DBG_LEAVE( DbgInfo );
3363  return pStats;
3364 } // wl_get_wireless_stats
3365 
3366 
3367 /*******************************************************************************
3368  * wl_spy_gather()
3369  *******************************************************************************
3370  *
3371  * DESCRIPTION:
3372  *
3373  * Gather wireless spy statistics.
3374  *
3375  * PARAMETERS:
3376  *
3377  * wrq - the wireless request buffer
3378  * lp - the device's private adapter structure
3379  *
3380  * RETURNS:
3381  *
3382  * 0 on success
3383  * errno value otherwise
3384  *
3385  ******************************************************************************/
3386 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3387 {
3388  struct iw_quality wstats;
3389  int status;
3390  u_char stats[2];
3391  DESC_STRCT desc[1];
3392  struct wl_private *lp = wl_priv(dev);
3393  /*------------------------------------------------------------------------*/
3394 
3395  /* shortcut */
3396  if (!lp->spy_data.spy_number) {
3397  return;
3398  }
3399 
3400  /* Gather wireless spy statistics: for each packet, compare the source
3401  address with out list, and if match, get the stats. */
3402  memset( stats, 0, sizeof(stats));
3403  memset( desc, 0, sizeof(DESC_STRCT));
3404 
3405  desc[0].buf_addr = stats;
3406  desc[0].BUF_SIZE = sizeof(stats);
3407  desc[0].next_desc_addr = 0; // terminate list
3408 
3409  status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3410 
3411  if( status == HCF_SUCCESS ) {
3412  wstats.level = (u_char) dbm(stats[1]);
3413  wstats.noise = (u_char) dbm(stats[0]);
3414  wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3415 
3416  wstats.updated = (IW_QUAL_QUAL_UPDATED |
3419  IW_QUAL_DBM);
3420 
3421  wireless_spy_update( dev, mac, &wstats );
3422  }
3423 } // wl_spy_gather
3424 /*============================================================================*/
3425 
3426 
3427 
3428 
3429 /*******************************************************************************
3430  * wl_wext_event_freq()
3431  *******************************************************************************
3432  *
3433  * DESCRIPTION:
3434  *
3435  * This function is used to send an event that the channel/freq
3436  * configuration for a specific device has changed.
3437  *
3438  *
3439  * PARAMETERS:
3440  *
3441  * dev - the network device for which this event is to be issued
3442  *
3443  * RETURNS:
3444  *
3445  * N/A
3446  *
3447  ******************************************************************************/
3448 void wl_wext_event_freq( struct net_device *dev )
3449 {
3450  union iwreq_data wrqu;
3451  struct wl_private *lp = wl_priv(dev);
3452  /*------------------------------------------------------------------------*/
3453 
3454 
3455  memset( &wrqu, 0, sizeof( wrqu ));
3456 
3457  wrqu.freq.m = lp->Channel;
3458  wrqu.freq.e = 0;
3459 
3460  wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3461 
3462  return;
3463 } // wl_wext_event_freq
3464 /*============================================================================*/
3465 
3466 
3467 
3468 
3469 /*******************************************************************************
3470  * wl_wext_event_mode()
3471  *******************************************************************************
3472  *
3473  * DESCRIPTION:
3474  *
3475  * This function is used to send an event that the mode of operation
3476  * for a specific device has changed.
3477  *
3478  *
3479  * PARAMETERS:
3480  *
3481  * dev - the network device for which this event is to be issued
3482  *
3483  * RETURNS:
3484  *
3485  * N/A
3486  *
3487  ******************************************************************************/
3488 void wl_wext_event_mode( struct net_device *dev )
3489 {
3490  union iwreq_data wrqu;
3491  struct wl_private *lp = wl_priv(dev);
3492  /*------------------------------------------------------------------------*/
3493 
3494 
3495  memset( &wrqu, 0, sizeof( wrqu ));
3496 
3497  if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3498  wrqu.mode = IW_MODE_INFRA;
3499  } else {
3500  wrqu.mode = IW_MODE_MASTER;
3501  }
3502 
3503  wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3504 
3505  return;
3506 } // wl_wext_event_mode
3507 /*============================================================================*/
3508 
3509 
3510 
3511 
3512 /*******************************************************************************
3513  * wl_wext_event_essid()
3514  *******************************************************************************
3515  *
3516  * DESCRIPTION:
3517  *
3518  * This function is used to send an event that the ESSID configuration for
3519  * a specific device has changed.
3520  *
3521  *
3522  * PARAMETERS:
3523  *
3524  * dev - the network device for which this event is to be issued
3525  *
3526  * RETURNS:
3527  *
3528  * N/A
3529  *
3530  ******************************************************************************/
3531 void wl_wext_event_essid( struct net_device *dev )
3532 {
3533  union iwreq_data wrqu;
3534  struct wl_private *lp = wl_priv(dev);
3535  /*------------------------------------------------------------------------*/
3536 
3537 
3538  memset( &wrqu, 0, sizeof( wrqu ));
3539 
3540  /* Fill out the buffer. Note that the buffer doesn't actually contain the
3541  ESSID, but a pointer to the contents. In addition, the 'extra' field of
3542  the call to wireless_send_event() must also point to where the ESSID
3543  lives */
3544  wrqu.essid.length = strlen( lp->NetworkName );
3545  wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3546  wrqu.essid.flags = 1;
3547 
3548  wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3549 
3550  return;
3551 } // wl_wext_event_essid
3552 /*============================================================================*/
3553 
3554 
3555 
3556 
3557 /*******************************************************************************
3558  * wl_wext_event_encode()
3559  *******************************************************************************
3560  *
3561  * DESCRIPTION:
3562  *
3563  * This function is used to send an event that the encryption configuration
3564  * for a specific device has changed.
3565  *
3566  *
3567  * PARAMETERS:
3568  *
3569  * dev - the network device for which this event is to be issued
3570  *
3571  * RETURNS:
3572  *
3573  * N/A
3574  *
3575  ******************************************************************************/
3577 {
3578  union iwreq_data wrqu;
3579  struct wl_private *lp = wl_priv(dev);
3580  int index = 0;
3581  /*------------------------------------------------------------------------*/
3582 
3583 
3584  memset( &wrqu, 0, sizeof( wrqu ));
3585 
3586  if( lp->EnableEncryption == 0 ) {
3587  wrqu.encoding.flags = IW_ENCODE_DISABLED;
3588  } else {
3589  wrqu.encoding.flags |= lp->TransmitKeyID;
3590 
3591  index = lp->TransmitKeyID - 1;
3592 
3593  /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3594  if we're in AP mode */
3595 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3596  //;?should we restore this to allow smaller memory footprint
3597 
3598  if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3599  if( lp->ExcludeUnencrypted ) {
3600  wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3601  } else {
3602  wrqu.encoding.flags |= IW_ENCODE_OPEN;
3603  }
3604  }
3605 
3606 #endif // HCF_TYPE_AP
3607 
3608  /* Only provide the key if permissions allow */
3609  if( capable( CAP_NET_ADMIN )) {
3610  wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3611  wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3612  } else {
3613  wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3614  }
3615  }
3616 
3617  wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3618  lp->DefaultKeys.key[index].key );
3619 
3620  return;
3621 } // wl_wext_event_encode
3622 /*============================================================================*/
3623 
3624 
3625 
3626 
3627 /*******************************************************************************
3628  * wl_wext_event_ap()
3629  *******************************************************************************
3630  *
3631  * DESCRIPTION:
3632  *
3633  * This function is used to send an event that the device has been
3634  * associated to a new AP.
3635  *
3636  *
3637  * PARAMETERS:
3638  *
3639  * dev - the network device for which this event is to be issued
3640  *
3641  * RETURNS:
3642  *
3643  * N/A
3644  *
3645  ******************************************************************************/
3646 void wl_wext_event_ap( struct net_device *dev )
3647 {
3648  union iwreq_data wrqu;
3649  struct wl_private *lp = wl_priv(dev);
3650  int status;
3651  /*------------------------------------------------------------------------*/
3652 
3653 
3654  /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3655  this event BEFORE sending the association event, as there are timing
3656  issues with the hostap supplicant. The supplicant will attempt to process
3657  an EAPOL-Key frame from an AP before receiving this information, which
3658  is required for a proper processed frame. */
3659  wl_wext_event_assoc_ie( dev );
3660 
3661  /* Get the BSSID */
3662  lp->ltvRecord.typ = CFG_CUR_BSSID;
3663  lp->ltvRecord.len = 4;
3664 
3665  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3666  if( status == HCF_SUCCESS ) {
3667  memset( &wrqu, 0, sizeof( wrqu ));
3668 
3669  memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3670 
3671  wrqu.addr.sa_family = ARPHRD_ETHER;
3672 
3673  wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3674  }
3675 
3676  return;
3677 } // wl_wext_event_ap
3678 /*============================================================================*/
3679 
3680 
3681 
3682 /*******************************************************************************
3683  * wl_wext_event_scan_complete()
3684  *******************************************************************************
3685  *
3686  * DESCRIPTION:
3687  *
3688  * This function is used to send an event that a request for a network scan
3689  * has completed.
3690  *
3691  *
3692  * PARAMETERS:
3693  *
3694  * dev - the network device for which this event is to be issued
3695  *
3696  * RETURNS:
3697  *
3698  * N/A
3699  *
3700  ******************************************************************************/
3702 {
3703  union iwreq_data wrqu;
3704  /*------------------------------------------------------------------------*/
3705 
3706 
3707  memset( &wrqu, 0, sizeof( wrqu ));
3708 
3709  wrqu.addr.sa_family = ARPHRD_ETHER;
3710  wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3711 
3712  return;
3713 } // wl_wext_event_scan_complete
3714 /*============================================================================*/
3715 
3716 
3717 
3718 
3719 /*******************************************************************************
3720  * wl_wext_event_new_sta()
3721  *******************************************************************************
3722  *
3723  * DESCRIPTION:
3724  *
3725  * This function is used to send an event that an AP has registered a new
3726  * station.
3727  *
3728  *
3729  * PARAMETERS:
3730  *
3731  * dev - the network device for which this event is to be issued
3732  *
3733  * RETURNS:
3734  *
3735  * N/A
3736  *
3737  ******************************************************************************/
3739 {
3740  union iwreq_data wrqu;
3741  /*------------------------------------------------------------------------*/
3742 
3743 
3744  memset( &wrqu, 0, sizeof( wrqu ));
3745 
3746  /* Send the station's mac address here */
3747  memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3748  wrqu.addr.sa_family = ARPHRD_ETHER;
3749  wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3750 
3751  return;
3752 } // wl_wext_event_new_sta
3753 /*============================================================================*/
3754 
3755 
3756 
3757 
3758 /*******************************************************************************
3759  * wl_wext_event_expired_sta()
3760  *******************************************************************************
3761  *
3762  * DESCRIPTION:
3763  *
3764  * This function is used to send an event that an AP has deregistered a
3765  * station.
3766  *
3767  *
3768  * PARAMETERS:
3769  *
3770  * dev - the network device for which this event is to be issued
3771  *
3772  * RETURNS:
3773  *
3774  * N/A
3775  *
3776  ******************************************************************************/
3778 {
3779  union iwreq_data wrqu;
3780  /*------------------------------------------------------------------------*/
3781 
3782 
3783  memset( &wrqu, 0, sizeof( wrqu ));
3784 
3785  memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3786  wrqu.addr.sa_family = ARPHRD_ETHER;
3787  wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3788 
3789  return;
3790 } // wl_wext_event_expired_sta
3791 /*============================================================================*/
3792 
3793 
3794 
3795 
3796 /*******************************************************************************
3797  * wl_wext_event_mic_failed()
3798  *******************************************************************************
3799  *
3800  * DESCRIPTION:
3801  *
3802  * This function is used to send an event that MIC calculations failed.
3803  *
3804  *
3805  * PARAMETERS:
3806  *
3807  * dev - the network device for which this event is to be issued
3808  *
3809  * RETURNS:
3810  *
3811  * N/A
3812  *
3813  ******************************************************************************/
3815 {
3816  union iwreq_data wrqu;
3817  struct wl_private *lp = wl_priv(dev);
3818  struct iw_michaelmicfailure wxmic;
3819  int key_idx;
3820  char *addr1;
3821  char *addr2;
3823  /*------------------------------------------------------------------------*/
3824 
3825 
3826  key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3827  key_idx &= 0x03;
3828 
3829  /* Cast the lookahead buffer into a RFS format */
3830  hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3831 
3832  /* Cast the addresses to byte buffers, as in the above RFS they are word
3833  length */
3834  addr1 = (char *)hdr->address1;
3835  addr2 = (char *)hdr->address2;
3836 
3837  DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3838  hdr->status );
3839 
3840  memset(&wrqu, 0, sizeof(wrqu));
3841  memset(&wxmic, 0, sizeof(wxmic));
3842 
3843  wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3844  wxmic.flags |= (addr1[0] & 1) ?
3846  wxmic.src_addr.sa_family = ARPHRD_ETHER;
3847  memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3848 
3849  wrqu.data.length = sizeof(wxmic);
3850  wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3851 
3852  return;
3853 } // wl_wext_event_mic_failed
3854 /*============================================================================*/
3855 
3856 
3857 
3858 
3859 /*******************************************************************************
3860  * wl_wext_event_assoc_ie()
3861  *******************************************************************************
3862  *
3863  * DESCRIPTION:
3864  *
3865  * This function is used to send an event containing the WPA-IE generated
3866  * by the firmware in an association request.
3867  *
3868  *
3869  * PARAMETERS:
3870  *
3871  * dev - the network device for which this event is to be issued
3872  *
3873  * RETURNS:
3874  *
3875  * N/A
3876  *
3877  ******************************************************************************/
3879 {
3880  union iwreq_data wrqu;
3881  struct wl_private *lp = wl_priv(dev);
3882  int status;
3883  PROBE_RESP data;
3884  hcf_16 length;
3885  hcf_8 *wpa_ie;
3886  /*------------------------------------------------------------------------*/
3887 
3888 
3889  memset( &wrqu, 0, sizeof( wrqu ));
3890 
3891  /* Retrieve the Association Request IE */
3892  lp->ltvRecord.len = 45;
3894 
3895  status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3896  if( status == HCF_SUCCESS )
3897  {
3898  length = 0;
3899  memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3900  wpa_ie = wl_parse_wpa_ie( &data, &length );
3901 
3902  if( length != 0 )
3903  {
3904  wrqu.data.length = wpa_ie[1] + 2;
3906  &wrqu, wpa_ie);
3907 
3908  /* This bit is a hack. We send the respie
3909  * event at the same time */
3911  &wrqu, wpa_ie);
3912  }
3913  }
3914 
3915  return;
3916 } // wl_wext_event_assoc_ie
3917 /*============================================================================*/
3918 /* Structures to export the Wireless Handlers */
3919 
3920 static const iw_handler wl_handler[] =
3921 {
3922  IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
3923  IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
3924  IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
3925  IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
3926  IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
3927  IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
3928  IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
3929  IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
3930  IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
3933 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3934  IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
3935 #endif
3936  IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
3937  IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
3938  IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
3939  IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
3940  IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
3941  IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
3942  IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
3943  IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
3944  IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
3945  IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
3946  IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
3947  IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
3948  IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
3949  IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
3950  IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
3951  IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
3952  IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
3953  IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3954  IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
3955 };
3956 
3957 static const iw_handler wl_private_handler[] =
3958 { /* SIOCIWFIRSTPRIV + */
3959  wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3960  wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3961  wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3962  wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3963 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3964  wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3965  wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3966 #endif
3967 };
3968 
3970  {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3971  {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3972  {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3973  {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3974 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3975  {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3976  {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3977 #endif
3978 };
3979 
3981 {
3982  .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3983  .private = (iw_handler *) wl_private_handler,
3984  .private_args = (struct iw_priv_args *) wl_priv_args,
3985  .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3986  .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3987  .standard = (iw_handler *) wl_handler,
3989 };