1 /*******************************************************************************
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
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
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.
42 * THIS SOFTWARE IS PROVIDED
\93AS IS
\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
43 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
45 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
46 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
55 ******************************************************************************/
57 /*******************************************************************************
59 ******************************************************************************/
60 #include <wl_version.h>
62 #include <linux/if_arp.h>
63 #include <linux/ioport.h>
64 #include <linux/delay.h>
65 #include <linux/etherdevice.h>
66 #include <asm/uaccess.h>
73 #include <wl_internal.h>
79 /*******************************************************************************
81 ******************************************************************************/
83 extern dbg_info_t *DbgInfo;
87 /* Set up the LTV to program the appropriate key */
88 static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr,
89 int set_tx, u8 *seq, u8 *key, size_t key_len)
93 hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] =
94 { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
99 * Check the key index here; if 0, load as Pairwise Key, otherwise,
100 * load as a group key. Note that for the Hermes, the RIDs for
101 * group/pairwise keys are different from each other and different
102 * than the default WEP keys as well.
107 ltv->typ = CFG_ADD_TKIP_MAPPED_KEY;
110 memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN);
113 /* Load the TKIP key */
114 memcpy(<v->u.u8[buf_idx], &key[0], 16);
118 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
119 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
122 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
123 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
125 /* Load the TxMIC key */
126 memcpy(<v->u.u8[buf_idx], &key[16], 8);
129 /* Load the RxMIC key */
130 memcpy(<v->u.u8[buf_idx], &key[24], 8);
138 ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY;
140 /* Load the key Index */
142 /* If this is a Tx Key, set bit 8000 */
145 ltv->u.u16[buf_idx] = cpu_to_le16(key_idx);
149 memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE);
150 buf_idx += IW_ENCODE_SEQ_MAX_SIZE;
152 /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
153 CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
154 memcpy(<v->u.u8[buf_idx], key, key_len);
158 memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE);
170 /* Set up the LTV to clear the appropriate key */
171 static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr)
177 if (!is_broadcast_ether_addr(addr)) {
179 ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY;
180 memcpy(<v->u.u8[0], addr, ETH_ALEN);
187 /* Clear the Group TKIP keys by index */
189 ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
190 ltv->u.u16[0] = cpu_to_le16(key_idx);
201 /* Set the WEP keys in the wl_private structure */
202 static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx,
203 u8 *key, size_t key_len,
204 bool enable, bool set_tx)
206 hcf_8 encryption_state = lp->EnableEncryption;
207 int tk = lp->TransmitKeyID - 1; /* current key */
210 /* Is encryption supported? */
211 if (!wl_has_wep(&(lp->hcfCtx))) {
212 DBG_WARNING(DbgInfo, "WEP not supported on this device\n");
217 DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n",
220 /* Check the size of the key */
225 /* Check the index */
226 if ((key_idx < 0) || (key_idx >= MAX_KEYS))
230 memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE);
232 /* Copy the key in the driver */
233 memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len);
236 lp->DefaultKeys.key[key_idx].len = key_len;
238 DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len);
239 DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n",
240 lp->DefaultKeys.key[key_idx].key,
241 lp->DefaultKeys.key[key_idx].len, key_idx);
243 /* Enable WEP (if possible) */
244 if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0))
245 lp->EnableEncryption = 1;
250 /* Do we want to just set the current transmit key? */
251 if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) {
252 DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx,
253 lp->DefaultKeys.key[key_idx].len);
255 if (lp->DefaultKeys.key[key_idx].len > 0) {
256 lp->TransmitKeyID = key_idx + 1;
257 lp->EnableEncryption = 1;
259 DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n");
266 DBG_WARNING(DbgInfo, "Invalid Key length\n");
273 lp->EnableEncryption = 1;
274 lp->wext_enc = IW_ENCODE_ALG_WEP;
276 lp->EnableEncryption = 0; /* disable encryption */
277 lp->wext_enc = IW_ENCODE_ALG_NONE;
280 DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state);
281 DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption);
282 DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len);
284 /* Write the changes to the card */
286 DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption,
289 if (lp->EnableEncryption == encryption_state) {
291 /* Dynamic WEP key update */
295 /* To switch encryption on/off, soft reset is
305 /*******************************************************************************
307 *******************************************************************************
316 * wrq - the wireless request buffer
322 ******************************************************************************/
323 static int wireless_commit(struct net_device *dev,
324 struct iw_request_info *info,
325 union iwreq_data *rqu, char *extra)
327 struct wl_private *lp = wl_priv(dev);
330 /*------------------------------------------------------------------------*/
332 DBG_FUNC( "wireless_commit" );
335 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
340 wl_lock( lp, &flags );
342 wl_act_int_off( lp );
348 wl_unlock(lp, &flags);
351 DBG_LEAVE( DbgInfo );
354 /*============================================================================*/
359 /*******************************************************************************
360 * wireless_get_protocol()
361 *******************************************************************************
365 * Returns a vendor-defined string that should identify the wireless
370 * wrq - the wireless request buffer
376 ******************************************************************************/
377 static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra)
379 DBG_FUNC( "wireless_get_protocol" );
380 DBG_ENTER( DbgInfo );
382 /* Originally, the driver was placing the string "Wireless" here. However,
383 the wireless extensions (/linux/wireless.h) indicate this string should
384 describe the wireless protocol. */
386 strcpy(name, "IEEE 802.11b");
390 } // wireless_get_protocol
391 /*============================================================================*/
396 /*******************************************************************************
397 * wireless_set_frequency()
398 *******************************************************************************
402 * Sets the frequency (channel) on which the card should Tx/Rx.
406 * wrq - the wireless request buffer
407 * lp - the device's private adapter structure
412 * errno value otherwise
414 ******************************************************************************/
415 static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
417 struct wl_private *lp = wl_priv(dev);
421 /*------------------------------------------------------------------------*/
424 DBG_FUNC( "wireless_set_frequency" );
425 DBG_ENTER( DbgInfo );
427 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
432 if( !capable( CAP_NET_ADMIN )) {
434 DBG_LEAVE( DbgInfo );
439 /* If frequency specified, look up channel */
441 int f = freq->m / 100000;
442 channel = wl_get_chan_from_freq( f );
446 /* Channel specified */
452 /* If the channel is an 802.11a channel, set Bit 8 */
454 channel = channel | 0x100;
458 wl_lock( lp, &flags );
460 wl_act_int_off( lp );
462 lp->Channel = channel;
465 /* Commit the adapter parameters */
468 /* Send an event that channel/freq has been set */
469 wl_wext_event_freq( lp->dev );
473 wl_unlock(lp, &flags);
476 DBG_LEAVE( DbgInfo );
478 } // wireless_set_frequency
479 /*============================================================================*/
484 /*******************************************************************************
485 * wireless_get_frequency()
486 *******************************************************************************
490 * Gets the frequency (channel) on which the card is Tx/Rx.
494 * wrq - the wireless request buffer
495 * lp - the device's private adapter structure
501 ******************************************************************************/
502 static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra)
505 struct wl_private *lp = wl_priv(dev);
508 /*------------------------------------------------------------------------*/
511 DBG_FUNC( "wireless_get_frequency" );
512 DBG_ENTER( DbgInfo );
514 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
519 wl_lock( lp, &flags );
521 wl_act_int_off( lp );
523 lp->ltvRecord.len = 2;
524 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
526 ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord ));
527 if( ret == HCF_SUCCESS ) {
528 hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
530 freq->m = wl_get_freq_from_chan( channel ) * 100000;
536 wl_unlock(lp, &flags);
538 ret = (ret == HCF_SUCCESS ? 0 : -EFAULT);
541 DBG_LEAVE( DbgInfo );
543 } // wireless_get_frequency
544 /*============================================================================*/
549 /*******************************************************************************
550 * wireless_get_range()
551 *******************************************************************************
555 * This function is used to provide misc info and statistics about the
560 * wrq - the wireless request buffer
561 * lp - the device's private adapter structure
566 * errno value otherwise
568 ******************************************************************************/
569 static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
571 struct wl_private *lp = wl_priv(dev);
573 struct iw_range *range = (struct iw_range *) extra;
579 /*------------------------------------------------------------------------*/
582 DBG_FUNC( "wireless_get_range" );
583 DBG_ENTER( DbgInfo );
585 /* Set range information */
586 data->length = sizeof(struct iw_range);
587 memset(range, 0, sizeof(struct iw_range));
589 wl_lock( lp, &flags );
591 wl_act_int_off( lp );
593 /* Set range information */
594 memset( range, 0, sizeof( struct iw_range ));
597 /* Get the current transmit rate from the adapter */
598 lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16));
599 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
601 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
602 if( status != HCF_SUCCESS ) {
603 /* Recovery action: reset and retry up to 10 times */
604 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status );
609 /* Holding the lock too long, makes a gap to allow other processes */
610 wl_unlock(lp, &flags);
611 wl_lock( lp, &flags );
613 status = wl_reset( dev );
614 if ( status != HCF_SUCCESS ) {
615 DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status );
621 /* Holding the lock too long, makes a gap to allow other processes */
622 wl_unlock(lp, &flags);
623 wl_lock( lp, &flags );
628 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries );
634 /* Holding the lock too long, makes a gap to allow other processes */
635 wl_unlock(lp, &flags);
636 wl_lock( lp, &flags );
638 pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 );
640 range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT;
643 DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries );
646 // NWID - NOT SUPPORTED
649 /* Channel/Frequency Info */
650 range->num_channels = RADIO_CHANNELS;
653 /* Signal Level Thresholds */
654 range->sensitivity = RADIO_SENSITIVITY_LEVELS;
658 range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY;
660 /* If the value returned in /proc/net/wireless is greater than the maximum range,
661 iwconfig assumes that the value is in dBm. Because an unsigned char is used,
662 it requires a bit of contorsion... */
664 range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 );
665 range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 );
668 /* Set available rates */
669 range->num_bitrates = 0;
671 lp->ltvRecord.len = 6;
672 lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES;
674 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
675 if( status == HCF_SUCCESS ) {
676 for( count = 0; count < MAX_RATES; count++ )
677 if( lp->ltvRecord.u.u8[count+2] != 0 ) {
678 range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2;
679 range->num_bitrates++;
682 DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status );
687 /* RTS Threshold info */
688 range->min_rts = MIN_RTS_BYTES;
689 range->max_rts = MAX_RTS_BYTES;
691 // Frag Threshold info - NOT SUPPORTED
693 // Power Management info - NOT SUPPORTED
697 /* Holding the lock too long, makes a gap to allow other processes */
698 wl_unlock(lp, &flags);
699 wl_lock( lp, &flags );
701 /* Is WEP supported? */
703 if( wl_has_wep( &( lp->hcfCtx ))) {
704 /* WEP: RC4 40 bits */
705 range->encoding_size[0] = MIN_KEY_SIZE;
708 range->encoding_size[1] = MAX_KEY_SIZE;
709 range->num_encoding_sizes = 2;
710 range->max_encoding_tokens = MAX_KEYS;
714 range->txpower_capa = IW_TXPOW_MWATT;
715 range->num_txpower = 1;
716 range->txpower[0] = RADIO_TX_POWER_MWATT;
718 /* Wireless Extension Info */
719 range->we_version_compiled = WIRELESS_EXT;
720 range->we_version_source = WIRELESS_SUPPORT;
722 // Retry Limits and Lifetime - NOT SUPPORTED
724 /* Holding the lock too long, makes a gap to allow other processes */
725 wl_unlock(lp, &flags);
726 wl_lock( lp, &flags );
728 DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" );
729 wl_wireless_stats( lp->dev );
730 range->avg_qual = lp->wstats.qual;
731 DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" );
733 /* Event capability (kernel + driver) */
734 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
735 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
736 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
737 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
738 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
739 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
740 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
741 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
743 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
744 range->scan_capa = IW_SCAN_CAPA_NONE;
749 wl_unlock(lp, &flags);
753 } // wireless_get_range
754 /*============================================================================*/
757 /*******************************************************************************
758 * wireless_get_bssid()
759 *******************************************************************************
763 * Gets the BSSID the wireless device is currently associated with.
767 * wrq - the wireless request buffer
768 * lp - the device's private adapter structure
773 * errno value otherwise
775 ******************************************************************************/
776 static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
778 struct wl_private *lp = wl_priv(dev);
781 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
783 #endif /* (HCF_TYPE) & HCF_TYPE_STA */
784 /*------------------------------------------------------------------------*/
787 DBG_FUNC( "wireless_get_bssid" );
788 DBG_ENTER( DbgInfo );
790 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
795 wl_lock( lp, &flags );
797 wl_act_int_off( lp );
799 memset( &ap_addr->sa_data, 0, ETH_ALEN );
801 ap_addr->sa_family = ARPHRD_ETHER;
803 /* Assume AP mode here, which means the BSSID is our own MAC address. In
804 STA mode, this address will be overwritten with the actual BSSID using
806 memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN);
809 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
810 //;?should we return an error status in AP mode
812 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
813 /* Get Current BSSID */
814 lp->ltvRecord.typ = CFG_CUR_BSSID;
815 lp->ltvRecord.len = 4;
816 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
818 if( status == HCF_SUCCESS ) {
819 /* Copy info into sockaddr struct */
820 memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN);
826 #endif // (HCF_TYPE) & HCF_TYPE_STA
830 wl_unlock(lp, &flags);
835 } // wireless_get_bssid
836 /*============================================================================*/
841 /*******************************************************************************
842 * wireless_get_ap_list()
843 *******************************************************************************
847 * Gets the results of a network scan.
851 * wrq - the wireless request buffer
852 * lp - the device's private adapter structure
857 * errno value otherwise
859 * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function
860 * implements SIOCGIWAPLIST only to provide backwards compatibility. For
861 * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN!
863 ******************************************************************************/
864 static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
866 struct wl_private *lp = wl_priv(dev);
872 struct sockaddr *hwa = NULL;
873 struct iw_quality *qual = NULL;
875 ScanResult *p = &lp->scan_results;
877 ProbeResult *p = &lp->probe_results;
879 /*------------------------------------------------------------------------*/
881 DBG_FUNC( "wireless_get_ap_list" );
882 DBG_ENTER( DbgInfo );
884 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
889 wl_lock( lp, &flags );
891 wl_act_int_off( lp );
893 /* Set the completion state to FALSE */
894 lp->scan_results.scan_complete = FALSE;
895 lp->probe_results.scan_complete = FALSE;
896 /* Channels to scan */
897 lp->ltvRecord.len = 2;
898 lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ;
899 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
900 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
901 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret );
903 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
904 disassociate from the network we are currently on */
905 lp->ltvRecord.len = 2;
906 lp->ltvRecord.typ = CFG_SCAN_SSID;
907 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
908 ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
909 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret );
911 /* Initiate the scan */
913 ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN );
915 ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
920 //;? unlock? what about the access to lp below? is it broken?
921 wl_unlock(lp, &flags);
923 if( ret == HCF_SUCCESS ) {
924 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
925 while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) {
926 DBG_TRACE( DbgInfo, "Waiting for scan results...\n" );
927 /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */
928 if( sec_count++ > MAX_SCAN_TIME_SEC ) {
931 /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do
932 other things in the meantime, This prevents system lockups by
933 giving some time back to the kernel */
934 for( count = 0; count < 100; count ++ ) {
943 if ( ret != HCF_SUCCESS ) {
944 DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" );
946 num_aps = (*p)/*lp->probe_results*/.num_aps;
947 if (num_aps > IW_MAX_AP) {
950 data->length = num_aps;
951 hwa = (struct sockaddr *)extra;
952 qual = (struct iw_quality *) extra +
953 ( sizeof( struct sockaddr ) * num_aps );
955 /* This flag is used to tell the user if we provide quality
956 information. Since we provide signal/noise levels but no
957 quality info on a scan, this is set to 0. Setting to 1 and
958 providing a quality of 0 produces weird results. If we ever
959 provide quality (or can calculate it), this can be changed */
962 for( count = 0; count < num_aps; count++ ) {
964 memcpy( hwa[count].sa_data,
965 (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN );
966 #else //;?why use BSSID and bssid as names in seemingly very comparable situations
967 DBG_PRINT("BSSID: %pM\n",
968 (*p).ProbeTable[count].BSSID);
969 memcpy( hwa[count].sa_data,
970 (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN );
973 /* Once the data is copied to the wireless struct, invalidate the
974 scan result to initiate a rescan on the next request */
975 (*p)/*lp->probe_results*/.scan_complete = FALSE;
976 /* Send the wireless event that the scan has completed, just in case
978 wl_wext_event_scan_complete( lp->dev );
982 DBG_LEAVE( DbgInfo );
984 } // wireless_get_ap_list
985 /*============================================================================*/
990 /*******************************************************************************
991 * wireless_set_sensitivity()
992 *******************************************************************************
996 * Sets the sensitivity (distance between APs) of the wireless card.
1000 * wrq - the wireless request buffer
1001 * lp - the device's private adapter structure
1006 * errno value otherwise
1008 ******************************************************************************/
1009 static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1011 struct wl_private *lp = wl_priv(dev);
1012 unsigned long flags;
1014 int dens = sens->value;
1015 /*------------------------------------------------------------------------*/
1018 DBG_FUNC( "wireless_set_sensitivity" );
1019 DBG_ENTER( DbgInfo );
1021 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1026 if(( dens < 1 ) || ( dens > 3 )) {
1031 wl_lock( lp, &flags );
1033 wl_act_int_off( lp );
1035 lp->DistanceBetweenAPs = dens;
1038 wl_act_int_on( lp );
1040 wl_unlock(lp, &flags);
1043 DBG_LEAVE( DbgInfo );
1045 } // wireless_set_sensitivity
1046 /*============================================================================*/
1051 /*******************************************************************************
1052 * wireless_get_sensitivity()
1053 *******************************************************************************
1057 * Gets the sensitivity (distance between APs) of the wireless card.
1061 * wrq - the wireless request buffer
1062 * lp - the device's private adapter structure
1067 * errno value otherwise
1069 ******************************************************************************/
1070 static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra)
1072 struct wl_private *lp = wl_priv(dev);
1074 /*------------------------------------------------------------------------*/
1075 /*------------------------------------------------------------------------*/
1078 DBG_FUNC( "wireless_get_sensitivity" );
1079 DBG_ENTER( DbgInfo );
1081 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1086 /* not worth locking ... */
1087 sens->value = lp->DistanceBetweenAPs;
1088 sens->fixed = 0; /* auto */
1090 DBG_LEAVE( DbgInfo );
1092 } // wireless_get_sensitivity
1093 /*============================================================================*/
1098 /*******************************************************************************
1099 * wireless_set_essid()
1100 *******************************************************************************
1104 * Sets the ESSID (network name) that the wireless device should associate
1109 * wrq - the wireless request buffer
1110 * lp - the device's private adapter structure
1115 * errno value otherwise
1117 ******************************************************************************/
1118 static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid)
1120 struct wl_private *lp = wl_priv(dev);
1121 unsigned long flags;
1124 DBG_FUNC( "wireless_set_essid" );
1125 DBG_ENTER( DbgInfo );
1127 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1132 if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
1137 wl_lock( lp, &flags );
1139 wl_act_int_off( lp );
1141 memset( lp->NetworkName, 0, sizeof( lp->NetworkName ));
1143 /* data->flags is zero to ask for "any" */
1144 if( data->flags == 0 ) {
1145 /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP"
1146 * ;?but there ain't no STAP anymore*/
1147 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
1148 strcpy( lp->NetworkName, "ANY" );
1150 //strcpy( lp->NetworkName, "ANY" );
1151 strcpy( lp->NetworkName, PARM_DEFAULT_SSID );
1154 memcpy( lp->NetworkName, ssid, data->length );
1157 DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid );
1159 /* Commit the adapter parameters */
1162 /* Send an event that ESSID has been set */
1163 wl_wext_event_essid( lp->dev );
1165 wl_act_int_on( lp );
1167 wl_unlock(lp, &flags);
1170 DBG_LEAVE( DbgInfo );
1172 } // wireless_set_essid
1173 /*============================================================================*/
1178 /*******************************************************************************
1179 * wireless_get_essid()
1180 *******************************************************************************
1184 * Gets the ESSID (network name) that the wireless device is associated
1189 * wrq - the wireless request buffer
1190 * lp - the device's private adapter structure
1195 * errno value otherwise
1197 ******************************************************************************/
1198 static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid)
1201 struct wl_private *lp = wl_priv(dev);
1202 unsigned long flags;
1206 /*------------------------------------------------------------------------*/
1209 DBG_FUNC( "wireless_get_essid" );
1210 DBG_ENTER( DbgInfo );
1212 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1217 wl_lock( lp, &flags );
1219 wl_act_int_off( lp );
1221 /* Get the desired network name */
1222 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1225 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1226 //;?should we return an error status in AP mode
1228 lp->ltvRecord.typ = CFG_DESIRED_SSID;
1233 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
1234 //;?should we restore this to allow smaller memory footprint
1236 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1237 lp->ltvRecord.typ = CFG_CNF_OWN_SSID;
1243 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1244 if( status == HCF_SUCCESS ) {
1245 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1247 /* Endian translate the string length */
1248 pName->length = CNV_LITTLE_TO_INT( pName->length );
1250 /* Copy the information into the user buffer */
1251 data->length = pName->length;
1253 if( pName->length < HCF_MAX_NAME_LEN ) {
1254 pName->name[pName->length] = '\0';
1260 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
1261 //;?should we return an error status in AP mode
1263 /* if desired is null ("any"), return current or "any" */
1264 if( pName->name[0] == '\0' ) {
1265 /* Get the current network name */
1266 lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 ));
1267 lp->ltvRecord.typ = CFG_CUR_SSID;
1269 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1271 if( status == HCF_SUCCESS ) {
1272 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1274 /* Endian translate the string length */
1275 pName->length = CNV_LITTLE_TO_INT( pName->length );
1277 /* Copy the information into the user buffer */
1278 data->length = pName->length;
1288 if (pName->length > IW_ESSID_MAX_SIZE) {
1293 memcpy(essid, pName->name, pName->length);
1300 wl_act_int_on( lp );
1302 wl_unlock(lp, &flags);
1305 DBG_LEAVE( DbgInfo );
1307 } // wireless_get_essid
1308 /*============================================================================*/
1313 /*******************************************************************************
1314 * wireless_set_encode()
1315 *******************************************************************************
1319 * Sets the encryption keys and status (enable or disable).
1323 * wrq - the wireless request buffer
1324 * lp - the device's private adapter structure
1329 * errno value otherwise
1331 ******************************************************************************/
1332 static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf)
1334 struct wl_private *lp = wl_priv(dev);
1335 unsigned long flags;
1336 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
1342 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
1347 if (erq->flags & IW_ENCODE_DISABLED)
1350 wl_lock(lp, &flags);
1354 ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length,
1357 /* Send an event that Encryption has been set */
1359 wl_wext_event_encode(dev);
1363 wl_unlock(lp, &flags);
1370 /*******************************************************************************
1371 * wireless_get_encode()
1372 *******************************************************************************
1376 * Gets the encryption keys and status.
1380 * wrq - the wireless request buffer
1381 * lp - the device's private adapter structure
1386 * errno value otherwise
1388 ******************************************************************************/
1389 static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key)
1392 struct wl_private *lp = wl_priv(dev);
1393 unsigned long flags;
1396 /*------------------------------------------------------------------------*/
1399 DBG_FUNC( "wireless_get_encode" );
1400 DBG_ENTER( DbgInfo );
1401 DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID);
1403 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1408 /* Only super-user can see WEP key */
1409 if( !capable( CAP_NET_ADMIN )) {
1411 DBG_LEAVE( DbgInfo );
1415 wl_lock( lp, &flags );
1417 wl_act_int_off( lp );
1419 /* Is it supported? */
1420 if( !wl_has_wep( &( lp->hcfCtx ))) {
1425 /* Basic checking */
1426 index = (erq->flags & IW_ENCODE_INDEX ) - 1;
1432 if( lp->EnableEncryption == 0 ) {
1433 erq->flags |= IW_ENCODE_DISABLED;
1436 /* Which key do we want */
1437 if(( index < 0 ) || ( index >= MAX_KEYS )) {
1438 index = lp->TransmitKeyID - 1;
1441 erq->flags |= index + 1;
1443 /* Copy the key to the user buffer */
1444 erq->length = lp->DefaultKeys.key[index].len;
1446 memcpy(key, lp->DefaultKeys.key[index].key, erq->length);
1450 wl_act_int_on( lp );
1452 wl_unlock(lp, &flags);
1455 DBG_LEAVE( DbgInfo );
1457 } // wireless_get_encode
1458 /*============================================================================*/
1463 /*******************************************************************************
1464 * wireless_set_nickname()
1465 *******************************************************************************
1469 * Sets the nickname, or station name, of the wireless device.
1473 * wrq - the wireless request buffer
1474 * lp - the device's private adapter structure
1479 * errno value otherwise
1481 ******************************************************************************/
1482 static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1484 struct wl_private *lp = wl_priv(dev);
1485 unsigned long flags;
1487 /*------------------------------------------------------------------------*/
1490 DBG_FUNC( "wireless_set_nickname" );
1491 DBG_ENTER( DbgInfo );
1493 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1498 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1499 if( !capable(CAP_NET_ADMIN )) {
1501 DBG_LEAVE( DbgInfo );
1506 /* Validate the new value */
1507 if(data->length > HCF_MAX_NAME_LEN) {
1512 wl_lock( lp, &flags );
1514 wl_act_int_off( lp );
1516 memset( lp->StationName, 0, sizeof( lp->StationName ));
1518 memcpy( lp->StationName, nickname, data->length );
1520 /* Commit the adapter parameters */
1523 wl_act_int_on( lp );
1525 wl_unlock(lp, &flags);
1528 DBG_LEAVE( DbgInfo );
1530 } // wireless_set_nickname
1531 /*============================================================================*/
1536 /*******************************************************************************
1537 * wireless_get_nickname()
1538 *******************************************************************************
1542 * Gets the nickname, or station name, of the wireless device.
1546 * wrq - the wireless request buffer
1547 * lp - the device's private adapter structure
1552 * errno value otherwise
1554 ******************************************************************************/
1555 static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname)
1557 struct wl_private *lp = wl_priv(dev);
1558 unsigned long flags;
1562 /*------------------------------------------------------------------------*/
1565 DBG_FUNC( "wireless_get_nickname" );
1566 DBG_ENTER( DbgInfo );
1568 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1573 wl_lock( lp, &flags );
1575 wl_act_int_off( lp );
1577 /* Get the current station name */
1578 lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 ));
1579 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1581 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1583 if( status == HCF_SUCCESS ) {
1584 pName = (wvName_t *)&( lp->ltvRecord.u.u32 );
1586 /* Endian translate the length */
1587 pName->length = CNV_LITTLE_TO_INT( pName->length );
1589 if ( pName->length > IW_ESSID_MAX_SIZE ) {
1592 /* Copy the information into the user buffer */
1593 data->length = pName->length;
1594 memcpy(nickname, pName->name, pName->length);
1600 wl_act_int_on( lp );
1602 wl_unlock(lp, &flags);
1607 } // wireless_get_nickname
1608 /*============================================================================*/
1613 /*******************************************************************************
1614 * wireless_set_porttype()
1615 *******************************************************************************
1619 * Sets the port type of the wireless device.
1623 * wrq - the wireless request buffer
1624 * lp - the device's private adapter structure
1629 * errno value otherwise
1631 ******************************************************************************/
1632 static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1634 struct wl_private *lp = wl_priv(dev);
1635 unsigned long flags;
1639 /*------------------------------------------------------------------------*/
1641 DBG_FUNC( "wireless_set_porttype" );
1642 DBG_ENTER( DbgInfo );
1644 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1649 wl_lock( lp, &flags );
1651 wl_act_int_off( lp );
1653 /* Validate the new value */
1657 /* When user requests ad-hoc, set IBSS mode! */
1661 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1669 /* Both automatic and infrastructure set port to BSS/STA mode */
1673 lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1;
1678 #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
1680 case IW_MODE_MASTER:
1682 /* Set BSS/AP mode */
1686 lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2;
1690 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1700 if( portType != 0 ) {
1701 /* Only do something if there is a mode change */
1702 if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) {
1703 lp->PortType = portType;
1704 lp->CreateIBSS = createIBSS;
1706 /* Commit the adapter parameters */
1709 /* Send an event that mode has been set */
1710 wl_wext_event_mode( lp->dev );
1714 wl_act_int_on( lp );
1716 wl_unlock(lp, &flags);
1719 DBG_LEAVE( DbgInfo );
1721 } // wireless_set_porttype
1722 /*============================================================================*/
1727 /*******************************************************************************
1728 * wireless_get_porttype()
1729 *******************************************************************************
1733 * Gets the port type of the wireless device.
1737 * wrq - the wireless request buffer
1738 * lp - the device's private adapter structure
1743 * errno value otherwise
1745 ******************************************************************************/
1746 static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra)
1749 struct wl_private *lp = wl_priv(dev);
1750 unsigned long flags;
1754 /*------------------------------------------------------------------------*/
1757 DBG_FUNC( "wireless_get_porttype" );
1758 DBG_ENTER( DbgInfo );
1760 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1765 wl_lock( lp, &flags );
1767 wl_act_int_off( lp );
1769 /* Get the current port type */
1770 lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 ));
1771 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1773 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1775 if( status == HCF_SUCCESS ) {
1776 pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 );
1778 *pPortType = CNV_LITTLE_TO_INT( *pPortType );
1780 switch( *pPortType ) {
1784 #if (HCF_TYPE) & HCF_TYPE_AP
1786 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1787 *mode = IW_MODE_MASTER;
1789 *mode = IW_MODE_INFRA;
1794 *mode = IW_MODE_INFRA;
1796 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1799 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
1800 *mode = IW_MODE_MASTER;
1802 if( lp->CreateIBSS ) {
1803 *mode = IW_MODE_ADHOC;
1805 *mode = IW_MODE_INFRA;
1813 *mode = IW_MODE_ADHOC;
1824 wl_act_int_on( lp );
1826 wl_unlock(lp, &flags);
1829 DBG_LEAVE( DbgInfo );
1831 } // wireless_get_porttype
1832 /*============================================================================*/
1837 /*******************************************************************************
1838 * wireless_set_power()
1839 *******************************************************************************
1843 * Sets the power management settings of the wireless device.
1847 * wrq - the wireless request buffer
1848 * lp - the device's private adapter structure
1853 * errno value otherwise
1855 ******************************************************************************/
1856 static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra)
1858 struct wl_private *lp = wl_priv(dev);
1859 unsigned long flags;
1861 /*------------------------------------------------------------------------*/
1864 DBG_FUNC( "wireless_set_power" );
1865 DBG_ENTER( DbgInfo );
1867 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1872 DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1874 #if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version
1875 if( !capable( CAP_NET_ADMIN )) {
1878 DBG_LEAVE( DbgInfo );
1883 wl_lock( lp, &flags );
1885 wl_act_int_off( lp );
1887 /* Set the power management state based on the 'disabled' value */
1888 if( wrq->disabled ) {
1894 /* Commit the adapter parameters */
1897 wl_act_int_on( lp );
1899 wl_unlock(lp, &flags);
1902 DBG_LEAVE( DbgInfo );
1904 } // wireless_set_power
1905 /*============================================================================*/
1910 /*******************************************************************************
1911 * wireless_get_power()
1912 *******************************************************************************
1916 * Gets the power management settings of the wireless device.
1920 * wrq - the wireless request buffer
1921 * lp - the device's private adapter structure
1926 * errno value otherwise
1928 ******************************************************************************/
1929 static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1932 struct wl_private *lp = wl_priv(dev);
1933 unsigned long flags;
1935 /*------------------------------------------------------------------------*/
1936 DBG_FUNC( "wireless_get_power" );
1937 DBG_ENTER( DbgInfo );
1939 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
1944 DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1946 wl_lock( lp, &flags );
1948 wl_act_int_off( lp );
1953 if( lp->PMEnabled ) {
1959 wl_act_int_on( lp );
1961 wl_unlock(lp, &flags);
1964 DBG_LEAVE( DbgInfo );
1966 } // wireless_get_power
1967 /*============================================================================*/
1972 /*******************************************************************************
1973 * wireless_get_tx_power()
1974 *******************************************************************************
1978 * Gets the transmit power of the wireless device's radio.
1982 * wrq - the wireless request buffer
1983 * lp - the device's private adapter structure
1988 * errno value otherwise
1990 ******************************************************************************/
1991 static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
1993 struct wl_private *lp = wl_priv(dev);
1994 unsigned long flags;
1996 /*------------------------------------------------------------------------*/
1997 DBG_FUNC( "wireless_get_tx_power" );
1998 DBG_ENTER( DbgInfo );
2000 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2005 wl_lock( lp, &flags );
2007 wl_act_int_off( lp );
2009 #ifdef USE_POWER_DBM
2010 rrq->value = RADIO_TX_POWER_DBM;
2011 rrq->flags = IW_TXPOW_DBM;
2013 rrq->value = RADIO_TX_POWER_MWATT;
2014 rrq->flags = IW_TXPOW_MWATT;
2019 wl_act_int_on( lp );
2021 wl_unlock(lp, &flags);
2024 DBG_LEAVE( DbgInfo );
2026 } // wireless_get_tx_power
2027 /*============================================================================*/
2032 /*******************************************************************************
2033 * wireless_set_rts_threshold()
2034 *******************************************************************************
2038 * Sets the RTS threshold for the wireless card.
2042 * wrq - the wireless request buffer
2043 * lp - the device's private adapter structure
2048 * errno value otherwise
2050 ******************************************************************************/
2051 static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2054 struct wl_private *lp = wl_priv(dev);
2055 unsigned long flags;
2056 int rthr = rts->value;
2057 /*------------------------------------------------------------------------*/
2060 DBG_FUNC( "wireless_set_rts_threshold" );
2061 DBG_ENTER( DbgInfo );
2063 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2068 if(rts->fixed == 0) {
2073 if( rts->disabled ) {
2077 if(( rthr < 256 ) || ( rthr > 2347 )) {
2082 wl_lock( lp, &flags );
2084 wl_act_int_off( lp );
2086 lp->RTSThreshold = rthr;
2090 wl_act_int_on( lp );
2092 wl_unlock(lp, &flags);
2095 DBG_LEAVE( DbgInfo );
2097 } // wireless_set_rts_threshold
2098 /*============================================================================*/
2103 /*******************************************************************************
2104 * wireless_get_rts_threshold()
2105 *******************************************************************************
2109 * Gets the RTS threshold for the wireless card.
2113 * wrq - the wireless request buffer
2114 * lp - the device's private adapter structure
2119 * errno value otherwise
2121 ******************************************************************************/
2122 static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra)
2125 struct wl_private *lp = wl_priv(dev);
2126 unsigned long flags;
2127 /*------------------------------------------------------------------------*/
2129 DBG_FUNC( "wireless_get_rts_threshold" );
2130 DBG_ENTER( DbgInfo );
2132 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2137 wl_lock( lp, &flags );
2139 wl_act_int_off( lp );
2141 rts->value = lp->RTSThreshold;
2143 rts->disabled = ( rts->value == 2347 );
2147 wl_act_int_on( lp );
2149 wl_unlock(lp, &flags);
2152 DBG_LEAVE( DbgInfo );
2154 } // wireless_get_rts_threshold
2155 /*============================================================================*/
2161 /*******************************************************************************
2162 * wireless_set_rate()
2163 *******************************************************************************
2167 * Set the default data rate setting used by the wireless device.
2171 * wrq - the wireless request buffer
2172 * lp - the device's private adapter structure
2177 * errno value otherwise
2179 ******************************************************************************/
2180 static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2182 struct wl_private *lp = wl_priv(dev);
2183 unsigned long flags;
2189 /*------------------------------------------------------------------------*/
2192 DBG_FUNC( "wireless_set_rate" );
2193 DBG_ENTER( DbgInfo );
2195 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2200 wl_lock( lp, &flags );
2202 wl_act_int_off( lp );
2206 /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check
2207 if Bit 9 is set in the current channel RID */
2208 lp->ltvRecord.len = 2;
2209 lp->ltvRecord.typ = CFG_CUR_CHANNEL;
2211 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2213 if( status == HCF_SUCCESS ) {
2214 index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0;
2216 DBG_PRINT( "Index: %d\n", index );
2218 DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" );
2219 DBG_LEAVE( DbgInfo );
2224 if( rrq->value > 0 &&
2225 rrq->value <= 1 * MEGABIT ) {
2226 lp->TxRateControl[index] = 0x0001;
2228 else if( rrq->value > 1 * MEGABIT &&
2229 rrq->value <= 2 * MEGABIT ) {
2230 if( rrq->fixed == 1 ) {
2231 lp->TxRateControl[index] = 0x0002;
2233 lp->TxRateControl[index] = 0x0003;
2236 else if( rrq->value > 2 * MEGABIT &&
2237 rrq->value <= 5 * MEGABIT ) {
2238 if( rrq->fixed == 1 ) {
2239 lp->TxRateControl[index] = 0x0004;
2241 lp->TxRateControl[index] = 0x0007;
2244 else if( rrq->value > 5 * MEGABIT &&
2245 rrq->value <= 6 * MEGABIT ) {
2246 if( rrq->fixed == 1 ) {
2247 lp->TxRateControl[index] = 0x0010;
2249 lp->TxRateControl[index] = 0x0017;
2252 else if( rrq->value > 6 * MEGABIT &&
2253 rrq->value <= 9 * MEGABIT ) {
2254 if( rrq->fixed == 1 ) {
2255 lp->TxRateControl[index] = 0x0020;
2257 lp->TxRateControl[index] = 0x0037;
2260 else if( rrq->value > 9 * MEGABIT &&
2261 rrq->value <= 11 * MEGABIT ) {
2262 if( rrq->fixed == 1 ) {
2263 lp->TxRateControl[index] = 0x0008;
2265 lp->TxRateControl[index] = 0x003F;
2268 else if( rrq->value > 11 * MEGABIT &&
2269 rrq->value <= 12 * MEGABIT ) {
2270 if( rrq->fixed == 1 ) {
2271 lp->TxRateControl[index] = 0x0040;
2273 lp->TxRateControl[index] = 0x007F;
2276 else if( rrq->value > 12 * MEGABIT &&
2277 rrq->value <= 18 * MEGABIT ) {
2278 if( rrq->fixed == 1 ) {
2279 lp->TxRateControl[index] = 0x0080;
2281 lp->TxRateControl[index] = 0x00FF;
2284 else if( rrq->value > 18 * MEGABIT &&
2285 rrq->value <= 24 * MEGABIT ) {
2286 if( rrq->fixed == 1 ) {
2287 lp->TxRateControl[index] = 0x0100;
2289 lp->TxRateControl[index] = 0x01FF;
2292 else if( rrq->value > 24 * MEGABIT &&
2293 rrq->value <= 36 * MEGABIT ) {
2294 if( rrq->fixed == 1 ) {
2295 lp->TxRateControl[index] = 0x0200;
2297 lp->TxRateControl[index] = 0x03FF;
2300 else if( rrq->value > 36 * MEGABIT &&
2301 rrq->value <= 48 * MEGABIT ) {
2302 if( rrq->fixed == 1 ) {
2303 lp->TxRateControl[index] = 0x0400;
2305 lp->TxRateControl[index] = 0x07FF;
2308 else if( rrq->value > 48 * MEGABIT &&
2309 rrq->value <= 54 * MEGABIT ) {
2310 if( rrq->fixed == 1 ) {
2311 lp->TxRateControl[index] = 0x0800;
2313 lp->TxRateControl[index] = 0x0FFF;
2316 else if( rrq->fixed == 0 ) {
2317 /* In this case, the user has not specified a bitrate, only the "auto"
2318 moniker. So, set to all supported rates */
2319 lp->TxRateControl[index] = PARM_MAX_TX_RATE;
2329 if( rrq->value > 0 &&
2330 rrq->value <= 1 * MEGABIT ) {
2331 lp->TxRateControl[0] = 1;
2333 else if( rrq->value > 1 * MEGABIT &&
2334 rrq->value <= 2 * MEGABIT ) {
2336 lp->TxRateControl[0] = 2;
2338 lp->TxRateControl[0] = 6;
2341 else if( rrq->value > 2 * MEGABIT &&
2342 rrq->value <= 5 * MEGABIT ) {
2344 lp->TxRateControl[0] = 4;
2346 lp->TxRateControl[0] = 7;
2349 else if( rrq->value > 5 * MEGABIT &&
2350 rrq->value <= 11 * MEGABIT ) {
2352 lp->TxRateControl[0] = 5;
2354 lp->TxRateControl[0] = 3;
2357 else if( rrq->fixed == 0 ) {
2358 /* In this case, the user has not specified a bitrate, only the "auto"
2359 moniker. So, set the rate to 11Mb auto */
2360 lp->TxRateControl[0] = 3;
2370 /* Commit the adapter parameters */
2375 wl_act_int_on( lp );
2377 wl_unlock(lp, &flags);
2380 DBG_LEAVE( DbgInfo );
2382 } // wireless_set_rate
2383 /*============================================================================*/
2388 /*******************************************************************************
2389 * wireless_get_rate()
2390 *******************************************************************************
2394 * Get the default data rate setting used by the wireless device.
2398 * wrq - the wireless request buffer
2399 * lp - the device's private adapter structure
2404 * errno value otherwise
2406 ******************************************************************************/
2407 static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra)
2410 struct wl_private *lp = wl_priv(dev);
2411 unsigned long flags;
2415 /*------------------------------------------------------------------------*/
2418 DBG_FUNC( "wireless_get_rate" );
2419 DBG_ENTER( DbgInfo );
2421 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2426 wl_lock( lp, &flags );
2428 wl_act_int_off( lp );
2430 /* Get the current transmit rate from the adapter */
2431 lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16));
2432 lp->ltvRecord.typ = CFG_CUR_TX_RATE;
2434 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2436 if( status == HCF_SUCCESS ) {
2439 txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] );
2441 if( txRate & 0x0001 ) {
2444 else if( txRate & 0x0002 ) {
2447 else if( txRate & 0x0004 ) {
2450 else if( txRate & 0x0008 ) {
2453 else if( txRate & 0x00010 ) {
2456 else if( txRate & 0x00020 ) {
2459 else if( txRate & 0x00040 ) {
2462 else if( txRate & 0x00080 ) {
2465 else if( txRate & 0x00100 ) {
2468 else if( txRate & 0x00200 ) {
2471 else if( txRate & 0x00400 ) {
2474 else if( txRate & 0x00800 ) {
2480 txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] );
2484 rrq->value = txRate * MEGABIT;
2490 wl_act_int_on( lp );
2492 wl_unlock(lp, &flags);
2495 DBG_LEAVE( DbgInfo );
2497 } // wireless_get_rate
2498 /*============================================================================*/
2503 #if 0 //;? Not used anymore
2504 /*******************************************************************************
2505 * wireless_get_private_interface()
2506 *******************************************************************************
2510 * Returns the Linux Wireless Extensions' compatible private interface of
2515 * wrq - the wireless request buffer
2516 * lp - the device's private adapter structure
2521 * errno value otherwise
2523 ******************************************************************************/
2524 int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp )
2527 /*------------------------------------------------------------------------*/
2530 DBG_FUNC( "wireless_get_private_interface" );
2531 DBG_ENTER( DbgInfo );
2533 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2538 if( wrq->u.data.pointer != NULL ) {
2539 struct iw_priv_args priv[] =
2541 { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
2542 { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
2543 { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
2544 { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
2545 { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
2546 { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
2549 /* Verify the user buffer */
2550 ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv ));
2553 DBG_LEAVE( DbgInfo );
2557 /* Copy the data into the user's buffer */
2558 wrq->u.data.length = NELEM( priv );
2559 copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv ));
2563 DBG_LEAVE( DbgInfo );
2565 } // wireless_get_private_interface
2566 /*============================================================================*/
2571 /*******************************************************************************
2572 * wireless_set_scan()
2573 *******************************************************************************
2577 * Instructs the driver to initiate a network scan.
2581 * wrq - the wireless request buffer
2582 * lp - the device's private adapter structure
2587 * errno value otherwise
2589 ******************************************************************************/
2590 static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2592 struct wl_private *lp = wl_priv(dev);
2593 unsigned long flags;
2597 /*------------------------------------------------------------------------*/
2599 //;? Note: shows results as trace, returns always 0 unless BUSY
2601 DBG_FUNC( "wireless_set_scan" );
2602 DBG_ENTER( DbgInfo );
2604 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2609 wl_lock( lp, &flags );
2611 wl_act_int_off( lp );
2614 * This looks like a nice place to test if the HCF is still
2615 * communicating with the card. It seems that sometimes BAP_1
2616 * gets corrupted. By looking at the comments in HCF the
2617 * cause is still a mystery. Okay, the communication to the
2618 * card is dead, reset the card to revive.
2620 if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0)
2622 DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" );
2627 /* Set the completion state to FALSE */
2628 lp->probe_results.scan_complete = FALSE;
2631 /* Channels to scan */
2633 lp->ltvRecord.len = 5;
2634 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2635 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band
2636 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band
2637 lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // ..
2638 lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // ..
2640 lp->ltvRecord.len = 2;
2641 lp->ltvRecord.typ = CFG_SCAN_CHANNEL;
2642 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF );
2645 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2647 DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status );
2649 // Holding the lock too long, makes a gap to allow other processes
2650 wl_unlock(lp, &flags);
2651 wl_lock( lp, &flags );
2653 if( status != HCF_SUCCESS ) {
2657 DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries );
2660 // Holding the lock too long, makes a gap to allow other processes
2661 wl_unlock(lp, &flags);
2662 wl_lock( lp, &flags );
2668 /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to
2669 disassociate from the network we are currently on */
2670 lp->ltvRecord.len = 18;
2671 lp->ltvRecord.typ = CFG_SCAN_SSID;
2672 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
2673 lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 );
2675 status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
2677 // Holding the lock too long, makes a gap to allow other processes
2678 wl_unlock(lp, &flags);
2679 wl_lock( lp, &flags );
2681 DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status );
2683 /* Initiate the scan */
2684 /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to
2685 retrieve probe response must always be used to support WPA */
2686 status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN );
2688 if( status == HCF_SUCCESS ) {
2689 DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" );
2691 DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" );
2694 wl_act_int_on( lp );
2696 wl_unlock(lp, &flags);
2701 } // wireless_set_scan
2702 /*============================================================================*/
2707 /*******************************************************************************
2708 * wireless_get_scan()
2709 *******************************************************************************
2713 * Instructs the driver to gather and return the results of a network scan.
2717 * wrq - the wireless request buffer
2718 * lp - the device's private adapter structure
2723 * errno value otherwise
2725 ******************************************************************************/
2726 static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra)
2728 struct wl_private *lp = wl_priv(dev);
2729 unsigned long flags;
2734 struct iw_event iwe;
2735 PROBE_RESP *probe_resp;
2739 /*------------------------------------------------------------------------*/
2742 DBG_FUNC( "wireless_get_scan" );
2743 DBG_ENTER( DbgInfo );
2745 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
2750 wl_lock( lp, &flags );
2752 wl_act_int_off( lp );
2754 /* If the scan is not done, tell the calling process to try again later */
2755 if( !lp->probe_results.scan_complete ) {
2760 DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n",
2761 lp->probe_results.num_aps );
2764 buf_end = extra + IW_SCAN_MAX_DATA;
2766 for( count = 0; count < lp->probe_results.num_aps; count++ ) {
2767 /* Reference the probe response from the table */
2768 probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count];
2771 /* First entry MUST be the MAC address */
2772 memset( &iwe, 0, sizeof( iwe ));
2774 iwe.cmd = SIOCGIWAP;
2775 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2776 memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN);
2777 iwe.len = IW_EV_ADDR_LEN;
2779 buf = iwe_stream_add_event(info, buf, buf_end,
2780 &iwe, IW_EV_ADDR_LEN);
2782 /* Use the mode to indicate if it's a station or AP */
2783 /* Won't always be an AP if in IBSS mode */
2784 memset( &iwe, 0, sizeof( iwe ));
2786 iwe.cmd = SIOCGIWMODE;
2788 if( probe_resp->capability & CAPABILITY_IBSS ) {
2789 iwe.u.mode = IW_MODE_INFRA;
2791 iwe.u.mode = IW_MODE_MASTER;
2794 iwe.len = IW_EV_UINT_LEN;
2796 buf = iwe_stream_add_event(info, buf, buf_end,
2797 &iwe, IW_EV_UINT_LEN);
2799 /* Any quality information */
2800 memset(&iwe, 0, sizeof(iwe));
2803 iwe.u.qual.level = dbm(probe_resp->signal);
2804 iwe.u.qual.noise = dbm(probe_resp->silence);
2805 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
2806 iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM;
2807 iwe.len = IW_EV_QUAL_LEN;
2809 buf = iwe_stream_add_event(info, buf, buf_end,
2810 &iwe, IW_EV_QUAL_LEN);
2813 /* ESSID information */
2814 if( probe_resp->rawData[1] > 0 ) {
2815 memset( &iwe, 0, sizeof( iwe ));
2817 iwe.cmd = SIOCGIWESSID;
2818 iwe.u.data.length = probe_resp->rawData[1];
2819 iwe.u.data.flags = 1;
2821 buf = iwe_stream_add_point(info, buf, buf_end,
2822 &iwe, &probe_resp->rawData[2]);
2826 /* Encryption Information */
2827 memset( &iwe, 0, sizeof( iwe ));
2829 iwe.cmd = SIOCGIWENCODE;
2830 iwe.u.data.length = 0;
2832 /* Check the capabilities field of the Probe Response to see if
2833 'privacy' is supported on the AP in question */
2834 if( probe_resp->capability & CAPABILITY_PRIVACY ) {
2835 iwe.u.data.flags |= IW_ENCODE_ENABLED;
2837 iwe.u.data.flags |= IW_ENCODE_DISABLED;
2840 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL);
2843 /* Frequency Info */
2844 memset( &iwe, 0, sizeof( iwe ));
2846 iwe.cmd = SIOCGIWFREQ;
2847 iwe.len = IW_EV_FREQ_LEN;
2848 iwe.u.freq.m = wl_parse_ds_ie( probe_resp );
2851 buf = iwe_stream_add_event(info, buf, buf_end,
2852 &iwe, IW_EV_FREQ_LEN);
2855 /* Custom info (Beacon Interval) */
2856 memset( &iwe, 0, sizeof( iwe ));
2857 memset( msg, 0, sizeof( msg ));
2859 iwe.cmd = IWEVCUSTOM;
2860 sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval );
2861 iwe.u.data.length = strlen( msg );
2863 buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg);
2870 wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len );
2871 if( wpa_ie != NULL ) {
2872 memset(&iwe, 0, sizeof(iwe));
2874 iwe.cmd = IWEVGENIE;
2875 iwe.u.data.length = wpa_ie_len;
2877 buf = iwe_stream_add_point(info, buf, buf_end,
2881 /* Add other custom info in formatted string format as needed... */
2884 data->length = buf - extra;
2888 wl_act_int_on( lp );
2890 wl_unlock(lp, &flags);
2893 DBG_LEAVE( DbgInfo );
2895 } // wireless_get_scan
2896 /*============================================================================*/
2899 static const char * const auth_names[] = {
2900 "IW_AUTH_WPA_VERSION",
2901 "IW_AUTH_CIPHER_PAIRWISE",
2902 "IW_AUTH_CIPHER_GROUP",
2904 "IW_AUTH_TKIP_COUNTERMEASURES",
2905 "IW_AUTH_DROP_UNENCRYPTED",
2906 "IW_AUTH_80211_AUTH_ALG",
2907 "IW_AUTH_WPA_ENABLED",
2908 "IW_AUTH_RX_UNENCRYPTED_EAPOL",
2909 "IW_AUTH_ROAMING_CONTROL",
2910 "IW_AUTH_PRIVACY_INVOKED",
2911 "IW_AUTH_CIPHER_GROUP_MGMT",
2917 static int wireless_set_auth(struct net_device *dev,
2918 struct iw_request_info *info,
2919 struct iw_param *data, char *extra)
2921 struct wl_private *lp = wl_priv(dev);
2922 unsigned long flags;
2925 int iwa_idx = data->flags & IW_AUTH_INDEX;
2926 int iwa_val = data->value;
2928 DBG_FUNC( "wireless_set_auth" );
2929 DBG_ENTER( DbgInfo );
2931 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
2936 wl_lock( lp, &flags );
2938 wl_act_int_off( lp );
2940 if (iwa_idx > IW_AUTH_MFP)
2941 iwa_idx = IW_AUTH_MFP + 1;
2942 DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]);
2944 case IW_AUTH_WPA_VERSION:
2945 /* We do support WPA */
2946 if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) ||
2947 (iwa_val == IW_AUTH_WPA_VERSION_DISABLED))
2953 case IW_AUTH_WPA_ENABLED:
2954 DBG_TRACE(DbgInfo, "val = %d\n", iwa_val);
2956 lp->EnableEncryption = 2;
2958 lp->EnableEncryption = 0;
2960 /* Write straight to the card */
2962 ltv.typ = CFG_CNF_ENCRYPTION;
2963 ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption);
2964 ret = hcf_put_info(&lp->hcfCtx, (LTVP)<v);
2968 case IW_AUTH_TKIP_COUNTERMEASURES:
2970 /* Immediately disable card */
2971 lp->driverEnable = !iwa_val;
2972 if (lp->driverEnable)
2973 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
2975 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
2980 /* Management Frame Protection not supported.
2981 * Only fail if set to required.
2983 if (iwa_val == IW_AUTH_MFP_REQUIRED)
2989 case IW_AUTH_KEY_MGMT:
2991 /* Record required management suite.
2992 * Will take effect on next commit */
2994 lp->AuthKeyMgmtSuite = 4;
2996 lp->AuthKeyMgmtSuite = 0;
3001 case IW_AUTH_80211_AUTH_ALG:
3003 /* Just record whether open or shared is required.
3004 * Will take effect on next commit */
3007 if (iwa_val & IW_AUTH_ALG_SHARED_KEY)
3008 lp->authentication = 1;
3009 else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM)
3010 lp->authentication = 0;
3015 case IW_AUTH_DROP_UNENCRYPTED:
3016 /* Only needed for AP */
3017 lp->ExcludeUnencrypted = iwa_val;
3021 case IW_AUTH_CIPHER_PAIRWISE:
3022 case IW_AUTH_CIPHER_GROUP:
3023 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3024 case IW_AUTH_ROAMING_CONTROL:
3025 case IW_AUTH_PRIVACY_INVOKED:
3026 /* Not used. May need to do something with
3027 * CIPHER_PAIRWISE and CIPHER_GROUP*/
3032 DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx);
3033 /* return an error */
3038 wl_act_int_on( lp );
3040 wl_unlock(lp, &flags);
3043 DBG_LEAVE( DbgInfo );
3045 } // wireless_set_auth
3046 /*============================================================================*/
3049 static void flush_tx(struct wl_private *lp)
3055 * Make sure that there is no data queued up in the firmware
3056 * before setting the TKIP keys. If this check is not
3057 * performed, some data may be sent out with incorrect MIC
3058 * and cause synchronization errors with the AP
3060 /* Check every 1ms for 100ms */
3061 for (count = 0; count < 100; count++) {
3065 ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */
3068 hcf_get_info(&(lp->hcfCtx), (LTVP)<v);
3070 if (ltv.u.u16[0] == 0)
3075 DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n");
3079 static int wireless_set_encodeext(struct net_device *dev,
3080 struct iw_request_info *info,
3081 struct iw_point *erq, char *keybuf)
3083 struct wl_private *lp = wl_priv(dev);
3084 unsigned long flags;
3086 int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1;
3088 struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf;
3090 bool set_tx = false;
3094 if (lp->portState == WVLAN_PORT_STATE_DISABLED) {
3099 if (erq->flags & IW_ENCODE_DISABLED) {
3100 ext->alg = IW_ENCODE_ALG_NONE;
3104 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
3107 wl_lock(lp, &flags);
3111 memset(<v, 0, sizeof(ltv));
3114 case IW_ENCODE_ALG_TKIP:
3115 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx);
3117 if (sizeof(ext->rx_seq) != 8) {
3118 DBG_TRACE(DbgInfo, "rx_seq size mismatch\n");
3124 ret = hermes_set_tkip_keys(<v, key_idx, ext->addr.sa_data,
3126 ext->rx_seq, ext->key, ext->key_len);
3129 DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n");
3135 lp->wext_enc = IW_ENCODE_ALG_TKIP;
3138 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3141 case IW_ENCODE_ALG_WEP:
3142 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx);
3144 if (erq->flags & IW_ENCODE_RESTRICTED) {
3145 DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n");
3150 ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len,
3155 case IW_ENCODE_ALG_CCMP:
3156 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx);
3160 case IW_ENCODE_ALG_NONE:
3161 DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx);
3163 if (lp->wext_enc == IW_ENCODE_ALG_TKIP) {
3164 ret = hermes_clear_tkip_keys(<v, key_idx,
3167 lp->wext_enc = IW_ENCODE_ALG_NONE;
3168 ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v);
3170 } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) {
3171 ret = hermes_set_wep_keys(lp, key_idx,
3172 ext->key, ext->key_len,
3181 DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx);
3190 wl_unlock(lp, &flags);
3196 /*============================================================================*/
3200 static int wireless_set_genie(struct net_device *dev,
3201 struct iw_request_info *info,
3202 struct iw_point *data, char *extra)
3209 /* We can't write this to the card, but apparently this
3210 * operation needs to succeed */
3216 /*============================================================================*/
3219 /*******************************************************************************
3220 * wl_wireless_stats()
3221 *******************************************************************************
3225 * Return the current device wireless statistics.
3229 * wrq - the wireless request buffer
3230 * lp - the device's private adapter structure
3235 * errno value otherwise
3237 ******************************************************************************/
3238 struct iw_statistics * wl_wireless_stats( struct net_device *dev )
3240 struct iw_statistics *pStats;
3241 struct wl_private *lp = wl_priv(dev);
3242 /*------------------------------------------------------------------------*/
3245 DBG_FUNC( "wl_wireless_stats" );
3247 DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
3251 /* Initialize the statistics */
3252 pStats = &( lp->wstats );
3253 pStats->qual.updated = 0x00;
3255 if( !( lp->flags & WVLAN2_UIL_BUSY ))
3257 CFG_COMMS_QUALITY_STRCT *pQual;
3258 CFG_HERMES_TALLIES_STRCT tallies;
3261 /* Update driver status */
3264 /* Get the current link quality information */
3265 lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 ));
3266 lp->ltvRecord.typ = CFG_COMMS_QUALITY;
3267 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3269 if( status == HCF_SUCCESS ) {
3270 pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord );
3272 pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual );
3273 pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl ));
3274 pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl ));
3276 pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED |
3277 IW_QUAL_LEVEL_UPDATED |
3278 IW_QUAL_NOISE_UPDATED |
3281 memset( &( pStats->qual ), 0, sizeof( pStats->qual ));
3284 /* Get the current tallies from the adapter */
3285 /* Only possible when the device is open */
3286 if(lp->portState == WVLAN_PORT_STATE_DISABLED) {
3287 if( wl_get_tallies( lp, &tallies ) == 0 ) {
3288 /* No endian translation is needed here, as CFG_TALLIES is an
3289 MSF RID; all processing is done on the host, not the card! */
3290 pStats->discard.nwid = 0L;
3291 pStats->discard.code = tallies.RxWEPUndecryptable;
3292 pStats->discard.misc = tallies.TxDiscards +
3293 tallies.RxFCSErrors +
3294 //tallies.RxDiscardsNoBuffer +
3295 tallies.TxDiscardsWrongSA;
3296 //;? Extra taken over from Linux driver based on 7.18 version
3297 pStats->discard.retries = tallies.TxRetryLimitExceeded;
3298 pStats->discard.fragment = tallies.RxMsgInBadMsgFragments;
3300 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3303 memset( &( pStats->discard ), 0, sizeof( pStats->discard ));
3307 DBG_LEAVE( DbgInfo );
3309 } // wl_wireless_stats
3310 /*============================================================================*/
3315 /*******************************************************************************
3316 * wl_get_wireless_stats()
3317 *******************************************************************************
3321 * Return the current device wireless statistics. This function calls
3322 * wl_wireless_stats, but acquires spinlocks first as it can be called
3323 * directly by the network layer.
3327 * wrq - the wireless request buffer
3328 * lp - the device's private adapter structure
3333 * errno value otherwise
3335 ******************************************************************************/
3336 struct iw_statistics * wl_get_wireless_stats( struct net_device *dev )
3338 unsigned long flags;
3339 struct wl_private *lp = wl_priv(dev);
3340 struct iw_statistics *pStats = NULL;
3341 /*------------------------------------------------------------------------*/
3343 DBG_FUNC( "wl_get_wireless_stats" );
3346 wl_lock( lp, &flags );
3348 wl_act_int_off( lp );
3351 if( lp->useRTS == 1 ) {
3352 DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" );
3356 pStats = wl_wireless_stats( dev );
3358 wl_act_int_on( lp );
3360 wl_unlock(lp, &flags);
3362 DBG_LEAVE( DbgInfo );
3364 } // wl_get_wireless_stats
3367 /*******************************************************************************
3369 *******************************************************************************
3373 * Gather wireless spy statistics.
3377 * wrq - the wireless request buffer
3378 * lp - the device's private adapter structure
3383 * errno value otherwise
3385 ******************************************************************************/
3386 inline void wl_spy_gather( struct net_device *dev, u_char *mac )
3388 struct iw_quality wstats;
3392 struct wl_private *lp = wl_priv(dev);
3393 /*------------------------------------------------------------------------*/
3396 if (!lp->spy_data.spy_number) {
3400 /* Gather wireless spy statistics: for each packet, compare the source
3401 address with out list, and if match, get the stats. */
3402 memset( stats, 0, sizeof(stats));
3403 memset( desc, 0, sizeof(DESC_STRCT));
3405 desc[0].buf_addr = stats;
3406 desc[0].BUF_SIZE = sizeof(stats);
3407 desc[0].next_desc_addr = 0; // terminate list
3409 status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 );
3411 if( status == HCF_SUCCESS ) {
3412 wstats.level = (u_char) dbm(stats[1]);
3413 wstats.noise = (u_char) dbm(stats[0]);
3414 wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0;
3416 wstats.updated = (IW_QUAL_QUAL_UPDATED |
3417 IW_QUAL_LEVEL_UPDATED |
3418 IW_QUAL_NOISE_UPDATED |
3421 wireless_spy_update( dev, mac, &wstats );
3424 /*============================================================================*/
3429 /*******************************************************************************
3430 * wl_wext_event_freq()
3431 *******************************************************************************
3435 * This function is used to send an event that the channel/freq
3436 * configuration for a specific device has changed.
3441 * dev - the network device for which this event is to be issued
3447 ******************************************************************************/
3448 void wl_wext_event_freq( struct net_device *dev )
3450 union iwreq_data wrqu;
3451 struct wl_private *lp = wl_priv(dev);
3452 /*------------------------------------------------------------------------*/
3455 memset( &wrqu, 0, sizeof( wrqu ));
3457 wrqu.freq.m = lp->Channel;
3460 wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL );
3463 } // wl_wext_event_freq
3464 /*============================================================================*/
3469 /*******************************************************************************
3470 * wl_wext_event_mode()
3471 *******************************************************************************
3475 * This function is used to send an event that the mode of operation
3476 * for a specific device has changed.
3481 * dev - the network device for which this event is to be issued
3487 ******************************************************************************/
3488 void wl_wext_event_mode( struct net_device *dev )
3490 union iwreq_data wrqu;
3491 struct wl_private *lp = wl_priv(dev);
3492 /*------------------------------------------------------------------------*/
3495 memset( &wrqu, 0, sizeof( wrqu ));
3497 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) {
3498 wrqu.mode = IW_MODE_INFRA;
3500 wrqu.mode = IW_MODE_MASTER;
3503 wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL );
3506 } // wl_wext_event_mode
3507 /*============================================================================*/
3512 /*******************************************************************************
3513 * wl_wext_event_essid()
3514 *******************************************************************************
3518 * This function is used to send an event that the ESSID configuration for
3519 * a specific device has changed.
3524 * dev - the network device for which this event is to be issued
3530 ******************************************************************************/
3531 void wl_wext_event_essid( struct net_device *dev )
3533 union iwreq_data wrqu;
3534 struct wl_private *lp = wl_priv(dev);
3535 /*------------------------------------------------------------------------*/
3538 memset( &wrqu, 0, sizeof( wrqu ));
3540 /* Fill out the buffer. Note that the buffer doesn't actually contain the
3541 ESSID, but a pointer to the contents. In addition, the 'extra' field of
3542 the call to wireless_send_event() must also point to where the ESSID
3544 wrqu.essid.length = strlen( lp->NetworkName );
3545 wrqu.essid.pointer = (caddr_t)lp->NetworkName;
3546 wrqu.essid.flags = 1;
3548 wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName );
3551 } // wl_wext_event_essid
3552 /*============================================================================*/
3557 /*******************************************************************************
3558 * wl_wext_event_encode()
3559 *******************************************************************************
3563 * This function is used to send an event that the encryption configuration
3564 * for a specific device has changed.
3569 * dev - the network device for which this event is to be issued
3575 ******************************************************************************/
3576 void wl_wext_event_encode( struct net_device *dev )
3578 union iwreq_data wrqu;
3579 struct wl_private *lp = wl_priv(dev);
3581 /*------------------------------------------------------------------------*/
3584 memset( &wrqu, 0, sizeof( wrqu ));
3586 if( lp->EnableEncryption == 0 ) {
3587 wrqu.encoding.flags = IW_ENCODE_DISABLED;
3589 wrqu.encoding.flags |= lp->TransmitKeyID;
3591 index = lp->TransmitKeyID - 1;
3593 /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted
3594 if we're in AP mode */
3595 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
3596 //;?should we restore this to allow smaller memory footprint
3598 if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) {
3599 if( lp->ExcludeUnencrypted ) {
3600 wrqu.encoding.flags |= IW_ENCODE_RESTRICTED;
3602 wrqu.encoding.flags |= IW_ENCODE_OPEN;
3606 #endif // HCF_TYPE_AP
3608 /* Only provide the key if permissions allow */
3609 if( capable( CAP_NET_ADMIN )) {
3610 wrqu.encoding.pointer = (caddr_t)lp->DefaultKeys.key[index].key;
3611 wrqu.encoding.length = lp->DefaultKeys.key[index].len;
3613 wrqu.encoding.flags |= IW_ENCODE_NOKEY;
3617 wireless_send_event( dev, SIOCSIWENCODE, &wrqu,
3618 lp->DefaultKeys.key[index].key );
3621 } // wl_wext_event_encode
3622 /*============================================================================*/
3627 /*******************************************************************************
3628 * wl_wext_event_ap()
3629 *******************************************************************************
3633 * This function is used to send an event that the device has been
3634 * associated to a new AP.
3639 * dev - the network device for which this event is to be issued
3645 ******************************************************************************/
3646 void wl_wext_event_ap( struct net_device *dev )
3648 union iwreq_data wrqu;
3649 struct wl_private *lp = wl_priv(dev);
3651 /*------------------------------------------------------------------------*/
3654 /* Retrieve the WPA-IEs used by the firmware and send an event. We must send
3655 this event BEFORE sending the association event, as there are timing
3656 issues with the hostap supplicant. The supplicant will attempt to process
3657 an EAPOL-Key frame from an AP before receiving this information, which
3658 is required for a proper processed frame. */
3659 wl_wext_event_assoc_ie( dev );
3662 lp->ltvRecord.typ = CFG_CUR_BSSID;
3663 lp->ltvRecord.len = 4;
3665 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3666 if( status == HCF_SUCCESS ) {
3667 memset( &wrqu, 0, sizeof( wrqu ));
3669 memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN );
3671 wrqu.addr.sa_family = ARPHRD_ETHER;
3673 wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL );
3677 } // wl_wext_event_ap
3678 /*============================================================================*/
3682 /*******************************************************************************
3683 * wl_wext_event_scan_complete()
3684 *******************************************************************************
3688 * This function is used to send an event that a request for a network scan
3694 * dev - the network device for which this event is to be issued
3700 ******************************************************************************/
3701 void wl_wext_event_scan_complete( struct net_device *dev )
3703 union iwreq_data wrqu;
3704 /*------------------------------------------------------------------------*/
3707 memset( &wrqu, 0, sizeof( wrqu ));
3709 wrqu.addr.sa_family = ARPHRD_ETHER;
3710 wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL );
3713 } // wl_wext_event_scan_complete
3714 /*============================================================================*/
3719 /*******************************************************************************
3720 * wl_wext_event_new_sta()
3721 *******************************************************************************
3725 * This function is used to send an event that an AP has registered a new
3731 * dev - the network device for which this event is to be issued
3737 ******************************************************************************/
3738 void wl_wext_event_new_sta( struct net_device *dev )
3740 union iwreq_data wrqu;
3741 /*------------------------------------------------------------------------*/
3744 memset( &wrqu, 0, sizeof( wrqu ));
3746 /* Send the station's mac address here */
3747 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3748 wrqu.addr.sa_family = ARPHRD_ETHER;
3749 wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL );
3752 } // wl_wext_event_new_sta
3753 /*============================================================================*/
3758 /*******************************************************************************
3759 * wl_wext_event_expired_sta()
3760 *******************************************************************************
3764 * This function is used to send an event that an AP has deregistered a
3770 * dev - the network device for which this event is to be issued
3776 ******************************************************************************/
3777 void wl_wext_event_expired_sta( struct net_device *dev )
3779 union iwreq_data wrqu;
3780 /*------------------------------------------------------------------------*/
3783 memset( &wrqu, 0, sizeof( wrqu ));
3785 memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN );
3786 wrqu.addr.sa_family = ARPHRD_ETHER;
3787 wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL );
3790 } // wl_wext_event_expired_sta
3791 /*============================================================================*/
3796 /*******************************************************************************
3797 * wl_wext_event_mic_failed()
3798 *******************************************************************************
3802 * This function is used to send an event that MIC calculations failed.
3807 * dev - the network device for which this event is to be issued
3813 ******************************************************************************/
3814 void wl_wext_event_mic_failed( struct net_device *dev )
3816 union iwreq_data wrqu;
3817 struct wl_private *lp = wl_priv(dev);
3818 struct iw_michaelmicfailure wxmic;
3822 WVLAN_RX_WMP_HDR *hdr;
3823 /*------------------------------------------------------------------------*/
3826 key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3;
3829 /* Cast the lookahead buffer into a RFS format */
3830 hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT];
3832 /* Cast the addresses to byte buffers, as in the above RFS they are word
3834 addr1 = (char *)hdr->address1;
3835 addr2 = (char *)hdr->address2;
3837 DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx,
3840 memset(&wrqu, 0, sizeof(wrqu));
3841 memset(&wxmic, 0, sizeof(wxmic));
3843 wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID;
3844 wxmic.flags |= (addr1[0] & 1) ?
3845 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
3846 wxmic.src_addr.sa_family = ARPHRD_ETHER;
3847 memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN);
3849 wrqu.data.length = sizeof(wxmic);
3850 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic);
3853 } // wl_wext_event_mic_failed
3854 /*============================================================================*/
3859 /*******************************************************************************
3860 * wl_wext_event_assoc_ie()
3861 *******************************************************************************
3865 * This function is used to send an event containing the WPA-IE generated
3866 * by the firmware in an association request.
3871 * dev - the network device for which this event is to be issued
3877 ******************************************************************************/
3878 void wl_wext_event_assoc_ie( struct net_device *dev )
3880 union iwreq_data wrqu;
3881 struct wl_private *lp = wl_priv(dev);
3886 /*------------------------------------------------------------------------*/
3889 memset( &wrqu, 0, sizeof( wrqu ));
3891 /* Retrieve the Association Request IE */
3892 lp->ltvRecord.len = 45;
3893 lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO;
3895 status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
3896 if( status == HCF_SUCCESS )
3899 memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 );
3900 wpa_ie = wl_parse_wpa_ie( &data, &length );
3904 wrqu.data.length = wpa_ie[1] + 2;
3905 wireless_send_event(dev, IWEVASSOCREQIE,
3908 /* This bit is a hack. We send the respie
3909 * event at the same time */
3910 wireless_send_event(dev, IWEVASSOCRESPIE,
3916 } // wl_wext_event_assoc_ie
3917 /*============================================================================*/
3918 /* Structures to export the Wireless Handlers */
3920 static const iw_handler wl_handler[] =
3922 IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit),
3923 IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol),
3924 IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency),
3925 IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency),
3926 IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype),
3927 IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype),
3928 IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity),
3929 IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity),
3930 IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range),
3931 IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
3932 IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
3933 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3934 IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid),
3936 IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list),
3937 IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan),
3938 IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan),
3939 IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid),
3940 IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid),
3941 IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname),
3942 IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname),
3943 IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate),
3944 IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate),
3945 IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold),
3946 IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold),
3947 IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power),
3948 IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode),
3949 IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode),
3950 IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power),
3951 IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power),
3952 IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie),
3953 IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth),
3954 IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext),
3957 static const iw_handler wl_private_handler[] =
3958 { /* SIOCIWFIRSTPRIV + */
3959 wvlan_set_netname, /* 0: SIOCSIWNETNAME */
3960 wvlan_get_netname, /* 1: SIOCGIWNETNAME */
3961 wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */
3962 wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */
3963 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
3964 wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */
3965 wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */
3969 struct iw_priv_args wl_priv_args[] = {
3970 {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" },
3971 {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" },
3972 {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" },
3973 {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" },
3974 #if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA
3975 {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" },
3976 {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" },
3980 const struct iw_handler_def wl_iw_handler_def =
3982 .num_private = sizeof(wl_private_handler) / sizeof(iw_handler),
3983 .private = (iw_handler *) wl_private_handler,
3984 .private_args = (struct iw_priv_args *) wl_priv_args,
3985 .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args),
3986 .num_standard = sizeof(wl_handler) / sizeof(iw_handler),
3987 .standard = (iw_handler *) wl_handler,
3988 .get_wireless_stats = wl_get_wireless_stats,