static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
- const char *band)
+ const char *bands)
{
union wpa_event_data event;
- enum set_band setband;
-
- if (os_strcmp(band, "AUTO") == 0)
- setband = WPA_SETBAND_AUTO;
- else if (os_strcmp(band, "5G") == 0)
- setband = WPA_SETBAND_5G;
- else if (os_strcmp(band, "2G") == 0)
- setband = WPA_SETBAND_2G;
- else
- return -1;
+ u32 setband_mask = WPA_SETBAND_AUTO;
+
+ /*
+ * For example:
+ * SET setband 2G,6G
+ * SET setband 5G
+ * SET setband AUTO
+ */
+ if (!os_strstr(bands, "AUTO")) {
+ if (os_strstr(bands, "5G"))
+ setband_mask |= WPA_SETBAND_5G;
+ if (os_strstr(bands, "6G"))
+ setband_mask |= WPA_SETBAND_6G;
+ if (os_strstr(bands, "2G"))
+ setband_mask |= WPA_SETBAND_2G;
+ if (setband_mask == WPA_SETBAND_AUTO)
+ return -1;
+ }
- if (hostapd_drv_set_band(hapd, setband) == 0) {
+ if (hostapd_drv_set_band(hapd, setband_mask) == 0) {
os_memset(&event, 0, sizeof(event));
event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
}
static inline int
-hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band)
+hostapd_drv_set_band(struct hostapd_data *hapd, u32 band_mask)
{
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
return -1;
- return hapd->driver->set_band(hapd->drv_priv, band);
+ return hapd->driver->set_band(hapd->drv_priv, band_mask);
}
#endif /* AP_DRV_OPS */
};
enum set_band {
- WPA_SETBAND_AUTO,
- WPA_SETBAND_5G,
- WPA_SETBAND_2G
+ WPA_SETBAND_AUTO = 0,
+ WPA_SETBAND_5G = BIT(0),
+ WPA_SETBAND_2G = BIT(1),
+ WPA_SETBAND_6G = BIT(2),
};
enum wpa_radio_work_band {
int (*do_acs)(void *priv, struct drv_acs_params *params);
/**
- * set_band - Notify driver of band selection
+ * set_band - Notify driver of band(s) selection
* @priv: Private driver interface data
- * @band: The selected band(s)
+ * @band_mask: The selected band(s) bit mask (from enum set_band)
* Returns 0 on success, -1 on failure
*/
- int (*set_band)(void *priv, enum set_band band);
+ int (*set_band)(void *priv, u32 band_mask);
/**
* get_pref_freq_list - Get preferred frequency list for an interface
}
-static int nl80211_set_band(void *priv, enum set_band band)
+static int nl80211_set_band(void *priv, u32 band_mask)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
struct nlattr *data;
int ret;
- enum qca_set_band qca_band;
+ enum qca_set_band qca_band_value;
+ u32 qca_band_mask = QCA_SETBAND_AUTO;
- if (!drv->setband_vendor_cmd_avail)
+ if (!drv->setband_vendor_cmd_avail ||
+ (band_mask > (WPA_SETBAND_2G | WPA_SETBAND_5G | WPA_SETBAND_6G)))
return -1;
- switch (band) {
- case WPA_SETBAND_AUTO:
- qca_band = QCA_SETBAND_AUTO;
- break;
- case WPA_SETBAND_5G:
- qca_band = QCA_SETBAND_5G;
- break;
- case WPA_SETBAND_2G:
- qca_band = QCA_SETBAND_2G;
- break;
- default:
- return -1;
- }
+ if (band_mask & WPA_SETBAND_5G)
+ qca_band_mask |= QCA_SETBAND_5G;
+ if (band_mask & WPA_SETBAND_2G)
+ qca_band_mask |= QCA_SETBAND_2G;
+ if (band_mask & WPA_SETBAND_6G)
+ qca_band_mask |= QCA_SETBAND_6G;
+
+ /*
+ * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE is a legacy interface hence make
+ * it suite to its values (AUTO/5G/2G) for backwards compatibility.
+ */
+ qca_band_value = ((qca_band_mask & QCA_SETBAND_5G) &&
+ (qca_band_mask & QCA_SETBAND_2G)) ?
+ QCA_SETBAND_AUTO :
+ qca_band_mask & ~QCA_SETBAND_6G;
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: QCA_BAND_MASK = 0x%x, QCA_BAND_VALUE = %d",
+ qca_band_mask, qca_band_value);
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
QCA_NL80211_VENDOR_SUBCMD_SETBAND) ||
!(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
- nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, qca_band)) {
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE,
+ qca_band_value) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_MASK,
+ qca_band_mask)) {
nlmsg_free(msg);
return -ENOBUFS;
}
}
-static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
+static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
{
union wpa_event_data event;
+ u32 setband_mask = WPA_SETBAND_AUTO;
- if (os_strcmp(band, "AUTO") == 0)
- wpa_s->setband = WPA_SETBAND_AUTO;
- else if (os_strcmp(band, "5G") == 0)
- wpa_s->setband = WPA_SETBAND_5G;
- else if (os_strcmp(band, "2G") == 0)
- wpa_s->setband = WPA_SETBAND_2G;
- else
- return -1;
+ /*
+ * For example:
+ * SET setband 2G,6G
+ * SET setband 5G
+ * SET setband AUTO
+ */
+ if (!os_strstr(bands, "AUTO")) {
+ if (os_strstr(bands, "5G"))
+ setband_mask |= WPA_SETBAND_5G;
+ if (os_strstr(bands, "6G"))
+ setband_mask |= WPA_SETBAND_6G;
+ if (os_strstr(bands, "2G"))
+ setband_mask |= WPA_SETBAND_2G;
+ if (setband_mask == WPA_SETBAND_AUTO)
+ return -1;
+ }
- if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
+ wpa_s->setband_mask = setband_mask;
+ if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
os_memset(&event, 0, sizeof(event));
event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
#endif /* CONFIG_MACSEC */
static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s,
- enum set_band band)
+ u32 band_mask)
{
if (!wpa_s->driver->set_band)
return -1;
- return wpa_s->driver->set_band(wpa_s->drv_priv, band);
+ return wpa_s->driver->set_band(wpa_s->drv_priv, band_mask);
}
static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s,
if (params->freqs)
return; /* already using a limited channel set */
- if (wpa_s->setband == WPA_SETBAND_5G)
+ if (wpa_s->setband_mask & WPA_SETBAND_5G)
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
0);
- else if (wpa_s->setband == WPA_SETBAND_2G)
+ if (wpa_s->setband_mask & WPA_SETBAND_2G)
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
0);
+ if (wpa_s->setband_mask & WPA_SETBAND_6G)
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
+ 1);
}
wpa_s->parent = parent ? parent : wpa_s;
wpa_s->p2pdev = wpa_s->parent;
wpa_s->sched_scanning = 0;
+ wpa_s->setband_mask = WPA_SETBAND_AUTO;
dl_list_init(&wpa_s->bss_tmp_disallowed);
dl_list_init(&wpa_s->fils_hlp_req);
struct wpa_ssid_value *disallow_aps_ssid;
size_t disallow_aps_ssid_count;
- enum set_band setband;
+ u32 setband_mask;
/* Preferred network for the next connection attempt */
struct wpa_ssid *next_ssid;