drivers: wifi: siwx91x: Add interface state validation

This patch introduces validation checks to ensure Wi-Fi commands are
executed only when the device is in a valid operational mode.

- Restricts command execution if the device is not in an appropriate mode
- Prevents reconfiguring the device when it is already in an active state
- Enabled Advanced multiprobe setting as default.

Signed-off-by: Arunmani Alagarsamy <arunmani.a@silabs.com>
This commit is contained in:
Arunmani Alagarsamy 2025-03-22 16:40:17 +05:30 committed by Benjamin Cabé
commit c8a29b3038
2 changed files with 47 additions and 35 deletions

View file

@ -131,7 +131,7 @@ config WIFI_SILABS_SIWX91X_ADV_PASSIVE_SCAN_DURATION
config WIFI_SILABS_SIWX91X_ADV_MULTIPROBE
int "Advanced multiprobe setting"
default 0
default 1
help
Configure the advanced multiprobe setting for WiFi scanning.
When set to 1, multiple probe requests will be sent to all access

View file

@ -48,20 +48,6 @@ static int siwx91x_sl_to_z_mode(sl_wifi_interface_t interface)
return 0;
}
static int siwx91x_bandwidth(enum wifi_frequency_bandwidths bandwidth)
{
switch (bandwidth) {
case WIFI_FREQ_BANDWIDTH_20MHZ:
return SL_WIFI_BANDWIDTH_20MHz;
case WIFI_FREQ_BANDWIDTH_40MHZ:
return SL_WIFI_BANDWIDTH_40MHz;
case WIFI_FREQ_BANDWIDTH_80MHZ:
return SL_WIFI_BANDWIDTH_80MHz;
default:
return -EINVAL;
}
}
static int siwx91x_map_ap_security(enum wifi_security_type security)
{
switch (security) {
@ -154,10 +140,10 @@ static unsigned int siwx91x_on_join(sl_wifi_event_t event,
static int siwx91x_status(const struct device *dev, struct wifi_iface_status *status)
{
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
sl_si91x_rsp_wireless_info_t wlan_info = { };
struct siwx91x_dev *sidev = dev->data;
uint8_t join_config;
sl_wifi_interface_t interface;
int32_t rssi;
int ret;
@ -170,7 +156,6 @@ static int siwx91x_status(const struct device *dev, struct wifi_iface_status *st
return 0;
}
interface = sl_wifi_get_default_interface();
ret = sl_wifi_get_wireless_info(&wlan_info);
if (ret) {
LOG_ERR("Failed to get the wireless info: 0x%x", ret);
@ -272,26 +257,36 @@ static int siwx91x_status(const struct device *dev, struct wifi_iface_status *st
static int siwx91x_disconnect(const struct device *dev)
{
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
struct siwx91x_dev *sidev = dev->data;
int ret;
ret = sl_wifi_disconnect(SL_WIFI_CLIENT_INTERFACE);
if (ret) {
if (sidev->state != WIFI_STATE_COMPLETED) {
LOG_ERR("Command given in invalid state");
return -EBUSY;
}
ret = sl_wifi_disconnect(interface);
if (ret != SL_STATUS_OK) {
LOG_ERR("Failed to disconnect: 0x%x", ret);
return -EIO;
}
if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X_NET_STACK_NATIVE)) {
net_if_dormant_on(sidev->iface);
}
sidev->state = WIFI_STATE_DISCONNECTED;
return 0;
}
static int siwx91x_ap_disable(const struct device *dev)
{
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
struct siwx91x_dev *sidev = dev->data;
int ret;
ret = sl_wifi_stop_ap(SL_WIFI_AP_2_4GHZ_INTERFACE);
ret = sl_wifi_stop_ap(interface);
if (ret) {
LOG_ERR("Failed to disable Wi-Fi AP mode: 0x%x", ret);
return -EIO;
@ -393,6 +388,7 @@ static int siwx91x_disconnect_if_required(const struct device *dev,
static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_params *params)
{
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
struct siwx91x_dev *sidev = dev->data;
/* Wiseconnect requires a valid PSK even if WIFI_SECURITY_TYPE_NONE is selected */
static const char dummy_psk[] = "dummy_value";
@ -404,7 +400,7 @@ static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_p
.keepalive_type = SL_SI91X_AP_NULL_BASED_KEEP_ALIVE,
.rate_protocol = SL_WIFI_RATE_PROTOCOL_AUTO,
.encryption = SL_WIFI_DEFAULT_ENCRYPTION,
.ssid.length = params->ssid_length,
.channel.bandwidth = SL_WIFI_BANDWIDTH_20MHz,
.tdi_flags = SL_WIFI_TDI_NONE,
.client_idle_timeout = 0xFF,
.beacon_interval = 100,
@ -415,6 +411,11 @@ static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_p
.is_11n_enabled = 1,
};
if (FIELD_GET(SIWX91X_INTERFACE_MASK, interface) != SL_WIFI_AP_INTERFACE) {
LOG_ERR("Interface not in AP mode");
return -EINVAL;
}
if (sidev->state == WIFI_STATE_COMPLETED) {
ret = siwx91x_ap_disable_if_required(dev, params);
if (ret < 0) {
@ -423,22 +424,20 @@ static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_p
}
if (params->band != WIFI_FREQ_BAND_UNKNOWN && params->band != WIFI_FREQ_BAND_2_4_GHZ) {
LOG_ERR("Unsupported band");
return -ENOTSUP;
}
if (params->channel == WIFI_CHANNEL_ANY) {
siwx91x_ap_cfg.channel.channel = SL_WIFI_AUTO_CHANNEL;
} else {
siwx91x_ap_cfg.channel.channel = params->channel;
if (params->bandwidth != WIFI_FREQ_BANDWIDTH_20MHZ) {
LOG_ERR("Unsupported bandwidth");
return -ENOTSUP;
}
if (siwx91x_bandwidth(params->bandwidth) < 0) {
if (params->ssid_length == 0 || params->ssid_length > WIFI_SSID_MAX_LEN) {
LOG_ERR("Invalid ssid length");
return -EINVAL;
}
siwx91x_ap_cfg.channel.bandwidth = siwx91x_bandwidth(params->bandwidth);
strncpy(siwx91x_ap_cfg.ssid.value, params->ssid, params->ssid_length);
sec = siwx91x_map_ap_security(params->security);
if (sec < 0) {
LOG_ERR("Invalid security type");
@ -446,7 +445,6 @@ static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_p
}
siwx91x_ap_cfg.security = sec;
if (params->security == WIFI_SECURITY_TYPE_NONE) {
ret = sl_net_set_credential(siwx91x_ap_cfg.credential_id, SL_NET_WIFI_PSK,
dummy_psk, strlen(dummy_psk));
@ -460,11 +458,20 @@ static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_p
return -EINVAL;
}
siwx91x_ap_cfg.ssid.length = params->ssid_length;
strncpy(siwx91x_ap_cfg.ssid.value, params->ssid, params->ssid_length);
if (params->mfp != WIFI_MFP_DISABLE) {
LOG_WRN("Needed MFP disable but got MFP %s, hence setting to MFP disable",
wifi_mfp_txt(params->mfp));
}
if (params->channel == WIFI_CHANNEL_ANY) {
siwx91x_ap_cfg.channel.channel = SL_WIFI_AUTO_CHANNEL;
} else {
siwx91x_ap_cfg.channel.channel = params->channel;
}
ret = sl_wifi_start_ap(SL_WIFI_AP_INTERFACE | SL_WIFI_2_4GHZ_INTERFACE, &siwx91x_ap_cfg);
if (ret != SL_STATUS_OK) {
LOG_ERR("Failed to enable AP mode: 0x%x", ret);
@ -478,11 +485,17 @@ static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_p
static int siwx91x_ap_sta_disconnect(const struct device *dev, const uint8_t *mac_addr)
{
ARG_UNUSED(dev);
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
sl_mac_address_t mac = { };
int ret;
__ASSERT(mac_addr, "mac_addr cannot be NULL");
if (FIELD_GET(SIWX91X_INTERFACE_MASK, interface) != SL_WIFI_AP_INTERFACE) {
LOG_ERR("Interface not in AP mode");
return -EINVAL;
}
memcpy(mac.octet, mac_addr, ARRAY_SIZE(mac.octet));
ret = sl_wifi_disconnect_ap_client(SL_WIFI_AP_INTERFACE | SL_WIFI_2_4GHZ_INTERFACE,
@ -533,6 +546,7 @@ static sl_status_t siwx91x_on_ap_sta_disconnect(sl_wifi_event_t event, void *dat
static int siwx91x_connect(const struct device *dev, struct wifi_connect_req_params *params)
{
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
sl_wifi_client_configuration_t wifi_config = {
.bss_type = SL_WIFI_BSS_TYPE_INFRASTRUCTURE,
.encryption = SL_WIFI_DEFAULT_ENCRYPTION,
@ -620,7 +634,7 @@ static int siwx91x_connect(const struct device *dev, struct wifi_connect_req_par
wifi_config.ssid.length = params->ssid_length,
memcpy(wifi_config.ssid.value, params->ssid, params->ssid_length);
ret = sl_wifi_connect(SL_WIFI_CLIENT_INTERFACE, &wifi_config, 0);
ret = sl_wifi_connect(interface, &wifi_config, 0);
if (ret != SL_STATUS_IN_PROGRESS) {
return -EIO;
}
@ -755,6 +769,7 @@ siwx91x_configure_scan_dwell_time(sl_wifi_scan_type_t scan_type, uint16_t dwell_
static int siwx91x_scan(const struct device *dev, struct wifi_scan_params *z_scan_config,
scan_result_cb_t cb)
{
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
sl_wifi_scan_configuration_t sl_scan_config = { };
sl_wifi_advanced_scan_configuration_t advanced_scan_config = {
.trigger_level = CONFIG_WIFI_SILABS_SIWX91X_ADV_SCAN_THRESHOLD,
@ -772,13 +787,11 @@ static int siwx91x_scan(const struct device *dev, struct wifi_scan_params *z_sca
#endif
};
struct siwx91x_dev *sidev = dev->data;
sl_wifi_interface_t interface;
sl_wifi_ssid_t ssid = { };
int ret;
__ASSERT(z_scan_config, "z_scan_config cannot be NULL");
interface = sl_wifi_get_default_interface();
if (FIELD_GET(SIWX91X_INTERFACE_MASK, interface) != SL_WIFI_CLIENT_INTERFACE) {
LOG_ERR("Interface not in STA mode");
return -EINVAL;
@ -984,13 +997,12 @@ static void siwx91x_ethernet_init(struct net_if *iface)
static int siwx91x_stats(const struct device *dev, struct net_stats_wifi *stats)
{
ARG_UNUSED(dev);
sl_wifi_interface_t interface;
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
sl_wifi_statistics_t statistics = { };
int ret;
__ASSERT(stats, "stats cannot be NULL");
interface = sl_wifi_get_default_interface();
ret = sl_wifi_get_statistics(FIELD_GET(SIWX91X_INTERFACE_MASK, interface), &statistics);
if (ret) {
LOG_ERR("Failed to get stat: 0x%x", ret);