X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=blobdiff_plain;f=target%2Flinux%2Fs3c24xx%2Ffiles-2.6.31%2Fdrivers%2Far6000%2Far6000%2Fwireless_ext.c;fp=target%2Flinux%2Fs3c24xx%2Ffiles-2.6.31%2Fdrivers%2Far6000%2Far6000%2Fwireless_ext.c;h=0000000000000000000000000000000000000000;hp=af78ae05fcb5d9a1ad73ad63a8b302b95f62f934;hb=882e36ca7f56ba2427d7f2791b26501f2e4669f4;hpb=851d953350108e427064a344da1407c96621fdf8 diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/wireless_ext.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/wireless_ext.c deleted file mode 100644 index af78ae05fc..0000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/wireless_ext.c +++ /dev/null @@ -1,1979 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "ar6000_drv.h" - -static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi); -extern unsigned int wmitimeout; -extern A_WAITQUEUE_HEAD arEvent; -extern wait_queue_head_t ar6000_scan_queue; - -/* - * Encode a WPA or RSN information element as a custom - * element using the hostap format. - */ -static u_int -encode_ie(void *buf, size_t bufsize, - const u_int8_t *ie, size_t ielen, - const char *leader, size_t leader_len) -{ - u_int8_t *p; - int i; - - if (bufsize < leader_len) - return 0; - p = buf; - memcpy(p, leader, leader_len); - bufsize -= leader_len; - p += leader_len; - for (i = 0; i < ielen && bufsize > 2; i++) - p += sprintf(p, "%02x", ie[i]); - return (i == ielen ? p - (u_int8_t *)buf : 0); -} - -void -ar6000_scan_node(void *arg, bss_t *ni) -{ - struct iw_event iwe; -#if WIRELESS_EXT > 14 - char buf[64*2 + 30]; -#endif - struct ar_giwscan_param *param; - A_CHAR *current_ev; - A_CHAR *end_buf; - struct ieee80211_common_ie *cie; - struct iw_request_info info; - - info.cmd = 0; - info.flags = 0; - - param = (struct ar_giwscan_param *)arg; - - if (param->current_ev >= param->end_buf) { - return; - } - if ((param->firstPass == TRUE) && - ((ni->ni_cie.ie_wpa == NULL) && (ni->ni_cie.ie_rsn == NULL))) { - /* - * Only forward wpa bss's in first pass - */ - return; - } - - if ((param->firstPass == FALSE) && - ((ni->ni_cie.ie_wpa != NULL) || (ni->ni_cie.ie_rsn != NULL))) { - /* - * Only forward non-wpa bss's in 2nd pass - */ - return; - } - - current_ev = param->current_ev; - end_buf = param->end_buf; - - cie = &ni->ni_cie; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6); - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_ADDR_LEN); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.u.data.length = cie->ie_ssid[1]; - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - &cie->ie_ssid[2]); - - if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) { - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ? - IW_MODE_MASTER : IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_UINT_LEN); - } - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = cie->ie_chan * 100000; - iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_FREQ_LEN); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - ar6000_set_quality(&iwe.u.qual, ni->ni_snr); - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_QUAL_LEN); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWENCODE; - if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) { - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - } else { - iwe.u.data.flags = IW_ENCODE_DISABLED; - } - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, ""); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, buf); - - if (cie->ie_wpa != NULL) { - static const char wpa_leader[] = "wpa_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa, - cie->ie_wpa[1]+2, - wpa_leader, sizeof(wpa_leader)-1); - - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) { - static const char rsn_leader[] = "rsn_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn, - cie->ie_rsn[1]+2, - rsn_leader, sizeof(rsn_leader)-1); - - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - if (cie->ie_wmm != NULL) { - static const char wmm_leader[] = "wmm_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm, - cie->ie_wmm[1]+2, - wmm_leader, sizeof(wmm_leader)-1); - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - if (cie->ie_ath != NULL) { - static const char ath_leader[] = "ath_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath, - cie->ie_ath[1]+2, - ath_leader, sizeof(ath_leader)-1); - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - param->current_ev = current_ev; -} - -int -ar6000_ioctl_giwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ar_giwscan_param param; - int i; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - param.current_ev = extra; - param.end_buf = extra + IW_SCAN_MAX_DATA; - param.firstPass = TRUE; - - /* - * Do two passes to insure WPA scan candidates - * are sorted to the front. This is a hack to deal with - * the wireless extensions capping scan results at - * IW_SCAN_MAX_DATA bytes. In densely populated environments - * it's easy to overflow this buffer (especially with WPA/RSN - * information elements). Note this sorting hack does not - * guarantee we won't overflow anyway. - */ - for (i = 0; i < 2; i++) { - /* - * Translate data to WE format. - */ - wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, ¶m); - param.firstPass = FALSE; - if (param.current_ev >= param.end_buf) { - data->length = param.current_ev - extra; - return -E2BIG; - } - } - - data->length = param.current_ev - extra; - return 0; -} - -extern int reconnect_flag; -/* SIOCSIWESSID */ -static int -ar6000_ioctl_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_STATUS status; - A_UINT8 arNetworkType; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - /* - * iwconfig passes a string with length excluding any trailing NUL. - * FIXME: we should be able to set an ESSID of 32 bytes, yet things fall - * over badly if we do. So we limit the ESSID to 31 bytes. - */ - if (data->flags && (!data->length || data->length >= sizeof(ar->arSsid))) { - /* - * ssid is invalid - */ - return -EINVAL; - } - /* Added for bug 25178, return an IOCTL error instead of target returning - Illegal parameter error when either the BSSID or channel is missing - and we cannot scan during connect. - */ - if (data->flags) { - if (ar->arSkipScan == TRUE && - (ar->arChannelHint == 0 || - (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] && - !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5]))) - { - return -EINVAL; - } - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - if (ar->arTxPending[WMI_CONTROL_PRI]) { - /* - * sleep until the command queue drains - */ - wait_event_interruptible_timeout(arEvent, - ar->arTxPending[WMI_CONTROL_PRI] == 0, wmitimeout * HZ); - if (signal_pending(current)) { - return -EINTR; - } - } - - if (!data->flags) { - arNetworkType = ar->arNetworkType; - ar6000_init_profile_info(ar); - ar->arNetworkType = arNetworkType; - } - - /* - * The original logic here prevented a disconnect if issuing an "essid off" - * if no ESSID was set, presumably to prevent sending multiple disconnects - * to the WMI. - * - * Unfortunately, this also meant that no disconnect was sent when we were - * already connected, but the profile has been changed since (which also - * clears the ESSID as a reminder that the WMI needs updating.) - * - * The "1 ||" makes sure we always disconnect or reconnect. The WMI doesn't - * seem to mind being sent multiple disconnects. - */ - if (1 || (ar->arSsidLen) || (!data->flags)) - { - if ((!data->flags) || - (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) || - (ar->arSsidLen != (data->length))) - { - /* - * SSID set previously or essid off has been issued. - * - * Disconnect Command is issued in two cases after wmi is ready - * (1) ssid is different from the previous setting - * (2) essid off has been issued - * - */ - if (ar->arWmiReady == TRUE) { - reconnect_flag = 0; - status = wmi_disconnect_cmd(ar->arWmi); - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - if (ar->arSkipScan == FALSE) { - A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); - } - if (!data->flags) { - up(&ar->arSem); - return 0; - } - } else { - up(&ar->arSem); - } - } - else - { - /* - * SSID is same, so we assume profile hasn't changed. - * If the interface is up and wmi is ready, we issue - * a reconnect cmd. Issue a reconnect only we are already - * connected. - */ - if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE)) - { - reconnect_flag = TRUE; - status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid, - ar->arChannelHint); - up(&ar->arSem); - if (status != A_OK) { - return -EIO; - } - return 0; - } - else{ - /* - * Dont return if connect is pending. - */ - if(!(ar->arConnectPending)) { - up(&ar->arSem); - return 0; - } - } - } - } - - ar->arSsidLen = data->length; - A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen); - - /* The ssid length check prevents second "essid off" from the user, - to be treated as a connect cmd. The second "essid off" is ignored. - */ - if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) ) - { - AR6000_SPIN_LOCK(&ar->arLock, 0); - if (SHARED_AUTH == ar->arDot11AuthMode) { - ar6000_install_static_wep_keys(ar); - } - AR_DEBUG_PRINTF("Connect called with authmode %d dot11 auth %d"\ - " PW crypto %d PW crypto Len %d GRP crypto %d"\ - " GRP crypto Len %d\n", - ar->arAuthMode, ar->arDot11AuthMode, - ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, - ar->arGroupCrypto, ar->arGroupCryptoLen); - reconnect_flag = 0; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, - ar->arDot11AuthMode, ar->arAuthMode, - ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, - ar->arGroupCrypto,ar->arGroupCryptoLen, - ar->arSsidLen, ar->arSsid, - ar->arReqBssid, ar->arChannelHint, - ar->arConnectCtrlFlags); - - - up(&ar->arSem); - - if (status != A_OK) { - return -EIO; - } - ar->arConnectPending = TRUE; - }else{ - up(&ar->arSem); - } - return 0; -} - -/* SIOCGIWESSID */ -static int -ar6000_ioctl_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - data->flags = 1; - data->length = ar->arSsidLen; - A_MEMCPY(essid, ar->arSsid, ar->arSsidLen); - - return 0; -} - - -void ar6000_install_static_wep_keys(AR_SOFTC_T *ar) -{ - A_UINT8 index; - A_UINT8 keyUsage; - - for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { - if (ar->arWepKeyList[index].arKeyLen) { - keyUsage = GROUP_USAGE; - if (index == ar->arDefTxKeyIndex) { - keyUsage |= TX_USAGE; - } - wmi_addKey_cmd(ar->arWmi, - index, - WEP_CRYPT, - keyUsage, - ar->arWepKeyList[index].arKeyLen, - NULL, - ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, - NO_SYNC_WMIFLAG); - } - } -} - -int -ar6000_ioctl_delkey(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return 0; -} - -int -ar6000_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra; - - if ((ar->arWmiReady == FALSE) || (ar->arConnected != TRUE)) - return -EIO; - - switch (mlme->im_op) { - case IEEE80211_MLME_DISASSOC: - case IEEE80211_MLME_DEAUTH: - /* Not Supported */ - break; - default: - break; - } - return 0; -} - - -int -ar6000_ioctl_setwmmparams(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return -EIO; /* for now */ -} - -int -ar6000_ioctl_getwmmparams(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return -EIO; /* for now */ -} - -int ar6000_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - /* The target generates the WPA/RSN IE */ - return 0; -} - -int -ar6000_ioctl_setauthalg(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_authalg *req = (struct ieee80211req_authalg *)extra; - int ret = 0; - - - AR6000_SPIN_LOCK(&ar->arLock, 0); - - if (req->auth_alg == AUTH_ALG_OPEN_SYSTEM) { - ar->arDot11AuthMode = OPEN_AUTH; - } else if (req->auth_alg == AUTH_ALG_LEAP) { - ar->arDot11AuthMode = LEAP_AUTH; - ar->arPairwiseCrypto = WEP_CRYPT; - ar->arGroupCrypto = WEP_CRYPT; - } else { - ret = -EIO; - } - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - return ret; -} -static int -ar6000_ioctl_addpmkid(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_addpmkid *req = (struct ieee80211req_addpmkid *)extra; - A_STATUS status; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - AR_DEBUG_PRINTF("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n", - req->pi_bssid[0], req->pi_bssid[1], req->pi_bssid[2], - req->pi_bssid[3], req->pi_bssid[4], req->pi_bssid[5], - req->pi_enable); - - status = wmi_setPmkid_cmd(ar->arWmi, req->pi_bssid, req->pi_pmkid, - req->pi_enable); - - if (status != A_OK) { - return -EIO; - } - - return 0; -} - -/* - * SIOCSIWRATE - */ -int -ar6000_ioctl_siwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT32 kbps; - - if (rrq->fixed) { - kbps = rrq->value / 1000; /* rrq->value is in bps */ - } else { - kbps = -1; /* -1 indicates auto rate */ - } - if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL) - { - AR_DEBUG_PRINTF("BitRate is not Valid %d\n", kbps); - return -EINVAL; - } - ar->arBitRate = kbps; - if(ar->arWmiReady == TRUE) - { - if (wmi_set_bitrate_cmd(ar->arWmi, kbps) != A_OK) { - return -EINVAL; - } - } - return 0; -} - -/* - * SIOCGIWRATE - */ -int -ar6000_ioctl_giwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int ret = 0; - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - if(ar->arWmiReady == TRUE) - { - ar->arBitRate = 0xFFFF; - if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ); - if (signal_pending(current)) { - ret = -EINTR; - } - } - /* If the interface is down or wmi is not ready or the target is not - connected - return the value stored in the device structure */ - if (!ret) { - if (ar->arBitRate == -1) { - rrq->fixed = TRUE; - rrq->value = 0; - } else { - rrq->value = ar->arBitRate * 1000; - } - } - - up(&ar->arSem); - - return ret; -} - -/* - * SIOCSIWTXPOW - */ -static int -ar6000_ioctl_siwtxpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT8 dbM; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arRadioSwitch == WLAN_ENABLED - && rrq->disabled) { - if (wmi_switch_radio(ar->arWmi, WLAN_DISABLED) < 0) - return -EIO; - ar->arRadioSwitch = WLAN_DISABLED; - } else if (ar->arRadioSwitch == WLAN_DISABLED - && !rrq->disabled) { - if (wmi_switch_radio(ar->arWmi, WLAN_ENABLED) < 0) - return -EIO; - ar->arRadioSwitch = WLAN_ENABLED; - } - - if (rrq->fixed) { - if (rrq->flags != IW_TXPOW_DBM) { - return -EOPNOTSUPP; - } - ar->arTxPwr= dbM = rrq->value; - ar->arTxPwrSet = TRUE; - } else { - ar->arTxPwr = dbM = 0; - ar->arTxPwrSet = FALSE; - } - if(ar->arWmiReady == TRUE) - { - AR_DEBUG_PRINTF("Set tx pwr cmd %d dbM\n", dbM); - wmi_set_txPwr_cmd(ar->arWmi, dbM); - } - return 0; -} - -/* - * SIOCGIWTXPOW - */ -int -ar6000_ioctl_giwtxpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int ret = 0; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arRadioSwitch == WLAN_DISABLED) { - rrq->disabled = 1; - return 0; - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE)) - { - ar->arTxPwr = 0; - - if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - - wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ); - - if (signal_pending(current)) { - ret = -EINTR; - } - } - /* If the interace is down or wmi is not ready or target is not connected - then return value stored in the device structure */ - - if (!ret) { - if (ar->arTxPwrSet == TRUE) { - rrq->fixed = TRUE; - } - rrq->value = ar->arTxPwr; - rrq->flags = IW_TXPOW_DBM; - } - - up(&ar->arSem); - - return ret; -} - -/* - * SIOCSIWRETRY - * since iwconfig only provides us with one max retry value, we use it - * to apply to data frames of the BE traffic class. - */ -static int -ar6000_ioctl_siwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (rrq->disabled) { - return -EOPNOTSUPP; - } - - if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) { - return -EOPNOTSUPP; - } - - if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) { - return - EINVAL; - } - if(ar->arWmiReady == TRUE) - { - if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE, - rrq->value, 0) != A_OK){ - return -EINVAL; - } - } - ar->arMaxRetries = rrq->value; - return 0; -} - -/* - * SIOCGIWRETRY - */ -static int -ar6000_ioctl_giwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - rrq->disabled = 0; - switch (rrq->flags & IW_RETRY_TYPE) { - case IW_RETRY_LIFETIME: - return -EOPNOTSUPP; - break; - case IW_RETRY_LIMIT: - rrq->flags = IW_RETRY_LIMIT; - switch (rrq->flags & IW_RETRY_MODIFIER) { - case IW_RETRY_MIN: - rrq->flags |= IW_RETRY_MIN; - rrq->value = WMI_MIN_RETRIES; - break; - case IW_RETRY_MAX: - rrq->flags |= IW_RETRY_MAX; - rrq->value = ar->arMaxRetries; - break; - } - break; - } - return 0; -} - -/* - * SIOCSIWENCODE - */ -static int -ar6000_ioctl_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *keybuf) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int index; - A_INT32 auth = ar->arDot11AuthMode; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - index = erq->flags & IW_ENCODE_INDEX; - - if (index && (((index - 1) < WMI_MIN_KEY_INDEX) || - ((index - 1) > WMI_MAX_KEY_INDEX))) - { - return -EIO; - } - - if (erq->flags & IW_ENCODE_DISABLED) { - /* - * Encryption disabled - */ - if (index) { - /* - * If key index was specified then clear the specified key - */ - index--; - A_MEMZERO(ar->arWepKeyList[index].arKey, - sizeof(ar->arWepKeyList[index].arKey)); - ar->arWepKeyList[index].arKeyLen = 0; - } - ar->arDot11AuthMode = OPEN_AUTH; - ar->arPairwiseCrypto = NONE_CRYPT; - ar->arGroupCrypto = NONE_CRYPT; - ar->arAuthMode = NONE_AUTH; - } else { - /* - * Enabling WEP encryption - */ - if (index) { - index--; /* keyindex is off base 1 in iwconfig */ - } - - if (erq->flags & IW_ENCODE_OPEN) { - auth = OPEN_AUTH; - } else if (erq->flags & IW_ENCODE_RESTRICTED) { - auth = SHARED_AUTH; - } - - if (erq->length) { - if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) { - return -EIO; - } - - A_MEMZERO(ar->arWepKeyList[index].arKey, - sizeof(ar->arWepKeyList[index].arKey)); - A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length); - ar->arWepKeyList[index].arKeyLen = erq->length; - } else { - if (ar->arWepKeyList[index].arKeyLen == 0) { - return -EIO; - } - ar->arDefTxKeyIndex = index; - } - - ar->arPairwiseCrypto = WEP_CRYPT; - ar->arGroupCrypto = WEP_CRYPT; - ar->arDot11AuthMode = auth; - ar->arAuthMode = NONE_AUTH; - } - - /* - * profile has changed. Erase ssid to signal change - */ - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - - return 0; -} - -static int -ar6000_ioctl_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT8 keyIndex; - struct ar_wep_key *wk; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arPairwiseCrypto == NONE_CRYPT) { - erq->length = 0; - erq->flags = IW_ENCODE_DISABLED; - } else { - /* get the keyIndex */ - keyIndex = erq->flags & IW_ENCODE_INDEX; - if (0 == keyIndex) { - keyIndex = ar->arDefTxKeyIndex; - } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) || - (keyIndex - 1 > WMI_MAX_KEY_INDEX)) - { - keyIndex = WMI_MIN_KEY_INDEX; - } else { - keyIndex--; - } - erq->flags = keyIndex + 1; - erq->flags |= IW_ENCODE_ENABLED; - wk = &ar->arWepKeyList[keyIndex]; - if (erq->length > wk->arKeyLen) { - erq->length = wk->arKeyLen; - } - if (wk->arKeyLen) { - A_MEMCPY(key, wk->arKey, erq->length); - } - if (ar->arDot11AuthMode == OPEN_AUTH) { - erq->flags |= IW_ENCODE_OPEN; - } else if (ar->arDot11AuthMode == SHARED_AUTH) { - erq->flags |= IW_ENCODE_RESTRICTED; - } - } - - return 0; -} - -static int ar6000_ioctl_siwpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_POWER_MODE power_mode; - - if (wrqu->power.disabled) - power_mode = MAX_PERF_POWER; - else - power_mode = REC_POWER; - - if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0) - return -EIO; - - return 0; -} - -static int ar6000_ioctl_giwpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - /* - * FIXME: - * https://docs.openmoko.org/trac/ticket/2267 - * When starting wpa_supplicant the kernel oopses. - * The following condition avoids the oops. - * Remove this comment to bless this solution. - */ - if (ar->arWlanState == WLAN_DISABLED || ar->arWmiReady == FALSE) - return -EIO; - - return wmi_get_power_mode_cmd(ar->arWmi); -} - -static int ar6000_ioctl_siwgenie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - /* The target does that for us */ - return 0; -} - -static int ar6000_ioctl_giwgenie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - return 0; -} - -static int ar6000_ioctl_siwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *param, - char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int reset = 0; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { - ar->arAuthMode = NONE_AUTH; - } - if (param->value & IW_AUTH_WPA_VERSION_WPA) { - ar->arAuthMode = WPA_AUTH; - } - if (param->value & IW_AUTH_WPA_VERSION_WPA2) { - ar->arAuthMode = WPA2_AUTH; - } - - reset = 1; - break; - case IW_AUTH_CIPHER_PAIRWISE: - if (param->value & IW_AUTH_CIPHER_NONE) { - ar->arPairwiseCrypto = NONE_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_WEP40) { - ar->arPairwiseCrypto = WEP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_TKIP) { - ar->arPairwiseCrypto = TKIP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_CCMP) { - ar->arPairwiseCrypto = AES_CRYPT; - } - - reset = 1; - break; - case IW_AUTH_CIPHER_GROUP: - if (param->value & IW_AUTH_CIPHER_NONE) { - ar->arGroupCrypto = NONE_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_WEP40) { - ar->arGroupCrypto = WEP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_TKIP) { - ar->arGroupCrypto = TKIP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_CCMP) { - ar->arGroupCrypto = AES_CRYPT; - } - - reset = 1; - break; - case IW_AUTH_KEY_MGMT: - if (param->value & IW_AUTH_KEY_MGMT_PSK) { - if (ar->arAuthMode == WPA_AUTH) { - ar->arAuthMode = WPA_PSK_AUTH; - } else if (ar->arAuthMode == WPA2_AUTH) { - ar->arAuthMode = WPA2_PSK_AUTH; - } - - reset = 1; - } - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - if (ar->arWmiReady == FALSE) { - return -EIO; - } - wmi_set_tkip_countermeasures_cmd(ar->arWmi, param->value); - break; - - case IW_AUTH_DROP_UNENCRYPTED: - break; - - case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - ar->arDot11AuthMode = OPEN_AUTH; - } - if (param->value & IW_AUTH_ALG_SHARED_KEY) { - ar->arDot11AuthMode = SHARED_AUTH; - } - if (param->value & IW_AUTH_ALG_LEAP) { - ar->arDot11AuthMode = LEAP_AUTH; - ar->arPairwiseCrypto = WEP_CRYPT; - ar->arGroupCrypto = WEP_CRYPT; - } - - reset = 1; - break; - - case IW_AUTH_WPA_ENABLED: - reset = 1; - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - break; - - case IW_AUTH_PRIVACY_INVOKED: - break; - - default: - printk("%s(): Unknown flag 0x%x\n", __FUNCTION__, param->flags); - return -EOPNOTSUPP; - } - - if (reset) { - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - } - - return 0; -} - -static int ar6000_ioctl_giwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *dwrq, - char *extra) -{ - return 0; -} - -static int ar6000_ioctl_siwencodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int alg = ext->alg, idx; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - /* Determine and validate the key index */ - idx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if (idx) { - if (idx < 0 || idx > 3) - return -EINVAL; - } - - if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { - struct ieee80211req_key ik; - KEY_USAGE key_usage; - CRYPTO_TYPE key_type = NONE_CRYPT; - int status; - - ar->user_saved_keys.keyOk = FALSE; - - if (alg == IW_ENCODE_ALG_TKIP) { - key_type = TKIP_CRYPT; - ik.ik_type = IEEE80211_CIPHER_TKIP; - } else { - key_type = AES_CRYPT; - ik.ik_type = IEEE80211_CIPHER_AES_CCM; - } - - ik.ik_keyix = idx; - ik.ik_keylen = ext->key_len; - ik.ik_flags = IEEE80211_KEY_RECV; - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - ik.ik_flags |= IEEE80211_KEY_XMIT - | IEEE80211_KEY_DEFAULT; - } - - if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - memcpy(&ik.ik_keyrsc, ext->rx_seq, 8); - } - - memcpy(ik.ik_keydata, ext->key, ext->key_len); - - ar->user_saved_keys.keyType = key_type; - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - key_usage = GROUP_USAGE; - memset(ik.ik_macaddr, 0, ETH_ALEN); - memcpy(&ar->user_saved_keys.bcast_ik, &ik, - sizeof(struct ieee80211req_key)); - } else { - key_usage = PAIRWISE_USAGE; - memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN); - memcpy(&ar->user_saved_keys.ucast_ik, &ik, - sizeof(struct ieee80211req_key)); - } - - status = wmi_addKey_cmd(ar->arWmi, ik.ik_keyix, key_type, - key_usage, ik.ik_keylen, - (A_UINT8 *)&ik.ik_keyrsc, - ik.ik_keydata, - KEY_OP_INIT_VAL, SYNC_BEFORE_WMIFLAG); - - if (status < 0) - return -EIO; - - ar->user_saved_keys.keyOk = TRUE; - - return 0; - - } else { - /* WEP falls back to SIWENCODE */ - return -EOPNOTSUPP; - } - - return 0; -} - - -static int ar6000_ioctl_giwencodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - return 0; -} - - -static int -ar6000_ioctl_setparam(struct net_device *dev, - struct iw_request_info *info, - void *erq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int *i = (int *)extra; - int param = i[0]; - int value = i[1]; - int ret = 0; - A_BOOL profChanged = FALSE; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (param) { - case IEEE80211_PARAM_WPA: - switch (value) { - case WPA_MODE_WPA1: - ar->arAuthMode = WPA_AUTH; - profChanged = TRUE; - break; - case WPA_MODE_WPA2: - ar->arAuthMode = WPA2_AUTH; - profChanged = TRUE; - break; - case WPA_MODE_NONE: - ar->arAuthMode = NONE_AUTH; - profChanged = TRUE; - break; - default: - printk("IEEE80211_PARAM_WPA: Unknown value %d\n", value); - } - break; - case IEEE80211_PARAM_AUTHMODE: - switch(value) { - case IEEE80211_AUTH_WPA_PSK: - if (WPA_AUTH == ar->arAuthMode) { - ar->arAuthMode = WPA_PSK_AUTH; - profChanged = TRUE; - } else if (WPA2_AUTH == ar->arAuthMode) { - ar->arAuthMode = WPA2_PSK_AUTH; - profChanged = TRUE; - } else { - AR_DEBUG_PRINTF("Error - Setting PSK mode when WPA "\ - "param was set to %d\n", - ar->arAuthMode); - ret = -1; - } - break; - case IEEE80211_AUTH_WPA_CCKM: - if (WPA2_AUTH == ar->arAuthMode) { - ar->arAuthMode = WPA2_AUTH_CCKM; - } else { - ar->arAuthMode = WPA_AUTH_CCKM; - } - break; - default: - break; - } - break; - case IEEE80211_PARAM_UCASTCIPHER: - switch (value) { - case IEEE80211_CIPHER_AES_CCM: - ar->arPairwiseCrypto = AES_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_TKIP: - ar->arPairwiseCrypto = TKIP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_WEP: - ar->arPairwiseCrypto = WEP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_NONE: - ar->arPairwiseCrypto = NONE_CRYPT; - profChanged = TRUE; - break; - } - break; - case IEEE80211_PARAM_UCASTKEYLEN: - if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) { - ret = -EIO; - } else { - ar->arPairwiseCryptoLen = value; - } - break; - case IEEE80211_PARAM_MCASTCIPHER: - switch (value) { - case IEEE80211_CIPHER_AES_CCM: - ar->arGroupCrypto = AES_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_TKIP: - ar->arGroupCrypto = TKIP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_WEP: - ar->arGroupCrypto = WEP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_NONE: - ar->arGroupCrypto = NONE_CRYPT; - profChanged = TRUE; - break; - } - break; - case IEEE80211_PARAM_MCASTKEYLEN: - if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) { - ret = -EIO; - } else { - ar->arGroupCryptoLen = value; - } - break; - case IEEE80211_PARAM_COUNTERMEASURES: - if (ar->arWmiReady == FALSE) { - return -EIO; - } - wmi_set_tkip_countermeasures_cmd(ar->arWmi, value); - break; - default: - break; - } - - if (profChanged == TRUE) { - /* - * profile has changed. Erase ssid to signal change - */ - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - } - - return ret; -} - -int -ar6000_ioctl_getparam(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return -EIO; /* for now */ -} - -int -ar6000_ioctl_setkey(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_key *ik = (struct ieee80211req_key *)extra; - KEY_USAGE keyUsage; - A_STATUS status; - CRYPTO_TYPE keyType = NONE_CRYPT; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - ar->user_saved_keys.keyOk = FALSE; - - if ( 0 == memcmp(ik->ik_macaddr, "\x00\x00\x00\x00\x00\x00", - IEEE80211_ADDR_LEN)) { - keyUsage = GROUP_USAGE; - A_MEMCPY(&ar->user_saved_keys.bcast_ik, ik, - sizeof(struct ieee80211req_key)); - } else { - keyUsage = PAIRWISE_USAGE; - A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik, - sizeof(struct ieee80211req_key)); - } - - switch (ik->ik_type) { - case IEEE80211_CIPHER_WEP: - keyType = WEP_CRYPT; - break; - case IEEE80211_CIPHER_TKIP: - keyType = TKIP_CRYPT; - break; - case IEEE80211_CIPHER_AES_CCM: - keyType = AES_CRYPT; - break; - default: - break; - } - ar->user_saved_keys.keyType = keyType; - - if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) { - if (NONE_CRYPT == keyType) { - return -EIO; - } - - status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage, - ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc, - ik->ik_keydata, KEY_OP_INIT_VAL, - SYNC_BEFORE_WMIFLAG); - - if (status != A_OK) { - return -EIO; - } - } else { - status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata); - } - - ar->user_saved_keys.keyOk = TRUE; - - return 0; -} - - -/* - * SIOCGIWNAME - */ -int -ar6000_ioctl_giwname(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (ar->arPhyCapability) { - case (WMI_11A_CAPABILITY): - strncpy(name, "AR6000 802.11a", IFNAMSIZ); - break; - case (WMI_11G_CAPABILITY): - strncpy(name, "AR6000 802.11g", IFNAMSIZ); - break; - case (WMI_11AG_CAPABILITY): - strncpy(name, "AR6000 802.11ag", IFNAMSIZ); - break; - default: - strncpy(name, "AR6000 802.11", IFNAMSIZ); - break; - } - - return 0; -} - -/* - * SIOCSIWFREQ - */ -int -ar6000_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - /* - * We support limiting the channels via wmiconfig. - * - * We use this command to configure the channel hint for the connect cmd - * so it is possible the target will end up connecting to a different - * channel. - */ - if (freq->e > 1) { - return -EINVAL; - } else if (freq->e == 1) { - ar->arChannelHint = freq->m / 100000; - } else { - ar->arChannelHint = wlan_ieee2freq(freq->m); - } - - A_PRINTF("channel hint set to %d\n", ar->arChannelHint); - return 0; -} - -/* - * SIOCGIWFREQ - */ -int -ar6000_ioctl_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arConnected != TRUE) { - return -EINVAL; - } - - freq->m = ar->arBssChannel * 100000; - freq->e = 1; - - return 0; -} - -/* - * SIOCSIWMODE - */ -int -ar6000_ioctl_siwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (*mode) { - case IW_MODE_INFRA: - ar->arNetworkType = INFRA_NETWORK; - break; - case IW_MODE_ADHOC: - ar->arNetworkType = ADHOC_NETWORK; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * SIOCGIWMODE - */ -int -ar6000_ioctl_giwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (ar->arNetworkType) { - case INFRA_NETWORK: - *mode = IW_MODE_INFRA; - break; - case ADHOC_NETWORK: - *mode = IW_MODE_ADHOC; - break; - default: - return -EIO; - } - return 0; -} - -/* - * SIOCSIWSENS - */ -int -ar6000_ioctl_siwsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *sens, char *extra) -{ - return 0; -} - -/* - * SIOCGIWSENS - */ -int -ar6000_ioctl_giwsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *sens, char *extra) -{ - sens->value = 0; - sens->fixed = 1; - - return 0; -} - -/* - * SIOCGIWRANGE - */ -int -ar6000_ioctl_giwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct iw_range *range = (struct iw_range *) extra; - int i, ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - ar->arNumChannels = -1; - A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList)); - - if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - - wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ); - - if (signal_pending(current)) { - up(&ar->arSem); - return -EINTR; - } - - data->length = sizeof(struct iw_range); - A_MEMZERO(range, sizeof(struct iw_range)); - - range->txpower_capa = IW_TXPOW_DBM; - - range->min_pmp = 1 * 1024; - range->max_pmp = 65535 * 1024; - range->min_pmt = 1 * 1024; - range->max_pmt = 1000 * 1024; - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = 0; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 13; - - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->min_retry = 0; - range->max_retry = 255; - - range->num_frequency = range->num_channels = ar->arNumChannels; - for (i = 0; i < ar->arNumChannels; i++) { - range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]); - range->freq[i].m = ar->arChannelList[i] * 100000; - range->freq[i].e = 1; - /* - * Linux supports max of 32 channels, bail out once you - * reach the max. - */ - if (i == IW_MAX_FREQUENCIES) { - break; - } - } - - /* Max quality is max field value minus noise floor */ - range->max_qual.qual = 0xff - 161; - - /* - * In order to use dBm measurements, 'level' must be lower - * than any possible measurement (see iw_print_stats() in - * wireless tools). It's unclear how this is meant to be - * done, but setting zero in these values forces dBm and - * the actual numbers are not used. - */ - range->max_qual.level = 0; - range->max_qual.noise = 0; - - range->sensitivity = 3; - - range->max_encoding_tokens = 4; - /* XXX query driver to find out supported key sizes */ - range->num_encoding_sizes = 3; - range->encoding_size[0] = 5; /* 40-bit */ - range->encoding_size[1] = 13; /* 104-bit */ - range->encoding_size[2] = 16; /* 128-bit */ - - range->num_bitrates = 0; - - /* estimated maximum TCP throughput values (bps) */ - range->throughput = 22000000; - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - up(&ar->arSem); - - return ret; -} - - -/* - * SIOCSIWAP - * This ioctl is used to set the desired bssid for the connect command. - */ -int -ar6000_ioctl_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ap_addr->sa_family != ARPHRD_ETHER) { - return -EIO; - } - - if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) { - A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); - } else { - A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid)); - } - - return 0; -} - -/* - * SIOCGIWAP - */ -int -ar6000_ioctl_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arConnected != TRUE) { - return -EINVAL; - } - - A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid)); - ap_addr->sa_family = ARPHRD_ETHER; - - return 0; -} - -/* - * SIOCGIWAPLIST - */ -int -ar6000_ioctl_iwaplist(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - return -EIO; /* for now */ -} - -/* - * SIOCSIWSCAN - */ -int -ar6000_ioctl_siwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ -#define ACT_DWELLTIME_DEFAULT 105 -#define HOME_TXDRAIN_TIME 100 -#define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - /* We ask for everything from the target */ - if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) { - printk("Couldn't set filtering\n"); - ret = -EIO; - } - - if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \ - HOME_TXDRAIN_TIME, SCAN_INT) != A_OK) { - ret = -EIO; - } - - ar->scan_complete = 0; - wait_event_interruptible_timeout(ar6000_scan_queue, ar->scan_complete, - 5 * HZ); - - if (wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0) != A_OK) { - printk("Couldn't set filtering\n"); - ret = -EIO; - } - - return ret; -#undef ACT_DWELLTIME_DEFAULT -#undef HOME_TXDRAIN_TIME -#undef SCAN_INT -} - - -/* - * Units are in db above the noise floor. That means the - * rssi values reported in the tx/rx descriptors in the - * driver are the SNR expressed in db. - * - * If you assume that the noise floor is -95, which is an - * excellent assumption 99.5 % of the time, then you can - * derive the absolute signal level (i.e. -95 + rssi). - * There are some other slight factors to take into account - * depending on whether the rssi measurement is from 11b, - * 11g, or 11a. These differences are at most 2db and - * can be documented. - * - * NB: various calculations are based on the orinoco/wavelan - * drivers for compatibility - */ -static void -ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi) -{ - if (rssi < 0) { - iq->qual = 0; - } else { - iq->qual = rssi; - } - - /* NB: max is 94 because noise is hardcoded to 161 */ - if (iq->qual > 94) - iq->qual = 94; - - iq->noise = 161; /* -95dBm */ - iq->level = iq->noise + iq->qual; - iq->updated = 7; -} - - -/* Structures to export the Wireless Handlers */ -static const iw_handler ath_handlers[] = { - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */ - (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */ - (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */ - (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */ - (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */ - (iw_handler) ar6000_ioctl_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* SIOCSIWTHRSPY */ - (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */ - (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */ - (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */ - (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */ - (iw_handler) ar6000_ioctl_siwessid, /* SIOCSIWESSID */ - (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) NULL, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */ - (iw_handler) ar6000_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) NULL, /* SIOCSIWRTS */ - (iw_handler) NULL, /* SIOCGIWRTS */ - (iw_handler) NULL, /* SIOCSIWFRAG */ - (iw_handler) NULL, /* SIOCGIWFRAG */ - (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */ - (iw_handler) ar6000_ioctl_giwtxpow, /* SIOCGIWTXPOW */ - (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */ - (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */ - (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */ - (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */ - (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */ - (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */ - (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */ - (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */ - (iw_handler) ar6000_ioctl_siwencodeext,/* SIOCSIWENCODEEXT */ - (iw_handler) ar6000_ioctl_giwencodeext,/* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ -}; - -static const iw_handler ath_priv_handlers[] = { - (iw_handler) ar6000_ioctl_setparam, /* SIOCWFIRSTPRIV+0 */ - (iw_handler) ar6000_ioctl_getparam, /* SIOCWFIRSTPRIV+1 */ - (iw_handler) ar6000_ioctl_setkey, /* SIOCWFIRSTPRIV+2 */ - (iw_handler) ar6000_ioctl_setwmmparams, /* SIOCWFIRSTPRIV+3 */ - (iw_handler) ar6000_ioctl_delkey, /* SIOCWFIRSTPRIV+4 */ - (iw_handler) ar6000_ioctl_getwmmparams, /* SIOCWFIRSTPRIV+5 */ - (iw_handler) ar6000_ioctl_setoptie, /* SIOCWFIRSTPRIV+6 */ - (iw_handler) ar6000_ioctl_setmlme, /* SIOCWFIRSTPRIV+7 */ - (iw_handler) ar6000_ioctl_addpmkid, /* SIOCWFIRSTPRIV+8 */ -}; - -#define IW_PRIV_TYPE_KEY \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_key)) -#define IW_PRIV_TYPE_DELKEY \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_del_key)) -#define IW_PRIV_TYPE_MLME \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_mlme)) -#define IW_PRIV_TYPE_ADDPMKID \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_addpmkid)) - -static const struct iw_priv_args ar6000_priv_args[] = { - { IEEE80211_IOCTL_SETKEY, - IW_PRIV_TYPE_KEY | IW_PRIV_SIZE_FIXED, 0, "setkey"}, - { IEEE80211_IOCTL_DELKEY, - IW_PRIV_TYPE_DELKEY | IW_PRIV_SIZE_FIXED, 0, "delkey"}, - { IEEE80211_IOCTL_SETPARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam"}, - { IEEE80211_IOCTL_GETPARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam"}, - { IEEE80211_IOCTL_SETWMMPARAMS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, 0, "setwmmparams"}, - { IEEE80211_IOCTL_GETWMMPARAMS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwmmparams"}, - { IEEE80211_IOCTL_SETOPTIE, - IW_PRIV_TYPE_BYTE, 0, "setie"}, - { IEEE80211_IOCTL_SETMLME, - IW_PRIV_TYPE_MLME, 0, "setmlme"}, - { IEEE80211_IOCTL_ADDPMKID, - IW_PRIV_TYPE_ADDPMKID | IW_PRIV_SIZE_FIXED, 0, "addpmkid"}, -}; - -void ar6000_ioctl_iwsetup(struct iw_handler_def *def) -{ - def->private_args = (struct iw_priv_args *)ar6000_priv_args; - def->num_private_args = ARRAY_SIZE(ar6000_priv_args); -} - -struct iw_handler_def ath_iw_handler_def = { - .standard = (iw_handler *)ath_handlers, - .num_standard = ARRAY_SIZE(ath_handlers), - .private = (iw_handler *)ath_priv_handlers, - .num_private = ARRAY_SIZE(ath_priv_handlers), -}; - -