⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee80211_wireless.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
/*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer, *    without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any *    redistribution must be conditioned upon including a substantially *    similar Disclaimer requirement for further binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names *    of any contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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, WHETHER * IN 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 DAMAGES. * * $Id$ *//* * Wireless extensions support for 802.11 common code. */#ifndef AUTOCONF_INCLUDED#include <linux/config.h>#endif#include <linux/version.h>#include <linux/module.h>#include <linux/netdevice.h>#include <linux/utsname.h>#include <linux/if_arp.h>		/* for ARPHRD_ETHER */#include <linux/delay.h>#include <linux/wireless.h>#include <net/iw_handler.h>#if WIRELESS_EXT < 15#error "Wireless extensions v15 or better is needed."#endif#include <asm/uaccess.h>#include <net80211/if_media.h>#include <net80211/if_athproto.h>#include <net80211/ieee80211_var.h>#include <net80211/ieee80211_linux.h>#include "ah.h"#define	IS_UP(_dev) \	(((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))#define	IS_UP_AUTO(_vap) \	(IS_UP((_vap)->iv_dev) && \	 (_vap)->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO)#define	RESCAN	1static voidpre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt);static intpreempt_scan(struct net_device *dev, int max_grace, int max_wait){	struct ieee80211vap *vap = netdev_priv(dev);	struct ieee80211com *ic = vap->iv_ic;	int total_delay = 0;	int canceled = 0, ready = 0;	while (!ready && total_delay < max_grace + max_wait) {		if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {			ready = 1;		} else {			if (!canceled && (total_delay > max_grace)) {				/* Cancel any existing active scan, so that any new parameters				 * in this scan ioctl (or the defaults) can be honored, then				 * wait around a while to see if the scan cancels properly. */				IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,						"%s: cancel pending scan request\n", __func__);				(void) ieee80211_cancel_scan(vap);				canceled = 1;			}			mdelay (1);			total_delay += 1;		}	}	if (!ready) {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,				"%s: Timeout canceling current scan.\n",				__func__);	}	return ready;}static struct iw_statistics *ieee80211_iw_getstats(struct net_device *dev){	struct ieee80211vap *vap = netdev_priv(dev);	struct iw_statistics *is = &vap->iv_iwstats;	struct ieee80211com *ic = vap->iv_ic;	set_quality(&is->qual, ieee80211_getrssi(vap->iv_ic),			ic->ic_channoise);	is->status = vap->iv_state;	is->discard.nwid = vap->iv_stats.is_rx_wrongbss +		vap->iv_stats.is_rx_ssidmismatch;	is->discard.code = vap->iv_stats.is_rx_wepfail +		vap->iv_stats.is_rx_decryptcrc;	is->discard.fragment = 0;	is->discard.retries = 0;	is->discard.misc = 0;	is->miss.beacon = 0;	return is;}static intieee80211_ioctl_giwname(struct net_device *dev, struct iw_request_info *info,	char *name, char *extra){	struct ieee80211vap *vap = netdev_priv(dev);	struct ieee80211_channel *c = vap->iv_ic->ic_curchan;	if (IEEE80211_IS_CHAN_108G(c))		strncpy(name, "IEEE 802.11Tg", IFNAMSIZ);	else if (IEEE80211_IS_CHAN_108A(c))		strncpy(name, "IEEE 802.11Ta", IFNAMSIZ);	else if (IEEE80211_IS_CHAN_TURBO(c))		strncpy(name, "IEEE 802.11T", IFNAMSIZ);	else if (IEEE80211_IS_CHAN_ANYG(c))		strncpy(name, "IEEE 802.11g", IFNAMSIZ);	else if (IEEE80211_IS_CHAN_A(c))		strncpy(name, "IEEE 802.11a", IFNAMSIZ);	else if (IEEE80211_IS_CHAN_B(c))		strncpy(name, "IEEE 802.11b", IFNAMSIZ);	else		strncpy(name, "IEEE 802.11", IFNAMSIZ);	/* XXX FHSS */	return 0;}/* * Get a key index from a request.  If nothing is * specified in the request we use the current xmit * key index.  Otherwise we just convert the index * to be base zero. */static intgetiwkeyix(struct ieee80211vap *vap, const struct iw_point *erq, ieee80211_keyix_t *rkix){	ieee80211_keyix_t kix;	kix = erq->flags & IW_ENCODE_INDEX;	if ((erq->flags & IW_ENCODE_INDEX) == (u_int8_t)IEEE80211_KEYIX_NONE)		kix = IEEE80211_KEYIX_NONE;	if (kix < 1 || kix > IEEE80211_WEP_NKID) {		kix = vap->iv_def_txkey;		if (kix == IEEE80211_KEYIX_NONE)			kix = 0;	} else		--kix;	if (kix < IEEE80211_WEP_NKID) {		*rkix = kix;		return 0;	} else		return -EINVAL;}static intieee80211_ioctl_siwencode(struct net_device *dev,	struct iw_request_info *info, struct iw_point *erq, char *keybuf){	struct ieee80211vap *vap = netdev_priv(dev);	int error;	int wepchange = 0;	ieee80211_keyix_t kix;	if ((erq->flags & IW_ENCODE_DISABLED) == 0) {		/* Check WEP support, load WEP module if needed */		if (!ieee80211_crypto_available(vap, IEEE80211_CIPHER_WEP))			return -EOPNOTSUPP;		/*		 * Enable crypto, set key contents, and		 * set the default transmit key.		 */		error = getiwkeyix(vap, erq, &kix);		if (error < 0)			return error;		if (erq->length > IEEE80211_KEYBUF_SIZE)			return -E2BIG;		/* XXX no way to install 0-length key */		ieee80211_key_update_begin(vap);		if (erq->length > 0) {			struct ieee80211_key *k = &vap->iv_nw_keys[kix];			/*			 * Set key contents.  This interface only supports WEP.			 * Indicate intended key index.			 			 */			k->wk_keyix = kix;			if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP,			    IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {				k->wk_keylen = erq->length;				memcpy(k->wk_key, keybuf, erq->length);				memset(k->wk_key + erq->length, 0,					IEEE80211_KEYBUF_SIZE - erq->length);				if (!ieee80211_crypto_setkey(vap, k, vap->iv_myaddr, NULL))					error = -EINVAL;		/* XXX */			} else				error = -EINVAL;		} else {			/*			 * When the length is zero the request only changes			 * the default transmit key.  Verify the new key has			 * a non-zero length.			 */			if (vap->iv_nw_keys[kix].wk_keylen == 0)				error = -EINVAL;		}		if (error == 0) {			/*			 * The default transmit key is only changed when:			 * 1. Privacy is enabled and no key matter is			 *    specified.			 * 2. Privacy is currently disabled.			 * This is deduced from the iwconfig man page.			 */			if (erq->length == 0 ||			    (vap->iv_flags & IEEE80211_F_PRIVACY) == 0)				vap->iv_def_txkey = kix;			wepchange = (vap->iv_flags & IEEE80211_F_PRIVACY) == 0;			vap->iv_flags |= IEEE80211_F_PRIVACY;		}		ieee80211_key_update_end(vap);	} else {		if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0)			return 0;		vap->iv_flags &= ~IEEE80211_F_PRIVACY;		wepchange = 1;		error = 0;	}	if (error == 0) {		/* Set policy for unencrypted frames */		if ((erq->flags & IW_ENCODE_OPEN) &&		    (!(erq->flags & IW_ENCODE_RESTRICTED))) {			vap->iv_flags &= ~IEEE80211_F_DROPUNENC;		} else if (!(erq->flags & IW_ENCODE_OPEN) &&			 (erq->flags & IW_ENCODE_RESTRICTED)) {			vap->iv_flags |= IEEE80211_F_DROPUNENC;		} else {			/* Default policy */			if (vap->iv_flags & IEEE80211_F_PRIVACY)				vap->iv_flags |= IEEE80211_F_DROPUNENC;			else				vap->iv_flags &= ~IEEE80211_F_DROPUNENC;		}	}	if ((error == 0) && IS_UP(vap->iv_dev)) {		/*		 * Device is up and running; we must kick it to		 * effect the change.  If we're enabling/disabling		 * crypto use then we must re-initialize the device		 * so the 802.11 state machine is reset.  Otherwise		 * the key state should have been updated above.		 */		if (wepchange && IS_UP_AUTO(vap))			ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);	}#ifdef ATH_SUPERG_XR	/* set the same params on the xr vap device if exists */	if (!error && vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))		ieee80211_ioctl_siwencode(vap->iv_xrvap->iv_dev, info, erq, keybuf);#endif	return error;}static intieee80211_ioctl_giwencode(struct net_device *dev, struct iw_request_info *info,	struct iw_point *erq, char *key){	struct ieee80211vap *vap = netdev_priv(dev);	struct ieee80211_key *k;	int error;	ieee80211_keyix_t kix;	if (vap->iv_flags & IEEE80211_F_PRIVACY) {		error = getiwkeyix(vap, erq, &kix);		if (error < 0)			return error;		k = &vap->iv_nw_keys[kix];		/* XXX no way to return cipher/key type */		erq->flags = kix + 1;			/* NB: base 1 */		if (erq->length > k->wk_keylen)			erq->length = k->wk_keylen;		memcpy(key, k->wk_key, erq->length);		erq->flags |= IW_ENCODE_ENABLED;	} else {		erq->length = 0;		erq->flags = IW_ENCODE_DISABLED;	}	if (vap->iv_flags & IEEE80211_F_DROPUNENC)		erq->flags |= IW_ENCODE_RESTRICTED;	else		erq->flags |= IW_ENCODE_OPEN;	return 0;}#ifndef ifr_media#define	ifr_media	ifr_ifru.ifru_ivalue#endifstatic intieee80211_ioctl_siwrate(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rrq, char *extra){	static const u_int mopts[] = {		IFM_AUTO,		IFM_IEEE80211_11A,		IFM_IEEE80211_11B,		IFM_IEEE80211_11G,		IFM_IEEE80211_FH,		IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,		IFM_IEEE80211_11G | IFM_IEEE80211_TURBO,	};	struct ieee80211vap *vap = netdev_priv(dev);	struct ieee80211com *ic = vap->iv_ic;	struct ifreq ifr;	int rate, retv;	if (vap->iv_media.ifm_cur == NULL)		return -EINVAL;	memset(&ifr, 0, sizeof(ifr));	ifr.ifr_media = vap->iv_media.ifm_cur->ifm_media &~ (IFM_MMASK|IFM_TMASK);	ifr.ifr_media |= mopts[vap->iv_des_mode];	if (rrq->fixed) {		/* XXX fudge checking rates */		rate = ieee80211_rate2media(ic, 2 * rrq->value / 1000000,			vap->iv_des_mode);		if (rate == IFM_AUTO)		/* NB: unknown rate */			return -EINVAL;	} else		rate = IFM_AUTO;	ifr.ifr_media |= IFM_SUBTYPE(rate);	/* refresh media capabilities based on channel */	ifmedia_removeall(&vap->iv_media);	(void) ieee80211_media_setup(ic, &vap->iv_media,		vap->iv_caps, vap->iv_media.ifm_change, vap->iv_media.ifm_status);	retv = ifmedia_ioctl(vap->iv_dev, &ifr, &vap->iv_media, SIOCSIFMEDIA);	if (retv == -ENETRESET)		retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;	if (retv)		IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, "%s returns %d\n", 				  __func__, retv);	return retv;}static intieee80211_ioctl_giwrate(struct net_device *dev,	struct iw_request_info *info,	struct iw_param *rrq, char *extra){	struct ieee80211vap *vap = netdev_priv(dev);	struct ifmediareq imr;	int rate;	memset(&imr, 0, sizeof(imr));	vap->iv_media.ifm_status(vap->iv_dev, &imr);	rrq->fixed = IFM_SUBTYPE(vap->iv_media.ifm_media) != IFM_AUTO;	/* media status will have the current xmit rate if available */	rate = ieee80211_media2rate(imr.ifm_active);	if (rate == -1)		/* IFM_AUTO */		rate = 0;	rrq->value = 1000000 * (rate / 2);	return 0;}static intieee80211_ioctl_siwsens(struct net_device *dev,	struct iw_request_info *info,	struct iw_param *sens, char *extra){	return -EOPNOTSUPP;}static intieee80211_ioctl_giwsens(struct net_device *dev,	struct iw_request_info *info,	struct iw_param *sens, char *extra){	sens->value = 1;	sens->fixed = 1;	return 0;}static intieee80211_ioctl_siwrts(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rts, char *extra){	struct ieee80211vap *vap = netdev_priv(dev);	struct ieee80211com *ic = vap->iv_ic;	u16 val;	if (rts->disabled)		val = IEEE80211_RTS_MAX;	else if ((IEEE80211_RTS_MIN <= rts->value) &&			(rts->value <= IEEE80211_RTS_MAX))		val = rts->value;	else		return -EINVAL;	if (val != vap->iv_rtsthreshold) {		vap->iv_rtsthreshold = val;		if (IS_UP(vap->iv_dev))			return ic->ic_reset(ic->ic_dev);	}	return 0;}static intieee80211_ioctl_giwrts(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rts, char *extra){	struct ieee80211vap *vap = netdev_priv(dev);	rts->value = vap->iv_rtsthreshold;	rts->disabled = (rts->value == IEEE80211_RTS_MAX);	rts->fixed = 1;	return 0;}static intieee80211_ioctl_siwfrag(struct net_device *dev,	struct iw_request_info *info,	struct iw_param *rts, char *extra){	struct ieee80211vap *vap = netdev_priv(dev);	struct ieee80211com *ic = vap->iv_ic;	u16 val;	if (rts->disabled)		val = 2346;	else if ((rts->value < 256) || (rts->value > 2346))		return -EINVAL;	else		val = (rts->value & ~0x1);	if (val != vap->iv_fragthreshold) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -