Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105773238
D6124.id15743.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D6124.id15743.diff
View Options
Index: head/sys/net80211/ieee80211.c
===================================================================
--- head/sys/net80211/ieee80211.c
+++ head/sys/net80211/ieee80211.c
@@ -970,6 +970,261 @@
}
}
+static __inline void
+set_extchan(struct ieee80211_channel *c)
+{
+
+ /*
+ * IEEE Std 802.11-2012, page 1738, subclause 20.3.15.4:
+ * "the secondary channel number shall be 'N + [1,-1] * 4'
+ */
+ if (c->ic_flags & IEEE80211_CHAN_HT40U)
+ c->ic_extieee = c->ic_ieee + 4;
+ else if (c->ic_flags & IEEE80211_CHAN_HT40D)
+ c->ic_extieee = c->ic_ieee - 4;
+ else
+ c->ic_extieee = 0;
+}
+
+static int
+addchan(struct ieee80211_channel chans[], int maxchans, int *nchans,
+ uint8_t ieee, uint16_t freq, int8_t maxregpower, uint32_t flags)
+{
+ struct ieee80211_channel *c;
+
+ if (*nchans >= maxchans)
+ return (ENOBUFS);
+
+ c = &chans[(*nchans)++];
+ c->ic_ieee = ieee;
+ c->ic_freq = freq != 0 ? freq : ieee80211_ieee2mhz(ieee, flags);
+ c->ic_maxregpower = maxregpower;
+ c->ic_maxpower = 2 * maxregpower;
+ c->ic_flags = flags;
+ set_extchan(c);
+
+ return (0);
+}
+
+static int
+copychan_prev(struct ieee80211_channel chans[], int maxchans, int *nchans,
+ uint32_t flags)
+{
+ struct ieee80211_channel *c;
+
+ KASSERT(*nchans > 0, ("channel list is empty\n"));
+
+ if (*nchans >= maxchans)
+ return (ENOBUFS);
+
+ c = &chans[(*nchans)++];
+ c[0] = c[-1];
+ c->ic_flags = flags;
+ set_extchan(c);
+
+ return (0);
+}
+
+static void
+getflags_2ghz(const uint8_t bands[], uint32_t flags[], int ht40)
+{
+ int nmodes;
+
+ nmodes = 0;
+ if (isset(bands, IEEE80211_MODE_11B))
+ flags[nmodes++] = IEEE80211_CHAN_B;
+ if (isset(bands, IEEE80211_MODE_11G))
+ flags[nmodes++] = IEEE80211_CHAN_G;
+ if (isset(bands, IEEE80211_MODE_11NG))
+ flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT20;
+ if (ht40) {
+ flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U;
+ flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D;
+ }
+ flags[nmodes] = 0;
+}
+
+static void
+getflags_5ghz(const uint8_t bands[], uint32_t flags[], int ht40)
+{
+ int nmodes;
+
+ nmodes = 0;
+ if (isset(bands, IEEE80211_MODE_11A))
+ flags[nmodes++] = IEEE80211_CHAN_A;
+ if (isset(bands, IEEE80211_MODE_11NA))
+ flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT20;
+ if (ht40) {
+ flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U;
+ flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D;
+ }
+ flags[nmodes] = 0;
+}
+
+static void
+getflags(const uint8_t bands[], uint32_t flags[], int ht40)
+{
+
+ flags[0] = 0;
+ if (isset(bands, IEEE80211_MODE_11A) ||
+ isset(bands, IEEE80211_MODE_11NA)) {
+ if (isset(bands, IEEE80211_MODE_11B) ||
+ isset(bands, IEEE80211_MODE_11G) ||
+ isset(bands, IEEE80211_MODE_11NG))
+ return;
+
+ getflags_5ghz(bands, flags, ht40);
+ } else
+ getflags_2ghz(bands, flags, ht40);
+}
+
+/*
+ * Add one 20 MHz channel into specified channel list.
+ */
+int
+ieee80211_add_channel(struct ieee80211_channel chans[], int maxchans,
+ int *nchans, uint8_t ieee, uint16_t freq, int8_t maxregpower,
+ uint32_t chan_flags, const uint8_t bands[])
+{
+ uint32_t flags[IEEE80211_MODE_MAX];
+ int i, error;
+
+ getflags(bands, flags, 0);
+ KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__));
+
+ error = addchan(chans, maxchans, nchans, ieee, freq, maxregpower,
+ flags[0] | chan_flags);
+ for (i = 1; flags[i] != 0 && error == 0; i++) {
+ error = copychan_prev(chans, maxchans, nchans,
+ flags[i] | chan_flags);
+ }
+
+ return (error);
+}
+
+static struct ieee80211_channel *
+findchannel(struct ieee80211_channel chans[], int nchans, uint16_t freq,
+ uint32_t flags)
+{
+ struct ieee80211_channel *c;
+ int i;
+
+ flags &= IEEE80211_CHAN_ALLTURBO;
+ /* brute force search */
+ for (i = 0; i < nchans; i++) {
+ c = &chans[i];
+ if (c->ic_freq == freq &&
+ (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)
+ return c;
+ }
+ return NULL;
+}
+
+/*
+ * Add 40 MHz channel pair into specified channel list.
+ */
+int
+ieee80211_add_channel_ht40(struct ieee80211_channel chans[], int maxchans,
+ int *nchans, uint8_t ieee, int8_t maxregpower, uint32_t flags)
+{
+ struct ieee80211_channel *cent, *extc;
+ uint16_t freq;
+ int error;
+
+ freq = ieee80211_ieee2mhz(ieee, flags);
+
+ /*
+ * Each entry defines an HT40 channel pair; find the
+ * center channel, then the extension channel above.
+ */
+ flags |= IEEE80211_CHAN_HT20;
+ cent = findchannel(chans, *nchans, freq, flags);
+ if (cent == NULL)
+ return (EINVAL);
+
+ extc = findchannel(chans, *nchans, freq + 20, flags);
+ if (extc == NULL)
+ return (ENOENT);
+
+ flags &= ~IEEE80211_CHAN_HT;
+ error = addchan(chans, maxchans, nchans, cent->ic_ieee, cent->ic_freq,
+ maxregpower, flags | IEEE80211_CHAN_HT40U);
+ if (error != 0)
+ return (error);
+
+ error = addchan(chans, maxchans, nchans, extc->ic_ieee, extc->ic_freq,
+ maxregpower, flags | IEEE80211_CHAN_HT40D);
+
+ return (error);
+}
+
+/*
+ * Adds channels into specified channel list (ieee[] array must be sorted).
+ * Channels are already sorted.
+ */
+static int
+add_chanlist(struct ieee80211_channel chans[], int maxchans, int *nchans,
+ const uint8_t ieee[], int nieee, uint32_t flags[])
+{
+ uint16_t freq;
+ int i, j, error;
+
+ for (i = 0; i < nieee; i++) {
+ freq = ieee80211_ieee2mhz(ieee[i], flags[0]);
+ for (j = 0; flags[j] != 0; j++) {
+ if (flags[j] & IEEE80211_CHAN_HT40D)
+ if (i == 0 || ieee[i] < ieee[0] + 4 ||
+ freq - 20 !=
+ ieee80211_ieee2mhz(ieee[i] - 4, flags[j]))
+ continue;
+ if (flags[j] & IEEE80211_CHAN_HT40U)
+ if (i == nieee - 1 ||
+ ieee[i] + 4 > ieee[nieee - 1] ||
+ freq + 20 !=
+ ieee80211_ieee2mhz(ieee[i] + 4, flags[j]))
+ continue;
+
+ if (j == 0) {
+ error = addchan(chans, maxchans, nchans,
+ ieee[i], freq, 0, flags[j]);
+ } else {
+ error = copychan_prev(chans, maxchans, nchans,
+ flags[j]);
+ }
+ if (error != 0)
+ return (error);
+ }
+ }
+
+ return (error);
+}
+
+int
+ieee80211_add_channel_list_2ghz(struct ieee80211_channel chans[], int maxchans,
+ int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[],
+ int ht40)
+{
+ uint32_t flags[IEEE80211_MODE_MAX];
+
+ getflags_2ghz(bands, flags, ht40);
+ KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__));
+
+ return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags));
+}
+
+int
+ieee80211_add_channel_list_5ghz(struct ieee80211_channel chans[], int maxchans,
+ int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[],
+ int ht40)
+{
+ uint32_t flags[IEEE80211_MODE_MAX];
+
+ getflags_5ghz(bands, flags, ht40);
+ KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__));
+
+ return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags));
+}
+
/*
* Locate a channel given a frequency+flags. We cache
* the previous lookup to optimize switching between two
@@ -979,7 +1234,6 @@
ieee80211_find_channel(struct ieee80211com *ic, int freq, int flags)
{
struct ieee80211_channel *c;
- int i;
flags &= IEEE80211_CHAN_ALLTURBO;
c = ic->ic_prevchan;
@@ -987,13 +1241,7 @@
(c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)
return c;
/* brute force search */
- for (i = 0; i < ic->ic_nchans; i++) {
- c = &ic->ic_channels[i];
- if (c->ic_freq == freq &&
- (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)
- return c;
- }
- return NULL;
+ return (findchannel(ic->ic_channels, ic->ic_nchans, freq, flags));
}
/*
Index: head/sys/net80211/ieee80211_regdomain.c
===================================================================
--- head/sys/net80211/ieee80211_regdomain.c
+++ head/sys/net80211/ieee80211_regdomain.c
@@ -98,22 +98,14 @@
{
}
-static void
-addchan(struct ieee80211com *ic, int ieee, int flags)
-{
- struct ieee80211_channel *c;
-
- c = &ic->ic_channels[ic->ic_nchans++];
- c->ic_freq = ieee80211_ieee2mhz(ieee, flags);
- c->ic_ieee = ieee;
- c->ic_flags = flags;
- if (flags & IEEE80211_CHAN_HT40U)
- c->ic_extieee = ieee + 4;
- else if (flags & IEEE80211_CHAN_HT40D)
- c->ic_extieee = ieee - 4;
- else
- c->ic_extieee = 0;
-}
+static const uint8_t def_chan_2ghz[] =
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
+static const uint8_t def_chan_5ghz_band1[] =
+ { 36, 40, 44, 48, 52, 56, 60, 64 };
+static const uint8_t def_chan_5ghz_band2[] =
+ { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 };
+static const uint8_t def_chan_5ghz_band3[] =
+ { 149, 153, 157, 161 };
/*
* Setup the channel list for the specified regulatory domain,
@@ -125,82 +117,34 @@
ieee80211_init_channels(struct ieee80211com *ic,
const struct ieee80211_regdomain *rd, const uint8_t bands[])
{
- int i;
+ struct ieee80211_channel *chans = ic->ic_channels;
+ int *nchans = &ic->ic_nchans;
+ int ht40;
/* XXX just do something for now */
- ic->ic_nchans = 0;
+ ht40 = !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40);
+ *nchans = 0;
if (isset(bands, IEEE80211_MODE_11B) ||
isset(bands, IEEE80211_MODE_11G) ||
isset(bands, IEEE80211_MODE_11NG)) {
- int maxchan = 11;
- if (rd != NULL && rd->ecm)
- maxchan = 14;
- for (i = 1; i <= maxchan; i++) {
- if (isset(bands, IEEE80211_MODE_11B))
- addchan(ic, i, IEEE80211_CHAN_B);
- if (isset(bands, IEEE80211_MODE_11G))
- addchan(ic, i, IEEE80211_CHAN_G);
- if (isset(bands, IEEE80211_MODE_11NG)) {
- addchan(ic, i,
- IEEE80211_CHAN_G | IEEE80211_CHAN_HT20);
- }
- if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) == 0)
- continue;
- if (i <= 7) {
- addchan(ic, i,
- IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U);
- addchan(ic, i + 4,
- IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D);
- }
- }
+ int nchan = nitems(def_chan_2ghz);
+ if (!(rd != NULL && rd->ecm))
+ nchan -= 3;
+
+ ieee80211_add_channel_list_2ghz(chans, IEEE80211_CHAN_MAX,
+ nchans, def_chan_2ghz, nchan, bands, ht40);
}
if (isset(bands, IEEE80211_MODE_11A) ||
isset(bands, IEEE80211_MODE_11NA)) {
- for (i = 36; i <= 64; i += 4) {
- addchan(ic, i, IEEE80211_CHAN_A);
- if (isset(bands, IEEE80211_MODE_11NA)) {
- addchan(ic, i,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT20);
- }
- if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) == 0)
- continue;
- if ((i % 8) == 4) {
- addchan(ic, i,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U);
- addchan(ic, i + 4,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D);
- }
- }
- for (i = 100; i <= 140; i += 4) {
- addchan(ic, i, IEEE80211_CHAN_A);
- if (isset(bands, IEEE80211_MODE_11NA)) {
- addchan(ic, i,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT20);
- }
- if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) == 0)
- continue;
- if ((i % 8) == 4 && i != 140) {
- addchan(ic, i,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U);
- addchan(ic, i + 4,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D);
- }
- }
- for (i = 149; i <= 161; i += 4) {
- addchan(ic, i, IEEE80211_CHAN_A);
- if (isset(bands, IEEE80211_MODE_11NA)) {
- addchan(ic, i,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT20);
- }
- if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) == 0)
- continue;
- if ((i % 8) == 5) {
- addchan(ic, i,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U);
- addchan(ic, i + 4,
- IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D);
- }
- }
+ ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX,
+ nchans, def_chan_5ghz_band1, nitems(def_chan_5ghz_band1),
+ bands, ht40);
+ ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX,
+ nchans, def_chan_5ghz_band2, nitems(def_chan_5ghz_band2),
+ bands, ht40);
+ ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX,
+ nchans, def_chan_5ghz_band3, nitems(def_chan_5ghz_band3),
+ bands, ht40);
}
if (rd != NULL)
ic->ic_regdomain = *rd;
Index: head/sys/net80211/ieee80211_var.h
===================================================================
--- head/sys/net80211/ieee80211_var.h
+++ head/sys/net80211/ieee80211_var.h
@@ -723,6 +723,14 @@
int ieee80211_chan2ieee(struct ieee80211com *,
const struct ieee80211_channel *);
u_int ieee80211_ieee2mhz(u_int, u_int);
+int ieee80211_add_channel(struct ieee80211_channel[], int, int *,
+ uint8_t, uint16_t, int8_t, uint32_t, const uint8_t[]);
+int ieee80211_add_channel_ht40(struct ieee80211_channel[], int, int *,
+ uint8_t, int8_t, uint32_t);
+int ieee80211_add_channel_list_2ghz(struct ieee80211_channel[], int, int *,
+ const uint8_t[], int, const uint8_t[], int);
+int ieee80211_add_channel_list_5ghz(struct ieee80211_channel[], int, int *,
+ const uint8_t[], int, const uint8_t[], int);
struct ieee80211_channel *ieee80211_find_channel(struct ieee80211com *,
int freq, int flags);
struct ieee80211_channel *ieee80211_find_channel_byieee(struct ieee80211com *,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 21, 12:17 PM (18 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15541274
Default Alt Text
D6124.id15743.diff (12 KB)
Attached To
Mode
D6124: net80211: provide a set of ieee80211_add_channel*() functions
Attached
Detach File
Event Timeline
Log In to Comment