Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_regdomain.c
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
null_setregdomain(struct ieee80211com *ic, | null_setregdomain(struct ieee80211com *ic, | ||||
struct ieee80211_regdomain *rd, | struct ieee80211_regdomain *rd, | ||||
int nchans, struct ieee80211_channel chans[]) | int nchans, struct ieee80211_channel chans[]) | ||||
{ | { | ||||
return 0; /* accept anything */ | 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 | void | ||||
ieee80211_regdomain_attach(struct ieee80211com *ic) | ieee80211_regdomain_attach(struct ieee80211com *ic) | ||||
{ | { | ||||
if (ic->ic_regdomain.regdomain == 0 && | if (ic->ic_regdomain.regdomain == 0 && | ||||
ic->ic_regdomain.country == CTRY_DEFAULT) { | ic->ic_regdomain.country == CTRY_DEFAULT) | ||||
ic->ic_regdomain.country = CTRY_UNITED_STATES; /* XXX */ | regdomain_init(ic); | ||||
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_getradiocaps = null_getradiocaps; | ic->ic_getradiocaps = null_getradiocaps; | ||||
ic->ic_setregdomain = null_setregdomain; | ic->ic_setregdomain = null_setregdomain; | ||||
} | } | ||||
void | void | ||||
ieee80211_regdomain_detach(struct ieee80211com *ic) | ieee80211_regdomain_detach(struct ieee80211com *ic) | ||||
{ | { | ||||
if (ic->ic_countryie != NULL) { | if (ic->ic_countryie != NULL) { | ||||
▲ Show 20 Lines • Show All 367 Lines • Show Last 20 Lines |