PERFORCE change 113263 for review
Sam Leffler
sam at FreeBSD.org
Sun Jan 21 19:51:57 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=113263
Change 113263 by sam at 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.
More information about the p4-projects
mailing list