NET: nl80211, fix lock imbalance and netdev referencing
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / wlags49_h2 / wl_wext.c
blob4434e006548847df1c0cee808edce7439312fb0a
1 /*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
14 * SOFTWARE LICENSE
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.
21 * Copyright © 2003 Agere Systems Inc.
22 * All rights reserved.
24 * Redistribution and use in source or binary forms, with or without
25 * modifications, are permitted provided that the following conditions are met:
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.
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.
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.
40 * Disclaimer
42 * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
43 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
45 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
46 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53 * DAMAGE.
55 ******************************************************************************/
57 /*******************************************************************************
58 * include files
59 ******************************************************************************/
60 #include <wl_version.h>
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <asm/uaccess.h>
67 #include <debug.h>
68 #include <hcf.h>
69 #include <hcfdef.h>
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>
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
85 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
86 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
87 iwe_stream_add_event(buf, end, iwe, len)
88 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
89 iwe_stream_add_point(buf, end, iwe, msg)
90 #else
91 #define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \
92 iwe_stream_add_event(info, buf, end, iwe, len)
93 #define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \
94 iwe_stream_add_point(info, buf, end, iwe, msg)
95 #endif
99 /*******************************************************************************
100 * global definitions
101 ******************************************************************************/
102 #if DBG
103 extern dbg_info_t *DbgInfo;
104 #endif // DBG
109 /*******************************************************************************
110 * wireless_commit()
111 *******************************************************************************
113 * DESCRIPTION:
115 * Commit
116 * protocol used.
118 * PARAMETERS:
120 * wrq - the wireless request buffer
122 * RETURNS:
124 * N/A
126 ******************************************************************************/
127 static int wireless_commit(struct net_device *dev,
128 struct iw_request_info *info,
129 union iwreq_data *rqu, char *extra)
131 struct wl_private *lp = wl_priv(dev);
132 unsigned long flags;
133 int ret = 0;
134 /*------------------------------------------------------------------------*/
136 DBG_FUNC( "wireless_commit" );
137 DBG_ENTER(DbgInfo);
139 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
140 ret = -EBUSY;
141 goto out;
144 wl_lock( lp, &flags );
146 wl_act_int_off( lp );
148 wl_apply(lp);
150 wl_act_int_on( lp );
152 wl_unlock(lp, &flags);
154 out:
155 DBG_LEAVE( DbgInfo );
156 return ret;
157 } // wireless_commit
158 /*============================================================================*/
163 /*******************************************************************************
164 * wireless_get_protocol()
165 *******************************************************************************
167 * DESCRIPTION:
169 * Returns a vendor-defined string that should identify the wireless
170 * protocol used.
172 * PARAMETERS:
174 * wrq - the wireless request buffer
176 * RETURNS:
178 * N/A
180 ******************************************************************************/
181 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
183 DBG_FUNC( "wireless_get_protocol" );
184 DBG_ENTER( DbgInfo );
186 /* Originally, the driver was placing the string "Wireless" here. However,
187 the wireless extensions (/linux/wireless.h) indicate this string should
188 describe the wireless protocol. */
190 strcpy(name, "IEEE 802.11b");
192 DBG_LEAVE(DbgInfo);
193 return 0;
194 } // wireless_get_protocol
195 /*============================================================================*/
200 /*******************************************************************************
201 * wireless_set_frequency()
202 *******************************************************************************
204 * DESCRIPTION:
206 * Sets the frequency (channel) on which the card should Tx/Rx.
208 * PARAMETERS:
210 * wrq - the wireless request buffer
211 * lp - the device's private adapter structure
213 * RETURNS:
215 * 0 on success
216 * errno value otherwise
218 ******************************************************************************/
219 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
221 struct wl_private *lp = wl_priv(dev);
222 unsigned long flags;
223 int channel = 0;
224 int ret = 0;
225 /*------------------------------------------------------------------------*/
228 DBG_FUNC( "wireless_set_frequency" );
229 DBG_ENTER( DbgInfo );
231 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
232 ret = -EBUSY;
233 goto out;
236 if( !capable( CAP_NET_ADMIN )) {
237 ret = -EPERM;
238 DBG_LEAVE( DbgInfo );
239 return ret;
243 /* If frequency specified, look up channel */
244 if( freq->e == 1 ) {
245 int f = freq->m / 100000;
246 channel = wl_get_chan_from_freq( f );
250 /* Channel specified */
251 if( freq->e == 0 ) {
252 channel = freq->m;
256 /* If the channel is an 802.11a channel, set Bit 8 */
257 if( channel > 14 ) {
258 channel = channel | 0x100;
262 wl_lock( lp, &flags );
264 wl_act_int_off( lp );
266 lp->Channel = channel;
269 /* Commit the adapter parameters */
270 wl_apply( lp );
272 /* Send an event that channel/freq has been set */
273 wl_wext_event_freq( lp->dev );
275 wl_act_int_on( lp );
277 wl_unlock(lp, &flags);
279 out:
280 DBG_LEAVE( DbgInfo );
281 return ret;
282 } // wireless_set_frequency
283 /*============================================================================*/
288 /*******************************************************************************
289 * wireless_get_frequency()
290 *******************************************************************************
292 * DESCRIPTION:
294 * Gets the frequency (channel) on which the card is Tx/Rx.
296 * PARAMETERS:
298 * wrq - the wireless request buffer
299 * lp - the device's private adapter structure
301 * RETURNS:
303 * N/A
305 ******************************************************************************/
306 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
309 struct wl_private *lp = wl_priv(dev);
310 unsigned long flags;
311 int ret = -1;
312 /*------------------------------------------------------------------------*/
315 DBG_FUNC( "wireless_get_frequency" );
316 DBG_ENTER( DbgInfo );
318 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
319 ret = -EBUSY;
320 goto out;
323 wl_lock( lp, &flags );
325 wl_act_int_off( lp );
327 lp->ltvRecord.len = 2;
328 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
330 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
331 if( ret == HCF_SUCCESS ) {
332 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
334 #ifdef USE_FREQUENCY
336 freq->m = wl_get_freq_from_chan( channel ) * 100000;
337 freq->e = 1;
338 #else
340 freq->m = channel;
341 freq->e = 0;
343 #endif /* USE_FREQUENCY */
346 wl_act_int_on( lp );
348 wl_unlock(lp, &flags);
350 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
352 out:
353 DBG_LEAVE( DbgInfo );
354 return ret;
355 } // wireless_get_frequency
356 /*============================================================================*/
361 /*******************************************************************************
362 * wireless_get_range()
363 *******************************************************************************
365 * DESCRIPTION:
367 * This function is used to provide misc info and statistics about the
368 * wireless device.
370 * PARAMETERS:
372 * wrq - the wireless request buffer
373 * lp - the device's private adapter structure
375 * RETURNS:
377 * 0 on success
378 * errno value otherwise
380 ******************************************************************************/
381 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
383 struct wl_private *lp = wl_priv(dev);
384 unsigned long flags;
385 struct iw_range *range = (struct iw_range *) extra;
386 int ret = 0;
387 int status = -1;
388 int count;
389 __u16 *pTxRate;
390 int retries = 0;
391 /*------------------------------------------------------------------------*/
394 DBG_FUNC( "wireless_get_range" );
395 DBG_ENTER( DbgInfo );
397 /* Set range information */
398 data->length = sizeof(struct iw_range);
399 memset(range, 0, sizeof(struct iw_range));
401 wl_lock( lp, &flags );
403 wl_act_int_off( lp );
405 /* Set range information */
406 memset( range, 0, sizeof( struct iw_range ));
408 retry:
409 /* Get the current transmit rate from the adapter */
410 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
411 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
413 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
414 if( status != HCF_SUCCESS ) {
415 /* Recovery action: reset and retry up to 10 times */
416 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
418 if (retries < 10) {
419 retries++;
421 /* Holding the lock too long, make a gap to allow other processes */
422 wl_unlock(lp, &flags);
423 wl_lock( lp, &flags );
425 status = wl_reset( dev );
426 if ( status != HCF_SUCCESS ) {
427 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
429 ret = -EFAULT;
430 goto out_unlock;
433 /* Holding the lock too long, make a gap to allow other processes */
434 wl_unlock(lp, &flags);
435 wl_lock( lp, &flags );
437 goto retry;
439 } else {
440 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
441 ret = -EFAULT;
442 goto out_unlock;
446 /* Holding the lock too long, make a gap to allow other processes */
447 wl_unlock(lp, &flags);
448 wl_lock( lp, &flags );
450 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
452 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
454 if (retries > 0) {
455 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
458 // NWID - NOT SUPPORTED
461 /* Channel/Frequency Info */
462 range->num_channels = RADIO_CHANNELS;
465 /* Signal Level Thresholds */
466 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
469 /* Link quality */
470 #ifdef USE_DBM
472 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
474 /* If the value returned in /proc/net/wireless is greater than the maximum range,
475 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
476 it requires a bit of contorsion... */
478 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
479 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
480 #else
482 range->max_qual.qual = 100;
483 range->max_qual.level = 100;
484 range->max_qual.noise = 100;
486 #endif /* USE_DBM */
489 /* Set available rates */
490 range->num_bitrates = 0;
492 lp->ltvRecord.len = 6;
493 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
495 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
496 if( status == HCF_SUCCESS ) {
497 for( count = 0; count < MAX_RATES; count++ )
498 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
499 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
500 range->num_bitrates++;
502 } else {
503 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
504 ret = -EFAULT;
505 goto out_unlock;
508 /* RTS Threshold info */
509 range->min_rts = MIN_RTS_BYTES;
510 range->max_rts = MAX_RTS_BYTES;
512 // Frag Threshold info - NOT SUPPORTED
514 // Power Management info - NOT SUPPORTED
516 /* Encryption */
518 #if WIRELESS_EXT > 8
520 /* Holding the lock too long, make a gap to allow other processes */
521 wl_unlock(lp, &flags);
522 wl_lock( lp, &flags );
524 /* Is WEP supported? */
526 if( wl_has_wep( &( lp->hcfCtx ))) {
527 /* WEP: RC4 40 bits */
528 range->encoding_size[0] = MIN_KEY_SIZE;
530 /* RC4 ~128 bits */
531 range->encoding_size[1] = MAX_KEY_SIZE;
532 range->num_encoding_sizes = 2;
533 range->max_encoding_tokens = MAX_KEYS;
536 #endif /* WIRELESS_EXT > 8 */
538 /* Tx Power Info */
539 range->txpower_capa = IW_TXPOW_MWATT;
540 range->num_txpower = 1;
541 range->txpower[0] = RADIO_TX_POWER_MWATT;
543 #if WIRELESS_EXT > 10
545 /* Wireless Extension Info */
546 range->we_version_compiled = WIRELESS_EXT;
547 range->we_version_source = WIRELESS_SUPPORT;
549 // Retry Limits and Lifetime - NOT SUPPORTED
551 #endif
554 #if WIRELESS_EXT > 11
556 /* Holding the lock too long, make a gap to allow other processes */
557 wl_unlock(lp, &flags);
558 wl_lock( lp, &flags );
560 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
561 wl_wireless_stats( lp->dev );
562 range->avg_qual = lp->wstats.qual;
563 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
565 #endif
567 /* Event capability (kernel + driver) */
568 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
569 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
570 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
571 range->event_capa[1] = IW_EVENT_CAPA_K_1;
572 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
573 IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
574 IW_EVENT_CAPA_MASK(IWEVEXPIRED));
576 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
578 out_unlock:
579 wl_act_int_on( lp );
581 wl_unlock(lp, &flags);
583 DBG_LEAVE(DbgInfo);
584 return ret;
585 } // wireless_get_range
586 /*============================================================================*/
589 /*******************************************************************************
590 * wireless_get_bssid()
591 *******************************************************************************
593 * DESCRIPTION:
595 * Gets the BSSID the wireless device is currently associated with.
597 * PARAMETERS:
599 * wrq - the wireless request buffer
600 * lp - the device's private adapter structure
602 * RETURNS:
604 * 0 on success
605 * errno value otherwise
607 ******************************************************************************/
608 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
610 struct wl_private *lp = wl_priv(dev);
611 unsigned long flags;
612 int ret = 0;
613 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
614 int status = -1;
615 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
616 /*------------------------------------------------------------------------*/
619 DBG_FUNC( "wireless_get_bssid" );
620 DBG_ENTER( DbgInfo );
622 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
623 ret = -EBUSY;
624 goto out;
627 wl_lock( lp, &flags );
629 wl_act_int_off( lp );
631 memset( &ap_addr->sa_data, 0, ETH_ALEN );
633 ap_addr->sa_family = ARPHRD_ETHER;
635 /* Assume AP mode here, which means the BSSID is our own MAC address. In
636 STA mode, this address will be overwritten with the actual BSSID using
637 the code below. */
638 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
641 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
642 //;?should we return an error status in AP mode
644 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
645 /* Get Current BSSID */
646 lp->ltvRecord.typ = CFG_CUR_BSSID;
647 lp->ltvRecord.len = 4;
648 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
650 if( status == HCF_SUCCESS ) {
651 /* Copy info into sockaddr struct */
652 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
653 } else {
654 ret = -EFAULT;
658 #endif // (HCF_TYPE) & HCF_TYPE_STA
660 wl_act_int_on( lp );
662 wl_unlock(lp, &flags);
664 out:
665 DBG_LEAVE(DbgInfo);
666 return ret;
667 } // wireless_get_bssid
668 /*============================================================================*/
673 /*******************************************************************************
674 * wireless_get_ap_list()
675 *******************************************************************************
677 * DESCRIPTION:
679 * Gets the results of a network scan.
681 * PARAMETERS:
683 * wrq - the wireless request buffer
684 * lp - the device's private adapter structure
686 * RETURNS:
688 * 0 on success
689 * errno value otherwise
691 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
692 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
693 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
695 ******************************************************************************/
696 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
698 struct wl_private *lp = wl_priv(dev);
699 unsigned long flags;
700 int ret;
701 int num_aps = -1;
702 int sec_count = 0;
703 hcf_32 count;
704 struct sockaddr *hwa = NULL;
705 struct iw_quality *qual = NULL;
706 #ifdef WARP
707 ScanResult *p = &lp->scan_results;
708 #else
709 ProbeResult *p = &lp->probe_results;
710 #endif // WARP
711 /*------------------------------------------------------------------------*/
713 DBG_FUNC( "wireless_get_ap_list" );
714 DBG_ENTER( DbgInfo );
716 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
717 ret = -EBUSY;
718 goto out;
721 wl_lock( lp, &flags );
723 wl_act_int_off( lp );
725 /* Set the completion state to FALSE */
726 lp->scan_results.scan_complete = FALSE;
727 lp->probe_results.scan_complete = FALSE;
728 /* Channels to scan */
729 lp->ltvRecord.len = 2;
730 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
731 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
732 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
733 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
735 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
736 disassociate from the network we are currently on */
737 lp->ltvRecord.len = 2;
738 lp->ltvRecord.typ = CFG_SCAN_SSID;
739 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
740 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
741 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
743 /* Initiate the scan */
744 #ifdef WARP
745 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
746 #else
747 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
748 #endif // WARP
750 wl_act_int_on( lp );
752 //;? unlock? what about the access to lp below? is it broken?
753 wl_unlock(lp, &flags);
755 if( ret == HCF_SUCCESS ) {
756 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
757 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
758 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
759 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
760 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
761 ret = -EIO;
762 } else {
763 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
764 other things in the meantime, This prevents system lockups by
765 giving some time back to the kernel */
766 for( count = 0; count < 100; count ++ ) {
767 mdelay( 10 );
768 schedule( );
773 rmb();
775 if ( ret != HCF_SUCCESS ) {
776 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
777 } else {
778 num_aps = (*p)/*lp->probe_results*/.num_aps;
779 if (num_aps > IW_MAX_AP) {
780 num_aps = IW_MAX_AP;
782 data->length = num_aps;
783 hwa = (struct sockaddr *)extra;
784 qual = (struct iw_quality *) extra +
785 ( sizeof( struct sockaddr ) * num_aps );
787 /* This flag is used to tell the user if we provide quality
788 information. Since we provide signal/noise levels but no
789 quality info on a scan, this is set to 0. Setting to 1 and
790 providing a quality of 0 produces weird results. If we ever
791 provide quality (or can calculate it), this can be changed */
792 data->flags = 0;
794 for( count = 0; count < num_aps; count++ ) {
795 #ifdef WARP
796 memcpy( hwa[count].sa_data,
797 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
798 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
799 DBG_PRINT( "BSSID: %s\n", DbgHwAddr( (*p)/*lp->probe_results*/.ProbeTable[count].BSSID ));
800 memcpy( hwa[count].sa_data,
801 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
802 #endif // WARP
804 /* Once the data is copied to the wireless struct, invalidate the
805 scan result to initiate a rescan on the next request */
806 (*p)/*lp->probe_results*/.scan_complete = FALSE;
807 /* Send the wireless event that the scan has completed, just in case
808 it's needed */
809 wl_wext_event_scan_complete( lp->dev );
812 out:
813 DBG_LEAVE( DbgInfo );
814 return ret;
815 } // wireless_get_ap_list
816 /*============================================================================*/
821 /*******************************************************************************
822 * wireless_set_sensitivity()
823 *******************************************************************************
825 * DESCRIPTION:
827 * Sets the sensitivity (distance between APs) of the wireless card.
829 * PARAMETERS:
831 * wrq - the wireless request buffer
832 * lp - the device's private adapter structure
834 * RETURNS:
836 * 0 on success
837 * errno value otherwise
839 ******************************************************************************/
840 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
842 struct wl_private *lp = wl_priv(dev);
843 unsigned long flags;
844 int ret = 0;
845 int dens = sens->value;
846 /*------------------------------------------------------------------------*/
849 DBG_FUNC( "wireless_set_sensitivity" );
850 DBG_ENTER( DbgInfo );
852 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
853 ret = -EBUSY;
854 goto out;
857 if(( dens < 1 ) || ( dens > 3 )) {
858 ret = -EINVAL;
859 goto out;
862 wl_lock( lp, &flags );
864 wl_act_int_off( lp );
866 lp->DistanceBetweenAPs = dens;
867 wl_apply( lp );
869 wl_act_int_on( lp );
871 wl_unlock(lp, &flags);
873 out:
874 DBG_LEAVE( DbgInfo );
875 return ret;
876 } // wireless_set_sensitivity
877 /*============================================================================*/
882 /*******************************************************************************
883 * wireless_get_sensitivity()
884 *******************************************************************************
886 * DESCRIPTION:
888 * Gets the sensitivity (distance between APs) of the wireless card.
890 * PARAMETERS:
892 * wrq - the wireless request buffer
893 * lp - the device's private adapter structure
895 * RETURNS:
897 * 0 on success
898 * errno value otherwise
900 ******************************************************************************/
901 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
903 struct wl_private *lp = wl_priv(dev);
904 int ret = 0;
905 /*------------------------------------------------------------------------*/
906 /*------------------------------------------------------------------------*/
909 DBG_FUNC( "wireless_get_sensitivity" );
910 DBG_ENTER( DbgInfo );
912 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
913 ret = -EBUSY;
914 goto out;
917 /* not worth locking ... */
918 sens->value = lp->DistanceBetweenAPs;
919 sens->fixed = 0; /* auto */
920 out:
921 DBG_LEAVE( DbgInfo );
922 return ret;
923 } // wireless_get_sensitivity
924 /*============================================================================*/
929 /*******************************************************************************
930 * wireless_set_essid()
931 *******************************************************************************
933 * DESCRIPTION:
935 * Sets the ESSID (network name) that the wireless device should associate
936 * with.
938 * PARAMETERS:
940 * wrq - the wireless request buffer
941 * lp - the device's private adapter structure
943 * RETURNS:
945 * 0 on success
946 * errno value otherwise
948 ******************************************************************************/
949 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
951 struct wl_private *lp = wl_priv(dev);
952 unsigned long flags;
953 int ret = 0;
955 DBG_FUNC( "wireless_set_essid" );
956 DBG_ENTER( DbgInfo );
958 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
959 ret = -EBUSY;
960 goto out;
963 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
964 ret = -EINVAL;
965 goto out;
968 wl_lock( lp, &flags );
970 wl_act_int_off( lp );
972 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
974 /* data->flags is zero to ask for "any" */
975 if( data->flags == 0 ) {
976 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
977 * ;?but there ain't no STAP anymore*/
978 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
979 strcpy( lp->NetworkName, "ANY" );
980 } else {
981 //strcpy( lp->NetworkName, "ANY" );
982 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
984 } else {
985 memcpy( lp->NetworkName, ssid, data->length );
988 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
990 /* Commit the adapter parameters */
991 wl_apply( lp );
993 /* Send an event that ESSID has been set */
994 wl_wext_event_essid( lp->dev );
996 wl_act_int_on( lp );
998 wl_unlock(lp, &flags);
1000 out:
1001 DBG_LEAVE( DbgInfo );
1002 return ret;
1003 } // wireless_set_essid
1004 /*============================================================================*/
1009 /*******************************************************************************
1010 * wireless_get_essid()
1011 *******************************************************************************
1013 * DESCRIPTION:
1015 * Gets the ESSID (network name) that the wireless device is associated
1016 * with.
1018 * PARAMETERS:
1020 * wrq - the wireless request buffer
1021 * lp - the device's private adapter structure
1023 * RETURNS:
1025 * 0 on success
1026 * errno value otherwise
1028 ******************************************************************************/
1029 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1032 struct wl_private *lp = wl_priv(dev);
1033 unsigned long flags;
1034 int ret = 0;
1035 int status = -1;
1036 wvName_t *pName;
1037 /*------------------------------------------------------------------------*/
1040 DBG_FUNC( "wireless_get_essid" );
1041 DBG_ENTER( DbgInfo );
1043 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1044 ret = -EBUSY;
1045 goto out;
1048 wl_lock( lp, &flags );
1050 wl_act_int_off( lp );
1052 /* Get the desired network name */
1053 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1056 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1057 //;?should we return an error status in AP mode
1059 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1061 #endif
1064 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1065 //;?should we restore this to allow smaller memory footprint
1067 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1068 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1071 #endif // HCF_AP
1074 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1075 if( status == HCF_SUCCESS ) {
1076 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1078 /* Endian translate the string length */
1079 pName->length = CNV_LITTLE_TO_INT( pName->length );
1081 /* Copy the information into the user buffer */
1082 data->length = pName->length;
1084 /* NOTE: Null terminating is necessary for proper display of the SSID in
1085 the wireless tools */
1086 data->length = pName->length + 1;
1087 if( pName->length < HCF_MAX_NAME_LEN ) {
1088 pName->name[pName->length] = '\0';
1091 data->flags = 1;
1094 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1095 //;?should we return an error status in AP mode
1096 #ifdef RETURN_CURRENT_NETWORKNAME
1098 /* if desired is null ("any"), return current or "any" */
1099 if( pName->name[0] == '\0' ) {
1100 /* Get the current network name */
1101 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1102 lp->ltvRecord.typ = CFG_CUR_SSID;
1104 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1106 if( status == HCF_SUCCESS ) {
1107 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1109 /* Endian translate the string length */
1110 pName->length = CNV_LITTLE_TO_INT( pName->length );
1112 /* Copy the information into the user buffer */
1113 data->length = pName->length + 1;
1114 if( pName->length < HCF_MAX_NAME_LEN ) {
1115 pName->name[pName->length] = '\0';
1118 data->flags = 1;
1119 } else {
1120 ret = -EFAULT;
1121 goto out_unlock;
1125 #endif // RETURN_CURRENT_NETWORKNAME
1126 #endif // HCF_STA
1128 data->length--;
1130 if (pName->length > IW_ESSID_MAX_SIZE) {
1131 ret = -EFAULT;
1132 goto out_unlock;
1135 memcpy(essid, pName->name, pName->length);
1136 } else {
1137 ret = -EFAULT;
1138 goto out_unlock;
1141 out_unlock:
1142 wl_act_int_on( lp );
1144 wl_unlock(lp, &flags);
1146 out:
1147 DBG_LEAVE( DbgInfo );
1148 return ret;
1149 } // wireless_get_essid
1150 /*============================================================================*/
1155 /*******************************************************************************
1156 * wireless_set_encode()
1157 *******************************************************************************
1159 * DESCRIPTION:
1161 * Sets the encryption keys and status (enable or disable).
1163 * PARAMETERS:
1165 * wrq - the wireless request buffer
1166 * lp - the device's private adapter structure
1168 * RETURNS:
1170 * 0 on success
1171 * errno value otherwise
1173 ******************************************************************************/
1174 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1176 struct wl_private *lp = wl_priv(dev);
1177 unsigned long flags;
1178 int ret = 0;
1180 #if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code...
1181 hcf_8 encryption_state;
1182 #endif // WIRELESS_EXT > 8
1183 /*------------------------------------------------------------------------*/
1186 DBG_FUNC( "wireless_set_encode" );
1187 DBG_ENTER( DbgInfo );
1189 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1190 ret = -EBUSY;
1191 goto out;
1194 wl_lock( lp, &flags );
1196 wl_act_int_off( lp );
1198 /* Is encryption supported? */
1199 if( !wl_has_wep( &( lp->hcfCtx ))) {
1200 DBG_WARNING( DbgInfo, "WEP not supported on this device\n" );
1201 ret = -EOPNOTSUPP;
1202 goto out_unlock;
1205 DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n",
1206 keybuf, erq->length,
1207 erq->flags);
1209 /* Save state of Encryption switch */
1210 encryption_state = lp->EnableEncryption;
1212 /* Basic checking: do we have a key to set? */
1213 if((erq->length) != 0) {
1214 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1215 int tk = lp->TransmitKeyID - 1; // current key
1218 /* Check the size of the key */
1219 switch(erq->length) {
1220 case 0:
1221 break;
1223 case MIN_KEY_SIZE:
1224 case MAX_KEY_SIZE:
1226 /* Check the index */
1227 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1228 index = tk;
1231 /* Cleanup */
1232 memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE );
1234 /* Copy the key in the driver */
1235 memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length);
1237 /* Set the length */
1238 lp->DefaultKeys.key[index].len = erq->length;
1240 DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length );
1241 DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key,
1242 lp->DefaultKeys.key[index].len, index );
1244 /* Enable WEP (if possible) */
1245 if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) {
1246 lp->EnableEncryption = 1;
1249 break;
1251 default:
1252 DBG_WARNING( DbgInfo, "Invalid Key length\n" );
1253 ret = -EINVAL;
1254 goto out_unlock;
1256 } else {
1257 int index = ( erq->flags & IW_ENCODE_INDEX ) - 1;
1260 /* Do we want to just set the current transmit key? */
1261 if(( index >= 0 ) && ( index < MAX_KEYS )) {
1262 DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index,
1263 lp->DefaultKeys.key[index].len );
1265 if( lp->DefaultKeys.key[index].len > 0 ) {
1266 lp->TransmitKeyID = index + 1;
1267 lp->EnableEncryption = 1;
1268 } else {
1269 DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" );
1270 DBG_LEAVE( DbgInfo );
1271 ret = -EINVAL;
1276 /* Read the flags */
1277 if( erq->flags & IW_ENCODE_DISABLED ) {
1278 lp->EnableEncryption = 0; // disable encryption
1279 } else {
1280 lp->EnableEncryption = 1;
1283 if( erq->flags & IW_ENCODE_RESTRICTED ) {
1284 DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" );
1285 ret = -EINVAL; // Invalid
1288 DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state );
1289 DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption );
1290 DBG_TRACE( DbgInfo, "erq->length : %d\n",
1291 erq->length);
1292 DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n",
1293 erq->flags);
1295 /* Write the changes to the card */
1296 if( ret == 0 ) {
1297 DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
1298 lp->TransmitKeyID );
1300 if( lp->EnableEncryption == encryption_state ) {
1301 if( erq->length != 0 ) {
1302 /* Dynamic WEP key update */
1303 wl_set_wep_keys( lp );
1305 } else {
1306 /* To switch encryption on/off, soft reset is required */
1307 wl_apply( lp );
1311 /* Send an event that Encryption has been set */
1312 wl_wext_event_encode( dev );
1314 out_unlock:
1316 wl_act_int_on( lp );
1318 wl_unlock(lp, &flags);
1320 out:
1321 DBG_LEAVE( DbgInfo );
1322 return ret;
1323 } // wireless_set_encode
1324 /*============================================================================*/
1329 /*******************************************************************************
1330 * wireless_get_encode()
1331 *******************************************************************************
1333 * DESCRIPTION:
1335 * Gets the encryption keys and status.
1337 * PARAMETERS:
1339 * wrq - the wireless request buffer
1340 * lp - the device's private adapter structure
1342 * RETURNS:
1344 * 0 on success
1345 * errno value otherwise
1347 ******************************************************************************/
1348 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1351 struct wl_private *lp = wl_priv(dev);
1352 unsigned long flags;
1353 int ret = 0;
1354 int index;
1355 /*------------------------------------------------------------------------*/
1358 DBG_FUNC( "wireless_get_encode" );
1359 DBG_ENTER( DbgInfo );
1360 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1362 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1363 ret = -EBUSY;
1364 goto out;
1367 /* Only super-user can see WEP key */
1368 if( !capable( CAP_NET_ADMIN )) {
1369 ret = -EPERM;
1370 DBG_LEAVE( DbgInfo );
1371 return ret;
1374 wl_lock( lp, &flags );
1376 wl_act_int_off( lp );
1378 /* Is it supported? */
1379 if( !wl_has_wep( &( lp->hcfCtx ))) {
1380 ret = -EOPNOTSUPP;
1381 goto out_unlock;
1384 /* Basic checking */
1385 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1388 /* Set the flags */
1389 erq->flags = 0;
1391 if( lp->EnableEncryption == 0 ) {
1392 erq->flags |= IW_ENCODE_DISABLED;
1395 /* Which key do we want */
1396 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1397 index = lp->TransmitKeyID - 1;
1400 erq->flags |= index + 1;
1402 /* Copy the key to the user buffer */
1403 erq->length = lp->DefaultKeys.key[index].len;
1405 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1407 out_unlock:
1409 wl_act_int_on( lp );
1411 wl_unlock(lp, &flags);
1413 out:
1414 DBG_LEAVE( DbgInfo );
1415 return ret;
1416 } // wireless_get_encode
1417 /*============================================================================*/
1422 /*******************************************************************************
1423 * wireless_set_nickname()
1424 *******************************************************************************
1426 * DESCRIPTION:
1428 * Sets the nickname, or station name, of the wireless device.
1430 * PARAMETERS:
1432 * wrq - the wireless request buffer
1433 * lp - the device's private adapter structure
1435 * RETURNS:
1437 * 0 on success
1438 * errno value otherwise
1440 ******************************************************************************/
1441 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1443 struct wl_private *lp = wl_priv(dev);
1444 unsigned long flags;
1445 int ret = 0;
1446 /*------------------------------------------------------------------------*/
1449 DBG_FUNC( "wireless_set_nickname" );
1450 DBG_ENTER( DbgInfo );
1452 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1453 ret = -EBUSY;
1454 goto out;
1457 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1458 if( !capable(CAP_NET_ADMIN )) {
1459 ret = -EPERM;
1460 DBG_LEAVE( DbgInfo );
1461 return ret;
1463 #endif
1465 /* Validate the new value */
1466 if(data->length > HCF_MAX_NAME_LEN) {
1467 ret = -EINVAL;
1468 goto out;
1471 wl_lock( lp, &flags );
1473 wl_act_int_off( lp );
1475 memset( lp->StationName, 0, sizeof( lp->StationName ));
1477 memcpy( lp->StationName, nickname, data->length );
1479 /* Commit the adapter parameters */
1480 wl_apply( lp );
1482 wl_act_int_on( lp );
1484 wl_unlock(lp, &flags);
1486 out:
1487 DBG_LEAVE( DbgInfo );
1488 return ret;
1489 } // wireless_set_nickname
1490 /*============================================================================*/
1495 /*******************************************************************************
1496 * wireless_get_nickname()
1497 *******************************************************************************
1499 * DESCRIPTION:
1501 * Gets the nickname, or station name, of the wireless device.
1503 * PARAMETERS:
1505 * wrq - the wireless request buffer
1506 * lp - the device's private adapter structure
1508 * RETURNS:
1510 * 0 on success
1511 * errno value otherwise
1513 ******************************************************************************/
1514 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1516 struct wl_private *lp = wl_priv(dev);
1517 unsigned long flags;
1518 int ret = 0;
1519 int status = -1;
1520 wvName_t *pName;
1521 /*------------------------------------------------------------------------*/
1524 DBG_FUNC( "wireless_get_nickname" );
1525 DBG_ENTER( DbgInfo );
1527 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1528 ret = -EBUSY;
1529 goto out;
1532 wl_lock( lp, &flags );
1534 wl_act_int_off( lp );
1536 /* Get the current station name */
1537 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1538 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1540 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1542 if( status == HCF_SUCCESS ) {
1543 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1545 /* Endian translate the length */
1546 pName->length = CNV_LITTLE_TO_INT( pName->length );
1548 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1549 ret = -EFAULT;
1550 } else {
1551 /* Copy the information into the user buffer */
1552 data->length = pName->length;
1553 memcpy(nickname, pName->name, pName->length);
1555 } else {
1556 ret = -EFAULT;
1559 wl_act_int_on( lp );
1561 wl_unlock(lp, &flags);
1563 out:
1564 DBG_LEAVE(DbgInfo);
1565 return ret;
1566 } // wireless_get_nickname
1567 /*============================================================================*/
1572 /*******************************************************************************
1573 * wireless_set_porttype()
1574 *******************************************************************************
1576 * DESCRIPTION:
1578 * Sets the port type of the wireless device.
1580 * PARAMETERS:
1582 * wrq - the wireless request buffer
1583 * lp - the device's private adapter structure
1585 * RETURNS:
1587 * 0 on success
1588 * errno value otherwise
1590 ******************************************************************************/
1591 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1593 struct wl_private *lp = wl_priv(dev);
1594 unsigned long flags;
1595 int ret = 0;
1596 hcf_16 portType;
1597 hcf_16 createIBSS;
1598 /*------------------------------------------------------------------------*/
1600 DBG_FUNC( "wireless_set_porttype" );
1601 DBG_ENTER( DbgInfo );
1603 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1604 ret = -EBUSY;
1605 goto out;
1608 wl_lock( lp, &flags );
1610 wl_act_int_off( lp );
1612 /* Validate the new value */
1613 switch( *mode ) {
1614 case IW_MODE_ADHOC:
1616 /* When user requests ad-hoc, set IBSS mode! */
1617 portType = 1;
1618 createIBSS = 1;
1620 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1622 break;
1625 case IW_MODE_AUTO:
1626 case IW_MODE_INFRA:
1628 /* Both automatic and infrastructure set port to BSS/STA mode */
1629 portType = 1;
1630 createIBSS = 0;
1632 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1634 break;
1637 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1639 case IW_MODE_MASTER:
1641 /* Set BSS/AP mode */
1642 portType = 1;
1644 lp->CreateIBSS = 0;
1645 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1647 break;
1649 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1652 default:
1654 portType = 0;
1655 createIBSS = 0;
1656 ret = -EINVAL;
1659 if( portType != 0 ) {
1660 /* Only do something if there is a mode change */
1661 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1662 lp->PortType = portType;
1663 lp->CreateIBSS = createIBSS;
1665 /* Commit the adapter parameters */
1666 wl_go( lp );
1668 /* Send an event that mode has been set */
1669 wl_wext_event_mode( lp->dev );
1673 wl_act_int_on( lp );
1675 wl_unlock(lp, &flags);
1677 out:
1678 DBG_LEAVE( DbgInfo );
1679 return ret;
1680 } // wireless_set_porttype
1681 /*============================================================================*/
1686 /*******************************************************************************
1687 * wireless_get_porttype()
1688 *******************************************************************************
1690 * DESCRIPTION:
1692 * Gets the port type of the wireless device.
1694 * PARAMETERS:
1696 * wrq - the wireless request buffer
1697 * lp - the device's private adapter structure
1699 * RETURNS:
1701 * 0 on success
1702 * errno value otherwise
1704 ******************************************************************************/
1705 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1708 struct wl_private *lp = wl_priv(dev);
1709 unsigned long flags;
1710 int ret = 0;
1711 int status = -1;
1712 hcf_16 *pPortType;
1713 /*------------------------------------------------------------------------*/
1716 DBG_FUNC( "wireless_get_porttype" );
1717 DBG_ENTER( DbgInfo );
1719 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1720 ret = -EBUSY;
1721 goto out;
1724 wl_lock( lp, &flags );
1726 wl_act_int_off( lp );
1728 /* Get the current port type */
1729 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1730 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1732 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1734 if( status == HCF_SUCCESS ) {
1735 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1737 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1739 switch( *pPortType ) {
1740 case 1:
1742 #if 0
1743 #if (HCF_TYPE) & HCF_TYPE_AP
1745 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1746 *mode = IW_MODE_MASTER;
1747 } else {
1748 *mode = IW_MODE_INFRA;
1751 #else
1753 *mode = IW_MODE_INFRA;
1755 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1756 #endif
1758 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1759 *mode = IW_MODE_MASTER;
1760 } else {
1761 if( lp->CreateIBSS ) {
1762 *mode = IW_MODE_ADHOC;
1763 } else {
1764 *mode = IW_MODE_INFRA;
1768 break;
1771 case 3:
1772 *mode = IW_MODE_ADHOC;
1773 break;
1775 default:
1776 ret = -EFAULT;
1777 break;
1779 } else {
1780 ret = -EFAULT;
1783 wl_act_int_on( lp );
1785 wl_unlock(lp, &flags);
1787 out:
1788 DBG_LEAVE( DbgInfo );
1789 return ret;
1790 } // wireless_get_porttype
1791 /*============================================================================*/
1796 /*******************************************************************************
1797 * wireless_set_power()
1798 *******************************************************************************
1800 * DESCRIPTION:
1802 * Sets the power management settings of the wireless device.
1804 * PARAMETERS:
1806 * wrq - the wireless request buffer
1807 * lp - the device's private adapter structure
1809 * RETURNS:
1811 * 0 on success
1812 * errno value otherwise
1814 ******************************************************************************/
1815 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1817 struct wl_private *lp = wl_priv(dev);
1818 unsigned long flags;
1819 int ret = 0;
1820 /*------------------------------------------------------------------------*/
1823 DBG_FUNC( "wireless_set_power" );
1824 DBG_ENTER( DbgInfo );
1826 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1827 ret = -EBUSY;
1828 goto out;
1831 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1833 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1834 if( !capable( CAP_NET_ADMIN )) {
1835 ret = -EPERM;
1837 DBG_LEAVE( DbgInfo );
1838 return ret;
1840 #endif
1842 wl_lock( lp, &flags );
1844 wl_act_int_off( lp );
1846 /* Set the power management state based on the 'disabled' value */
1847 if( wrq->disabled ) {
1848 lp->PMEnabled = 0;
1849 } else {
1850 lp->PMEnabled = 1;
1853 /* Commit the adapter parameters */
1854 wl_apply( lp );
1856 wl_act_int_on( lp );
1858 wl_unlock(lp, &flags);
1860 out:
1861 DBG_LEAVE( DbgInfo );
1862 return ret;
1863 } // wireless_set_power
1864 /*============================================================================*/
1869 /*******************************************************************************
1870 * wireless_get_power()
1871 *******************************************************************************
1873 * DESCRIPTION:
1875 * Gets the power management settings of the wireless device.
1877 * PARAMETERS:
1879 * wrq - the wireless request buffer
1880 * lp - the device's private adapter structure
1882 * RETURNS:
1884 * 0 on success
1885 * errno value otherwise
1887 ******************************************************************************/
1888 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1891 struct wl_private *lp = wl_priv(dev);
1892 unsigned long flags;
1893 int ret = 0;
1894 /*------------------------------------------------------------------------*/
1895 DBG_FUNC( "wireless_get_power" );
1896 DBG_ENTER( DbgInfo );
1898 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1899 ret = -EBUSY;
1900 goto out;
1903 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1905 wl_lock( lp, &flags );
1907 wl_act_int_off( lp );
1909 rrq->flags = 0;
1910 rrq->value = 0;
1912 if( lp->PMEnabled ) {
1913 rrq->disabled = 0;
1914 } else {
1915 rrq->disabled = 1;
1918 wl_act_int_on( lp );
1920 wl_unlock(lp, &flags);
1922 out:
1923 DBG_LEAVE( DbgInfo );
1924 return ret;
1925 } // wireless_get_power
1926 /*============================================================================*/
1931 /*******************************************************************************
1932 * wireless_get_tx_power()
1933 *******************************************************************************
1935 * DESCRIPTION:
1937 * Gets the transmit power of the wireless device's radio.
1939 * PARAMETERS:
1941 * wrq - the wireless request buffer
1942 * lp - the device's private adapter structure
1944 * RETURNS:
1946 * 0 on success
1947 * errno value otherwise
1949 ******************************************************************************/
1950 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1952 struct wl_private *lp = wl_priv(dev);
1953 unsigned long flags;
1954 int ret = 0;
1955 /*------------------------------------------------------------------------*/
1956 DBG_FUNC( "wireless_get_tx_power" );
1957 DBG_ENTER( DbgInfo );
1959 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1960 ret = -EBUSY;
1961 goto out;
1964 wl_lock( lp, &flags );
1966 wl_act_int_off( lp );
1968 #ifdef USE_POWER_DBM
1969 rrq->value = RADIO_TX_POWER_DBM;
1970 rrq->flags = IW_TXPOW_DBM;
1971 #else
1972 rrq->value = RADIO_TX_POWER_MWATT;
1973 rrq->flags = IW_TXPOW_MWATT;
1974 #endif
1975 rrq->fixed = 1;
1976 rrq->disabled = 0;
1978 wl_act_int_on( lp );
1980 wl_unlock(lp, &flags);
1982 out:
1983 DBG_LEAVE( DbgInfo );
1984 return ret;
1985 } // wireless_get_tx_power
1986 /*============================================================================*/
1991 /*******************************************************************************
1992 * wireless_set_rts_threshold()
1993 *******************************************************************************
1995 * DESCRIPTION:
1997 * Sets the RTS threshold for the wireless card.
1999 * PARAMETERS:
2001 * wrq - the wireless request buffer
2002 * lp - the device's private adapter structure
2004 * RETURNS:
2006 * 0 on success
2007 * errno value otherwise
2009 ******************************************************************************/
2010 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2012 int ret = 0;
2013 struct wl_private *lp = wl_priv(dev);
2014 unsigned long flags;
2015 int rthr = rts->value;
2016 /*------------------------------------------------------------------------*/
2019 DBG_FUNC( "wireless_set_rts_threshold" );
2020 DBG_ENTER( DbgInfo );
2022 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2023 ret = -EBUSY;
2024 goto out;
2027 if(rts->fixed == 0) {
2028 ret = -EINVAL;
2029 goto out;
2032 #if WIRELESS_EXT > 8
2033 if( rts->disabled ) {
2034 rthr = 2347;
2036 #endif /* WIRELESS_EXT > 8 */
2038 if(( rthr < 256 ) || ( rthr > 2347 )) {
2039 ret = -EINVAL;
2040 goto out;
2043 wl_lock( lp, &flags );
2045 wl_act_int_off( lp );
2047 lp->RTSThreshold = rthr;
2049 wl_apply( lp );
2051 wl_act_int_on( lp );
2053 wl_unlock(lp, &flags);
2055 out:
2056 DBG_LEAVE( DbgInfo );
2057 return ret;
2058 } // wireless_set_rts_threshold
2059 /*============================================================================*/
2064 /*******************************************************************************
2065 * wireless_get_rts_threshold()
2066 *******************************************************************************
2068 * DESCRIPTION:
2070 * Gets the RTS threshold for the wireless card.
2072 * PARAMETERS:
2074 * wrq - the wireless request buffer
2075 * lp - the device's private adapter structure
2077 * RETURNS:
2079 * 0 on success
2080 * errno value otherwise
2082 ******************************************************************************/
2083 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2085 int ret = 0;
2086 struct wl_private *lp = wl_priv(dev);
2087 unsigned long flags;
2088 /*------------------------------------------------------------------------*/
2090 DBG_FUNC( "wireless_get_rts_threshold" );
2091 DBG_ENTER( DbgInfo );
2093 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2094 ret = -EBUSY;
2095 goto out;
2098 wl_lock( lp, &flags );
2100 wl_act_int_off( lp );
2102 rts->value = lp->RTSThreshold;
2104 #if WIRELESS_EXT > 8
2106 rts->disabled = ( rts->value == 2347 );
2108 #endif /* WIRELESS_EXT > 8 */
2110 rts->fixed = 1;
2112 wl_act_int_on( lp );
2114 wl_unlock(lp, &flags);
2116 out:
2117 DBG_LEAVE( DbgInfo );
2118 return ret;
2119 } // wireless_get_rts_threshold
2120 /*============================================================================*/
2126 /*******************************************************************************
2127 * wireless_set_rate()
2128 *******************************************************************************
2130 * DESCRIPTION:
2132 * Set the default data rate setting used by the wireless device.
2134 * PARAMETERS:
2136 * wrq - the wireless request buffer
2137 * lp - the device's private adapter structure
2139 * RETURNS:
2141 * 0 on success
2142 * errno value otherwise
2144 ******************************************************************************/
2145 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2147 struct wl_private *lp = wl_priv(dev);
2148 unsigned long flags;
2149 int ret = 0;
2150 #ifdef WARP
2151 int status = -1;
2152 int index = 0;
2153 #endif // WARP
2154 /*------------------------------------------------------------------------*/
2157 DBG_FUNC( "wireless_set_rate" );
2158 DBG_ENTER( DbgInfo );
2160 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2161 ret = -EBUSY;
2162 goto out;
2165 wl_lock( lp, &flags );
2167 wl_act_int_off( lp );
2169 #ifdef WARP
2171 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2172 if Bit 9 is set in the current channel RID */
2173 lp->ltvRecord.len = 2;
2174 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2176 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2178 if( status == HCF_SUCCESS ) {
2179 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2181 DBG_PRINT( "Index: %d\n", index );
2182 } else {
2183 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2184 DBG_LEAVE( DbgInfo );
2185 ret = -EINVAL;
2186 goto out_unlock;
2189 if( rrq->value > 0 &&
2190 rrq->value <= 1 * MEGABIT ) {
2191 lp->TxRateControl[index] = 0x0001;
2193 else if( rrq->value > 1 * MEGABIT &&
2194 rrq->value <= 2 * MEGABIT ) {
2195 if( rrq->fixed == 1 ) {
2196 lp->TxRateControl[index] = 0x0002;
2197 } else {
2198 lp->TxRateControl[index] = 0x0003;
2201 else if( rrq->value > 2 * MEGABIT &&
2202 rrq->value <= 5 * MEGABIT ) {
2203 if( rrq->fixed == 1 ) {
2204 lp->TxRateControl[index] = 0x0004;
2205 } else {
2206 lp->TxRateControl[index] = 0x0007;
2209 else if( rrq->value > 5 * MEGABIT &&
2210 rrq->value <= 6 * MEGABIT ) {
2211 if( rrq->fixed == 1 ) {
2212 lp->TxRateControl[index] = 0x0010;
2213 } else {
2214 lp->TxRateControl[index] = 0x0017;
2217 else if( rrq->value > 6 * MEGABIT &&
2218 rrq->value <= 9 * MEGABIT ) {
2219 if( rrq->fixed == 1 ) {
2220 lp->TxRateControl[index] = 0x0020;
2221 } else {
2222 lp->TxRateControl[index] = 0x0037;
2225 else if( rrq->value > 9 * MEGABIT &&
2226 rrq->value <= 11 * MEGABIT ) {
2227 if( rrq->fixed == 1 ) {
2228 lp->TxRateControl[index] = 0x0008;
2229 } else {
2230 lp->TxRateControl[index] = 0x003F;
2233 else if( rrq->value > 11 * MEGABIT &&
2234 rrq->value <= 12 * MEGABIT ) {
2235 if( rrq->fixed == 1 ) {
2236 lp->TxRateControl[index] = 0x0040;
2237 } else {
2238 lp->TxRateControl[index] = 0x007F;
2241 else if( rrq->value > 12 * MEGABIT &&
2242 rrq->value <= 18 * MEGABIT ) {
2243 if( rrq->fixed == 1 ) {
2244 lp->TxRateControl[index] = 0x0080;
2245 } else {
2246 lp->TxRateControl[index] = 0x00FF;
2249 else if( rrq->value > 18 * MEGABIT &&
2250 rrq->value <= 24 * MEGABIT ) {
2251 if( rrq->fixed == 1 ) {
2252 lp->TxRateControl[index] = 0x0100;
2253 } else {
2254 lp->TxRateControl[index] = 0x01FF;
2257 else if( rrq->value > 24 * MEGABIT &&
2258 rrq->value <= 36 * MEGABIT ) {
2259 if( rrq->fixed == 1 ) {
2260 lp->TxRateControl[index] = 0x0200;
2261 } else {
2262 lp->TxRateControl[index] = 0x03FF;
2265 else if( rrq->value > 36 * MEGABIT &&
2266 rrq->value <= 48 * MEGABIT ) {
2267 if( rrq->fixed == 1 ) {
2268 lp->TxRateControl[index] = 0x0400;
2269 } else {
2270 lp->TxRateControl[index] = 0x07FF;
2273 else if( rrq->value > 48 * MEGABIT &&
2274 rrq->value <= 54 * MEGABIT ) {
2275 if( rrq->fixed == 1 ) {
2276 lp->TxRateControl[index] = 0x0800;
2277 } else {
2278 lp->TxRateControl[index] = 0x0FFF;
2281 else if( rrq->fixed == 0 ) {
2282 /* In this case, the user has not specified a bitrate, only the "auto"
2283 moniker. So, set to all supported rates */
2284 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2285 } else {
2286 rrq->value = 0;
2287 ret = -EINVAL;
2288 goto out_unlock;
2292 #else
2294 if( rrq->value > 0 &&
2295 rrq->value <= 1 * MEGABIT ) {
2296 lp->TxRateControl[0] = 1;
2298 else if( rrq->value > 1 * MEGABIT &&
2299 rrq->value <= 2 * MEGABIT ) {
2300 if( rrq->fixed ) {
2301 lp->TxRateControl[0] = 2;
2302 } else {
2303 lp->TxRateControl[0] = 6;
2306 else if( rrq->value > 2 * MEGABIT &&
2307 rrq->value <= 5 * MEGABIT ) {
2308 if( rrq->fixed ) {
2309 lp->TxRateControl[0] = 4;
2310 } else {
2311 lp->TxRateControl[0] = 7;
2314 else if( rrq->value > 5 * MEGABIT &&
2315 rrq->value <= 11 * MEGABIT ) {
2316 if( rrq->fixed) {
2317 lp->TxRateControl[0] = 5;
2318 } else {
2319 lp->TxRateControl[0] = 3;
2322 else if( rrq->fixed == 0 ) {
2323 /* In this case, the user has not specified a bitrate, only the "auto"
2324 moniker. So, set the rate to 11Mb auto */
2325 lp->TxRateControl[0] = 3;
2326 } else {
2327 rrq->value = 0;
2328 ret = -EINVAL;
2329 goto out_unlock;
2332 #endif // WARP
2335 /* Commit the adapter parameters */
2336 wl_apply( lp );
2338 out_unlock:
2340 wl_act_int_on( lp );
2342 wl_unlock(lp, &flags);
2344 out:
2345 DBG_LEAVE( DbgInfo );
2346 return ret;
2347 } // wireless_set_rate
2348 /*============================================================================*/
2353 /*******************************************************************************
2354 * wireless_get_rate()
2355 *******************************************************************************
2357 * DESCRIPTION:
2359 * Get the default data rate setting used by the wireless device.
2361 * PARAMETERS:
2363 * wrq - the wireless request buffer
2364 * lp - the device's private adapter structure
2366 * RETURNS:
2368 * 0 on success
2369 * errno value otherwise
2371 ******************************************************************************/
2372 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2375 struct wl_private *lp = wl_priv(dev);
2376 unsigned long flags;
2377 int ret = 0;
2378 int status = -1;
2379 hcf_16 txRate;
2380 /*------------------------------------------------------------------------*/
2383 DBG_FUNC( "wireless_get_rate" );
2384 DBG_ENTER( DbgInfo );
2386 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2387 ret = -EBUSY;
2388 goto out;
2391 wl_lock( lp, &flags );
2393 wl_act_int_off( lp );
2395 /* Get the current transmit rate from the adapter */
2396 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2397 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2399 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2401 if( status == HCF_SUCCESS ) {
2402 #ifdef WARP
2404 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2406 if( txRate & 0x0001 ) {
2407 txRate = 1;
2409 else if( txRate & 0x0002 ) {
2410 txRate = 2;
2412 else if( txRate & 0x0004 ) {
2413 txRate = 5;
2415 else if( txRate & 0x0008 ) {
2416 txRate = 11;
2418 else if( txRate & 0x00010 ) {
2419 txRate = 6;
2421 else if( txRate & 0x00020 ) {
2422 txRate = 9;
2424 else if( txRate & 0x00040 ) {
2425 txRate = 12;
2427 else if( txRate & 0x00080 ) {
2428 txRate = 18;
2430 else if( txRate & 0x00100 ) {
2431 txRate = 24;
2433 else if( txRate & 0x00200 ) {
2434 txRate = 36;
2436 else if( txRate & 0x00400 ) {
2437 txRate = 48;
2439 else if( txRate & 0x00800 ) {
2440 txRate = 54;
2443 #else
2445 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2447 #endif // WARP
2449 rrq->value = txRate * MEGABIT;
2450 } else {
2451 rrq->value = 0;
2452 ret = -EFAULT;
2455 wl_act_int_on( lp );
2457 wl_unlock(lp, &flags);
2459 out:
2460 DBG_LEAVE( DbgInfo );
2461 return ret;
2462 } // wireless_get_rate
2463 /*============================================================================*/
2468 #if 0 //;? Not used anymore
2469 /*******************************************************************************
2470 * wireless_get_private_interface()
2471 *******************************************************************************
2473 * DESCRIPTION:
2475 * Returns the Linux Wireless Extensions' compatible private interface of
2476 * the driver.
2478 * PARAMETERS:
2480 * wrq - the wireless request buffer
2481 * lp - the device's private adapter structure
2483 * RETURNS:
2485 * 0 on success
2486 * errno value otherwise
2488 ******************************************************************************/
2489 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2491 int ret = 0;
2492 /*------------------------------------------------------------------------*/
2495 DBG_FUNC( "wireless_get_private_interface" );
2496 DBG_ENTER( DbgInfo );
2498 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2499 ret = -EBUSY;
2500 goto out;
2503 if( wrq->u.data.pointer != NULL ) {
2504 struct iw_priv_args priv[] =
2506 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2507 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2508 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2509 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2510 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2511 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2514 /* Verify the user buffer */
2515 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2517 if( ret != 0 ) {
2518 DBG_LEAVE( DbgInfo );
2519 return ret;
2522 /* Copy the data into the user's buffer */
2523 wrq->u.data.length = NELEM( priv );
2524 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2527 out:
2528 DBG_LEAVE( DbgInfo );
2529 return ret;
2530 } // wireless_get_private_interface
2531 /*============================================================================*/
2532 #endif
2536 #if WIRELESS_EXT > 13
2538 /*******************************************************************************
2539 * wireless_set_scan()
2540 *******************************************************************************
2542 * DESCRIPTION:
2544 * Instructs the driver to initiate a network scan.
2546 * PARAMETERS:
2548 * wrq - the wireless request buffer
2549 * lp - the device's private adapter structure
2551 * RETURNS:
2553 * 0 on success
2554 * errno value otherwise
2556 ******************************************************************************/
2557 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2559 struct wl_private *lp = wl_priv(dev);
2560 unsigned long flags;
2561 int ret = 0;
2562 int status = -1;
2563 int retries = 0;
2564 /*------------------------------------------------------------------------*/
2566 //;? Note: shows results as trace, retruns always 0 unless BUSY
2568 DBG_FUNC( "wireless_set_scan" );
2569 DBG_ENTER( DbgInfo );
2571 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2572 ret = -EBUSY;
2573 goto out;
2576 wl_lock( lp, &flags );
2578 wl_act_int_off( lp );
2581 * This looks like a nice place to test if the HCF is still
2582 * communicating with the card. It seems that sometimes BAP_1
2583 * gets corrupted. By looking at the comments in HCF the
2584 * cause is still a mistery. Okay, the communication to the
2585 * card is dead, reset the card to revive.
2587 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2589 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2590 wl_reset( dev );
2593 retry:
2594 /* Set the completion state to FALSE */
2595 lp->probe_results.scan_complete = FALSE;
2598 /* Channels to scan */
2599 #ifdef WARP
2600 lp->ltvRecord.len = 5;
2601 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2602 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2603 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2604 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2605 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2606 #else
2607 lp->ltvRecord.len = 2;
2608 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2609 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2610 #endif // WARP
2612 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2614 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2616 // Holding the lock too long, make a gap to allow other processes
2617 wl_unlock(lp, &flags);
2618 wl_lock( lp, &flags );
2620 if( status != HCF_SUCCESS ) {
2621 //Recovery
2622 retries++;
2623 if(retries <= 10) {
2624 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2625 wl_reset( dev );
2627 // Holding the lock too long, make a gap to allow other processes
2628 wl_unlock(lp, &flags);
2629 wl_lock( lp, &flags );
2631 goto retry;
2635 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2636 disassociate from the network we are currently on */
2637 lp->ltvRecord.len = 18;
2638 lp->ltvRecord.typ = CFG_SCAN_SSID;
2639 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2640 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2642 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2644 // Holding the lock too long, make a gap to allow other processes
2645 wl_unlock(lp, &flags);
2646 wl_lock( lp, &flags );
2648 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2650 /* Initiate the scan */
2651 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2652 retrieve probe responses must always be used to support WPA */
2653 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2655 if( status == HCF_SUCCESS ) {
2656 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2657 } else {
2658 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2661 wl_act_int_on( lp );
2663 wl_unlock(lp, &flags);
2665 out:
2666 DBG_LEAVE(DbgInfo);
2667 return ret;
2668 } // wireless_set_scan
2669 /*============================================================================*/
2674 /*******************************************************************************
2675 * wireless_get_scan()
2676 *******************************************************************************
2678 * DESCRIPTION:
2680 * Instructs the driver to gather and return the results of a network scan.
2682 * PARAMETERS:
2684 * wrq - the wireless request buffer
2685 * lp - the device's private adapter structure
2687 * RETURNS:
2689 * 0 on success
2690 * errno value otherwise
2692 ******************************************************************************/
2693 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2695 struct wl_private *lp = wl_priv(dev);
2696 unsigned long flags;
2697 int ret = 0;
2698 int count;
2699 char *buf;
2700 char *buf_end;
2701 struct iw_event iwe;
2702 PROBE_RESP *probe_resp;
2703 hcf_8 msg[512];
2704 hcf_8 *wpa_ie;
2705 hcf_16 wpa_ie_len;
2706 /*------------------------------------------------------------------------*/
2709 DBG_FUNC( "wireless_get_scan" );
2710 DBG_ENTER( DbgInfo );
2712 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2713 ret = -EBUSY;
2714 goto out;
2717 wl_lock( lp, &flags );
2719 wl_act_int_off( lp );
2721 /* If the scan is not done, tell the calling process to try again later */
2722 if( !lp->probe_results.scan_complete ) {
2723 ret = -EAGAIN;
2724 goto out_unlock;
2727 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2728 lp->probe_results.num_aps );
2730 buf = extra;
2731 buf_end = extra + IW_SCAN_MAX_DATA;
2733 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2734 /* Reference the probe response from the table */
2735 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2738 /* First entry MUST be the MAC address */
2739 memset( &iwe, 0, sizeof( iwe ));
2741 iwe.cmd = SIOCGIWAP;
2742 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2743 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2744 iwe.len = IW_EV_ADDR_LEN;
2746 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN);
2749 /* Use the mode to indicate if it's a station or AP */
2750 /* Won't always be an AP if in IBSS mode */
2751 memset( &iwe, 0, sizeof( iwe ));
2753 iwe.cmd = SIOCGIWMODE;
2755 if( probe_resp->capability & CAPABILITY_IBSS ) {
2756 iwe.u.mode = IW_MODE_INFRA;
2757 } else {
2758 iwe.u.mode = IW_MODE_MASTER;
2761 iwe.len = IW_EV_UINT_LEN;
2763 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN);
2766 /* Any quality information */
2767 memset(&iwe, 0, sizeof(iwe));
2769 iwe.cmd = IWEVQUAL;
2770 iwe.u.qual.level = dbm(probe_resp->signal);
2771 iwe.u.qual.noise = dbm(probe_resp->silence);
2772 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2773 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2774 iwe.len = IW_EV_QUAL_LEN;
2776 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN);
2779 /* ESSID information */
2780 if( probe_resp->rawData[1] > 0 ) {
2781 memset( &iwe, 0, sizeof( iwe ));
2783 iwe.cmd = SIOCGIWESSID;
2784 iwe.u.data.length = probe_resp->rawData[1];
2785 iwe.u.data.flags = 1;
2787 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]);
2791 /* Encryption Information */
2792 memset( &iwe, 0, sizeof( iwe ));
2794 iwe.cmd = SIOCGIWENCODE;
2795 iwe.u.data.length = 0;
2797 /* Check the capabilities field of the Probe Response to see if
2798 'privacy' is supported on the AP in question */
2799 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2800 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2801 } else {
2802 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2805 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL);
2808 /* Frequency Info */
2809 memset( &iwe, 0, sizeof( iwe ));
2811 iwe.cmd = SIOCGIWFREQ;
2812 iwe.len = IW_EV_FREQ_LEN;
2813 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2814 iwe.u.freq.e = 0;
2816 buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN);
2819 #if WIRELESS_EXT > 14
2820 /* Custom info (Beacon Interval) */
2821 memset( &iwe, 0, sizeof( iwe ));
2822 memset( msg, 0, sizeof( msg ));
2824 iwe.cmd = IWEVCUSTOM;
2825 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2826 iwe.u.data.length = strlen( msg );
2828 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2831 /* Custom info (WPA-IE) */
2832 wpa_ie = NULL;
2833 wpa_ie_len = 0;
2835 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2836 if( wpa_ie != NULL ) {
2837 memset( &iwe, 0, sizeof( iwe ));
2838 memset( msg, 0, sizeof( msg ));
2840 iwe.cmd = IWEVCUSTOM;
2841 sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2842 iwe.u.data.length = strlen( msg );
2844 buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg);
2847 /* Add other custom info in formatted string format as needed... */
2848 #endif
2851 data->length = buf - extra;
2853 out_unlock:
2855 wl_act_int_on( lp );
2857 wl_unlock(lp, &flags);
2859 out:
2860 DBG_LEAVE( DbgInfo );
2861 return ret;
2862 } // wireless_get_scan
2863 /*============================================================================*/
2865 #endif // WIRELESS_EXT > 13
2868 #if WIRELESS_EXT > 17
2870 static int wireless_set_auth(struct net_device *dev,
2871 struct iw_request_info *info,
2872 struct iw_param *data, char *extra)
2874 struct wl_private *lp = wl_priv(dev);
2875 unsigned long flags;
2876 int ret;
2877 int iwa_idx = data->flags & IW_AUTH_INDEX;
2878 int iwa_val = data->value;
2880 DBG_FUNC( "wireless_set_auth" );
2881 DBG_ENTER( DbgInfo );
2883 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2884 ret = -EBUSY;
2885 goto out;
2888 wl_lock( lp, &flags );
2890 wl_act_int_off( lp );
2892 switch (iwa_idx) {
2893 case IW_AUTH_WPA_VERSION:
2894 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n");
2895 /* We do support WPA only; how should DISABLED be treated? */
2896 if (iwa_val == IW_AUTH_WPA_VERSION_WPA)
2897 ret = 0;
2898 else
2899 ret = -EINVAL;
2900 break;
2902 case IW_AUTH_WPA_ENABLED:
2903 DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val);
2904 if (iwa_val)
2905 lp->EnableEncryption = 2;
2906 else
2907 lp->EnableEncryption = 0;
2908 ret = 0;
2909 break;
2911 case IW_AUTH_TKIP_COUNTERMEASURES:
2912 DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n");
2913 lp->driverEnable = !iwa_val;
2914 if(lp->driverEnable)
2915 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2916 else
2917 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2918 ret = 0;
2919 break;
2921 case IW_AUTH_DROP_UNENCRYPTED:
2922 DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n");
2923 /* We do not actually do anything here, just to silence
2924 * wpa_supplicant */
2925 ret = 0;
2926 break;
2928 case IW_AUTH_CIPHER_PAIRWISE:
2929 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n");
2930 /* not implemented, return an error */
2931 ret = -EINVAL;
2932 break;
2934 case IW_AUTH_CIPHER_GROUP:
2935 DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n");
2936 /* not implemented, return an error */
2937 ret = -EINVAL;
2938 break;
2940 case IW_AUTH_KEY_MGMT:
2941 DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n");
2942 /* not implemented, return an error */
2943 ret = -EINVAL;
2944 break;
2946 case IW_AUTH_80211_AUTH_ALG:
2947 DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n");
2948 /* not implemented, return an error */
2949 ret = -EINVAL;
2950 break;
2952 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2953 DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n");
2954 /* not implemented, return an error */
2955 ret = -EINVAL;
2956 break;
2958 case IW_AUTH_ROAMING_CONTROL:
2959 DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n");
2960 /* not implemented, return an error */
2961 ret = -EINVAL;
2962 break;
2964 case IW_AUTH_PRIVACY_INVOKED:
2965 DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n");
2966 /* not implemented, return an error */
2967 ret = -EINVAL;
2968 break;
2970 default:
2971 DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
2972 /* return an error */
2973 ret = -EINVAL;
2974 break;
2977 wl_act_int_on( lp );
2979 wl_unlock(lp, &flags);
2981 out:
2982 DBG_LEAVE( DbgInfo );
2983 return ret;
2984 } // wireless_set_auth
2985 /*============================================================================*/
2989 static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr,
2990 int set_tx, u8 *seq, u8 *key, size_t key_len)
2992 int ret = -EINVAL;
2993 // int count = 0;
2994 int buf_idx = 0;
2995 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
2996 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
2998 DBG_FUNC( "hermes_set_key" );
2999 DBG_ENTER( DbgInfo );
3002 * Check the key index here; if 0, load as Pairwise Key, otherwise,
3003 * load as a group key. Note that for the Hermes, the RIDs for
3004 * group/pariwise keys are different from each other and different
3005 * than the default WEP keys as well.
3007 switch (alg)
3009 case IW_ENCODE_ALG_TKIP:
3010 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3011 #if 0
3013 * Make sure that there is no data queued up in the firmware
3014 * before setting the TKIP keys. If this check is not
3015 * performed, some data may be sent out with incorrect MIC
3016 * and cause synchronizarion errors with the AP
3018 /* Check every 1ms for 100ms */
3019 for( count = 0; count < 100; count++ )
3021 usleep( 1000 );
3023 ltv.len = 2;
3024 ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
3025 ltv.u.u16[0] = 0;
3027 wl_get_info( sock, &ltv, ifname );
3029 if( ltv.u.u16[0] == 0 )
3031 break;
3035 if( count == 100 )
3037 wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" );
3039 #endif
3041 switch (key_idx) {
3042 case 0:
3043 ltv->len = 28;
3044 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
3046 /* Load the BSSID */
3047 memcpy(&ltv->u.u8[buf_idx], addr, ETH_ALEN);
3048 buf_idx += ETH_ALEN;
3050 /* Load the TKIP key */
3051 memcpy(&ltv->u.u8[buf_idx], &key[0], 16);
3052 buf_idx += 16;
3054 /* Load the TSC */
3055 memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3056 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3058 /* Load the RSC */
3059 memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3060 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3062 /* Load the TxMIC key */
3063 memcpy(&ltv->u.u8[buf_idx], &key[16], 8);
3064 buf_idx += 8;
3066 /* Load the RxMIC key */
3067 memcpy(&ltv->u.u8[buf_idx], &key[24], 8);
3069 ret = 0;
3070 break;
3071 case 1:
3072 case 2:
3073 case 3:
3074 ltv->len = 26;
3075 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
3077 /* Load the key Index */
3078 ltv->u.u16[buf_idx] = key_idx;
3079 /* If this is a Tx Key, set bit 8000 */
3080 if(set_tx)
3081 ltv->u.u16[buf_idx] |= 0x8000;
3082 buf_idx += 2;
3084 /* Load the RSC */
3085 memcpy(&ltv->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
3086 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
3088 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
3089 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
3090 memcpy(&ltv->u.u8[buf_idx], key, key_len);
3091 buf_idx += key_len;
3093 /* Load the TSC */
3094 memcpy(&ltv->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
3096 ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]);
3098 ret = 0;
3099 break;
3100 default:
3101 break;
3104 break;
3106 case IW_ENCODE_ALG_WEP:
3107 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3108 break;
3110 case IW_ENCODE_ALG_CCMP:
3111 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3112 break;
3114 case IW_ENCODE_ALG_NONE:
3115 DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3116 switch (key_idx) {
3117 case 0:
3118 if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) {
3119 //if (addr != NULL) {
3120 ltv->len = 7;
3121 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
3122 memcpy(&ltv->u.u8[0], addr, ETH_ALEN);
3123 ret = 0;
3125 break;
3126 case 1:
3127 case 2:
3128 case 3:
3129 /* Clear the Group TKIP keys by index */
3130 ltv->len = 2;
3131 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
3132 ltv->u.u16[0] = key_idx;
3134 ret = 0;
3135 break;
3136 default:
3137 break;
3139 break;
3140 default:
3141 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3142 break;
3145 DBG_LEAVE( DbgInfo );
3146 return ret;
3147 } // hermes_set_key
3148 /*============================================================================*/
3152 static int wireless_set_encodeext (struct net_device *dev,
3153 struct iw_request_info *info,
3154 struct iw_point *erq, char *keybuf)
3156 struct wl_private *lp = wl_priv(dev);
3157 unsigned long flags;
3158 int ret;
3159 int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1;
3160 ltv_t ltv;
3161 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3163 DBG_FUNC( "wireless_set_encodeext" );
3164 DBG_ENTER( DbgInfo );
3166 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3167 ret = -EBUSY;
3168 goto out;
3171 if (sizeof(ext->rx_seq) != 8) {
3172 DBG_TRACE(DbgInfo, "rz_seq size mismatch\n");
3173 DBG_LEAVE(DbgInfo);
3174 return -EINVAL;
3177 /* Handle WEP keys via the old set encode procedure */
3178 if(ext->alg == IW_ENCODE_ALG_WEP) {
3179 struct iw_point wep_erq;
3180 char *wep_keybuf;
3182 /* Build request structure */
3183 wep_erq.flags = erq->flags; // take over flags with key index
3184 wep_erq.length = ext->key_len; // take length from extended key info
3185 wep_keybuf = ext->key; // pointer to the key text
3187 /* Call wireless_set_encode tot handle the WEP key */
3188 ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf);
3189 goto out;
3192 /* Proceed for extended encode functions for WAP and NONE */
3193 wl_lock( lp, &flags );
3195 wl_act_int_off( lp );
3197 memset(&ltv, 0, sizeof(ltv));
3198 ret = hermes_set_key(&ltv, ext->alg, key_idx, ext->addr.sa_data,
3199 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
3200 ext->rx_seq, ext->key, ext->key_len);
3202 if (ret != 0) {
3203 DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n");
3204 goto out_unlock;
3207 /* Put the key in HCF */
3208 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3210 out_unlock:
3211 if(ret == HCF_SUCCESS) {
3212 DBG_TRACE( DbgInfo, "Put key info succes\n");
3213 } else {
3214 DBG_TRACE( DbgInfo, "Put key info failed, key not set\n");
3217 wl_act_int_on( lp );
3219 wl_unlock(lp, &flags);
3221 out:
3222 DBG_LEAVE( DbgInfo );
3223 return ret;
3224 } // wireless_set_encodeext
3225 /*============================================================================*/
3229 static int wireless_get_genie(struct net_device *dev,
3230 struct iw_request_info *info,
3231 struct iw_point *data, char *extra)
3234 struct wl_private *lp = wl_priv(dev);
3235 unsigned long flags;
3236 int ret = 0;
3237 ltv_t ltv;
3239 DBG_FUNC( "wireless_get_genie" );
3240 DBG_ENTER( DbgInfo );
3242 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3243 ret = -EBUSY;
3244 goto out;
3247 wl_lock( lp, &flags );
3249 wl_act_int_off( lp );
3251 memset(&ltv, 0, sizeof(ltv));
3252 ltv.len = 2;
3253 ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
3254 lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4;
3255 ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]);
3257 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)&ltv);
3259 wl_act_int_on( lp );
3261 wl_unlock(lp, &flags);
3263 out:
3264 DBG_LEAVE( DbgInfo );
3265 return ret;
3267 /*============================================================================*/
3270 #endif // WIRELESS_EXT > 17
3272 /*******************************************************************************
3273 * wl_wireless_stats()
3274 *******************************************************************************
3276 * DESCRIPTION:
3278 * Return the current device wireless statistics.
3280 * PARAMETERS:
3282 * wrq - the wireless request buffer
3283 * lp - the device's private adapter structure
3285 * RETURNS:
3287 * 0 on success
3288 * errno value otherwise
3290 ******************************************************************************/
3291 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3293 struct iw_statistics *pStats;
3294 struct wl_private *lp = wl_priv(dev);
3295 /*------------------------------------------------------------------------*/
3298 DBG_FUNC( "wl_wireless_stats" );
3299 DBG_ENTER(DbgInfo);
3300 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3302 pStats = NULL;
3304 /* Initialize the statistics */
3305 pStats = &( lp->wstats );
3306 pStats->qual.updated = 0x00;
3308 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3310 CFG_COMMS_QUALITY_STRCT *pQual;
3311 CFG_HERMES_TALLIES_STRCT tallies;
3312 int status;
3314 /* Update driver status */
3315 pStats->status = 0;
3317 /* Get the current link quality information */
3318 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3319 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3320 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3322 if( status == HCF_SUCCESS ) {
3323 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3325 #ifdef USE_DBM
3326 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3327 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3328 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3330 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3331 IW_QUAL_LEVEL_UPDATED |
3332 IW_QUAL_NOISE_UPDATED |
3333 IW_QUAL_DBM);
3334 #else
3335 pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ),
3336 HCF_MIN_COMM_QUALITY,
3337 HCF_MAX_COMM_QUALITY );
3339 pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ),
3340 HCF_MIN_SIGNAL_LEVEL,
3341 HCF_MAX_SIGNAL_LEVEL );
3343 pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ),
3344 HCF_MIN_NOISE_LEVEL,
3345 HCF_MAX_NOISE_LEVEL );
3347 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3348 IW_QUAL_LEVEL_UPDATED |
3349 IW_QUAL_NOISE_UPDATED);
3350 #endif /* USE_DBM */
3351 } else {
3352 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3355 /* Get the current tallies from the adapter */
3356 /* Only possible when the device is open */
3357 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3358 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3359 /* No endian translation is needed here, as CFG_TALLIES is an
3360 MSF RID; all processing is done on the host, not the card! */
3361 pStats->discard.nwid = 0L;
3362 pStats->discard.code = tallies.RxWEPUndecryptable;
3363 pStats->discard.misc = tallies.TxDiscards +
3364 tallies.RxFCSErrors +
3365 //tallies.RxDiscardsNoBuffer +
3366 tallies.TxDiscardsWrongSA;
3367 //;? Extra taken over from Linux driver based on 7.18 version
3368 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3369 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3370 } else {
3371 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3373 } else {
3374 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3378 DBG_LEAVE( DbgInfo );
3379 return pStats;
3380 } // wl_wireless_stats
3381 /*============================================================================*/
3386 /*******************************************************************************
3387 * wl_get_wireless_stats()
3388 *******************************************************************************
3390 * DESCRIPTION:
3392 * Return the current device wireless statistics. This function calls
3393 * wl_wireless_stats, but acquires spinlocks first as it can be called
3394 * directly by the network layer.
3396 * PARAMETERS:
3398 * wrq - the wireless request buffer
3399 * lp - the device's private adapter structure
3401 * RETURNS:
3403 * 0 on success
3404 * errno value otherwise
3406 ******************************************************************************/
3407 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3409 unsigned long flags;
3410 struct wl_private *lp = wl_priv(dev);
3411 struct iw_statistics *pStats = NULL;
3412 /*------------------------------------------------------------------------*/
3414 DBG_FUNC( "wl_get_wireless_stats" );
3415 DBG_ENTER(DbgInfo);
3417 wl_lock( lp, &flags );
3419 wl_act_int_off( lp );
3421 #ifdef USE_RTS
3422 if( lp->useRTS == 1 ) {
3423 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3424 } else
3425 #endif
3427 pStats = wl_wireless_stats( dev );
3429 wl_act_int_on( lp );
3431 wl_unlock(lp, &flags);
3433 DBG_LEAVE( DbgInfo );
3434 return pStats;
3435 } // wl_get_wireless_stats
3438 /*******************************************************************************
3439 * wl_spy_gather()
3440 *******************************************************************************
3442 * DESCRIPTION:
3444 * Gather wireless spy statistics.
3446 * PARAMETERS:
3448 * wrq - the wireless request buffer
3449 * lp - the device's private adapter structure
3451 * RETURNS:
3453 * 0 on success
3454 * errno value otherwise
3456 ******************************************************************************/
3457 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3459 struct iw_quality wstats;
3460 int status;
3461 u_char stats[2];
3462 DESC_STRCT desc[1];
3463 struct wl_private *lp = wl_priv(dev);
3464 /*------------------------------------------------------------------------*/
3466 /* shortcut */
3467 if (!lp->spy_data.spy_number) {
3468 return;
3471 /* Gather wireless spy statistics: for each packet, compare the source
3472 address with out list, and if match, get the stats. */
3473 memset( stats, 0, sizeof(stats));
3474 memset( desc, 0, sizeof(DESC_STRCT));
3476 desc[0].buf_addr = stats;
3477 desc[0].BUF_SIZE = sizeof(stats);
3478 desc[0].next_desc_addr = 0; // terminate list
3480 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3482 if( status == HCF_SUCCESS ) {
3483 wstats.level = (u_char) dbm(stats[1]);
3484 wstats.noise = (u_char) dbm(stats[0]);
3485 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3487 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3488 IW_QUAL_LEVEL_UPDATED |
3489 IW_QUAL_NOISE_UPDATED |
3490 IW_QUAL_DBM);
3492 wireless_spy_update( dev, mac, &wstats );
3494 } // wl_spy_gather
3495 /*============================================================================*/
3500 /*******************************************************************************
3501 * wl_wext_event_freq()
3502 *******************************************************************************
3504 * DESCRIPTION:
3506 * This function is used to send an event that the channel/freq
3507 * configuration for a specific device has changed.
3510 * PARAMETERS:
3512 * dev - the network device for which this event is to be issued
3514 * RETURNS:
3516 * N/A
3518 ******************************************************************************/
3519 void wl_wext_event_freq( struct net_device *dev )
3521 #if WIRELESS_EXT > 13
3522 union iwreq_data wrqu;
3523 struct wl_private *lp = wl_priv(dev);
3524 /*------------------------------------------------------------------------*/
3527 memset( &wrqu, 0, sizeof( wrqu ));
3529 wrqu.freq.m = lp->Channel;
3530 wrqu.freq.e = 0;
3532 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3533 #endif /* WIRELESS_EXT > 13 */
3535 return;
3536 } // wl_wext_event_freq
3537 /*============================================================================*/
3542 /*******************************************************************************
3543 * wl_wext_event_mode()
3544 *******************************************************************************
3546 * DESCRIPTION:
3548 * This function is used to send an event that the mode of operation
3549 * for a specific device has changed.
3552 * PARAMETERS:
3554 * dev - the network device for which this event is to be issued
3556 * RETURNS:
3558 * N/A
3560 ******************************************************************************/
3561 void wl_wext_event_mode( struct net_device *dev )
3563 #if WIRELESS_EXT > 13
3564 union iwreq_data wrqu;
3565 struct wl_private *lp = wl_priv(dev);
3566 /*------------------------------------------------------------------------*/
3569 memset( &wrqu, 0, sizeof( wrqu ));
3571 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3572 wrqu.mode = IW_MODE_INFRA;
3573 } else {
3574 wrqu.mode = IW_MODE_MASTER;
3577 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3578 #endif /* WIRELESS_EXT > 13 */
3580 return;
3581 } // wl_wext_event_mode
3582 /*============================================================================*/
3587 /*******************************************************************************
3588 * wl_wext_event_essid()
3589 *******************************************************************************
3591 * DESCRIPTION:
3593 * This function is used to send an event that the ESSID configuration for
3594 * a specific device has changed.
3597 * PARAMETERS:
3599 * dev - the network device for which this event is to be issued
3601 * RETURNS:
3603 * N/A
3605 ******************************************************************************/
3606 void wl_wext_event_essid( struct net_device *dev )
3608 #if WIRELESS_EXT > 13
3609 union iwreq_data wrqu;
3610 struct wl_private *lp = wl_priv(dev);
3611 /*------------------------------------------------------------------------*/
3614 memset( &wrqu, 0, sizeof( wrqu ));
3616 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3617 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3618 the call to wireless_send_event() must also point to where the ESSID
3619 lives */
3620 wrqu.essid.length = strlen( lp->NetworkName );
3621 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3622 wrqu.essid.flags = 1;
3624 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3625 #endif /* WIRELESS_EXT > 13 */
3627 return;
3628 } // wl_wext_event_essid
3629 /*============================================================================*/
3634 /*******************************************************************************
3635 * wl_wext_event_encode()
3636 *******************************************************************************
3638 * DESCRIPTION:
3640 * This function is used to send an event that the encryption configuration
3641 * for a specific device has changed.
3644 * PARAMETERS:
3646 * dev - the network device for which this event is to be issued
3648 * RETURNS:
3650 * N/A
3652 ******************************************************************************/
3653 void wl_wext_event_encode( struct net_device *dev )
3655 #if WIRELESS_EXT > 13
3656 union iwreq_data wrqu;
3657 struct wl_private *lp = wl_priv(dev);
3658 int index = 0;
3659 /*------------------------------------------------------------------------*/
3662 memset( &wrqu, 0, sizeof( wrqu ));
3664 if( lp->EnableEncryption == 0 ) {
3665 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3666 } else {
3667 wrqu.encoding.flags |= lp->TransmitKeyID;
3669 index = lp->TransmitKeyID - 1;
3671 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3672 if we're in AP mode */
3673 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3674 //;?should we restore this to allow smaller memory footprint
3676 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3677 if( lp->ExcludeUnencrypted ) {
3678 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3679 } else {
3680 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3684 #endif // HCF_TYPE_AP
3686 /* Only provide the key if permissions allow */
3687 if( capable( CAP_NET_ADMIN )) {
3688 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3689 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3690 } else {
3691 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3695 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3696 lp->DefaultKeys.key[index].key );
3697 #endif /* WIRELESS_EXT > 13 */
3699 return;
3700 } // wl_wext_event_encode
3701 /*============================================================================*/
3706 /*******************************************************************************
3707 * wl_wext_event_ap()
3708 *******************************************************************************
3710 * DESCRIPTION:
3712 * This function is used to send an event that the device has been
3713 * associated to a new AP.
3716 * PARAMETERS:
3718 * dev - the network device for which this event is to be issued
3720 * RETURNS:
3722 * N/A
3724 ******************************************************************************/
3725 void wl_wext_event_ap( struct net_device *dev )
3727 #if WIRELESS_EXT > 13
3728 union iwreq_data wrqu;
3729 struct wl_private *lp = wl_priv(dev);
3730 int status;
3731 /*------------------------------------------------------------------------*/
3734 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3735 this event BEFORE sending the association event, as there are timing
3736 issues with the hostap supplicant. The supplicant will attempt to process
3737 an EAPOL-Key frame from an AP before receiving this information, which
3738 is required properly process the said frame. */
3739 wl_wext_event_assoc_ie( dev );
3741 /* Get the BSSID */
3742 lp->ltvRecord.typ = CFG_CUR_BSSID;
3743 lp->ltvRecord.len = 4;
3745 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3746 if( status == HCF_SUCCESS ) {
3747 memset( &wrqu, 0, sizeof( wrqu ));
3749 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3751 wrqu.addr.sa_family = ARPHRD_ETHER;
3753 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3756 #endif /* WIRELESS_EXT > 13 */
3758 return;
3759 } // wl_wext_event_ap
3760 /*============================================================================*/
3764 /*******************************************************************************
3765 * wl_wext_event_scan_complete()
3766 *******************************************************************************
3768 * DESCRIPTION:
3770 * This function is used to send an event that a request for a network scan
3771 * has completed.
3774 * PARAMETERS:
3776 * dev - the network device for which this event is to be issued
3778 * RETURNS:
3780 * N/A
3782 ******************************************************************************/
3783 void wl_wext_event_scan_complete( struct net_device *dev )
3785 #if WIRELESS_EXT > 13
3786 union iwreq_data wrqu;
3787 /*------------------------------------------------------------------------*/
3790 memset( &wrqu, 0, sizeof( wrqu ));
3792 wrqu.addr.sa_family = ARPHRD_ETHER;
3793 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3794 #endif /* WIRELESS_EXT > 13 */
3796 return;
3797 } // wl_wext_event_scan_complete
3798 /*============================================================================*/
3803 /*******************************************************************************
3804 * wl_wext_event_new_sta()
3805 *******************************************************************************
3807 * DESCRIPTION:
3809 * This function is used to send an event that an AP has registered a new
3810 * station.
3813 * PARAMETERS:
3815 * dev - the network device for which this event is to be issued
3817 * RETURNS:
3819 * N/A
3821 ******************************************************************************/
3822 void wl_wext_event_new_sta( struct net_device *dev )
3824 #if WIRELESS_EXT > 14
3825 union iwreq_data wrqu;
3826 /*------------------------------------------------------------------------*/
3829 memset( &wrqu, 0, sizeof( wrqu ));
3831 /* Send the station's mac address here */
3832 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3833 wrqu.addr.sa_family = ARPHRD_ETHER;
3834 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3835 #endif /* WIRELESS_EXT > 14 */
3837 return;
3838 } // wl_wext_event_new_sta
3839 /*============================================================================*/
3844 /*******************************************************************************
3845 * wl_wext_event_expired_sta()
3846 *******************************************************************************
3848 * DESCRIPTION:
3850 * This function is used to send an event that an AP has deregistered a
3851 * station.
3854 * PARAMETERS:
3856 * dev - the network device for which this event is to be issued
3858 * RETURNS:
3860 * N/A
3862 ******************************************************************************/
3863 void wl_wext_event_expired_sta( struct net_device *dev )
3865 #if WIRELESS_EXT > 14
3866 union iwreq_data wrqu;
3867 /*------------------------------------------------------------------------*/
3870 memset( &wrqu, 0, sizeof( wrqu ));
3872 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3873 wrqu.addr.sa_family = ARPHRD_ETHER;
3874 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3875 #endif /* WIRELESS_EXT > 14 */
3877 return;
3878 } // wl_wext_event_expired_sta
3879 /*============================================================================*/
3884 /*******************************************************************************
3885 * wl_wext_event_mic_failed()
3886 *******************************************************************************
3888 * DESCRIPTION:
3890 * This function is used to send an event that MIC calculations failed.
3893 * PARAMETERS:
3895 * dev - the network device for which this event is to be issued
3897 * RETURNS:
3899 * N/A
3901 ******************************************************************************/
3902 void wl_wext_event_mic_failed( struct net_device *dev )
3904 #if WIRELESS_EXT > 14
3905 char msg[512];
3906 union iwreq_data wrqu;
3907 struct wl_private *lp = wl_priv(dev);
3908 int key_idx;
3909 char *addr1;
3910 char *addr2;
3911 WVLAN_RX_WMP_HDR *hdr;
3912 /*------------------------------------------------------------------------*/
3915 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3916 key_idx &= 0x03;
3918 /* Cast the lookahead buffer into a RFS format */
3919 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3921 /* Cast the addresses to byte buffers, as in the above RFS they are word
3922 length */
3923 addr1 = (char *)hdr->address1;
3924 addr2 = (char *)hdr->address2;
3926 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3927 hdr->status );
3929 memset( &wrqu, 0, sizeof( wrqu ));
3930 memset( msg, 0, sizeof( msg ));
3933 /* Becuase MIC failures are not part of the Wireless Extensions yet, they
3934 must be passed as a string using an IWEVCUSTOM event. In order for the
3935 event to be effective, the string format must be known by both the
3936 driver and the supplicant. The following is the string format used by the
3937 hostap project's WPA supplicant, and will be used here until the Wireless
3938 Extensions interface adds this support:
3940 MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2)
3943 /* NOTE: Format of MAC address (using colons to seperate bytes) may cause
3944 a problem in future versions of the supplicant, if they ever
3945 actually parse these parameters */
3946 #if DBG
3947 sprintf( msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
3948 "%s)", key_idx, addr1[0] & 0x01 ? "broad" : "uni",
3949 DbgHwAddr( addr2 ));
3950 #endif
3951 wrqu.data.length = strlen( msg );
3952 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
3953 #endif /* WIRELESS_EXT > 14 */
3955 return;
3956 } // wl_wext_event_mic_failed
3957 /*============================================================================*/
3962 /*******************************************************************************
3963 * wl_wext_event_assoc_ie()
3964 *******************************************************************************
3966 * DESCRIPTION:
3968 * This function is used to send an event containing the WPA-IE generated
3969 * by the firmware in an association request.
3972 * PARAMETERS:
3974 * dev - the network device for which this event is to be issued
3976 * RETURNS:
3978 * N/A
3980 ******************************************************************************/
3981 void wl_wext_event_assoc_ie( struct net_device *dev )
3983 #if WIRELESS_EXT > 14
3984 char msg[512];
3985 union iwreq_data wrqu;
3986 struct wl_private *lp = wl_priv(dev);
3987 int status;
3988 PROBE_RESP data;
3989 hcf_16 length;
3990 hcf_8 *wpa_ie;
3991 /*------------------------------------------------------------------------*/
3994 memset( &wrqu, 0, sizeof( wrqu ));
3995 memset( msg, 0, sizeof( msg ));
3997 /* Retrieve the Association Request IE */
3998 lp->ltvRecord.len = 45;
3999 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
4001 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
4002 if( status == HCF_SUCCESS )
4004 length = 0;
4005 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
4006 wpa_ie = wl_parse_wpa_ie( &data, &length );
4008 /* Becuase this event (Association WPA-IE) is not part of the Wireless
4009 Extensions yet, it must be passed as a string using an IWEVCUSTOM event.
4010 In order for the event to be effective, the string format must be known
4011 by both the driver and the supplicant. The following is the string format
4012 used by the hostap project's WPA supplicant, and will be used here until
4013 the Wireless Extensions interface adds this support:
4015 ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE)
4018 if( length != 0 )
4020 sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length ));
4021 wrqu.data.length = strlen( msg );
4022 wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg );
4025 #endif /* WIRELESS_EXT > 14 */
4027 return;
4028 } // wl_wext_event_assoc_ie
4029 /*============================================================================*/
4030 /* Structures to export the Wireless Handlers */
4032 static const iw_handler wl_handler[] =
4034 (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */
4035 (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */
4036 (iw_handler) NULL, /* SIOCSIWNWID */
4037 (iw_handler) NULL, /* SIOCGIWNWID */
4038 (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */
4039 (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */
4040 (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */
4041 (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */
4042 (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */
4043 (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */
4044 (iw_handler) NULL , /* SIOCSIWRANGE */
4045 (iw_handler) wireless_get_range, /* SIOCGIWRANGE */
4046 (iw_handler) NULL , /* SIOCSIWPRIV */
4047 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
4048 (iw_handler) NULL , /* SIOCSIWSTATS */
4049 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
4050 iw_handler_set_spy, /* SIOCSIWSPY */
4051 iw_handler_get_spy, /* SIOCGIWSPY */
4052 NULL, /* SIOCSIWTHRSPY */
4053 NULL, /* SIOCGIWTHRSPY */
4054 (iw_handler) NULL, /* SIOCSIWAP */
4055 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4056 (iw_handler) wireless_get_bssid, /* SIOCGIWAP */
4057 #else
4058 (iw_handler) NULL, /* SIOCGIWAP */
4059 #endif
4060 (iw_handler) NULL, /* SIOCSIWMLME */
4061 (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */
4062 (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */
4063 (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */
4064 (iw_handler) wireless_set_essid, /* SIOCSIWESSID */
4065 (iw_handler) wireless_get_essid, /* SIOCGIWESSID */
4066 (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */
4067 (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */
4068 (iw_handler) NULL, /* -- hole -- */
4069 (iw_handler) NULL, /* -- hole -- */
4070 (iw_handler) wireless_set_rate, /* SIOCSIWRATE */
4071 (iw_handler) wireless_get_rate, /* SIOCGIWRATE */
4072 (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */
4073 (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */
4074 (iw_handler) NULL, /* SIOCSIWFRAG */
4075 (iw_handler) NULL, /* SIOCGIWFRAG */
4076 (iw_handler) NULL, /* SIOCSIWTXPOW */
4077 (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */
4078 (iw_handler) NULL, /* SIOCSIWRETRY */
4079 (iw_handler) NULL, /* SIOCGIWRETRY */
4080 (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */
4081 (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */
4082 (iw_handler) wireless_set_power, /* SIOCSIWPOWER */
4083 (iw_handler) wireless_get_power, /* SIOCGIWPOWER */
4084 (iw_handler) NULL, /* -- hole -- */
4085 (iw_handler) NULL, /* -- hole -- */
4086 (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */
4087 (iw_handler) NULL, /* SIOCGIWGENIE */
4088 (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */
4089 (iw_handler) NULL, /* SIOCGIWAUTH */
4090 (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */
4091 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
4092 (iw_handler) NULL, /* SIOCSIWPMKSA */
4093 (iw_handler) NULL, /* -- hole -- */
4096 static const iw_handler wl_private_handler[] =
4097 { /* SIOCIWFIRSTPRIV + */
4098 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
4099 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
4100 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
4101 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
4102 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
4103 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
4104 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
4105 #endif
4108 struct iw_priv_args wl_priv_args[] = {
4109 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
4110 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
4111 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
4112 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
4113 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
4114 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
4115 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
4116 #endif
4119 const struct iw_handler_def wl_iw_handler_def =
4121 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
4122 .private = (iw_handler *) wl_private_handler,
4123 .private_args = (struct iw_priv_args *) wl_priv_args,
4124 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
4125 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
4126 .standard = (iw_handler *) wl_handler,
4127 .get_wireless_stats = wl_get_wireless_stats,
4130 #endif // WIRELESS_EXT