Page MenuHomeFreeBSD

D6205.diff
No OneTemporary

D6205.diff

Index: sys/net80211/ieee80211_regdomain.c
===================================================================
--- sys/net80211/ieee80211_regdomain.c
+++ sys/net80211/ieee80211_regdomain.c
@@ -64,17 +64,112 @@
return 0; /* accept anything */
}
+/* FCC regdomain limitations. Extracted from regdomain.xml */
+static const struct freqband {
+ uint16_t freq_min;
+ uint16_t freq_max;
+ int8_t maxregpower;
+ uint32_t flags;
+} fcc_bands[] = {
+ { 2412, 2462, 30, IEEE80211_CHAN_B },
+ { 2412, 2462, 30, IEEE80211_CHAN_G },
+ { 2412, 2462, 30, IEEE80211_CHAN_G | IEEE80211_CHAN_HT20 },
+ { 2432, 2462, 30, IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D },
+ { 2412, 2442, 30, IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U },
+ { 5180, 5240, 17, IEEE80211_CHAN_A },
+ { 5180, 5240, 17, IEEE80211_CHAN_A | IEEE80211_CHAN_HT20 },
+ { 5200, 5240, 17, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D },
+ { 5180, 5220, 17, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U },
+ { 5745, 5805, 23, IEEE80211_CHAN_A },
+ { 5745, 5805, 23, IEEE80211_CHAN_A | IEEE80211_CHAN_HT20 },
+ { 5765, 5805, 23, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D },
+ { 5745, 5785, 23, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U },
+ { 5825, 5825, 23, IEEE80211_CHAN_A | IEEE80211_CHAN_PASSIVE },
+ { 0, 0, 0, 0 }
+};
+
+static void
+removechan(struct ieee80211com *ic, int idx)
+{
+ struct ieee80211_channel *chan = &ic->ic_channels[0];
+
+ KASSERT(idx < ic->ic_nchans, ("wrong index %d (%d)\n", idx,
+ ic->ic_nchans));
+
+ ic->ic_nchans--;
+ memcpy(&chan[idx], &chan[ic->ic_nchans], sizeof(*chan));
+ memset(&chan[ic->ic_nchans], 0, sizeof(*chan));
+}
+
+static int
+checkchan(struct ieee80211_channel *c, const struct freqband fbands[])
+{
+ const struct freqband *fb;
+ uint32_t flags;
+ int i;
+
+ flags = c->ic_flags & IEEE80211_CHAN_ALLTURBO;
+ /* brute force search */
+ for (i = 0; fbands[i].freq_max != 0; i++) {
+ fb = &fbands[i];
+
+ if (flags == (fb->flags & IEEE80211_CHAN_ALLTURBO) &&
+ fb->freq_min <= c->ic_freq &&
+ fb->freq_max >= c->ic_freq) {
+ if (fb->maxregpower < c->ic_maxregpower) {
+ c->ic_maxregpower = fb->maxregpower;
+ c->ic_maxpower = fb->maxregpower * 2;
+
+ if (c->ic_minpower > c->ic_maxpower)
+ c->ic_minpower = c->ic_maxpower;
+ }
+ /* add PASSIVE, DFS etc flags. */
+ c->ic_flags |= (fb->flags & ~IEEE80211_CHAN_ALLTURBO);
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+static void
+channel_plan_init(struct ieee80211com *ic, const struct freqband fbands[])
+{
+ int i, found;
+
+ for (i = 0; i < ic->ic_nchans;) {
+ found = checkchan(&ic->ic_channels[i], fbands);
+ if (!found)
+ removechan(ic, i);
+ else
+ i++;
+ }
+
+ ieee80211_chan_init(ic);
+}
+
+static void
+regdomain_init(struct ieee80211com *ic)
+{
+ struct ieee80211_regdomain *rd = &ic->ic_regdomain;
+
+ /* init by default to FCC/US */
+ rd->regdomain = SKU_FCC;
+ rd->country = CTRY_UNITED_STATES;
+ rd->location = ' '; /* both */
+ rd->isocc[0] = 'U';
+ rd->isocc[1] = 'S';
+
+ channel_plan_init(ic, fcc_bands);
+}
+
void
ieee80211_regdomain_attach(struct ieee80211com *ic)
{
if (ic->ic_regdomain.regdomain == 0 &&
- ic->ic_regdomain.country == CTRY_DEFAULT) {
- ic->ic_regdomain.country = CTRY_UNITED_STATES; /* XXX */
- ic->ic_regdomain.location = ' '; /* both */
- ic->ic_regdomain.isocc[0] = 'U'; /* XXX */
- ic->ic_regdomain.isocc[1] = 'S'; /* XXX */
- /* NB: driver calls ieee80211_init_channels or similar */
- }
+ ic->ic_regdomain.country == CTRY_DEFAULT)
+ regdomain_init(ic);
+
ic->ic_getradiocaps = null_getradiocaps;
ic->ic_setregdomain = null_setregdomain;
}

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 22, 8:38 PM (9 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31998832
Default Alt Text
D6205.diff (3 KB)

Event Timeline