diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h index c488c00..5307346 100644 --- a/sys/net80211/_ieee80211.h +++ b/sys/net80211/_ieee80211.h @@ -205,6 +205,14 @@ struct ieee80211_channel { #define IEEE80211_CHAN_ST \ (IEEE80211_CHAN_108A | IEEE80211_CHAN_STURBO) +/* This is only good for HT20 11ng - adrian */ +#define IEEE80211_CHAN_NG \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_HT20 | IEEE80211_CHAN_DYN) + +/* Again, this is only good for HT20/11na - adrian */ +#define IEEE80211_CHAN_NA \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_HT20 | IEEE80211_CHAN_OFDM) + #define IEEE80211_CHAN_ALL \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_GFSK | \ IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN | \ diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index a1d0c42..84a04bc 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -431,9 +431,9 @@ static const u_int chanflags[IEEE80211_MODE_MAX] = { [IEEE80211_MODE_STURBO_A] = IEEE80211_CHAN_ST, [IEEE80211_MODE_HALF] = IEEE80211_CHAN_HALF, [IEEE80211_MODE_QUARTER] = IEEE80211_CHAN_QUARTER, - /* check legacy */ - [IEEE80211_MODE_11NA] = IEEE80211_CHAN_A, - [IEEE80211_MODE_11NG] = IEEE80211_CHAN_G, + /* check 11NA/11NG HT20 only related flags - HT40 will not currently function with these flags -adrian */ + [IEEE80211_MODE_11NA] = IEEE80211_CHAN_NA, + [IEEE80211_MODE_11NG] = IEEE80211_CHAN_NG, }; static void @@ -942,6 +942,42 @@ tdma_isfull(const struct ieee80211_tdma_param *tdma) #endif /* IEEE80211_SUPPORT_TDMA */ /* + * Match HT channel details. + * + * HT channels need to be treated differently to normal channels - + * multiple flag combinations are possible for the same PHY mode. + * Specifically: + * + 11na - OFDM flag, HT20/HT40U/HT40D flag + * + 11ng - CCK/OFDM (dynamic) flag(s), HT20/HT40U/HT40D flag + * + * The chanflags[] array simply compares values. What we need to do + * here is compare that the mask'ed values match. + */ +static int +match_ht_chan(struct ieee80211vap *vap, struct ieee80211_scan_entry *se) +{ + uint32_t mask; + + /* general flags, everyone wants */ + mask = IEEE80211_CHAN_HT20 | IEEE80211_CHAN_HT40U | IEEE80211_CHAN_HT40D; + + /* Figure out mode specific mask bits */ + switch (vap->iv_des_mode) { + case IEEE80211_MODE_11NA: + mask = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM; + break; + case IEEE80211_MODE_11NG: + mask = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN; + break; + default: + /* XXX shouldn't get here */ + return 0; + } + + return (vap->iv_ic->ic_curchan->ic_flags & mask) == (se->se_chan->ic_flags & mask); +} + +/* * Test a scan candidate for suitability/compatibility. */ static int @@ -964,10 +1000,34 @@ match_bss(struct ieee80211vap *vap, * list so we check the desired mode here to weed them * out. */ - if (vap->iv_des_mode != IEEE80211_MODE_AUTO && + + /* + * For 802.11n channel scanning, should the current desired mode flags + * should match the vap configuration rather than curchan? -adrian + */ + if (vap->iv_des_mode == IEEE80211_MODE_11NA || vap->iv_des_mode == IEEE80211_MODE_11NG) { + if (match_ht_chan(vap, se) <= 0) { + fail |= MATCH_CHANNEL; +#ifdef IEEE80211_DEBUG + if (ieee80211_msg(vap, debug)) { + printf("mode: %d; scan channel flags: %x; curchan flags: %x; curchan %p\n", + vap->iv_des_mode, se->se_chan->ic_flags, + vap->iv_ic->ic_curchan->ic_flags, vap->iv_ic->ic_curchan); + } +#endif + } + } else if (vap->iv_des_mode != IEEE80211_MODE_AUTO && (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) != - chanflags[vap->iv_des_mode]) + chanflags[vap->iv_des_mode]) { fail |= MATCH_CHANNEL; +#ifdef IEEE80211_DEBUG + if (ieee80211_msg(vap, debug)) { + printf("mode: %d; ic_flags: %x; chanflags %x\n", + vap->iv_des_mode, se->se_chan->ic_flags, + chanflags[vap->iv_des_mode]); + } +#endif + } if (vap->iv_opmode == IEEE80211_M_IBSS) { if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0) fail |= MATCH_CAPINFO; diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 5764fa0..e6e49a7 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -404,6 +404,10 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) goto invalid; } ieee80211_sync_curchan(ic); + /* XXX better place? */ + ieee80211_node_set_chan(ni, + ieee80211_ht_adjust_channel(ic, ic->ic_curchan, + ieee80211_htchanflags(ic->ic_curchan))); if (ostate != IEEE80211_S_RUN && (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) { /*