diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 5a21af296..26b6fa3ee 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -58,6 +58,16 @@ #define HOSTAPD_CHAN_VHT_130_30 0x04000000 #define HOSTAPD_CHAN_VHT_150_10 0x08000000 +/* Allowed bandwidth mask */ +enum hostapd_chan_width_attr { + HOSTAPD_CHAN_WIDTH_10 = BIT(0), + HOSTAPD_CHAN_WIDTH_20 = BIT(1), + HOSTAPD_CHAN_WIDTH_40P = BIT(2), + HOSTAPD_CHAN_WIDTH_40M = BIT(3), + HOSTAPD_CHAN_WIDTH_80 = BIT(4), + HOSTAPD_CHAN_WIDTH_160 = BIT(5), +}; + /* Filter gratuitous ARP */ #define WPA_DATA_FRAME_FILTER_FLAG_ARP BIT(0) /* Filter unsolicited Neighbor Advertisement */ @@ -110,6 +120,13 @@ struct hostapd_channel_data { */ int flag; + /** + * allowed_bw - Allowed channel width bitmask + * + * See enum hostapd_chan_width_attr. + */ + u32 allowed_bw; + /** * max_tx_power - Regulatory transmit power limit in dBm */ diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index 3f33bb5fb..61b39b197 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -1131,6 +1131,7 @@ static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv, for (i = 0; i < 14; i++) { mode->channels[i].chan = i + 1; mode->channels[i].freq = chan2freq[i]; + mode->channels[i].allowed_bw = HOSTAPD_CHAN_WIDTH_20; /* TODO: Get allowed channel list from the driver */ if (i >= 11) mode->channels[i].flag = HOSTAPD_CHAN_DISABLED; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 9039f57c2..084db0bd1 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1441,6 +1441,7 @@ static void phy_info_freq(struct hostapd_hw_modes *mode, u8 channel; chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); chan->flag = 0; + chan->allowed_bw = ~0; chan->dfs_cac_ms = 0; if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES) chan->chan = channel; @@ -1456,6 +1457,19 @@ static void phy_info_freq(struct hostapd_hw_modes *mode, if (tb_freq[NL80211_FREQUENCY_ATTR_GO_CONCURRENT]) chan->flag |= HOSTAPD_CHAN_GO_CONCURRENT; + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_10MHZ]) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_10; + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_20MHZ]) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_20; + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_HT40_PLUS]) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_40P; + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_HT40_MINUS]) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_40M; + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_80MHZ]) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_80; + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_160MHZ]) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_160; + if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) { enum nl80211_dfs_state state = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]); @@ -1490,6 +1504,12 @@ static int phy_info_freqs(struct phy_info_arg *phy_info, [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, [NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 }, + [NL80211_FREQUENCY_ATTR_NO_10MHZ] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_NO_20MHZ] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_NO_HT40_PLUS] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_NO_HT40_MINUS] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_NO_80MHZ] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_NO_160MHZ] = { .type = NLA_FLAG }, }; int new_channels = 0; struct hostapd_channel_data *channel;