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