drivers: wifi: siwx91x: Add Access Point (AP) mode support This commit introduces Access Point (AP) mode support It enables the following AP-related commands: - ap enable: Enable the AP mode. - ap disable: Disable the AP mode. Signed-off-by: Arunmani Alagarsamy <arunmani.a@silabs.com>
diff --git a/drivers/wifi/siwx91x/siwx91x_wifi.c b/drivers/wifi/siwx91x/siwx91x_wifi.c index 7b85ca7..eb829fd 100644 --- a/drivers/wifi/siwx91x/siwx91x_wifi.c +++ b/drivers/wifi/siwx91x/siwx91x_wifi.c
@@ -16,6 +16,7 @@ #include "sl_net_constants.h" #include "sl_wifi_types.h" #include "sl_wifi_callback_framework.h" +#include "sl_net_default_values.h" #include "sl_wifi.h" #include "sl_net.h" @@ -39,6 +40,34 @@ 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_security(enum wifi_security_type security) +{ + switch (security) { + case WIFI_SECURITY_TYPE_NONE: + return SL_WIFI_OPEN; + case WIFI_SECURITY_TYPE_WPA_PSK: + return SL_WIFI_WPA; + case WIFI_SECURITY_TYPE_PSK: + return SL_WIFI_WPA2; + default: + return -EINVAL; + } +} + static unsigned int siwx91x_on_join(sl_wifi_event_t event, char *result, uint32_t result_size, void *arg) { @@ -64,6 +93,91 @@ return 0; } +static int siwx91x_ap_enable(const struct device *dev, struct wifi_connect_req_params *params) +{ + 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"; + sl_status_t ret; + int sec; + + sl_wifi_ap_configuration_t siwx91x_ap_cfg = { + .credential_id = SL_NET_DEFAULT_WIFI_AP_CREDENTIAL_ID, + .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, + .tdi_flags = SL_WIFI_TDI_NONE, + .client_idle_timeout = 0xFF, + .beacon_interval = 100, + .dtim_beacon_count = 3, + .maximum_clients = 4, + .beacon_stop = 0, + .options = 0, + .is_11n_enabled = 1, + }; + + if (params->band != WIFI_FREQ_BAND_UNKNOWN && params->band != WIFI_FREQ_BAND_2_4_GHZ) { + 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 (siwx91x_bandwidth(params->bandwidth) < 0) { + return -EINVAL; + } + + siwx91x_ap_cfg.channel.bandwidth = siwx91x_bandwidth(params->bandwidth); + strncpy(siwx91x_ap_cfg.ssid.value, params->ssid, params->ssid_length); + + sec = siwx91x_security(params->security); + if (sec < 0) { + return -EINVAL; + } + + 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)); + } else { + ret = sl_net_set_credential(siwx91x_ap_cfg.credential_id, SL_NET_WIFI_PSK, + params->psk, params->psk_length); + } + + if (ret != SL_STATUS_OK) { + return -EINVAL; + } + + 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); + return -EIO; + } + + sidev->state = WIFI_STATE_COMPLETED; + return 0; +} + +static int siwx91x_ap_disable(const struct device *dev) +{ + struct siwx91x_dev *sidev = dev->data; + int ret; + + ret = sl_wifi_stop_ap(SL_WIFI_AP_2_4GHZ_INTERFACE); + if (ret) { + LOG_ERR("Failed to disable Wi-Fi AP mode: 0x%x", ret); + return -EIO; + } + + sidev->state = WIFI_STATE_INTERFACE_DISABLED; + return ret; +} + static int siwx91x_connect(const struct device *dev, struct wifi_connect_req_params *params) { sl_wifi_client_configuration_t wifi_config = { @@ -434,7 +548,6 @@ sl_wifi_set_scan_callback(siwx91x_on_scan, sidev); sl_wifi_set_join_callback(siwx91x_on_join, sidev); - status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, &sidev->macaddr); if (status) { LOG_ERR("sl_wifi_get_mac_address(): %#04x", status); @@ -454,11 +567,13 @@ } static const struct wifi_mgmt_ops siwx91x_mgmt = { - .scan = siwx91x_scan, - .connect = siwx91x_connect, - .disconnect = siwx91x_disconnect, - .iface_status = siwx91x_status, - .mode = siwx91x_mode, + .scan = siwx91x_scan, + .connect = siwx91x_connect, + .disconnect = siwx91x_disconnect, + .ap_enable = siwx91x_ap_enable, + .ap_disable = siwx91x_ap_disable, + .iface_status = siwx91x_status, + .mode = siwx91x_mode, }; static const struct net_wifi_mgmt_offload siwx91x_api = {