From d6bf86af1ef1e6b179b4d41c4131b804b9a0a248 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Wed, 28 Jan 2009 19:15:52 +0000 Subject: [PATCH] Fix 1/2 and 1/4 width channel handling: o only include 1/2 and 1/4 width channels when they are specified in the regulatory database description; previously we treated them as if they were part of the band and blindly added them for 11a/g o check the channel list returned in the devcaps to identify whether a device supports 1/2 or 1/4 width channels on a band; this might be better brought out as a capability bit to avoid filling the channel list w/ 1/2 and 1/4 width channels but then cards that only support these channels in a range of frequencies could not be described (though right now we don't check frequency range only band) --- sbin/ifconfig/ifieee80211.c | 68 +++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index fa97675c7a58..c0f756c984d6 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -1789,6 +1789,19 @@ chanlookup(const struct ieee80211_channel chans[], int nchans, return NULL; } +static int +chanfind(const struct ieee80211_channel chans[], int nchans, int flags) +{ + int i; + + for (i = 0; i < nchans; i++) { + const struct ieee80211_channel *c = &chans[i]; + if ((c->ic_flags & flags) == flags) + return 1; + } + return 0; +} + static void regdomain_addchans(struct ieee80211req_chaninfo *ci, const netband_head *bands, @@ -1799,9 +1812,15 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci, const struct netband *nb; const struct freqband *b; struct ieee80211_channel *c, *prev; - int freq, channelSep; + int freq, channelSep, hasHalfChans, hasQuarterChans; channelSep = (chanFlags & IEEE80211_CHAN_2GHZ) ? 0 : 40; + hasHalfChans = chanfind(avail->ic_chans, avail->ic_nchans, + IEEE80211_CHAN_HALF | + (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ))); + hasQuarterChans = chanfind(avail->ic_chans, avail->ic_nchans, + IEEE80211_CHAN_QUARTER | + (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ))); LIST_FOREACH(nb, bands, next) { b = nb->band; if (verbose) @@ -1812,28 +1831,31 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci, uint32_t flags = nb->flags | b->flags; /* check if device can operate on this frequency */ - if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, chanFlags) == NULL) { + /* + * XXX GSM frequency mapping is handled in the kernel + * so we cannot find them in the calibration table; + * just construct the list and the kernel will reject + * if it's wrong. + */ + if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, chanFlags) == NULL && + (flags & IEEE80211_CHAN_GSM) == 0) { if (verbose) printf("%u: skip, flags 0x%x not available\n", freq, chanFlags); continue; } - /* - * NB: don't enforce 1/2 and 1/4 rate channels being - * specified in the device's calibration list for - * 900MHz cards because most are not self-identifying. - */ - if ((flags & IEEE80211_CHAN_HALF) && - ((chanFlags & IEEE80211_CHAN_HALF) == 0 && - (flags & IEEE80211_CHAN_GSM) == 0)) { + if ((flags & IEEE80211_CHAN_HALF) && !hasHalfChans) { if (verbose) - printf("%u: skip, device does not support half-rate channels\n", freq); + printf("%u: skip, device does not " + "support half-rate channel\n", + freq); continue; } if ((flags & IEEE80211_CHAN_QUARTER) && - ((chanFlags & IEEE80211_CHAN_QUARTER) == 0 && - (flags & IEEE80211_CHAN_GSM) == 0)) { + !hasQuarterChans) { if (verbose) - printf("%u: skip, device does not support quarter-rate channels\n", freq); + printf("%u: skip, device does not " + "support quarter-rate channel\n", + freq); continue; } if ((flags & IEEE80211_CHAN_HT20) && @@ -1932,26 +1954,12 @@ regdomain_makechannels( if (!LIST_EMPTY(&rd->bands_11b)) regdomain_addchans(ci, &rd->bands_11b, reg, IEEE80211_CHAN_B, &dc->dc_chaninfo); - if (!LIST_EMPTY(&rd->bands_11g)) { + if (!LIST_EMPTY(&rd->bands_11g)) regdomain_addchans(ci, &rd->bands_11g, reg, IEEE80211_CHAN_G, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11g, reg, - IEEE80211_CHAN_G | IEEE80211_CHAN_HALF, - &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11g, reg, - IEEE80211_CHAN_G | IEEE80211_CHAN_QUARTER, - &dc->dc_chaninfo); - } - if (!LIST_EMPTY(&rd->bands_11a)) { + if (!LIST_EMPTY(&rd->bands_11a)) regdomain_addchans(ci, &rd->bands_11a, reg, IEEE80211_CHAN_A, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11a, reg, - IEEE80211_CHAN_A | IEEE80211_CHAN_HALF, - &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11a, reg, - IEEE80211_CHAN_A | IEEE80211_CHAN_QUARTER, - &dc->dc_chaninfo); - } if (!LIST_EMPTY(&rd->bands_11na)) { regdomain_addchans(ci, &rd->bands_11na, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT20,