diff --git a/src/drivers/driver.h b/src/drivers/driver.h index bbaf8eafa..eedc3f647 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -43,6 +43,7 @@ #define HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL 0x00000800 #define HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL 0x00001000 +#define HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL 0x00002000 #define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000 #define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000 diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index cef23b183..3bcd66c24 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -2405,6 +2405,57 @@ static void nl80211_reg_rule_vht(struct nlattr *tb[], } +static void nl80211_set_6ghz_mode(struct hostapd_hw_modes *mode, int start, + int end, int max_bw) +{ + int c; + + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if (chan->freq - 10 < start || chan->freq + 10 > end) + continue; + + if (max_bw >= 80) + chan->flag |= HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL; + + if (max_bw >= 160) + chan->flag |= HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL; + + if (max_bw >= 320) + chan->flag |= HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL; + } +} + + +static void nl80211_reg_rule_6ghz(struct nlattr *tb[], + struct phy_info_arg *results) +{ + u32 start, end, max_bw; + u16 m; + + if (!tb[NL80211_ATTR_FREQ_RANGE_START] || + !tb[NL80211_ATTR_FREQ_RANGE_END] || + !tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) + return; + + start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000; + end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000; + max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000; + + if (max_bw < 80) + return; + + for (m = 0; m < *results->num_modes; m++) { + if (results->modes[m].num_channels == 0 || + !is_6ghz_freq(results->modes[m].channels[0].freq)) + continue; + + nl80211_set_6ghz_mode(&results->modes[m], start, end, max_bw); + } +} + + static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region, u8 *dfs_domain) { @@ -2523,6 +2574,13 @@ static int nl80211_get_reg(struct nl_msg *msg, void *arg) nl80211_reg_rule_vht(tb_rule, results); } + nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) + { + nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX, + nla_data(nl_rule), nla_len(nl_rule), reg_policy); + nl80211_reg_rule_6ghz(tb_rule, results); + } + return NL_SKIP; }