All pastes #522525 Raw Edit

Miscellany

public text v1 · immutable
#522525 ·published 2007-05-30 13:18 UTC
rendered paste body
static int
ieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
	struct iw_freq *freq, char *extra)
{
	struct ieee80211vap *vap = dev->priv;
	struct ieee80211com *ic = vap->iv_ic;
	struct ieee80211_channel *c, *c2;
	int i;
	
	if (freq->e > 1)
		return -EINVAL;
	if (freq->e == 1)
		i = (ic->ic_mhz2ieee)(ic, freq->m / 100000, 0);
	else
		i = freq->m;
	if (i != 0) {
		if (i > IEEE80211_CHAN_MAX)
			return -EINVAL;
		c = findchannel(ic, i, vap->iv_des_mode);
		if (c == NULL) {
			c = findchannel(ic, i, IEEE80211_MODE_AUTO);
			if (c == NULL)			/* no channel */
				return -EINVAL;
		}
		/*
		 * Fine tune channel selection based on desired mode:
		 *   if 11b is requested, find the 11b version of any
		 *      11g channel returned,
		 *   if static turbo, find the turbo version of any
		 *	11a channel return,
		 *   otherwise we should be ok with what we've got.
		 */
		switch (vap->iv_des_mode) {
		case IEEE80211_MODE_11B:
			if (IEEE80211_IS_CHAN_ANYG(c)) {
				c2 = findchannel(ic, i, IEEE80211_MODE_11B);
				/* NB: should not happen, =>'s 11g w/o 11b */
				if (c2 != NULL)
					c = c2;
			}
			break;
		case IEEE80211_MODE_TURBO_A:
			if (IEEE80211_IS_CHAN_A(c)) {
				c2 = findchannel(ic, i, IEEE80211_MODE_TURBO_A);
				if (c2 != NULL)
					c = c2;
			}
			break;
		default:		/* NB: no static turboG */
			break;
		}
		if (ieee80211_check_mode_consistency(ic,vap->iv_des_mode,c)) {
			if (vap->iv_opmode == IEEE80211_M_HOSTAP)
				return -EINVAL;
		}
		if (vap->iv_state == IEEE80211_S_RUN && c == ic->ic_bsschan)
			return 0;			/* no change, return */

		/* Don't allow to change to channel with radar found */
		if (c->ic_flags & IEEE80211_CHAN_RADAR)
			return -EINVAL;

		/*
		 * Mark desired channel and if running force a
		 * radio change.
		 */
		vap->iv_des_chan = c;
	} else {
		/*
		 * Intepret channel 0 to mean "no desired channel";
		 * otherwise there's no way to undo fixing the desired
		 * channel.
		 */
		if (vap->iv_des_chan == IEEE80211_CHAN_ANYC)
			return 0;
		vap->iv_des_chan = IEEE80211_CHAN_ANYC;
	}
#if 0
	if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
		int mode = ieee80211_chan2mode(vap->iv_des_chan);
		if (mode != ic->ic_curmode)
			ieee80211_setmode(ic, mode);
	}
#endif
	if ((vap->iv_opmode == IEEE80211_M_MONITOR ||
	    vap->iv_opmode == IEEE80211_M_WDS) &&
	    vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
		/*
		 * Monitor and wds modes can switch directly.
		 */
		ic->ic_curchan = vap->iv_des_chan;
		if (vap->iv_state == IEEE80211_S_RUN) {
			ic->ic_set_channel(ic);
		}
	} else {
		/*
		 * Need to go through the state machine in case we need
		 * to reassociate or the like.  The state machine will
		 * pickup the desired channel and avoid scanning.
		 */
		if (IS_UP_AUTO(vap))
			ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
	}
	return 0;
}