diff options
Diffstat (limited to 'drivers/staging/wlags49_h2/wl_wext.c')
-rw-r--r-- | drivers/staging/wlags49_h2/wl_wext.c | 3794 |
1 files changed, 0 insertions, 3794 deletions
diff --git a/drivers/staging/wlags49_h2/wl_wext.c b/drivers/staging/wlags49_h2/wl_wext.c deleted file mode 100644 index 3aeff818afc2..000000000000 --- a/drivers/staging/wlags49_h2/wl_wext.c +++ /dev/null @@ -1,3794 +0,0 @@ -/******************************************************************************* - * Agere Systems Inc. - * Wireless device driver for Linux (wlags49). - * - * Copyright (c) 1998-2003 Agere Systems Inc. - * All rights reserved. - * http://www.agere.com - * - * Initially developed by TriplePoint, Inc. - * http://www.triplepoint.com - * - *------------------------------------------------------------------------------ - * - * SOFTWARE LICENSE - * - * This software is provided subject to the following terms and conditions, - * which you should read carefully before using the software. Using this - * software indicates your acceptance of these terms and conditions. If you do - * not agree with these terms and conditions, do not use the software. - * - * Copyright © 2003 Agere Systems Inc. - * All rights reserved. - * - * Redistribution and use in source or binary forms, with or without - * modifications, are permitted provided that the following conditions are met: - * - * . Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following Disclaimer as comments in the code as - * well as in the documentation and/or other materials provided with the - * distribution. - * - * . Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following Disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * . Neither the name of Agere Systems Inc. nor the names of the contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * Disclaimer - * - * THIS SOFTWARE IS PROVIDED AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY - * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN - * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - ******************************************************************************/ - -/******************************************************************************* - * include files - ******************************************************************************/ -#include <wl_version.h> - -#include <linux/if_arp.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> -#include <asm/uaccess.h> - -#include <debug.h> -#include <hcf.h> -#include <hcfdef.h> - -#include <wl_if.h> -#include <wl_internal.h> -#include <wl_util.h> -#include <wl_main.h> -#include <wl_wext.h> -#include <wl_priv.h> - -/* Set up the LTV to program the appropriate key */ -static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr, - int set_tx, u8 *seq, u8 *key, size_t key_len) -{ - int ret = -EINVAL; - int buf_idx = 0; - hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] = - { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 }; - - /* - * Check the key index here; if 0, load as Pairwise Key, otherwise, - * load as a group key. Note that for the Hermes, the RIDs for - * group/pairwise keys are different from each other and different - * than the default WEP keys as well. - */ - switch (key_idx) { - case 0: - ltv->len = 28; - ltv->typ = CFG_ADD_TKIP_MAPPED_KEY; - - /* Load the BSSID */ - memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN); - buf_idx += ETH_ALEN; - - /* Load the TKIP key */ - memcpy(<v->u.u8[buf_idx], &key[0], 16); - buf_idx += 16; - - /* Load the TSC */ - memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); - buf_idx += IW_ENCODE_SEQ_MAX_SIZE; - - /* Load the RSC */ - memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); - buf_idx += IW_ENCODE_SEQ_MAX_SIZE; - - /* Load the TxMIC key */ - memcpy(<v->u.u8[buf_idx], &key[16], 8); - buf_idx += 8; - - /* Load the RxMIC key */ - memcpy(<v->u.u8[buf_idx], &key[24], 8); - - ret = 0; - break; - case 1: - case 2: - case 3: - ltv->len = 26; - ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY; - - /* Load the key Index */ - - /* If this is a Tx Key, set bit 8000 */ - if (set_tx) - key_idx |= 0x8000; - ltv->u.u16[buf_idx] = cpu_to_le16(key_idx); - buf_idx += 2; - - /* Load the RSC */ - memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); - buf_idx += IW_ENCODE_SEQ_MAX_SIZE; - - /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in - CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */ - memcpy(<v->u.u8[buf_idx], key, key_len); - buf_idx += key_len; - - /* Load the TSC */ - memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); - - ret = 0; - break; - default: - break; - } - - return ret; -} - -/* Set up the LTV to clear the appropriate key */ -static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr) -{ - switch (key_idx) { - case 0: - if (!is_broadcast_ether_addr(addr)) { - ltv->len = 7; - ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY; - memcpy(<v->u.u8[0], addr, ETH_ALEN); - } - break; - case 1: - case 2: - case 3: - /* Clear the Group TKIP keys by index */ - ltv->len = 2; - ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY; - ltv->u.u16[0] = cpu_to_le16(key_idx); - - break; - default: - break; - } - - return 0; -} - -/* Set the WEP keys in the wl_private structure */ -static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx, - u8 *key, size_t key_len, - bool enable, bool set_tx) -{ - hcf_8 encryption_state = lp->EnableEncryption; - int tk = lp->TransmitKeyID - 1; /* current key */ - int ret = 0; - - /* Is encryption supported? */ - if (!wl_has_wep(&(lp->hcfCtx))) { - DBG_WARNING(DbgInfo, "WEP not supported on this device\n"); - ret = -EOPNOTSUPP; - goto out; - } - - DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n", - key, key_len); - - /* Check the size of the key */ - switch (key_len) { - case MIN_KEY_SIZE: - case MAX_KEY_SIZE: - - /* Check the index */ - if ((key_idx < 0) || (key_idx >= MAX_KEYS)) - key_idx = tk; - - /* Cleanup */ - memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE); - - /* Copy the key in the driver */ - memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len); - - /* Set the length */ - lp->DefaultKeys.key[key_idx].len = key_len; - - DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len); - DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n", - lp->DefaultKeys.key[key_idx].key, - lp->DefaultKeys.key[key_idx].len, key_idx); - - /* Enable WEP (if possible) */ - if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0)) - lp->EnableEncryption = 1; - - break; - - case 0: - /* Do we want to just set the current transmit key? */ - if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) { - DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx, - lp->DefaultKeys.key[key_idx].len); - - if (lp->DefaultKeys.key[key_idx].len > 0) { - lp->TransmitKeyID = key_idx + 1; - lp->EnableEncryption = 1; - } else { - DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n"); - ret = -EINVAL; - } - } - break; - - default: - DBG_WARNING(DbgInfo, "Invalid Key length\n"); - ret = -EINVAL; - goto out; - } - - /* Read the flags */ - if (enable) { - lp->EnableEncryption = 1; - lp->wext_enc = IW_ENCODE_ALG_WEP; - } else { - lp->EnableEncryption = 0; /* disable encryption */ - lp->wext_enc = IW_ENCODE_ALG_NONE; - } - - DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state); - DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption); - DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len); - - /* Write the changes to the card */ - if (ret == 0) { - DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, - lp->TransmitKeyID); - - if (lp->EnableEncryption == encryption_state) { - if (key_len != 0) { - /* Dynamic WEP key update */ - wl_set_wep_keys(lp); - } - } else { - /* To switch encryption on/off, soft reset is - * required */ - wl_apply(lp); - } - } - -out: - return ret; -} - -/******************************************************************************* - * wireless_commit() - ******************************************************************************* - * - * DESCRIPTION: - * - * Commit - * protocol used. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -static int wireless_commit(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *rqu, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - wl_apply(lp); - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_commit -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_protocol() - ******************************************************************************* - * - * DESCRIPTION: - * - * Returns a vendor-defined string that should identify the wireless - * protocol used. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -static int wireless_get_protocol(struct net_device *dev, struct iw_request_info *info, char *name, char *extra) -{ - /* Originally, the driver was placing the string "Wireless" here. However, - the wireless extensions (/linux/wireless.h) indicate this string should - describe the wireless protocol. */ - - strcpy(name, "IEEE 802.11b"); - - return 0; -} // wireless_get_protocol -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_frequency() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the frequency (channel) on which the card should Tx/Rx. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int channel = 0; - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if( !capable( CAP_NET_ADMIN )) { - ret = -EPERM; - return ret; - } - - - /* If frequency specified, look up channel */ - if( freq->e == 1 ) { - int f = freq->m / 100000; - channel = wl_get_chan_from_freq( f ); - } - - - /* Channel specified */ - if( freq->e == 0 ) { - channel = freq->m; - } - - - /* If the channel is an 802.11a channel, set Bit 8 */ - if( channel > 14 ) { - channel = channel | 0x100; - } - - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - lp->Channel = channel; - - - /* Commit the adapter parameters */ - wl_apply( lp ); - - /* Send an event that channel/freq has been set */ - wl_wext_event_freq( lp->dev ); - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_frequency -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_frequency() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the frequency (channel) on which the card is Tx/Rx. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -static int wireless_get_frequency(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) - -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = -1; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_CUR_CHANNEL; - - ret = hcf_get_info( &(lp->hcfCtx), (LTVP)&( lp->ltvRecord )); - if( ret == HCF_SUCCESS ) { - hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ); - - freq->m = wl_get_freq_from_chan( channel ) * 100000; - freq->e = 1; - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - - ret = (ret == HCF_SUCCESS ? 0 : -EFAULT); - -out: - return ret; -} // wireless_get_frequency -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_range() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to provide misc info and statistics about the - * wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - struct iw_range *range = (struct iw_range *) extra; - int ret = 0; - int status = -1; - int count; - __u16 *pTxRate; - int retries = 0; - - /* Set range information */ - data->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Set range information */ - memset( range, 0, sizeof( struct iw_range )); - -retry: - /* Get the current transmit rate from the adapter */ - lp->ltvRecord.len = 1 + (sizeof(*pTxRate) / sizeof(hcf_16)); - lp->ltvRecord.typ = CFG_CUR_TX_RATE; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - if( status != HCF_SUCCESS ) { - /* Recovery action: reset and retry up to 10 times */ - DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: 0x%x\n", status ); - - if (retries < 10) { - retries++; - - /* Holding the lock too long, makes a gap to allow other processes */ - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - status = wl_reset( dev ); - if ( status != HCF_SUCCESS ) { - DBG_TRACE( DbgInfo, "reset failed: 0x%x\n", status ); - - ret = -EFAULT; - goto out_unlock; - } - - /* Holding the lock too long, makes a gap to allow other processes */ - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - goto retry; - - } else { - DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE failed: %d retries\n", retries ); - ret = -EFAULT; - goto out_unlock; - } - } - - /* Holding the lock too long, makes a gap to allow other processes */ - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - pTxRate = (__u16 *)&( lp->ltvRecord.u.u32 ); - - range->throughput = CNV_LITTLE_TO_INT( *pTxRate ) * MEGABIT; - - if (retries > 0) { - DBG_TRACE( DbgInfo, "Get CFG_CUR_TX_RATE succes: %d retries\n", retries ); - } - - // NWID - NOT SUPPORTED - - - /* Channel/Frequency Info */ - range->num_channels = RADIO_CHANNELS; - - - /* Signal Level Thresholds */ - range->sensitivity = RADIO_SENSITIVITY_LEVELS; - - - /* Link quality */ - range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY; - - /* If the value returned in /proc/net/wireless is greater than the maximum range, - iwconfig assumes that the value is in dBm. Because an unsigned char is used, - it requires a bit of contorsion... */ - - range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 ); - range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 ); - - - /* Set available rates */ - range->num_bitrates = 0; - - lp->ltvRecord.len = 6; - lp->ltvRecord.typ = CFG_SUPPORTED_DATA_RATES; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - if( status == HCF_SUCCESS ) { - for( count = 0; count < MAX_RATES; count++ ) - if( lp->ltvRecord.u.u8[count+2] != 0 ) { - range->bitrate[count] = lp->ltvRecord.u.u8[count+2] * MEGABIT / 2; - range->num_bitrates++; - } - } else { - DBG_TRACE( DbgInfo, "CFG_SUPPORTED_DATA_RATES: 0x%x\n", status ); - ret = -EFAULT; - goto out_unlock; - } - - /* RTS Threshold info */ - range->min_rts = MIN_RTS_BYTES; - range->max_rts = MAX_RTS_BYTES; - - // Frag Threshold info - NOT SUPPORTED - - // Power Management info - NOT SUPPORTED - - /* Encryption */ - - /* Holding the lock too long, makes a gap to allow other processes */ - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - /* Is WEP supported? */ - - if( wl_has_wep( &( lp->hcfCtx ))) { - /* WEP: RC4 40 bits */ - range->encoding_size[0] = MIN_KEY_SIZE; - - /* RC4 ~128 bits */ - range->encoding_size[1] = MAX_KEY_SIZE; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = MAX_KEYS; - } - - /* Tx Power Info */ - range->txpower_capa = IW_TXPOW_MWATT; - range->num_txpower = 1; - range->txpower[0] = RADIO_TX_POWER_MWATT; - - /* Wireless Extension Info */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = WIRELESS_SUPPORT; - - // Retry Limits and Lifetime - NOT SUPPORTED - - /* Holding the lock too long, makes a gap to allow other processes */ - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - DBG_TRACE( DbgInfo, "calling wl_wireless_stats\n" ); - wl_wireless_stats( lp->dev ); - range->avg_qual = lp->wstats.qual; - DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" ); - - /* Event capability (kernel + driver) */ - IW_EVENT_CAPA_SET_KERNEL(range->event_capa); - IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); - IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); - IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED); - IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED); - IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); - IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE); - IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE); - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP; - range->scan_capa = IW_SCAN_CAPA_NONE; - -out_unlock: - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - - return ret; -} // wireless_get_range -/*============================================================================*/ - - -/******************************************************************************* - * wireless_get_bssid() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the BSSID the wireless device is currently associated with. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_bssid(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; -#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA - int status = -1; -#endif /* (HCF_TYPE) & HCF_TYPE_STA */ - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - ap_addr->sa_family = ARPHRD_ETHER; - - /* Assume AP mode here, which means the BSSID is our own MAC address. In - STA mode, this address will be overwritten with the actual BSSID using - the code below. */ - memcpy(&ap_addr->sa_data, lp->dev->dev_addr, ETH_ALEN); - - -#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA - //;?should we return an error status in AP mode - - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { - /* Get Current BSSID */ - lp->ltvRecord.typ = CFG_CUR_BSSID; - lp->ltvRecord.len = 4; - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - if( status == HCF_SUCCESS ) { - /* Copy info into sockaddr struct */ - memcpy(&ap_addr->sa_data, lp->ltvRecord.u.u8, ETH_ALEN); - } else { - ret = -EFAULT; - } - } - -#endif // (HCF_TYPE) & HCF_TYPE_STA - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_bssid -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_ap_list() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the results of a network scan. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - * NOTE: SIOCGIWAPLIST has been deprecated by SIOCSIWSCAN. This function - * implements SIOCGIWAPLIST only to provide backwards compatibility. For - * all systems using WIRELESS_EXT v14 and higher, use SIOCSIWSCAN! - * - ******************************************************************************/ -static int wireless_get_ap_list (struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret; - int num_aps = -1; - int sec_count = 0; - hcf_32 count; - struct sockaddr *hwa = NULL; - struct iw_quality *qual = NULL; -#ifdef WARP - ScanResult *p = &lp->scan_results; -#else - ProbeResult *p = &lp->probe_results; -#endif // WARP - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Set the completion state to FALSE */ - lp->scan_results.scan_complete = FALSE; - lp->probe_results.scan_complete = FALSE; - /* Channels to scan */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_SCAN_CHANNELS_2GHZ; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF ); - ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNELS_2GHZ result: 0x%x\n", ret ); - - /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to - disassociate from the network we are currently on */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_SCAN_SSID; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); - ret = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' ret: 0x%x\n", ret ); - - /* Initiate the scan */ -#ifdef WARP - ret = hcf_action( &( lp->hcfCtx ), MDD_ACT_SCAN ); -#else - ret = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN ); -#endif // WARP - - wl_act_int_on( lp ); - - //;? unlock? what about the access to lp below? is it broken? - wl_unlock(lp, &flags); - - if( ret == HCF_SUCCESS ) { - DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" ); - while( (*p).scan_complete == FALSE && ret == HCF_SUCCESS ) { - DBG_TRACE( DbgInfo, "Waiting for scan results...\n" ); - /* Abort the scan if we've waited for more than MAX_SCAN_TIME_SEC */ - if( sec_count++ > MAX_SCAN_TIME_SEC ) { - ret = -EIO; - } else { - /* Wait for 1 sec in 10ms intervals, scheduling the kernel to do - other things in the meantime, This prevents system lockups by - giving some time back to the kernel */ - for( count = 0; count < 100; count ++ ) { - mdelay( 10 ); - schedule( ); - } - } - } - - rmb(); - - if ( ret != HCF_SUCCESS ) { - DBG_ERROR( DbgInfo, "timeout waiting for scan results\n" ); - } else { - num_aps = (*p)/*lp->probe_results*/.num_aps; - if (num_aps > IW_MAX_AP) { - num_aps = IW_MAX_AP; - } - data->length = num_aps; - hwa = (struct sockaddr *)extra; - qual = (struct iw_quality *) extra + - ( sizeof( struct sockaddr ) * num_aps ); - - /* This flag is used to tell the user if we provide quality - information. Since we provide signal/noise levels but no - quality info on a scan, this is set to 0. Setting to 1 and - providing a quality of 0 produces weird results. If we ever - provide quality (or can calculate it), this can be changed */ - data->flags = 0; - - for( count = 0; count < num_aps; count++ ) { -#ifdef WARP - memcpy( hwa[count].sa_data, - (*p)/*lp->scan_results*/.APTable[count].bssid, ETH_ALEN ); -#else //;?why use BSSID and bssid as names in seemingly very comparable situations - DBG_PRINT("BSSID: %pM\n", - (*p).ProbeTable[count].BSSID); - memcpy( hwa[count].sa_data, - (*p)/*lp->probe_results*/.ProbeTable[count].BSSID, ETH_ALEN ); -#endif // WARP - } - /* Once the data is copied to the wireless struct, invalidate the - scan result to initiate a rescan on the next request */ - (*p)/*lp->probe_results*/.scan_complete = FALSE; - /* Send the wireless event that the scan has completed, just in case - it's needed */ - wl_wext_event_scan_complete( lp->dev ); - } - } -out: - return ret; -} // wireless_get_ap_list -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_sensitivity() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the sensitivity (distance between APs) of the wireless card. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int dens = sens->value; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if(( dens < 1 ) || ( dens > 3 )) { - ret = -EINVAL; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - lp->DistanceBetweenAPs = dens; - wl_apply( lp ); - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_sensitivity -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_sensitivity() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the sensitivity (distance between APs) of the wireless card. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_sensitivity(struct net_device *dev, struct iw_request_info *info, struct iw_param *sens, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - /* not worth locking ... */ - sens->value = lp->DistanceBetweenAPs; - sens->fixed = 0; /* auto */ -out: - return ret; -} // wireless_get_sensitivity -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_essid() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the ESSID (network name) that the wireless device should associate - * with. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN) { - ret = -EINVAL; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - memset( lp->NetworkName, 0, sizeof( lp->NetworkName )); - - /* data->flags is zero to ask for "any" */ - if( data->flags == 0 ) { - /* Need this because in STAP build PARM_DEFAULT_SSID is "LinuxAP" - * ;?but there ain't no STAP anymore*/ - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { - strcpy( lp->NetworkName, "ANY" ); - } else { - //strcpy( lp->NetworkName, "ANY" ); - strcpy( lp->NetworkName, PARM_DEFAULT_SSID ); - } - } else { - memcpy( lp->NetworkName, ssid, data->length ); - } - - DBG_NOTICE( DbgInfo, "set NetworkName: %s\n", ssid ); - - /* Commit the adapter parameters */ - wl_apply( lp ); - - /* Send an event that ESSID has been set */ - wl_wext_event_essid( lp->dev ); - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_essid -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_essid() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the ESSID (network name) that the wireless device is associated - * with. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid) - -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int status = -1; - wvName_t *pName; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Get the desired network name */ - lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 )); - - -#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA - //;?should we return an error status in AP mode - - lp->ltvRecord.typ = CFG_DESIRED_SSID; - -#endif - - -#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP - //;?should we restore this to allow smaller memory footprint - - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { - lp->ltvRecord.typ = CFG_CNF_OWN_SSID; - } - -#endif // HCF_AP - - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - if( status == HCF_SUCCESS ) { - pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); - - /* Endian translate the string length */ - pName->length = CNV_LITTLE_TO_INT( pName->length ); - - /* Copy the information into the user buffer */ - data->length = pName->length; - - if( pName->length < HCF_MAX_NAME_LEN ) { - pName->name[pName->length] = '\0'; - } - - data->flags = 1; - - -#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA - //;?should we return an error status in AP mode - - /* if desired is null ("any"), return current or "any" */ - if( pName->name[0] == '\0' ) { - /* Get the current network name */ - lp->ltvRecord.len = 1 + ( sizeof(*pName ) / sizeof( hcf_16 )); - lp->ltvRecord.typ = CFG_CUR_SSID; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - if( status == HCF_SUCCESS ) { - pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); - - /* Endian translate the string length */ - pName->length = CNV_LITTLE_TO_INT( pName->length ); - - /* Copy the information into the user buffer */ - data->length = pName->length; - data->flags = 1; - } else { - ret = -EFAULT; - goto out_unlock; - } - } - -#endif // HCF_STA - - if (pName->length > IW_ESSID_MAX_SIZE) { - ret = -EFAULT; - goto out_unlock; - } - - memcpy(essid, pName->name, pName->length); - } else { - ret = -EFAULT; - goto out_unlock; - } - -out_unlock: - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_essid -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_encode() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the encryption keys and status (enable or disable). - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1; - int ret = 0; - bool enable = true; - - if (lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if (erq->flags & IW_ENCODE_DISABLED) - enable = false; - - wl_lock(lp, &flags); - - wl_act_int_off(lp); - - ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length, - enable, true); - - /* Send an event that Encryption has been set */ - if (ret == 0) - wl_wext_event_encode(dev); - - wl_act_int_on(lp); - - wl_unlock(lp, &flags); - -out: - return ret; -} - -/******************************************************************************* - * wireless_get_encode() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the encryption keys and status. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key) - -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int index; - - DBG_NOTICE(DbgInfo, "GIWENCODE: encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID); - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - /* Only super-user can see WEP key */ - if( !capable( CAP_NET_ADMIN )) { - ret = -EPERM; - return ret; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Is it supported? */ - if( !wl_has_wep( &( lp->hcfCtx ))) { - ret = -EOPNOTSUPP; - goto out_unlock; - } - - /* Basic checking */ - index = (erq->flags & IW_ENCODE_INDEX ) - 1; - - - /* Set the flags */ - erq->flags = 0; - - if( lp->EnableEncryption == 0 ) { - erq->flags |= IW_ENCODE_DISABLED; - } - - /* Which key do we want */ - if(( index < 0 ) || ( index >= MAX_KEYS )) { - index = lp->TransmitKeyID - 1; - } - - erq->flags |= index + 1; - - /* Copy the key to the user buffer */ - erq->length = lp->DefaultKeys.key[index].len; - - memcpy(key, lp->DefaultKeys.key[index].key, erq->length); - -out_unlock: - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_encode -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_nickname() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the nickname, or station name, of the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - -#if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version - if( !capable(CAP_NET_ADMIN )) { - ret = -EPERM; - return ret; - } -#endif - - /* Validate the new value */ - if(data->length > HCF_MAX_NAME_LEN) { - ret = -EINVAL; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - memset( lp->StationName, 0, sizeof( lp->StationName )); - - memcpy( lp->StationName, nickname, data->length ); - - /* Commit the adapter parameters */ - wl_apply( lp ); - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_nickname -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_nickname() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the nickname, or station name, of the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_nickname(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int status = -1; - wvName_t *pName; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Get the current station name */ - lp->ltvRecord.len = 1 + ( sizeof( *pName ) / sizeof( hcf_16 )); - lp->ltvRecord.typ = CFG_CNF_OWN_NAME; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - if( status == HCF_SUCCESS ) { - pName = (wvName_t *)&( lp->ltvRecord.u.u32 ); - - /* Endian translate the length */ - pName->length = CNV_LITTLE_TO_INT( pName->length ); - - if ( pName->length > IW_ESSID_MAX_SIZE ) { - ret = -EFAULT; - } else { - /* Copy the information into the user buffer */ - data->length = pName->length; - memcpy(nickname, pName->name, pName->length); - } - } else { - ret = -EFAULT; - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_nickname -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_porttype() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the port type of the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - hcf_16 portType; - hcf_16 createIBSS; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Validate the new value */ - switch( *mode ) { - case IW_MODE_ADHOC: - - /* When user requests ad-hoc, set IBSS mode! */ - portType = 1; - createIBSS = 1; - - lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1; - - break; - - - case IW_MODE_AUTO: - case IW_MODE_INFRA: - - /* Both automatic and infrastructure set port to BSS/STA mode */ - portType = 1; - createIBSS = 0; - - lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //1; - - break; - - -#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP - - case IW_MODE_MASTER: - - /* Set BSS/AP mode */ - portType = 1; - - lp->CreateIBSS = 0; - lp->DownloadFirmware = WVLAN_DRV_MODE_AP; //2; - - break; - -#endif /* (HCF_TYPE) & HCF_TYPE_AP */ - - - default: - - portType = 0; - createIBSS = 0; - ret = -EINVAL; - } - - if( portType != 0 ) { - /* Only do something if there is a mode change */ - if( ( lp->PortType != portType ) || (lp->CreateIBSS != createIBSS)) { - lp->PortType = portType; - lp->CreateIBSS = createIBSS; - - /* Commit the adapter parameters */ - wl_go( lp ); - - /* Send an event that mode has been set */ - wl_wext_event_mode( lp->dev ); - } - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_porttype -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_porttype() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the port type of the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_porttype(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra) - -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int status = -1; - hcf_16 *pPortType; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Get the current port type */ - lp->ltvRecord.len = 1 + ( sizeof( *pPortType ) / sizeof( hcf_16 )); - lp->ltvRecord.typ = CFG_CNF_PORT_TYPE; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - if( status == HCF_SUCCESS ) { - pPortType = (hcf_16 *)&( lp->ltvRecord.u.u32 ); - - *pPortType = CNV_LITTLE_TO_INT( *pPortType ); - - switch( *pPortType ) { - case 1: - -#if 0 -#if (HCF_TYPE) & HCF_TYPE_AP - - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { - *mode = IW_MODE_MASTER; - } else { - *mode = IW_MODE_INFRA; - } - -#else - - *mode = IW_MODE_INFRA; - -#endif /* (HCF_TYPE) & HCF_TYPE_AP */ -#endif - - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { - *mode = IW_MODE_MASTER; - } else { - if( lp->CreateIBSS ) { - *mode = IW_MODE_ADHOC; - } else { - *mode = IW_MODE_INFRA; - } - } - - break; - - - case 3: - *mode = IW_MODE_ADHOC; - break; - - default: - ret = -EFAULT; - break; - } - } else { - ret = -EFAULT; - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_porttype -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_power() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the power management settings of the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - DBG_PRINT( "THIS CORRUPTS PMEnabled ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" ); - -#if 0 //;? Needed, was present in original code but not in 7.18 Linux 2.6 kernel version - if( !capable( CAP_NET_ADMIN )) { - ret = -EPERM; - return ret; - } -#endif - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Set the power management state based on the 'disabled' value */ - if( wrq->disabled ) { - lp->PMEnabled = 0; - } else { - lp->PMEnabled = 1; - } - - /* Commit the adapter parameters */ - wl_apply( lp ); - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_power -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_power() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the power management settings of the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) - -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - DBG_PRINT( "THIS IS PROBABLY AN OVER-SIMPLIFICATION ;?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" ); - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - rrq->flags = 0; - rrq->value = 0; - - if( lp->PMEnabled ) { - rrq->disabled = 0; - } else { - rrq->disabled = 1; - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_power -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_tx_power() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the transmit power of the wireless device's radio. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_tx_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - -#ifdef USE_POWER_DBM - rrq->value = RADIO_TX_POWER_DBM; - rrq->flags = IW_TXPOW_DBM; -#else - rrq->value = RADIO_TX_POWER_MWATT; - rrq->flags = IW_TXPOW_MWATT; -#endif - rrq->fixed = 1; - rrq->disabled = 0; - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_tx_power -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_set_rts_threshold() - ******************************************************************************* - * - * DESCRIPTION: - * - * Sets the RTS threshold for the wireless card. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra) -{ - int ret = 0; - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int rthr = rts->value; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if(rts->fixed == 0) { - ret = -EINVAL; - goto out; - } - - if( rts->disabled ) { - rthr = 2347; - } - - if(( rthr < 256 ) || ( rthr > 2347 )) { - ret = -EINVAL; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - lp->RTSThreshold = rthr; - - wl_apply( lp ); - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_rts_threshold -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_rts_threshold() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gets the RTS threshold for the wireless card. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra) -{ - int ret = 0; - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - rts->value = lp->RTSThreshold; - - rts->disabled = ( rts->value == 2347 ); - - rts->fixed = 1; - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_rts_threshold -/*============================================================================*/ - - - - - -/******************************************************************************* - * wireless_set_rate() - ******************************************************************************* - * - * DESCRIPTION: - * - * Set the default data rate setting used by the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; -#ifdef WARP - int status = -1; - int index = 0; -#endif // WARP - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - -#ifdef WARP - - /* Determine if the card is operating in the 2.4 or 5.0 GHz band; check - if Bit 9 is set in the current channel RID */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_CUR_CHANNEL; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - if( status == HCF_SUCCESS ) { - index = ( CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ) & 0x100 ) ? 1 : 0; - - DBG_PRINT( "Index: %d\n", index ); - } else { - DBG_ERROR( DbgInfo, "Could not determine radio frequency\n" ); - ret = -EINVAL; - goto out_unlock; - } - - if( rrq->value > 0 && - rrq->value <= 1 * MEGABIT ) { - lp->TxRateControl[index] = 0x0001; - } - else if( rrq->value > 1 * MEGABIT && - rrq->value <= 2 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0002; - } else { - lp->TxRateControl[index] = 0x0003; - } - } - else if( rrq->value > 2 * MEGABIT && - rrq->value <= 5 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0004; - } else { - lp->TxRateControl[index] = 0x0007; - } - } - else if( rrq->value > 5 * MEGABIT && - rrq->value <= 6 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0010; - } else { - lp->TxRateControl[index] = 0x0017; - } - } - else if( rrq->value > 6 * MEGABIT && - rrq->value <= 9 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0020; - } else { - lp->TxRateControl[index] = 0x0037; - } - } - else if( rrq->value > 9 * MEGABIT && - rrq->value <= 11 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0008; - } else { - lp->TxRateControl[index] = 0x003F; - } - } - else if( rrq->value > 11 * MEGABIT && - rrq->value <= 12 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0040; - } else { - lp->TxRateControl[index] = 0x007F; - } - } - else if( rrq->value > 12 * MEGABIT && - rrq->value <= 18 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0080; - } else { - lp->TxRateControl[index] = 0x00FF; - } - } - else if( rrq->value > 18 * MEGABIT && - rrq->value <= 24 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0100; - } else { - lp->TxRateControl[index] = 0x01FF; - } - } - else if( rrq->value > 24 * MEGABIT && - rrq->value <= 36 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0200; - } else { - lp->TxRateControl[index] = 0x03FF; - } - } - else if( rrq->value > 36 * MEGABIT && - rrq->value <= 48 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0400; - } else { - lp->TxRateControl[index] = 0x07FF; - } - } - else if( rrq->value > 48 * MEGABIT && - rrq->value <= 54 * MEGABIT ) { - if( rrq->fixed == 1 ) { - lp->TxRateControl[index] = 0x0800; - } else { - lp->TxRateControl[index] = 0x0FFF; - } - } - else if( rrq->fixed == 0 ) { - /* In this case, the user has not specified a bitrate, only the "auto" - moniker. So, set to all supported rates */ - lp->TxRateControl[index] = PARM_MAX_TX_RATE; - } else { - rrq->value = 0; - ret = -EINVAL; - goto out_unlock; - } - - -#else - - if( rrq->value > 0 && - rrq->value <= 1 * MEGABIT ) { - lp->TxRateControl[0] = 1; - } - else if( rrq->value > 1 * MEGABIT && - rrq->value <= 2 * MEGABIT ) { - if( rrq->fixed ) { - lp->TxRateControl[0] = 2; - } else { - lp->TxRateControl[0] = 6; - } - } - else if( rrq->value > 2 * MEGABIT && - rrq->value <= 5 * MEGABIT ) { - if( rrq->fixed ) { - lp->TxRateControl[0] = 4; - } else { - lp->TxRateControl[0] = 7; - } - } - else if( rrq->value > 5 * MEGABIT && - rrq->value <= 11 * MEGABIT ) { - if( rrq->fixed) { - lp->TxRateControl[0] = 5; - } else { - lp->TxRateControl[0] = 3; - } - } - else if( rrq->fixed == 0 ) { - /* In this case, the user has not specified a bitrate, only the "auto" - moniker. So, set the rate to 11Mb auto */ - lp->TxRateControl[0] = 3; - } else { - rrq->value = 0; - ret = -EINVAL; - goto out_unlock; - } - -#endif // WARP - - - /* Commit the adapter parameters */ - wl_apply( lp ); - -out_unlock: - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_rate -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_rate() - ******************************************************************************* - * - * DESCRIPTION: - * - * Get the default data rate setting used by the wireless device. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) - -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int status = -1; - hcf_16 txRate; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Get the current transmit rate from the adapter */ - lp->ltvRecord.len = 1 + ( sizeof(txRate)/sizeof(hcf_16)); - lp->ltvRecord.typ = CFG_CUR_TX_RATE; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - if( status == HCF_SUCCESS ) { -#ifdef WARP - - txRate = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ); - - if( txRate & 0x0001 ) { - txRate = 1; - } - else if( txRate & 0x0002 ) { - txRate = 2; - } - else if( txRate & 0x0004 ) { - txRate = 5; - } - else if( txRate & 0x0008 ) { - txRate = 11; - } - else if( txRate & 0x00010 ) { - txRate = 6; - } - else if( txRate & 0x00020 ) { - txRate = 9; - } - else if( txRate & 0x00040 ) { - txRate = 12; - } - else if( txRate & 0x00080 ) { - txRate = 18; - } - else if( txRate & 0x00100 ) { - txRate = 24; - } - else if( txRate & 0x00200 ) { - txRate = 36; - } - else if( txRate & 0x00400 ) { - txRate = 48; - } - else if( txRate & 0x00800 ) { - txRate = 54; - } - -#else - - txRate = (hcf_16)CNV_LITTLE_TO_LONG( lp->ltvRecord.u.u32[0] ); - -#endif // WARP - - rrq->value = txRate * MEGABIT; - } else { - rrq->value = 0; - ret = -EFAULT; - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_rate -/*============================================================================*/ - - - - -#if 0 //;? Not used anymore -/******************************************************************************* - * wireless_get_private_interface() - ******************************************************************************* - * - * DESCRIPTION: - * - * Returns the Linux Wireless Extensions' compatible private interface of - * the driver. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -int wireless_get_private_interface( struct iwreq *wrq, struct wl_private *lp ) -{ - int ret = 0; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if( wrq->u.data.pointer != NULL ) { - struct iw_priv_args priv[] = - { - { SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" }, - { SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" }, - { SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" }, - { SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" }, - { SIOCSIWPORTTYPE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" }, - { SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "gport_type" }, - }; - - /* Verify the user buffer */ - ret = verify_area( VERIFY_WRITE, wrq->u.data.pointer, sizeof( priv )); - - if( ret != 0 ) - return ret; - - /* Copy the data into the user's buffer */ - wrq->u.data.length = NELEM( priv ); - copy_to_user( wrq->u.data.pointer, &priv, sizeof( priv )); - } - -out: - return ret; -} // wireless_get_private_interface -/*============================================================================*/ -#endif - - - -/******************************************************************************* - * wireless_set_scan() - ******************************************************************************* - * - * DESCRIPTION: - * - * Instructs the driver to initiate a network scan. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int status = -1; - int retries = 0; - - //;? Note: shows results as trace, returns always 0 unless BUSY - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* - * This looks like a nice place to test if the HCF is still - * communicating with the card. It seems that sometimes BAP_1 - * gets corrupted. By looking at the comments in HCF the - * cause is still a mystery. Okay, the communication to the - * card is dead, reset the card to revive. - */ - if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0) - { - DBG_TRACE( DbgInfo, "CARD is in DEFUNCT mode, reset it to bring it back to life\n" ); - wl_reset( dev ); - } - -retry: - /* Set the completion state to FALSE */ - lp->probe_results.scan_complete = FALSE; - - - /* Channels to scan */ -#ifdef WARP - lp->ltvRecord.len = 5; - lp->ltvRecord.typ = CFG_SCAN_CHANNEL; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x3FFF ); // 2.4 GHz Band - lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0xFFFF ); // 5.0 GHz Band - lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE( 0xFFFF ); // .. - lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE( 0x0007 ); // .. -#else - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_SCAN_CHANNEL; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x7FFF ); -#endif // WARP - - status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - DBG_TRACE( DbgInfo, "CFG_SCAN_CHANNEL result : 0x%x\n", status ); - - // Holding the lock too long, makes a gap to allow other processes - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - if( status != HCF_SUCCESS ) { - //Recovery - retries++; - if(retries <= 10) { - DBG_TRACE( DbgInfo, "Reset card to recover, attempt: %d\n", retries ); - wl_reset( dev ); - - // Holding the lock too long, makes a gap to allow other processes - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - goto retry; - } - } - - /* Set the SCAN_SSID to "ANY". Using this RID for scan prevents the need to - disassociate from the network we are currently on */ - lp->ltvRecord.len = 18; - lp->ltvRecord.typ = CFG_SCAN_SSID; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); - lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( 0 ); - - status = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - // Holding the lock too long, makes a gap to allow other processes - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - DBG_TRACE( DbgInfo, "CFG_SCAN_SSID to 'any' status: 0x%x\n", status ); - - /* Initiate the scan */ - /* NOTE: Using HCF_ACT_SCAN has been removed, as using HCF_ACT_ACS_SCAN to - retrieve probe response must always be used to support WPA */ - status = hcf_action( &( lp->hcfCtx ), HCF_ACT_ACS_SCAN ); - - if( status == HCF_SUCCESS ) { - DBG_TRACE( DbgInfo, "SUCCESSFULLY INITIATED SCAN...\n" ); - } else { - DBG_TRACE( DbgInfo, "INITIATE SCAN FAILED...\n" ); - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_scan -/*============================================================================*/ - - - - -/******************************************************************************* - * wireless_get_scan() - ******************************************************************************* - * - * DESCRIPTION: - * - * Instructs the driver to gather and return the results of a network scan. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -static int wireless_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; - int count; - char *buf; - char *buf_end; - struct iw_event iwe; - PROBE_RESP *probe_resp; - hcf_8 msg[512]; - hcf_8 *wpa_ie; - hcf_16 wpa_ie_len; - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* If the scan is not done, tell the calling process to try again later */ - if( !lp->probe_results.scan_complete ) { - ret = -EAGAIN; - goto out_unlock; - } - - DBG_TRACE( DbgInfo, "SCAN COMPLETE, Num of APs: %d\n", - lp->probe_results.num_aps ); - - buf = extra; - buf_end = extra + IW_SCAN_MAX_DATA; - - for( count = 0; count < lp->probe_results.num_aps; count++ ) { - /* Reference the probe response from the table */ - probe_resp = (PROBE_RESP *)&lp->probe_results.ProbeTable[count]; - - - /* First entry MUST be the MAC address */ - memset( &iwe, 0, sizeof( iwe )); - - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN); - iwe.len = IW_EV_ADDR_LEN; - - buf = iwe_stream_add_event(info, buf, buf_end, - &iwe, IW_EV_ADDR_LEN); - - /* Use the mode to indicate if it's a station or AP */ - /* Won't always be an AP if in IBSS mode */ - memset( &iwe, 0, sizeof( iwe )); - - iwe.cmd = SIOCGIWMODE; - - if( probe_resp->capability & CAPABILITY_IBSS ) { - iwe.u.mode = IW_MODE_INFRA; - } else { - iwe.u.mode = IW_MODE_MASTER; - } - - iwe.len = IW_EV_UINT_LEN; - - buf = iwe_stream_add_event(info, buf, buf_end, - &iwe, IW_EV_UINT_LEN); - - /* Any quality information */ - memset(&iwe, 0, sizeof(iwe)); - - iwe.cmd = IWEVQUAL; - iwe.u.qual.level = dbm(probe_resp->signal); - iwe.u.qual.noise = dbm(probe_resp->silence); - iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; - iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM; - iwe.len = IW_EV_QUAL_LEN; - - buf = iwe_stream_add_event(info, buf, buf_end, - &iwe, IW_EV_QUAL_LEN); - - - /* ESSID information */ - if( probe_resp->rawData[1] > 0 ) { - memset( &iwe, 0, sizeof( iwe )); - - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = probe_resp->rawData[1]; - iwe.u.data.flags = 1; - - buf = iwe_stream_add_point(info, buf, buf_end, - &iwe, &probe_resp->rawData[2]); - } - - - /* Encryption Information */ - memset( &iwe, 0, sizeof( iwe )); - - iwe.cmd = SIOCGIWENCODE; - iwe.u.data.length = 0; - - /* Check the capabilities field of the Probe Response to see if - 'privacy' is supported on the AP in question */ - if( probe_resp->capability & CAPABILITY_PRIVACY ) { - iwe.u.data.flags |= IW_ENCODE_ENABLED; - } else { - iwe.u.data.flags |= IW_ENCODE_DISABLED; - } - - buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL); - - - /* Frequency Info */ - memset( &iwe, 0, sizeof( iwe )); - - iwe.cmd = SIOCGIWFREQ; - iwe.len = IW_EV_FREQ_LEN; - iwe.u.freq.m = wl_parse_ds_ie( probe_resp ); - iwe.u.freq.e = 0; - - buf = iwe_stream_add_event(info, buf, buf_end, - &iwe, IW_EV_FREQ_LEN); - - - /* Custom info (Beacon Interval) */ - memset( &iwe, 0, sizeof( iwe )); - memset( msg, 0, sizeof( msg )); - - iwe.cmd = IWEVCUSTOM; - sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval ); - iwe.u.data.length = strlen( msg ); - - buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg); - - - /* WPA-IE */ - wpa_ie = NULL; - wpa_ie_len = 0; - - wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len ); - if( wpa_ie != NULL ) { - memset(&iwe, 0, sizeof(iwe)); - - iwe.cmd = IWEVGENIE; - iwe.u.data.length = wpa_ie_len; - - buf = iwe_stream_add_point(info, buf, buf_end, - &iwe, wpa_ie); - } - - /* Add other custom info in formatted string format as needed... */ - } - - data->length = buf - extra; - -out_unlock: - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_get_scan -/*============================================================================*/ - -#if DBG -static const char * const auth_names[] = { - "IW_AUTH_WPA_VERSION", - "IW_AUTH_CIPHER_PAIRWISE", - "IW_AUTH_CIPHER_GROUP", - "IW_AUTH_KEY_MGMT", - "IW_AUTH_TKIP_COUNTERMEASURES", - "IW_AUTH_DROP_UNENCRYPTED", - "IW_AUTH_80211_AUTH_ALG", - "IW_AUTH_WPA_ENABLED", - "IW_AUTH_RX_UNENCRYPTED_EAPOL", - "IW_AUTH_ROAMING_CONTROL", - "IW_AUTH_PRIVACY_INVOKED", - "IW_AUTH_CIPHER_GROUP_MGMT", - "IW_AUTH_MFP", - "Unsupported" -}; -#endif - -static int wireless_set_auth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - ltv_t ltv; - int ret; - int iwa_idx = data->flags & IW_AUTH_INDEX; - int iwa_val = data->value; - - if (lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - if (iwa_idx > IW_AUTH_MFP) - iwa_idx = IW_AUTH_MFP + 1; - DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]); - switch (iwa_idx) { - case IW_AUTH_WPA_VERSION: - /* We do support WPA */ - if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) || - (iwa_val == IW_AUTH_WPA_VERSION_DISABLED)) - ret = 0; - else - ret = -EINVAL; - break; - - case IW_AUTH_WPA_ENABLED: - DBG_TRACE(DbgInfo, "val = %d\n", iwa_val); - if (iwa_val) - lp->EnableEncryption = 2; - else - lp->EnableEncryption = 0; - - /* Write straight to the card */ - ltv.len = 2; - ltv.typ = CFG_CNF_ENCRYPTION; - ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption); - ret = hcf_put_info(&lp->hcfCtx, (LTVP)<v); - - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - - /* Immediately disable card */ - lp->driverEnable = !iwa_val; - if (lp->driverEnable) - hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0); - else - hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0); - ret = 0; - break; - - case IW_AUTH_MFP: - /* Management Frame Protection not supported. - * Only fail if set to required. - */ - if (iwa_val == IW_AUTH_MFP_REQUIRED) - ret = -EINVAL; - else - ret = 0; - break; - - case IW_AUTH_KEY_MGMT: - - /* Record required management suite. - * Will take effect on next commit */ - if (iwa_val != 0) - lp->AuthKeyMgmtSuite = 4; - else - lp->AuthKeyMgmtSuite = 0; - - ret = -EINPROGRESS; - break; - - case IW_AUTH_80211_AUTH_ALG: - - /* Just record whether open or shared is required. - * Will take effect on next commit */ - ret = -EINPROGRESS; - - if (iwa_val & IW_AUTH_ALG_SHARED_KEY) - lp->authentication = 1; - else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM) - lp->authentication = 0; - else - ret = -EINVAL; - break; - - case IW_AUTH_DROP_UNENCRYPTED: - /* Only needed for AP */ - lp->ExcludeUnencrypted = iwa_val; - ret = -EINPROGRESS; - break; - - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - case IW_AUTH_ROAMING_CONTROL: - case IW_AUTH_PRIVACY_INVOKED: - /* Not used. May need to do something with - * CIPHER_PAIRWISE and CIPHER_GROUP*/ - ret = -EINPROGRESS; - break; - - default: - DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx); - /* return an error */ - ret = -EOPNOTSUPP; - break; - } - - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - -out: - return ret; -} // wireless_set_auth -/*============================================================================*/ - - -static void flush_tx(struct wl_private *lp) -{ - ltv_t ltv; - int count; - - /* - * Make sure that there is no data queued up in the firmware - * before setting the TKIP keys. If this check is not - * performed, some data may be sent out with incorrect MIC - * and cause synchronization errors with the AP - */ - /* Check every 1ms for 100ms */ - for (count = 0; count < 100; count++) { - udelay(1000); - - ltv.len = 2; - ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */ - ltv.u.u16[0] = 0; - - hcf_get_info(&(lp->hcfCtx), (LTVP)<v); - - if (ltv.u.u16[0] == 0) - break; - } - - if (count >= 100) - DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n"); - -} - -static int wireless_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *keybuf) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret; - int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1; - ltv_t ltv; - struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf; - bool enable = true; - bool set_tx = false; - - if (lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if (erq->flags & IW_ENCODE_DISABLED) { - ext->alg = IW_ENCODE_ALG_NONE; - enable = false; - } - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - set_tx = true; - - wl_lock(lp, &flags); - - wl_act_int_off(lp); - - memset(<v, 0, sizeof(ltv)); - - switch (ext->alg) { - case IW_ENCODE_ALG_TKIP: - DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx); - - if (sizeof(ext->rx_seq) != 8) { - DBG_TRACE(DbgInfo, "rx_seq size mismatch\n"); - ret = -EINVAL; - goto out_unlock; - } - - ret = hermes_set_tkip_keys(<v, key_idx, ext->addr.sa_data, - set_tx, - ext->rx_seq, ext->key, ext->key_len); - - if (ret != 0) { - DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n"); - goto out_unlock; - } - - flush_tx(lp); - - lp->wext_enc = IW_ENCODE_ALG_TKIP; - - /* Write the key */ - ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); - break; - - case IW_ENCODE_ALG_WEP: - DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx); - - if (erq->flags & IW_ENCODE_RESTRICTED) { - DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n"); - ret = -EINVAL; - goto out_unlock; - } - - ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len, - enable, set_tx); - - break; - - case IW_ENCODE_ALG_CCMP: - DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx); - ret = -EOPNOTSUPP; - break; - - case IW_ENCODE_ALG_NONE: - DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx); - - if (lp->wext_enc == IW_ENCODE_ALG_TKIP) { - ret = hermes_clear_tkip_keys(<v, key_idx, - ext->addr.sa_data); - flush_tx(lp); - lp->wext_enc = IW_ENCODE_ALG_NONE; - ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); - - } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) { - ret = hermes_set_wep_keys(lp, key_idx, - ext->key, ext->key_len, - false, false); - } else { - ret = 0; - } - - break; - - default: - DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx); - ret = -EOPNOTSUPP; - break; - } - -out_unlock: - - wl_act_int_on(lp); - - wl_unlock(lp, &flags); - -out: - return ret; -} -/*============================================================================*/ - - - -static int wireless_set_genie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) - -{ - /* We can't write this to the card, but apparently this - * operation needs to succeed */ - - return 0; -} -/*============================================================================*/ - - -/******************************************************************************* - * wl_wireless_stats() - ******************************************************************************* - * - * DESCRIPTION: - * - * Return the current device wireless statistics. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -struct iw_statistics * wl_wireless_stats( struct net_device *dev ) -{ - struct iw_statistics *pStats; - struct wl_private *lp = wl_priv(dev); - - DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); - - pStats = NULL; - - /* Initialize the statistics */ - pStats = &( lp->wstats ); - pStats->qual.updated = 0x00; - - if( !( lp->flags & WVLAN2_UIL_BUSY )) - { - CFG_COMMS_QUALITY_STRCT *pQual; - CFG_HERMES_TALLIES_STRCT tallies; - int status; - - /* Update driver status */ - pStats->status = 0; - - /* Get the current link quality information */ - lp->ltvRecord.len = 1 + ( sizeof( *pQual ) / sizeof( hcf_16 )); - lp->ltvRecord.typ = CFG_COMMS_QUALITY; - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - if( status == HCF_SUCCESS ) { - pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord ); - - pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual ); - pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl )); - pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl )); - - pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED | - IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED | - IW_QUAL_DBM); - } else { - memset( &( pStats->qual ), 0, sizeof( pStats->qual )); - } - - /* Get the current tallies from the adapter */ - /* Only possible when the device is open */ - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - if( wl_get_tallies( lp, &tallies ) == 0 ) { - /* No endian translation is needed here, as CFG_TALLIES is an - MSF RID; all processing is done on the host, not the card! */ - pStats->discard.nwid = 0L; - pStats->discard.code = tallies.RxWEPUndecryptable; - pStats->discard.misc = tallies.TxDiscards + - tallies.RxFCSErrors + - //tallies.RxDiscardsNoBuffer + - tallies.TxDiscardsWrongSA; - //;? Extra taken over from Linux driver based on 7.18 version - pStats->discard.retries = tallies.TxRetryLimitExceeded; - pStats->discard.fragment = tallies.RxMsgInBadMsgFragments; - } else { - memset( &( pStats->discard ), 0, sizeof( pStats->discard )); - } - } else { - memset( &( pStats->discard ), 0, sizeof( pStats->discard )); - } - } - - return pStats; -} // wl_wireless_stats -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_get_wireless_stats() - ******************************************************************************* - * - * DESCRIPTION: - * - * Return the current device wireless statistics. This function calls - * wl_wireless_stats, but acquires spinlocks first as it can be called - * directly by the network layer. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -struct iw_statistics * wl_get_wireless_stats( struct net_device *dev ) -{ - unsigned long flags; - struct wl_private *lp = wl_priv(dev); - struct iw_statistics *pStats = NULL; - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - -#ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_TRACE( DbgInfo, "Skipping wireless stats, in RTS mode\n" ); - } else -#endif - { - pStats = wl_wireless_stats( dev ); - } - wl_act_int_on( lp ); - - wl_unlock(lp, &flags); - - return pStats; -} // wl_get_wireless_stats - - -/******************************************************************************* - * wl_spy_gather() - ******************************************************************************* - * - * DESCRIPTION: - * - * Gather wireless spy statistics. - * - * PARAMETERS: - * - * wrq - the wireless request buffer - * lp - the device's private adapter structure - * - * RETURNS: - * - * 0 on success - * errno value otherwise - * - ******************************************************************************/ -inline void wl_spy_gather( struct net_device *dev, u_char *mac ) -{ - struct iw_quality wstats; - int status; - u_char stats[2]; - DESC_STRCT desc[1]; - struct wl_private *lp = wl_priv(dev); - /*------------------------------------------------------------------------*/ - - /* shortcut */ - if (!lp->spy_data.spy_number) { - return; - } - - /* Gather wireless spy statistics: for each packet, compare the source - address with out list, and if match, get the stats. */ - memset( stats, 0, sizeof(stats)); - memset( desc, 0, sizeof(DESC_STRCT)); - - desc[0].buf_addr = stats; - desc[0].BUF_SIZE = sizeof(stats); - desc[0].next_desc_addr = 0; // terminate list - - status = hcf_rcv_msg( &( lp->hcfCtx ), &desc[0], 0 ); - - if( status == HCF_SUCCESS ) { - wstats.level = (u_char) dbm(stats[1]); - wstats.noise = (u_char) dbm(stats[0]); - wstats.qual = wstats.level > wstats.noise ? wstats.level - wstats.noise : 0; - - wstats.updated = (IW_QUAL_QUAL_UPDATED | - IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED | - IW_QUAL_DBM); - - wireless_spy_update( dev, mac, &wstats ); - } -} // wl_spy_gather -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_freq() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that the channel/freq - * configuration for a specific device has changed. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_freq( struct net_device *dev ) -{ - union iwreq_data wrqu; - struct wl_private *lp = wl_priv(dev); - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - wrqu.freq.m = lp->Channel; - wrqu.freq.e = 0; - - wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL ); - - return; -} // wl_wext_event_freq -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_mode() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that the mode of operation - * for a specific device has changed. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_mode( struct net_device *dev ) -{ - union iwreq_data wrqu; - struct wl_private *lp = wl_priv(dev); - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { - wrqu.mode = IW_MODE_INFRA; - } else { - wrqu.mode = IW_MODE_MASTER; - } - - wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL ); - - return; -} // wl_wext_event_mode -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_essid() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that the ESSID configuration for - * a specific device has changed. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_essid( struct net_device *dev ) -{ - union iwreq_data wrqu; - struct wl_private *lp = wl_priv(dev); - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - /* Fill out the buffer. Note that the buffer doesn't actually contain the - ESSID, but a pointer to the contents. In addition, the 'extra' field of - the call to wireless_send_event() must also point to where the ESSID - lives */ - wrqu.essid.length = strlen( lp->NetworkName ); - wrqu.essid.pointer = (void __user *)lp->NetworkName; - wrqu.essid.flags = 1; - - wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName ); - - return; -} // wl_wext_event_essid -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_encode() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that the encryption configuration - * for a specific device has changed. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_encode( struct net_device *dev ) -{ - union iwreq_data wrqu; - struct wl_private *lp = wl_priv(dev); - int index = 0; - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - if( lp->EnableEncryption == 0 ) { - wrqu.encoding.flags = IW_ENCODE_DISABLED; - } else { - wrqu.encoding.flags |= lp->TransmitKeyID; - - index = lp->TransmitKeyID - 1; - - /* Only set IW_ENCODE_RESTRICTED/OPEN flag using lp->ExcludeUnencrypted - if we're in AP mode */ -#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP - //;?should we restore this to allow smaller memory footprint - - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { - if( lp->ExcludeUnencrypted ) { - wrqu.encoding.flags |= IW_ENCODE_RESTRICTED; - } else { - wrqu.encoding.flags |= IW_ENCODE_OPEN; - } - } - -#endif // HCF_TYPE_AP - - /* Only provide the key if permissions allow */ - if( capable( CAP_NET_ADMIN )) { - wrqu.encoding.pointer = (void __user *)lp->DefaultKeys.key[index].key; - wrqu.encoding.length = lp->DefaultKeys.key[index].len; - } else { - wrqu.encoding.flags |= IW_ENCODE_NOKEY; - } - } - - wireless_send_event( dev, SIOCSIWENCODE, &wrqu, - lp->DefaultKeys.key[index].key ); - - return; -} // wl_wext_event_encode -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_ap() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that the device has been - * associated to a new AP. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_ap( struct net_device *dev ) -{ - union iwreq_data wrqu; - struct wl_private *lp = wl_priv(dev); - int status; - /*------------------------------------------------------------------------*/ - - - /* Retrieve the WPA-IEs used by the firmware and send an event. We must send - this event BEFORE sending the association event, as there are timing - issues with the hostap supplicant. The supplicant will attempt to process - an EAPOL-Key frame from an AP before receiving this information, which - is required for a proper processed frame. */ - wl_wext_event_assoc_ie( dev ); - - /* Get the BSSID */ - lp->ltvRecord.typ = CFG_CUR_BSSID; - lp->ltvRecord.len = 4; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - if( status == HCF_SUCCESS ) { - memset( &wrqu, 0, sizeof( wrqu )); - - memcpy( wrqu.addr.sa_data, lp->ltvRecord.u.u8, ETH_ALEN ); - - wrqu.addr.sa_family = ARPHRD_ETHER; - - wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL ); - } - - return; -} // wl_wext_event_ap -/*============================================================================*/ - - - -/******************************************************************************* - * wl_wext_event_scan_complete() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that a request for a network scan - * has completed. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_scan_complete( struct net_device *dev ) -{ - union iwreq_data wrqu; - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - wrqu.addr.sa_family = ARPHRD_ETHER; - wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL ); - - return; -} // wl_wext_event_scan_complete -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_new_sta() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that an AP has registered a new - * station. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_new_sta( struct net_device *dev ) -{ - union iwreq_data wrqu; - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - /* Send the station's mac address here */ - memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN ); - wrqu.addr.sa_family = ARPHRD_ETHER; - wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL ); - - return; -} // wl_wext_event_new_sta -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_expired_sta() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that an AP has deregistered a - * station. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_expired_sta( struct net_device *dev ) -{ - union iwreq_data wrqu; - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN ); - wrqu.addr.sa_family = ARPHRD_ETHER; - wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL ); - - return; -} // wl_wext_event_expired_sta -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_mic_failed() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event that MIC calculations failed. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_mic_failed( struct net_device *dev ) -{ - union iwreq_data wrqu; - struct wl_private *lp = wl_priv(dev); - struct iw_michaelmicfailure wxmic; - int key_idx; - char *addr1; - char *addr2; - WVLAN_RX_WMP_HDR *hdr; - /*------------------------------------------------------------------------*/ - - - key_idx = lp->lookAheadBuf[HFS_STAT+1] >> 3; - key_idx &= 0x03; - - /* Cast the lookahead buffer into a RFS format */ - hdr = (WVLAN_RX_WMP_HDR *)&lp->lookAheadBuf[HFS_STAT]; - - /* Cast the addresses to byte buffers, as in the above RFS they are word - length */ - addr1 = (char *)hdr->address1; - addr2 = (char *)hdr->address2; - - DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx, - hdr->status ); - - memset(&wrqu, 0, sizeof(wrqu)); - memset(&wxmic, 0, sizeof(wxmic)); - - wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID; - wxmic.flags |= (addr1[0] & 1) ? - IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE; - wxmic.src_addr.sa_family = ARPHRD_ETHER; - memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN); - - wrqu.data.length = sizeof(wxmic); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic); - - return; -} // wl_wext_event_mic_failed -/*============================================================================*/ - - - - -/******************************************************************************* - * wl_wext_event_assoc_ie() - ******************************************************************************* - * - * DESCRIPTION: - * - * This function is used to send an event containing the WPA-IE generated - * by the firmware in an association request. - * - * - * PARAMETERS: - * - * dev - the network device for which this event is to be issued - * - * RETURNS: - * - * N/A - * - ******************************************************************************/ -void wl_wext_event_assoc_ie( struct net_device *dev ) -{ - union iwreq_data wrqu; - struct wl_private *lp = wl_priv(dev); - int status; - PROBE_RESP data; - hcf_16 length; - hcf_8 *wpa_ie; - /*------------------------------------------------------------------------*/ - - - memset( &wrqu, 0, sizeof( wrqu )); - - /* Retrieve the Association Request IE */ - lp->ltvRecord.len = 45; - lp->ltvRecord.typ = CFG_CUR_ASSOC_REQ_INFO; - - status = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - if( status == HCF_SUCCESS ) - { - length = 0; - memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 ); - wpa_ie = wl_parse_wpa_ie( &data, &length ); - - if( length != 0 ) - { - wrqu.data.length = wpa_ie[1] + 2; - wireless_send_event(dev, IWEVASSOCREQIE, - &wrqu, wpa_ie); - - /* This bit is a hack. We send the respie - * event at the same time */ - wireless_send_event(dev, IWEVASSOCRESPIE, - &wrqu, wpa_ie); - } - } - - return; -} // wl_wext_event_assoc_ie -/*============================================================================*/ -/* Structures to export the Wireless Handlers */ - -static const iw_handler wl_handler[] = -{ - IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit), - IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol), - IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency), - IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency), - IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype), - IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype), - IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity), - IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity), - IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range), - IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), - IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), -#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA - IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid), -#endif - IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list), - IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan), - IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan), - IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid), - IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid), - IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname), - IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname), - IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate), - IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate), - IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold), - IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold), - IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power), - IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode), - IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode), - IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power), - IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power), - IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie), - IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth), - IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext), -}; - -static const iw_handler wl_private_handler[] = -{ /* SIOCIWFIRSTPRIV + */ - wvlan_set_netname, /* 0: SIOCSIWNETNAME */ - wvlan_get_netname, /* 1: SIOCGIWNETNAME */ - wvlan_set_station_nickname, /* 2: SIOCSIWSTANAME */ - wvlan_get_station_nickname, /* 3: SIOCGIWSTANAME */ -#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA - wvlan_set_porttype, /* 4: SIOCSIWPORTTYPE */ - wvlan_get_porttype, /* 5: SIOCGIWPORTTYPE */ -#endif -}; - -static struct iw_priv_args wl_priv_args[] = { - {SIOCSIWNETNAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "snetwork_name" }, - {SIOCGIWNETNAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gnetwork_name" }, - {SIOCSIWSTANAME, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, 0, "sstation_name" }, - {SIOCGIWSTANAME, 0, IW_PRIV_TYPE_CHAR | HCF_MAX_NAME_LEN, "gstation_name" }, -#if 1 //;? #if (HCF_TYPE) & HCF_TYPE_STA - {SIOCSIWPORTTYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "sport_type" }, - {SIOCGIWPORTTYPE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gport_type" }, -#endif -}; - -const struct iw_handler_def wl_iw_handler_def = -{ - .num_private = sizeof(wl_private_handler) / sizeof(iw_handler), - .private = (iw_handler *) wl_private_handler, - .private_args = (struct iw_priv_args *) wl_priv_args, - .num_private_args = sizeof(wl_priv_args) / sizeof(struct iw_priv_args), - .num_standard = sizeof(wl_handler) / sizeof(iw_handler), - .standard = (iw_handler *) wl_handler, - .get_wireless_stats = wl_get_wireless_stats, -}; |