#define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
#define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
+#define HOSTAPD_CHAN_AUTO_BW 0x00040000
/* Allowed bandwidth mask */
enum hostapd_chan_width_attr {
static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
- int end, int max_bw)
+ int end, int max_bw, u32 flags)
{
int c;
if (max_bw >= 160)
chan->flag |= HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL;
+
+ if (flags & NL80211_RRF_AUTO_BW)
+ chan->flag |= HOSTAPD_CHAN_AUTO_BW;
}
}
static void nl80211_reg_rule_vht(struct nlattr *tb[],
struct phy_info_arg *results)
{
- u32 start, end, max_bw;
+ u32 start, end, max_bw, flags = 0;
u16 m;
if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
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 (tb[NL80211_ATTR_REG_RULE_FLAGS])
+ flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
+
if (max_bw < 80)
return;
if (!results->modes[m].vht_capab)
continue;
- nl80211_set_vht_mode(&results->modes[m], start, end, max_bw);
+ nl80211_set_vht_mode(&results->modes[m], start, end,
+ max_bw, flags);
}
}
return NOT_ALLOWED;
if (!(flags & HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL) ||
- !(flags & HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL))
+ (!(flags & HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL) &&
+ !(flags & HOSTAPD_CHAN_AUTO_BW)))
return NOT_ALLOWED;
if (flags & HOSTAPD_CHAN_NO_IR)
if (!is_6ghz_op_class(op_class)) {
if (!(flags & HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL) ||
- !(flags & HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL))
+ (!(flags & HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL) &&
+ !(flags & HOSTAPD_CHAN_AUTO_BW)))
return NOT_ALLOWED;
} else if (is_6ghz_op_class(op_class) &&
(!(wpas_get_6ghz_he_chwidth_capab(mode) &