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