Merge branches 'misc' and 'powercap'
[deliverable/linux.git] / drivers / staging / wlags49_h2 / wl_wext.c
CommitLineData
68c0bdff
HG
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 *
d36b6910 21 * Copyright © 2003 Agere Systems Inc.
68c0bdff
HG
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 *
d36b6910 42 * THIS SOFTWARE IS PROVIDED \93AS IS\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
68c0bdff
HG
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
68c0bdff
HG
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>
4f19b38f 65#include <linux/etherdevice.h>
68c0bdff
HG
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
05df482e
DK
79/* Set up the LTV to program the appropriate key */
80static 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
05df482e
DK
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
05df482e
DK
156 return ret;
157}
158
159/* Set up the LTV to clear the appropriate key */
160static 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:
4f19b38f 166 if (!is_broadcast_ether_addr(addr)) {
05df482e
DK
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 */
191static 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 }
68c0bdff 259
05df482e
DK
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
290out:
291 return ret;
292}
68c0bdff
HG
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 ******************************************************************************/
312static 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;
68c0bdff
HG
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
335out:
68c0bdff
HG
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 ******************************************************************************/
361static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
362{
68c0bdff
HG
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
68c0bdff
HG
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 ******************************************************************************/
395static 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;
68c0bdff
HG
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;
68c0bdff
HG
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
449out:
68c0bdff
HG
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 ******************************************************************************/
475static 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;
68c0bdff
HG
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
68c0bdff
HG
498 freq->m = wl_get_freq_from_chan( channel ) * 100000;
499 freq->e = 1;
68c0bdff
HG
500 }
501
502 wl_act_int_on( lp );
503
504 wl_unlock(lp, &flags);
505
506 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
507
508out:
68c0bdff
HG
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 ******************************************************************************/
536static 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;
68c0bdff
HG
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
558retry:
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
86f9150c 571 /* Holding the lock too long, makes a gap to allow other processes */
68c0bdff
HG
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
86f9150c 583 /* Holding the lock too long, makes a gap to allow other processes */
68c0bdff
HG
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
86f9150c 596 /* Holding the lock too long, makes a gap to allow other processes */
68c0bdff
HG
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 */
68c0bdff
HG
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 );
68c0bdff
HG
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
86f9150c 659 /* Holding the lock too long, makes a gap to allow other processes */
68c0bdff
HG
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
68c0bdff
HG
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
68c0bdff
HG
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
86f9150c 686 /* Holding the lock too long, makes a gap to allow other processes */
68c0bdff
HG
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
68c0bdff 695 /* Event capability (kernel + driver) */
87063460
DK
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);
68c0bdff
HG
704
705 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
87063460 706 range->scan_capa = IW_SCAN_CAPA_NONE;
68c0bdff
HG
707
708out_unlock:
709 wl_act_int_on( lp );
710
711 wl_unlock(lp, &flags);
712
68c0bdff
HG
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 ******************************************************************************/
737static 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 */
68c0bdff
HG
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
68c0bdff
HG
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
786out:
68c0bdff
HG
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 ******************************************************************************/
817static 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
68c0bdff
HG
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
2b6d83d6
AS
916 DBG_PRINT("BSSID: %pM\n",
917 (*p).ProbeTable[count].BSSID);
68c0bdff
HG
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 }
930out:
68c0bdff
HG
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 ******************************************************************************/
957static 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;
68c0bdff
HG
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
985out:
68c0bdff
HG
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 ******************************************************************************/
1012static 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;
68c0bdff
HG
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 */
1025out:
68c0bdff
HG
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 ******************************************************************************/
1053static 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
68c0bdff
HG
1059 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1060 ret = -EBUSY;
1061 goto out;
1062 }
1063
6b89db36 1064 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN) {
68c0bdff
HG
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
1101out:
68c0bdff
HG
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 ******************************************************************************/
1129static 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;
68c0bdff
HG
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
68c0bdff
HG
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
68c0bdff
HG
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 */
e7751b63 1204 data->length = pName->length;
68c0bdff
HG
1205 data->flags = 1;
1206 } else {
1207 ret = -EFAULT;
1208 goto out_unlock;
1209 }
1210 }
1211
68c0bdff
HG
1212#endif // HCF_STA
1213
68c0bdff
HG
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
1225out_unlock:
1226 wl_act_int_on( lp );
1227
1228 wl_unlock(lp, &flags);
1229
1230out:
68c0bdff
HG
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 ******************************************************************************/
1257static 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;
05df482e
DK
1261 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1262 int ret = 0;
1263 bool enable = true;
68c0bdff 1264
05df482e 1265 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
68c0bdff
HG
1266 ret = -EBUSY;
1267 goto out;
1268 }
1269
05df482e
DK
1270 if (erq->flags & IW_ENCODE_DISABLED)
1271 enable = false;
68c0bdff 1272
05df482e 1273 wl_lock(lp, &flags);
68c0bdff 1274
05df482e 1275 wl_act_int_off(lp);
68c0bdff 1276
05df482e
DK
1277 ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1278 enable, true);
68c0bdff
HG
1279
1280 /* Send an event that Encryption has been set */
05df482e
DK
1281 if (ret == 0)
1282 wl_wext_event_encode(dev);
68c0bdff 1283
05df482e 1284 wl_act_int_on(lp);
68c0bdff
HG
1285
1286 wl_unlock(lp, &flags);
1287
1288out:
68c0bdff 1289 return ret;
05df482e 1290}
68c0bdff
HG
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 ******************************************************************************/
1311static 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;
68c0bdff 1318
68c0bdff
HG
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;
68c0bdff
HG
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
1365out_unlock:
1366
1367 wl_act_int_on( lp );
1368
1369 wl_unlock(lp, &flags);
1370
1371out:
68c0bdff
HG
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 ******************************************************************************/
1398static 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;
68c0bdff
HG
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;
68c0bdff
HG
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
1437out:
68c0bdff
HG
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 ******************************************************************************/
1464static 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;
68c0bdff
HG
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
1508out:
68c0bdff
HG
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 ******************************************************************************/
1535static 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;
68c0bdff
HG
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
1617out:
68c0bdff
HG
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 ******************************************************************************/
1644static 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;
68c0bdff
HG
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
1721out:
68c0bdff
HG
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 ******************************************************************************/
1748static 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;
68c0bdff
HG
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;
68c0bdff
HG
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
1786out:
68c0bdff
HG
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 ******************************************************************************/
1813static 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;
68c0bdff
HG
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
1844out:
68c0bdff
HG
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 ******************************************************************************/
1871static 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;
68c0bdff
HG
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
1900out:
68c0bdff
HG
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 ******************************************************************************/
1927static 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;
68c0bdff
HG
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
68c0bdff
HG
1944 if( rts->disabled ) {
1945 rthr = 2347;
1946 }
68c0bdff
HG
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
1965out:
68c0bdff
HG
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 ******************************************************************************/
1992static 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;
68c0bdff
HG
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
68c0bdff
HG
2009 rts->disabled = ( rts->value == 2347 );
2010
68c0bdff
HG
2011 rts->fixed = 1;
2012
2013 wl_act_int_on( lp );
2014
2015 wl_unlock(lp, &flags);
2016
2017out:
68c0bdff
HG
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 ******************************************************************************/
2045static 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
68c0bdff
HG
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" );
68c0bdff
HG
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
2232out_unlock:
2233
2234 wl_act_int_on( lp );
2235
2236 wl_unlock(lp, &flags);
2237
2238out:
68c0bdff
HG
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 ******************************************************************************/
2265static 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;
68c0bdff
HG
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
2347out:
68c0bdff
HG
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 ******************************************************************************/
2376int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2377{
2378 int ret = 0;
68c0bdff
HG
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
3c319c96 2399 if( ret != 0 )
68c0bdff 2400 return ret;
68c0bdff
HG
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
2407out:
68c0bdff
HG
2408 return ret;
2409} // wireless_get_private_interface
2410/*============================================================================*/
2411#endif
2412
2413
2414
68c0bdff
HG
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 ******************************************************************************/
2434static 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;
68c0bdff 2441
cb154c18 2442 //;? Note: shows results as trace, returns always 0 unless BUSY
68c0bdff 2443
68c0bdff
HG
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
25985edc 2457 * cause is still a mystery. Okay, the communication to the
68c0bdff
HG
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
2466retry:
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
86f9150c 2489 // Holding the lock too long, makes a gap to allow other processes
68c0bdff
HG
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
86f9150c 2500 // Holding the lock too long, makes a gap to allow other processes
68c0bdff
HG
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
86f9150c 2517 // Holding the lock too long, makes a gap to allow other processes
68c0bdff
HG
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
86f9150c 2525 retrieve probe response must always be used to support WPA */
68c0bdff
HG
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
2538out:
68c0bdff
HG
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 ******************************************************************************/
2565static 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;
68c0bdff
HG
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
25b20463
DK
2613 buf = iwe_stream_add_event(info, buf, buf_end,
2614 &iwe, IW_EV_ADDR_LEN);
68c0bdff
HG
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
25b20463
DK
2630 buf = iwe_stream_add_event(info, buf, buf_end,
2631 &iwe, IW_EV_UINT_LEN);
68c0bdff
HG
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;
e81589a7 2640 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
68c0bdff
HG
2641 iwe.len = IW_EV_QUAL_LEN;
2642
25b20463
DK
2643 buf = iwe_stream_add_event(info, buf, buf_end,
2644 &iwe, IW_EV_QUAL_LEN);
68c0bdff
HG
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
25b20463
DK
2655 buf = iwe_stream_add_point(info, buf, buf_end,
2656 &iwe, &probe_resp->rawData[2]);
68c0bdff
HG
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
25b20463 2674 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
68c0bdff
HG
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
25b20463
DK
2685 buf = iwe_stream_add_event(info, buf, buf_end,
2686 &iwe, IW_EV_FREQ_LEN);
68c0bdff
HG
2687
2688
68c0bdff
HG
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
25b20463 2697 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
68c0bdff
HG
2698
2699
68da1056 2700 /* WPA-IE */
68c0bdff
HG
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 ) {
68da1056 2706 memset(&iwe, 0, sizeof(iwe));
68c0bdff 2707
68da1056
DK
2708 iwe.cmd = IWEVGENIE;
2709 iwe.u.data.length = wpa_ie_len;
68c0bdff 2710
25b20463 2711 buf = iwe_stream_add_point(info, buf, buf_end,
68da1056 2712 &iwe, wpa_ie);
68c0bdff
HG
2713 }
2714
2715 /* Add other custom info in formatted string format as needed... */
68c0bdff
HG
2716 }
2717
2718 data->length = buf - extra;
2719
2720out_unlock:
2721
2722 wl_act_int_on( lp );
2723
2724 wl_unlock(lp, &flags);
2725
2726out:
68c0bdff
HG
2727 return ret;
2728} // wireless_get_scan
2729/*============================================================================*/
2730
9ef02300
DK
2731#if DBG
2732static 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
68c0bdff 2749
68c0bdff
HG
2750static 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;
9ef02300
DK
2756 ltv_t ltv;
2757 int ret;
2758 int iwa_idx = data->flags & IW_AUTH_INDEX;
2759 int iwa_val = data->value;
68c0bdff 2760
9ef02300 2761 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
68c0bdff
HG
2762 ret = -EBUSY;
2763 goto out;
2764 }
2765
2766 wl_lock( lp, &flags );
2767
2768 wl_act_int_off( lp );
2769
9ef02300
DK
2770 if (iwa_idx > IW_AUTH_MFP)
2771 iwa_idx = IW_AUTH_MFP + 1;
2772 DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
68c0bdff 2773 switch (iwa_idx) {
9ef02300
DK
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))
68c0bdff 2778 ret = 0;
9ef02300
DK
2779 else
2780 ret = -EINVAL;
2781 break;
68c0bdff 2782
9ef02300
DK
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;
68c0bdff 2789
9ef02300
DK
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);
68c0bdff 2795
9ef02300 2796 break;
68c0bdff 2797
9ef02300 2798 case IW_AUTH_TKIP_COUNTERMEASURES:
68c0bdff 2799
9ef02300
DK
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;
68c0bdff 2808
9ef02300
DK
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)
68c0bdff 2814 ret = -EINVAL;
9ef02300
DK
2815 else
2816 ret = 0;
2817 break;
68c0bdff 2818
9ef02300 2819 case IW_AUTH_KEY_MGMT:
68c0bdff 2820
9ef02300
DK
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;
68c0bdff 2827
9ef02300
DK
2828 ret = -EINPROGRESS;
2829 break;
68c0bdff 2830
9ef02300
DK
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
68c0bdff 2842 ret = -EINVAL;
9ef02300
DK
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;
68c0bdff
HG
2866 }
2867
2868 wl_act_int_on( lp );
2869
2870 wl_unlock(lp, &flags);
2871
2872out:
68c0bdff
HG
2873 return ret;
2874} // wireless_set_auth
2875/*============================================================================*/
2876
2877
05df482e 2878static void flush_tx(struct wl_private *lp)
68c0bdff 2879{
05df482e
DK
2880 ltv_t ltv;
2881 int count;
68c0bdff
HG
2882
2883 /*
05df482e
DK
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
86f9150c 2887 * and cause synchronization errors with the AP
05df482e
DK
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 }
68c0bdff 2902
05df482e
DK
2903 if (count >= 100)
2904 DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
68c0bdff 2905
05df482e 2906}
68c0bdff 2907
05df482e
DK
2908static 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;
68c0bdff 2920
05df482e
DK
2921 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2922 ret = -EBUSY;
2923 goto out;
2924 }
68c0bdff 2925
05df482e
DK
2926 if (erq->flags & IW_ENCODE_DISABLED) {
2927 ext->alg = IW_ENCODE_ALG_NONE;
2928 enable = false;
2929 }
68c0bdff 2930
05df482e
DK
2931 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2932 set_tx = true;
68c0bdff 2933
05df482e 2934 wl_lock(lp, &flags);
68c0bdff 2935
05df482e 2936 wl_act_int_off(lp);
68c0bdff 2937
05df482e 2938 memset(&ltv, 0, sizeof(ltv));
68c0bdff 2939
05df482e
DK
2940 switch (ext->alg) {
2941 case IW_ENCODE_ALG_TKIP:
2942 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
68c0bdff 2943
05df482e
DK
2944 if (sizeof(ext->rx_seq) != 8) {
2945 DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
05df482e
DK
2946 ret = -EINVAL;
2947 goto out_unlock;
2948 }
68c0bdff 2949
05df482e
DK
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);
68c0bdff 2953
05df482e
DK
2954 if (ret != 0) {
2955 DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
2956 goto out_unlock;
2957 }
68c0bdff 2958
05df482e 2959 flush_tx(lp);
68c0bdff 2960
05df482e 2961 lp->wext_enc = IW_ENCODE_ALG_TKIP;
68c0bdff 2962
05df482e
DK
2963 /* Write the key */
2964 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
2965 break;
68c0bdff 2966
05df482e
DK
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;
68c0bdff
HG
2974 }
2975
05df482e
DK
2976 ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
2977 enable, set_tx);
68c0bdff 2978
68c0bdff
HG
2979 break;
2980
2981 case IW_ENCODE_ALG_CCMP:
05df482e
DK
2982 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
2983 ret = -EOPNOTSUPP;
68c0bdff
HG
2984 break;
2985
2986 case IW_ENCODE_ALG_NONE:
05df482e
DK
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 {
68c0bdff 3001 ret = 0;
68c0bdff 3002 }
05df482e 3003
68c0bdff 3004 break;
05df482e 3005
68c0bdff
HG
3006 default:
3007 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
05df482e 3008 ret = -EOPNOTSUPP;
68c0bdff
HG
3009 break;
3010 }
3011
68c0bdff 3012out_unlock:
68c0bdff 3013
05df482e 3014 wl_act_int_on(lp);
68c0bdff
HG
3015
3016 wl_unlock(lp, &flags);
3017
3018out:
68c0bdff 3019 return ret;
05df482e 3020}
68c0bdff
HG
3021/*============================================================================*/
3022
3023
3024
729336b3
DK
3025static int wireless_set_genie(struct net_device *dev,
3026 struct iw_request_info *info,
3027 struct iw_point *data, char *extra)
68c0bdff
HG
3028
3029{
68c0bdff 3030 int ret = 0;
68c0bdff 3031
729336b3
DK
3032 /* We can't write this to the card, but apparently this
3033 * operation needs to succeed */
3034 ret = 0;
68c0bdff 3035
68c0bdff
HG
3036 return ret;
3037}
3038/*============================================================================*/
3039
3040
68c0bdff
HG
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 ******************************************************************************/
3060struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3061{
3062 struct iw_statistics *pStats;
3063 struct wl_private *lp = wl_priv(dev);
68c0bdff 3064
68c0bdff
HG
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;
68c0bdff
HG
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
68c0bdff
HG
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 ));
e81589a7
HG
3093
3094 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3095 IW_QUAL_LEVEL_UPDATED |
3096 IW_QUAL_NOISE_UPDATED |
3097 IW_QUAL_DBM);
68c0bdff
HG
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
68c0bdff
HG
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 ******************************************************************************/
3153struct 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;
68c0bdff
HG
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
68c0bdff
HG
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 ******************************************************************************/
3198inline 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
e81589a7
HG
3228 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3229 IW_QUAL_LEVEL_UPDATED |
3230 IW_QUAL_NOISE_UPDATED |
3231 IW_QUAL_DBM);
68c0bdff
HG
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 ******************************************************************************/
3260void wl_wext_event_freq( struct net_device *dev )
3261{
68c0bdff
HG
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 );
68c0bdff
HG
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 ******************************************************************************/
3300void wl_wext_event_mode( struct net_device *dev )
3301{
68c0bdff
HG
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 );
68c0bdff
HG
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 ******************************************************************************/
3343void wl_wext_event_essid( struct net_device *dev )
3344{
68c0bdff
HG
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 );
68c0bdff
HG
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 ******************************************************************************/
3388void wl_wext_event_encode( struct net_device *dev )
3389{
68c0bdff
HG
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 );
68c0bdff
HG
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 ******************************************************************************/
3458void wl_wext_event_ap( struct net_device *dev )
3459{
68c0bdff
HG
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
86f9150c 3470 is required for a proper processed frame. */
68c0bdff
HG
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
68c0bdff
HG
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 ******************************************************************************/
3513void wl_wext_event_scan_complete( struct net_device *dev )
3514{
68c0bdff
HG
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 );
68c0bdff
HG
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 ******************************************************************************/
3550void wl_wext_event_new_sta( struct net_device *dev )
3551{
68c0bdff
HG
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 );
68c0bdff
HG
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 ******************************************************************************/
3589void wl_wext_event_expired_sta( struct net_device *dev )
3590{
68c0bdff
HG
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 );
68c0bdff
HG
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 ******************************************************************************/
3626void wl_wext_event_mic_failed( struct net_device *dev )
3627{
68c0bdff
HG
3628 union iwreq_data wrqu;
3629 struct wl_private *lp = wl_priv(dev);
a4f7b2e8 3630 struct iw_michaelmicfailure wxmic;
68c0bdff
HG
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
a4f7b2e8
DK
3652 memset(&wrqu, 0, sizeof(wrqu));
3653 memset(&wxmic, 0, sizeof(wxmic));
68c0bdff 3654
a4f7b2e8
DK
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);
68c0bdff 3660
a4f7b2e8
DK
3661 wrqu.data.length = sizeof(wxmic);
3662 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
68c0bdff
HG
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 ******************************************************************************/
3690void wl_wext_event_assoc_ie( struct net_device *dev )
3691{
68c0bdff
HG
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 ));
68c0bdff
HG
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
68c0bdff
HG
3714 if( length != 0 )
3715 {
a4f7b2e8
DK
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);
68c0bdff
HG
3724 }
3725 }
68c0bdff
HG
3726
3727 return;
3728} // wl_wext_event_assoc_ie
3729/*============================================================================*/
3730/* Structures to export the Wireless Handlers */
3731
3732static const iw_handler wl_handler[] =
3733{
bc79be9b
DK
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),
68c0bdff 3745#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
bc79be9b 3746 IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
68c0bdff 3747#endif
bc79be9b
DK
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),
729336b3 3764 IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
bc79be9b
DK
3765 IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3766 IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
68c0bdff
HG
3767};
3768
3769static 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
3781struct 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
3792const 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};
This page took 0.522626 seconds and 5 git commands to generate.