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 config WIFI_SILABS_SIWX91X_ADV_MULTIPROBE
int "Advanced multiprobe setting" int "Advanced multiprobe setting"
default 0 default 1
help help
Configure the advanced multiprobe setting for WiFi scanning. Configure the advanced multiprobe setting for WiFi scanning.
When set to 1, multiple probe requests will be sent to all access 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; 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) static int siwx91x_map_ap_security(enum wifi_security_type security)
{ {
switch (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) 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 = { }; sl_si91x_rsp_wireless_info_t wlan_info = { };
struct siwx91x_dev *sidev = dev->data; struct siwx91x_dev *sidev = dev->data;
uint8_t join_config; uint8_t join_config;
sl_wifi_interface_t interface;
int32_t rssi; int32_t rssi;
int ret; int ret;
@ -170,7 +156,6 @@ static int siwx91x_status(const struct device *dev, struct wifi_iface_status *st
return 0; return 0;
} }
interface = sl_wifi_get_default_interface();
ret = sl_wifi_get_wireless_info(&wlan_info); ret = sl_wifi_get_wireless_info(&wlan_info);
if (ret) { if (ret) {
LOG_ERR("Failed to get the wireless info: 0x%x", 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) static int siwx91x_disconnect(const struct device *dev)
{ {
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
struct siwx91x_dev *sidev = dev->data; struct siwx91x_dev *sidev = dev->data;
int ret; int ret;
ret = sl_wifi_disconnect(SL_WIFI_CLIENT_INTERFACE); if (sidev->state != WIFI_STATE_COMPLETED) {
if (ret) { 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; return -EIO;
} }
if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X_NET_STACK_NATIVE)) { if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X_NET_STACK_NATIVE)) {
net_if_dormant_on(sidev->iface); net_if_dormant_on(sidev->iface);
} }
sidev->state = WIFI_STATE_DISCONNECTED; sidev->state = WIFI_STATE_DISCONNECTED;
return 0; return 0;
} }
static int siwx91x_ap_disable(const struct device *dev) 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; struct siwx91x_dev *sidev = dev->data;
int ret; int ret;
ret = sl_wifi_stop_ap(SL_WIFI_AP_2_4GHZ_INTERFACE); ret = sl_wifi_stop_ap(interface);
if (ret) { if (ret) {
LOG_ERR("Failed to disable Wi-Fi AP mode: 0x%x", ret); LOG_ERR("Failed to disable Wi-Fi AP mode: 0x%x", ret);
return -EIO; 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) 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; struct siwx91x_dev *sidev = dev->data;
/* Wiseconnect requires a valid PSK even if WIFI_SECURITY_TYPE_NONE is selected */ /* Wiseconnect requires a valid PSK even if WIFI_SECURITY_TYPE_NONE is selected */
static const char dummy_psk[] = "dummy_value"; 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, .keepalive_type = SL_SI91X_AP_NULL_BASED_KEEP_ALIVE,
.rate_protocol = SL_WIFI_RATE_PROTOCOL_AUTO, .rate_protocol = SL_WIFI_RATE_PROTOCOL_AUTO,
.encryption = SL_WIFI_DEFAULT_ENCRYPTION, .encryption = SL_WIFI_DEFAULT_ENCRYPTION,
.ssid.length = params->ssid_length, .channel.bandwidth = SL_WIFI_BANDWIDTH_20MHz,
.tdi_flags = SL_WIFI_TDI_NONE, .tdi_flags = SL_WIFI_TDI_NONE,
.client_idle_timeout = 0xFF, .client_idle_timeout = 0xFF,
.beacon_interval = 100, .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, .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) { if (sidev->state == WIFI_STATE_COMPLETED) {
ret = siwx91x_ap_disable_if_required(dev, params); ret = siwx91x_ap_disable_if_required(dev, params);
if (ret < 0) { 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) { if (params->band != WIFI_FREQ_BAND_UNKNOWN && params->band != WIFI_FREQ_BAND_2_4_GHZ) {
LOG_ERR("Unsupported band");
return -ENOTSUP; return -ENOTSUP;
} }
if (params->channel == WIFI_CHANNEL_ANY) { if (params->bandwidth != WIFI_FREQ_BANDWIDTH_20MHZ) {
siwx91x_ap_cfg.channel.channel = SL_WIFI_AUTO_CHANNEL; LOG_ERR("Unsupported bandwidth");
} else { return -ENOTSUP;
siwx91x_ap_cfg.channel.channel = params->channel;
} }
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; 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); sec = siwx91x_map_ap_security(params->security);
if (sec < 0) { if (sec < 0) {
LOG_ERR("Invalid security type"); 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; siwx91x_ap_cfg.security = sec;
if (params->security == WIFI_SECURITY_TYPE_NONE) { if (params->security == WIFI_SECURITY_TYPE_NONE) {
ret = sl_net_set_credential(siwx91x_ap_cfg.credential_id, SL_NET_WIFI_PSK, ret = sl_net_set_credential(siwx91x_ap_cfg.credential_id, SL_NET_WIFI_PSK,
dummy_psk, strlen(dummy_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; 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) { if (params->mfp != WIFI_MFP_DISABLE) {
LOG_WRN("Needed MFP disable but got MFP %s, hence setting to MFP disable", LOG_WRN("Needed MFP disable but got MFP %s, hence setting to MFP disable",
wifi_mfp_txt(params->mfp)); 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); ret = sl_wifi_start_ap(SL_WIFI_AP_INTERFACE | SL_WIFI_2_4GHZ_INTERFACE, &siwx91x_ap_cfg);
if (ret != SL_STATUS_OK) { if (ret != SL_STATUS_OK) {
LOG_ERR("Failed to enable AP mode: 0x%x", ret); 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) static int siwx91x_ap_sta_disconnect(const struct device *dev, const uint8_t *mac_addr)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
sl_mac_address_t mac = { }; sl_mac_address_t mac = { };
int ret; int ret;
__ASSERT(mac_addr, "mac_addr cannot be NULL"); __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)); memcpy(mac.octet, mac_addr, ARRAY_SIZE(mac.octet));
ret = sl_wifi_disconnect_ap_client(SL_WIFI_AP_INTERFACE | SL_WIFI_2_4GHZ_INTERFACE, 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) 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 = { sl_wifi_client_configuration_t wifi_config = {
.bss_type = SL_WIFI_BSS_TYPE_INFRASTRUCTURE, .bss_type = SL_WIFI_BSS_TYPE_INFRASTRUCTURE,
.encryption = SL_WIFI_DEFAULT_ENCRYPTION, .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, wifi_config.ssid.length = params->ssid_length,
memcpy(wifi_config.ssid.value, params->ssid, 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) { if (ret != SL_STATUS_IN_PROGRESS) {
return -EIO; 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, static int siwx91x_scan(const struct device *dev, struct wifi_scan_params *z_scan_config,
scan_result_cb_t cb) 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_scan_configuration_t sl_scan_config = { };
sl_wifi_advanced_scan_configuration_t advanced_scan_config = { sl_wifi_advanced_scan_configuration_t advanced_scan_config = {
.trigger_level = CONFIG_WIFI_SILABS_SIWX91X_ADV_SCAN_THRESHOLD, .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 #endif
}; };
struct siwx91x_dev *sidev = dev->data; struct siwx91x_dev *sidev = dev->data;
sl_wifi_interface_t interface;
sl_wifi_ssid_t ssid = { }; sl_wifi_ssid_t ssid = { };
int ret; int ret;
__ASSERT(z_scan_config, "z_scan_config cannot be NULL"); __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) { if (FIELD_GET(SIWX91X_INTERFACE_MASK, interface) != SL_WIFI_CLIENT_INTERFACE) {
LOG_ERR("Interface not in STA mode"); LOG_ERR("Interface not in STA mode");
return -EINVAL; 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) static int siwx91x_stats(const struct device *dev, struct net_stats_wifi *stats)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
sl_wifi_interface_t interface; sl_wifi_interface_t interface = sl_wifi_get_default_interface();
sl_wifi_statistics_t statistics = { }; sl_wifi_statistics_t statistics = { };
int ret; int ret;
__ASSERT(stats, "stats cannot be NULL"); __ASSERT(stats, "stats cannot be NULL");
interface = sl_wifi_get_default_interface();
ret = sl_wifi_get_statistics(FIELD_GET(SIWX91X_INTERFACE_MASK, interface), &statistics); ret = sl_wifi_get_statistics(FIELD_GET(SIWX91X_INTERFACE_MASK, interface), &statistics);
if (ret) { if (ret) {
LOG_ERR("Failed to get stat: 0x%x", ret); LOG_ERR("Failed to get stat: 0x%x", ret);