Date: Sun, 21 Jan 2007 19:51:56 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 113263 for review Message-ID: <200701211951.l0LJpunf019736@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=113263 Change 113263 by sam@sam_ebb on 2007/01/21 19:51:42 Cleanup channel manipulation ioctls a bit: o change IEEE80211_IOC_CHANINFO to return the complete channel list the kernel uses, don't suppress/combine duplicates o add IEEE80211_IOC_CURCHAN ioctl to replace IEEE80211_IOC_CHANNEL for getting and setting the current channel; this allows us to unambiguously specify a channel when a single frequency can be operated in multiple ways (e.g. different channel width) Affected files ... .. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#64 edit .. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.h#36 edit Differences ... ==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#64 (text+ko) ==== @@ -158,29 +158,14 @@ static int ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq) { - struct ieee80211req_chaninfo chans; /* XXX off stack? */ - u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage */ - int i, space; - - memset(&chans, 0, sizeof(chans)); - memset(&reported, 0, sizeof(reported)); - for (i = 0; i < ic->ic_nchans; i++) { - const struct ieee80211_channel *c = &ic->ic_channels[i]; + int space; - /* discard if previously reported (e.g. b/g) */ - if (isclr(reported, c->ic_ieee)) { - setbit(reported, c->ic_ieee); - chans.ic_chans[chans.ic_nchans].ic_freq = c->ic_freq; - chans.ic_chans[chans.ic_nchans].ic_flags = c->ic_flags; - if (++chans.ic_nchans >= IEEE80211_CHAN_MAX) - break; - } - } space = __offsetof(struct ieee80211req_chaninfo, - ic_chans[chans.ic_nchans]); + ic_chans[ic->ic_nchans]); if (space > ireq->i_len) space = ireq->i_len; - return copyout(&chans, ireq->i_data, space); + /* XXX assumes compatible layout */ + return copyout(&ic->ic_nchans, ireq->i_data, space); } static int @@ -804,6 +789,14 @@ return (ic->ic_flags & cap) != 0; } +static int +ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq) +{ + if (ireq->i_len != sizeof(struct ieee80211_channel)) + return EINVAL; + return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan)); +} + /* * When building the kernel with -O2 on the i386 architecture, gcc * seems to want to inline this function into ieee80211_ioctl() @@ -1098,6 +1091,9 @@ case IEEE80211_IOC_BMISSTHRESHOLD: ireq->i_val = ic->ic_bmissthreshold; break; + case IEEE80211_IOC_CURCHAN: + error = ieee80211_ioctl_getcurchan(ic, ireq); + break; default: error = EINVAL; break; @@ -1767,6 +1763,65 @@ } static int +ieee80211_ioctl_setcurchan(struct ieee80211com *ic, + const struct ieee80211req *ireq) +{ + struct ieee80211_channel chan; + int error; + + if (ireq->i_len != sizeof(chan)) + return EINVAL; + error = copyin(ireq->i_data, &chan, sizeof(chan)); + if (error != 0) + return error; + /* XXX 0xffff overflows 16-bit signed */ + if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) { + ic->ic_des_chan = IEEE80211_CHAN_ANYC; + } else { + struct ieee80211_channel *c; + + c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags); + if (c == NULL) + return EINVAL; + /* XXX? */ + if (ic->ic_opmode == IEEE80211_M_HOSTAP && + !check_mode_consistency(c, ic->ic_des_mode)) + return EINVAL; + if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_bsschan) + return 0; /* NB: nothing to do */ + ic->ic_des_chan = c; + } + error = 0; + if ((ic->ic_opmode == IEEE80211_M_MONITOR || + ic->ic_opmode == IEEE80211_M_WDS) && + ic->ic_des_chan != IEEE80211_CHAN_ANYC) { + /* + * Monitor and wds modes can switch directly. + */ + ic->ic_curchan = ic->ic_des_chan; + if (ic->ic_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(ic)) + error = ieee80211_init(ic, RESCAN); + else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) { + /* + * When not up+running and a real channel has + * been specified fix the current channel so + * there is immediate feedback; e.g. via ifconfig. + */ + ic->ic_curchan = ic->ic_des_chan; + } + } + return error; +} + +static int ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) { static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; @@ -2265,6 +2320,9 @@ ic->ic_bmissthreshold = ireq->i_val; error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; break; + case IEEE80211_IOC_CURCHAN: + error = ieee80211_ioctl_setcurchan(ic, ireq); + break; default: error = EINVAL; break; ==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.h#36 (text+ko) ==== @@ -471,6 +471,7 @@ #define IEEE80211_IOC_BMISSTHRESHOLD 77 /* beacon miss threshold */ #define IEEE80211_IOC_STA_INFO 78 /* station/neighbor info */ #define IEEE80211_IOC_WPAIE2 79 /* WPA+RSN info elements */ +#define IEEE80211_IOC_CURCHAN 80 /* current channel */ /* * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701211951.l0LJpunf019736>