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