PLINK_BLOCKED,
};
+enum set_band {
+ WPA_SETBAND_AUTO,
+ WPA_SETBAND_5G,
+ WPA_SETBAND_2G
+};
+
#endif /* DEFS_H */
QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG = 102,
QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103,
QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104,
+ QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
};
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10,
/* Unsigned 32-bit value */
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11,
+ /* Unsigned 32-bit value from enum qca_set_band. */
+ QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12,
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
QCA_IFACE_TYPE_TDLS,
};
+enum qca_set_band {
+ QCA_SETBAND_AUTO,
+ QCA_SETBAND_5G,
+ QCA_SETBAND_2G,
+};
+
#endif /* QCA_VENDOR_H */
* indicates support for such offloading (WPA_DRIVER_FLAGS_ACS_OFFLOAD).
*/
int (*do_acs)(void *priv, struct drv_acs_params *params);
+
+ /**
+ * set_band - Notify driver of band selection
+ * @priv: Private driver interface data
+ * @band: The selected band(s)
+ * Returns 0 on success, -1 on failure
+ */
+ int (*set_band)(void *priv, enum set_band band);
};
}
+static int nl80211_set_band(void *priv, enum set_band band)
+{
+ 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;
+
+ if (!drv->setband_vendor_cmd_avail)
+ 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 (!(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)) {
+ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
+ nla_nest_end(msg, data);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Driver setband function failed: %s",
+ strerror(errno));
+ }
+ return ret;
+}
+
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
.add_tx_ts = nl80211_add_ts,
.del_tx_ts = nl80211_del_ts,
.do_acs = wpa_driver_do_acs,
+ .set_band = nl80211_set_band,
};
unsigned int get_features_vendor_cmd_avail:1;
unsigned int set_rekey_offload:1;
unsigned int p2p_go_ctwindow_supported:1;
+ unsigned int setband_vendor_cmd_avail:1;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
drv->capa.flags |=
WPA_DRIVER_FLAGS_ACS_OFFLOAD;
break;
+ case QCA_NL80211_VENDOR_SUBCMD_SETBAND:
+ drv->setband_vendor_cmd_avail = 1;
+ break;
}
}
}
+static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
+{
+ union wpa_event_data event;
+
+ 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;
+
+ if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
+ os_memset(&event, 0, sizeof(event));
+ event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+ event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+ wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
+ }
+
+ return 0;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
ret = wpas_ctrl_set_blob(wpa_s, value);
#endif /* CONFIG_NO_CONFIG_BLOBS */
} else if (os_strcasecmp(cmd, "setband") == 0) {
- if (os_strcmp(value, "AUTO") == 0)
- wpa_s->setband = WPA_SETBAND_AUTO;
- else if (os_strcmp(value, "5G") == 0)
- wpa_s->setband = WPA_SETBAND_5G;
- else if (os_strcmp(value, "2G") == 0)
- wpa_s->setband = WPA_SETBAND_2G;
- else
- ret = -1;
+ ret = wpas_ctrl_set_band(wpa_s, value);
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
}
#endif /* CONFIG_MACSEC */
+static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s,
+ enum set_band band)
+{
+ if (!wpa_s->driver->set_band)
+ return -1;
+ return wpa_s->driver->set_band(wpa_s->drv_priv, band);
+}
+
#endif /* DRIVER_I_H */
struct wpa_ssid_value *disallow_aps_ssid;
size_t disallow_aps_ssid_count;
- enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband;
+ enum set_band setband;
/* Preferred network for the next connection attempt */
struct wpa_ssid *next_ssid;