Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1682 lines
44 KiB

/*
* Copyright (c) 2016 Intel Corporation.
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L /* For strnlen() */
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_wifi_mgmt, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL);
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/wifi_mgmt.h>
#ifdef CONFIG_WIFI_NM
#include <zephyr/net/wifi_nm.h>
#endif /* CONFIG_WIFI_NM */
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
#define MAX_NEIGHBOR_AP_LIMIT 6U
#define MAX_EVENT_STR_LEN 32
struct wifi_rrm_neighbor_ap_t {
char ssid[WIFI_SSID_MAX_LEN + 1];
uint8_t bssid[WIFI_SSID_MAX_LEN];
uint8_t bssid_info[WIFI_SSID_MAX_LEN];
int op_class;
int channel;
int phy_type;
};
struct wifi_rrm_neighbor_report_t {
struct wifi_rrm_neighbor_ap_t neighbor_ap[MAX_NEIGHBOR_AP_LIMIT];
int neighbor_cnt;
};
struct wifi_roaming_params {
bool is_11r_used;
bool is_11k_enabled;
struct wifi_rrm_neighbor_report_t neighbor_rep;
};
static struct wifi_roaming_params roaming_params;
#endif
const char *wifi_security_txt(enum wifi_security_type security)
{
switch (security) {
case WIFI_SECURITY_TYPE_NONE:
return "OPEN";
case WIFI_SECURITY_TYPE_PSK:
return "WPA2-PSK";
case WIFI_SECURITY_TYPE_PSK_SHA256:
return "WPA2-PSK-SHA256";
case WIFI_SECURITY_TYPE_SAE_HNP:
return "WPA3-SAE-HNP";
case WIFI_SECURITY_TYPE_SAE_H2E:
return "WPA3-SAE-H2E";
case WIFI_SECURITY_TYPE_SAE_AUTO:
return "WPA3-SAE-AUTO";
case WIFI_SECURITY_TYPE_WAPI:
return "WAPI";
case WIFI_SECURITY_TYPE_EAP_TLS:
return "EAP-TLS";
case WIFI_SECURITY_TYPE_WEP:
return "WEP";
case WIFI_SECURITY_TYPE_WPA_PSK:
return "WPA-PSK";
case WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL:
return "WPA/WPA2/WPA3 PSK";
case WIFI_SECURITY_TYPE_DPP:
return "DPP";
case WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2:
return "EAP-PEAP-MSCHAPV2";
case WIFI_SECURITY_TYPE_EAP_PEAP_GTC:
return "EAP-PEAP-GTC";
case WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2:
return "EAP-TTLS-MSCHAPV2";
case WIFI_SECURITY_TYPE_EAP_PEAP_TLS:
return "EAP-PEAP-TLS";
case WIFI_SECURITY_TYPE_FT_PSK:
return "FT-PSK";
case WIFI_SECURITY_TYPE_FT_SAE:
return "FT-SAE";
case WIFI_SECURITY_TYPE_FT_EAP:
return "FT-EAP";
case WIFI_SECURITY_TYPE_FT_EAP_SHA384:
return "FT-EAP-SHA384";
case WIFI_SECURITY_TYPE_SAE_EXT_KEY:
return "WPA3-SAE-EXT-KEY";
case WIFI_SECURITY_TYPE_UNKNOWN:
default:
return "UNKNOWN";
}
}
const char *wifi_wpa3_enterprise_txt(enum wifi_wpa3_enterprise_type wpa3_ent)
{
switch (wpa3_ent) {
case WIFI_WPA3_ENTERPRISE_SUITEB:
return "WPA3-SuiteB";
case WIFI_WPA3_ENTERPRISE_SUITEB_192:
return "WPA3-SuiteB-192";
case WIFI_WPA3_ENTERPRISE_ONLY:
return "WPA3-Enterprise-Only";
default:
return "";
}
}
const char *wifi_mfp_txt(enum wifi_mfp_options mfp)
{
switch (mfp) {
case WIFI_MFP_DISABLE:
return "Disable";
case WIFI_MFP_OPTIONAL:
return "Optional";
case WIFI_MFP_REQUIRED:
return "Required";
case WIFI_MFP_UNKNOWN:
default:
return "UNKNOWN";
}
}
const char *wifi_band_txt(enum wifi_frequency_bands band)
{
switch (band) {
case WIFI_FREQ_BAND_2_4_GHZ:
return "2.4GHz";
case WIFI_FREQ_BAND_5_GHZ:
return "5GHz";
case WIFI_FREQ_BAND_6_GHZ:
return "6GHz";
case WIFI_FREQ_BAND_UNKNOWN:
default:
return "UNKNOWN";
}
}
const char *const wifi_bandwidth_txt(enum wifi_frequency_bandwidths bandwidth)
{
switch (bandwidth) {
case WIFI_FREQ_BANDWIDTH_20MHZ:
return "20 MHz";
case WIFI_FREQ_BANDWIDTH_40MHZ:
return "40 MHz";
case WIFI_FREQ_BANDWIDTH_80MHZ:
return "80 MHz";
case WIFI_FREQ_BANDWIDTH_UNKNOWN:
default:
return "UNKNOWN";
}
}
const char *wifi_state_txt(enum wifi_iface_state state)
{
switch (state) {
case WIFI_STATE_DISCONNECTED:
return "DISCONNECTED";
case WIFI_STATE_INACTIVE:
return "INACTIVE";
case WIFI_STATE_INTERFACE_DISABLED:
return "INTERFACE_DISABLED";
case WIFI_STATE_SCANNING:
return "SCANNING";
case WIFI_STATE_AUTHENTICATING:
return "AUTHENTICATING";
case WIFI_STATE_ASSOCIATING:
return "ASSOCIATING";
case WIFI_STATE_ASSOCIATED:
return "ASSOCIATED";
case WIFI_STATE_4WAY_HANDSHAKE:
return "4WAY_HANDSHAKE";
case WIFI_STATE_GROUP_HANDSHAKE:
return "GROUP_HANDSHAKE";
case WIFI_STATE_COMPLETED:
return "COMPLETED";
case WIFI_STATE_UNKNOWN:
default:
return "UNKNOWN";
}
}
const char *wifi_mode_txt(enum wifi_iface_mode mode)
{
switch (mode) {
case WIFI_MODE_INFRA:
return "STATION";
case WIFI_MODE_IBSS:
return "ADHOC";
case WIFI_MODE_AP:
return "ACCESS POINT";
case WIFI_MODE_P2P_GO:
return "P2P GROUP OWNER";
case WIFI_MODE_P2P_GROUP_FORMATION:
return "P2P GROUP FORMATION";
case WIFI_MODE_MESH:
return "MESH";
case WIFI_MODE_UNKNOWN:
default:
return "UNKNOWN";
}
}
const char *wifi_link_mode_txt(enum wifi_link_mode link_mode)
{
switch (link_mode) {
case WIFI_0:
return "WIFI 0 (802.11)";
case WIFI_1:
return "WIFI 1 (802.11b)";
case WIFI_2:
return "WIFI 2 (802.11a)";
case WIFI_3:
return "WIFI 3 (802.11g)";
case WIFI_4:
return "WIFI 4 (802.11n/HT)";
case WIFI_5:
return "WIFI 5 (802.11ac/VHT)";
case WIFI_6:
return "WIFI 6 (802.11ax/HE)";
case WIFI_6E:
return "WIFI 6E (802.11ax 6GHz/HE)";
case WIFI_7:
return "WIFI 7 (802.11be/EHT)";
case WIFI_LINK_MODE_UNKNOWN:
default:
return "UNKNOWN";
}
}
const char *wifi_ps_txt(enum wifi_ps ps_name)
{
switch (ps_name) {
case WIFI_PS_DISABLED:
return "Power save disabled";
case WIFI_PS_ENABLED:
return "Power save enabled";
default:
return "UNKNOWN";
}
}
const char *wifi_ps_mode_txt(enum wifi_ps_mode ps_mode)
{
switch (ps_mode) {
case WIFI_PS_MODE_LEGACY:
return "Legacy power save";
case WIFI_PS_MODE_WMM:
return "WMM power save";
default:
return "UNKNOWN";
}
}
const char *wifi_twt_operation_txt(enum wifi_twt_operation twt_operation)
{
switch (twt_operation) {
case WIFI_TWT_SETUP:
return "TWT setup";
case WIFI_TWT_TEARDOWN:
return "TWT teardown";
default:
return "UNKNOWN";
}
}
const char *wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation)
{
switch (twt_negotiation) {
case WIFI_TWT_INDIVIDUAL:
return "TWT individual negotiation";
case WIFI_TWT_BROADCAST:
return "TWT broadcast negotiation";
case WIFI_TWT_WAKE_TBTT:
return "TWT wake TBTT negotiation";
default:
return "UNKNOWN";
}
}
const char *wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup)
{
switch (twt_setup) {
case WIFI_TWT_SETUP_CMD_REQUEST:
return "TWT request";
case WIFI_TWT_SETUP_CMD_SUGGEST:
return "TWT suggest";
case WIFI_TWT_SETUP_CMD_DEMAND:
return "TWT demand";
case WIFI_TWT_SETUP_CMD_GROUPING:
return "TWT grouping";
case WIFI_TWT_SETUP_CMD_ACCEPT:
return "TWT accept";
case WIFI_TWT_SETUP_CMD_ALTERNATE:
return "TWT alternate";
case WIFI_TWT_SETUP_CMD_DICTATE:
return "TWT dictate";
case WIFI_TWT_SETUP_CMD_REJECT:
return "TWT reject";
default:
return "UNKNOWN";
}
}
const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode)
{
switch (ps_wakeup_mode) {
case WIFI_PS_WAKEUP_MODE_DTIM:
return "PS wakeup mode DTIM";
case WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL:
return "PS wakeup mode listen interval";
default:
return "UNKNOWN";
}
}
const char *wifi_ps_exit_strategy_txt(enum wifi_ps_exit_strategy ps_exit_strategy)
{
switch (ps_exit_strategy) {
case WIFI_PS_EXIT_EVERY_TIM:
return "Every TIM";
case WIFI_PS_EXIT_CUSTOM_ALGO:
return "Custom algorithm";
default:
return "UNKNOWN";
}
}
const char *wifi_conn_status_txt(enum wifi_conn_status status)
{
switch (status) {
case WIFI_STATUS_CONN_SUCCESS:
return "Connection successful";
case WIFI_STATUS_CONN_FAIL:
return "Connection failed";
case WIFI_STATUS_CONN_WRONG_PASSWORD:
return "Wrong password";
case WIFI_STATUS_CONN_TIMEOUT:
return "Connection timeout";
case WIFI_STATUS_CONN_AP_NOT_FOUND:
return "AP not found";
default:
return "UNKNOWN";
}
}
static const struct wifi_mgmt_ops *const get_wifi_api(struct net_if *iface)
{
const struct device *dev = net_if_get_device(iface);
struct net_wifi_mgmt_offload *off_api;
if (dev == NULL) {
return NULL;
}
off_api = (struct net_wifi_mgmt_offload *) dev->api;
#ifdef CONFIG_WIFI_NM
struct wifi_nm_instance *nm = wifi_nm_get_instance_iface(iface);
if (nm) {
return nm->ops;
}
#endif /* CONFIG_WIFI_NM */
return off_api ? off_api->wifi_mgmt_api : NULL;
}
static int wifi_connect(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
struct wifi_connect_req_params *params =
(struct wifi_connect_req_params *)data;
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->connect == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
LOG_HEXDUMP_DBG(params->ssid, params->ssid_length, "ssid");
LOG_HEXDUMP_DBG(params->psk, params->psk_length, "psk");
if (params->sae_password) {
LOG_HEXDUMP_DBG(params->sae_password, params->sae_password_length, "sae");
}
NET_DBG("ch %u sec %u", params->channel, params->security);
if ((params->security > WIFI_SECURITY_TYPE_MAX) ||
(params->ssid_length > WIFI_SSID_MAX_LEN) ||
(params->ssid_length == 0U) ||
((params->security == WIFI_SECURITY_TYPE_PSK ||
params->security == WIFI_SECURITY_TYPE_WPA_PSK ||
params->security == WIFI_SECURITY_TYPE_PSK_SHA256 ||
params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) &&
((params->psk_length < 8) || (params->psk_length > 64) ||
(params->psk_length == 0U) || !params->psk)) ||
((params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
params->security == WIFI_SECURITY_TYPE_SAE_AUTO) &&
((params->psk_length == 0U) || !params->psk) &&
((params->sae_password_length == 0U) || !params->sae_password)) ||
((params->channel != WIFI_CHANNEL_ANY) &&
(params->channel > WIFI_CHANNEL_MAX)) ||
!params->ssid) {
return -EINVAL;
}
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
memset(&roaming_params, 0x0, sizeof(roaming_params));
roaming_params.is_11r_used = params->ft_used;
#endif
return wifi_mgmt_api->connect(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT, wifi_connect);
static void scan_result_cb(struct net_if *iface, int status,
struct wifi_scan_result *entry)
{
if (!iface) {
return;
}
if (!entry) {
struct wifi_status scan_status = {
.status = status,
};
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_DONE,
iface, &scan_status,
sizeof(struct wifi_status));
return;
}
#ifndef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_RESULT, iface,
entry, sizeof(struct wifi_scan_result));
#endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY */
}
static int wifi_scan(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
struct wifi_scan_params *params = data;
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->scan == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
#ifdef CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN
struct wifi_scan_params default_params = {0};
if (params == NULL) {
params = &default_params;
}
params->scan_type = WIFI_SCAN_TYPE_PASSIVE;
#endif /* CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN */
return wifi_mgmt_api->scan(dev, params, scan_result_cb);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN, wifi_scan);
static int wifi_disconnect(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->disconnect == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->disconnect(dev);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT, wifi_disconnect);
void wifi_mgmt_raise_connect_result_event(struct net_if *iface, int status)
{
struct wifi_status cnx_status = {
.status = status,
};
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_CONNECT_RESULT,
iface, &cnx_status,
sizeof(struct wifi_status));
}
void wifi_mgmt_raise_disconnect_result_event(struct net_if *iface, int status)
{
struct wifi_status cnx_status = {
.status = status,
};
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_RESULT,
iface, &cnx_status,
sizeof(struct wifi_status));
}
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
static int wifi_start_roaming(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (roaming_params.is_11r_used) {
if (wifi_mgmt_api->start_11r_roaming == NULL) {
return -ENOTSUP;
}
return wifi_mgmt_api->start_11r_roaming(dev);
} else if (roaming_params.is_11k_enabled) {
memset(&roaming_params.neighbor_rep, 0x0, sizeof(roaming_params.neighbor_rep));
if (wifi_mgmt_api->send_11k_neighbor_request == NULL) {
return -ENOTSUP;
}
return wifi_mgmt_api->send_11k_neighbor_request(dev, NULL);
} else if (wifi_mgmt_api->bss_ext_capab &&
wifi_mgmt_api->bss_ext_capab(dev, WIFI_EXT_CAPAB_BSS_TRANSITION)) {
if (wifi_mgmt_api->btm_query) {
return wifi_mgmt_api->btm_query(dev, 0x10);
} else {
return -ENOTSUP;
}
} else if (wifi_mgmt_api->legacy_roam) {
return wifi_mgmt_api->legacy_roam(dev);
} else {
return -ENOTSUP;
}
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_START_ROAMING, wifi_start_roaming);
static int wifi_neighbor_rep_complete(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_scan_params params = {0};
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
for (int i = 0; i < roaming_params.neighbor_rep.neighbor_cnt; i++) {
params.band_chan[i].channel = roaming_params.neighbor_rep.neighbor_ap[i].channel;
if (params.band_chan[i].channel > 14) {
params.band_chan[i].band = WIFI_FREQ_BAND_5_GHZ;
} else {
params.band_chan[i].band = WIFI_FREQ_BAND_2_4_GHZ;
}
}
if (wifi_mgmt_api == NULL || wifi_mgmt_api->candidate_scan == NULL) {
return -ENOTSUP;
}
return wifi_mgmt_api->candidate_scan(dev, &params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_NEIGHBOR_REP_COMPLETE,
wifi_neighbor_rep_complete);
void wifi_mgmt_raise_neighbor_rep_recv_event(struct net_if *iface, char *inbuf, size_t buf_len)
{
const uint8_t *buf = inbuf;
char event[MAX_EVENT_STR_LEN + 1] = {0};
char bssid[WIFI_SSID_MAX_LEN + 1] = {0};
char bssid_info[WIFI_SSID_MAX_LEN + 1] = {0};
int op_class, channel, phy_type;
int idx = roaming_params.neighbor_rep.neighbor_cnt;
if (!buf || buf[0] == '\0') {
return;
}
if (sscanf(buf,
"%" STRINGIFY(MAX_EVENT_STR_LEN) "s "
"bssid=%" STRINGIFY(WIFI_SSID_MAX_LEN) "s "
"info=%" STRINGIFY(WIFI_SSID_MAX_LEN) "s "
"op_class=%d chan=%d phy_type=%d",
event, bssid, bssid_info, &op_class, &channel, &phy_type) == 6) {
int i;
int match = 0;
size_t len = 0;
for (i = 0; i < roaming_params.neighbor_rep.neighbor_cnt; i++) {
if (strncmp((const char *)roaming_params.neighbor_rep.neighbor_ap[i].bssid,
bssid, sizeof(bssid)) == 0) {
match = 1;
break;
}
if (roaming_params.neighbor_rep.neighbor_ap[i].channel == channel) {
match = 1;
break;
}
}
if (!match && (roaming_params.neighbor_rep.neighbor_cnt < MAX_NEIGHBOR_AP_LIMIT)) {
memcpy((char *)roaming_params.neighbor_rep.neighbor_ap[idx].bssid,
bssid,
sizeof(roaming_params.neighbor_rep.neighbor_ap[idx].bssid));
len = strnlen(bssid, sizeof(bssid) - 1);
roaming_params.neighbor_rep.neighbor_ap[idx].bssid[len] = (uint8_t)'\0';
memcpy((char *)roaming_params.neighbor_rep.neighbor_ap[idx].bssid_info,
bssid_info,
sizeof(roaming_params.neighbor_rep.neighbor_ap[idx].bssid_info));
len = strnlen(bssid_info, sizeof(bssid_info) - 1);
roaming_params.neighbor_rep.neighbor_ap[idx].bssid_info[len] =
(uint8_t)'\0';
roaming_params.neighbor_rep.neighbor_ap[idx].channel = channel;
roaming_params.neighbor_rep.neighbor_ap[idx].op_class = op_class;
roaming_params.neighbor_rep.neighbor_ap[idx].phy_type = phy_type;
roaming_params.neighbor_rep.neighbor_cnt += 1;
} else if (match) {
LOG_INF("BSSID already present in neighbor list, Skipping %s ",
bssid);
} else {
LOG_INF("Maximum neighbors added to list, Skipping.");
}
} else {
LOG_INF("Failed to Parse Neighbor Report - Skipping entry\n");
}
}
#endif
static int wifi_ap_enable(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
struct wifi_connect_req_params *params =
(struct wifi_connect_req_params *)data;
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_enable == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->ap_enable(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE, wifi_ap_enable);
static int wifi_ap_disable(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_disable == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->ap_disable(dev);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE, wifi_ap_disable);
static int wifi_ap_sta_disconnect(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
uint8_t *mac = data;
if (dev == NULL) {
return -ENODEV;
}
if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_sta_disconnect == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (!data || len != sizeof(uint8_t) * WIFI_MAC_ADDR_LEN) {
return -EINVAL;
}
return wifi_mgmt_api->ap_sta_disconnect(dev, mac);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_STA_DISCONNECT, wifi_ap_sta_disconnect);
static int wifi_ap_config_params(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_ap_config_params *params = data;
if (dev == NULL) {
return -ENODEV;
}
if (wifi_mgmt_api == NULL ||
wifi_mgmt_api->ap_config_params == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (!data || len != sizeof(*params)) {
return -EINVAL;
}
if (params->type & WIFI_AP_CONFIG_PARAM_MAX_NUM_STA) {
if (params->max_num_sta > CONFIG_WIFI_MGMT_AP_MAX_NUM_STA) {
LOG_INF("Maximum number of stations(%d) "
"exceeded default configured value = %d.",
params->max_num_sta, CONFIG_WIFI_MGMT_AP_MAX_NUM_STA);
return -EINVAL;
}
}
return wifi_mgmt_api->ap_config_params(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_CONFIG_PARAM, wifi_ap_config_params);
static int wifi_ap_set_rts_threshold(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
unsigned int *rts_threshold = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_rts_threshold == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (data == NULL || len != sizeof(*rts_threshold)) {
return -EINVAL;
}
return wifi_mgmt_api->set_rts_threshold(dev, *rts_threshold);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_RTS_THRESHOLD, wifi_ap_set_rts_threshold);
static int wifi_iface_status(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_iface_status *status = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->iface_status == NULL) {
return -ENOTSUP;
}
if (!data || len != sizeof(*status)) {
return -EINVAL;
}
return wifi_mgmt_api->iface_status(dev, status);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_IFACE_STATUS, wifi_iface_status);
void wifi_mgmt_raise_iface_status_event(struct net_if *iface,
struct wifi_iface_status *iface_status)
{
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_IFACE_STATUS,
iface, iface_status,
sizeof(struct wifi_iface_status));
}
#ifdef CONFIG_NET_STATISTICS_WIFI
static int wifi_iface_stats(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct net_stats_wifi *stats = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_stats == NULL) {
return -ENOTSUP;
}
if (!data || len != sizeof(*stats)) {
return -EINVAL;
}
return wifi_mgmt_api->get_stats(dev, stats);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_WIFI, wifi_iface_stats);
static int wifi_iface_stats_reset(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->reset_stats == NULL) {
return -ENOTSUP;
}
return wifi_mgmt_api->reset_stats(dev);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_RESET_WIFI, wifi_iface_stats_reset);
#endif /* CONFIG_NET_STATISTICS_WIFI */
static int wifi_11k_cfg(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_11k_params *params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->cfg_11k == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
if (params->oper == WIFI_MGMT_SET) {
roaming_params.is_11k_enabled = params->enable_11k;
}
#endif
return wifi_mgmt_api->cfg_11k(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_11K_CONFIG, wifi_11k_cfg);
static int wifi_11k_neighbor_request(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_11k_params *params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->send_11k_neighbor_request == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->send_11k_neighbor_request(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_11K_NEIGHBOR_REQUEST,
wifi_11k_neighbor_request);
static int wifi_set_power_save(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_ps_params *ps_params = data;
struct wifi_iface_status info = { 0 };
if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_power_save == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
switch (ps_params->type) {
case WIFI_PS_PARAM_LISTEN_INTERVAL:
case WIFI_PS_PARAM_MODE:
if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
sizeof(struct wifi_iface_status))) {
ps_params->fail_reason =
WIFI_PS_PARAM_FAIL_UNABLE_TO_GET_IFACE_STATUS;
return -EIO;
}
if (info.state >= WIFI_STATE_ASSOCIATED) {
ps_params->fail_reason =
WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED;
return -ENOTSUP;
}
break;
case WIFI_PS_PARAM_STATE:
case WIFI_PS_PARAM_WAKEUP_MODE:
case WIFI_PS_PARAM_TIMEOUT:
break;
case WIFI_PS_PARAM_EXIT_STRATEGY:
if (ps_params->exit_strategy > WIFI_PS_EXIT_MAX) {
ps_params->fail_reason =
WIFI_PS_PARAM_FAIL_INVALID_EXIT_STRATEGY;
return -EINVAL;
}
break;
default:
ps_params->fail_reason =
WIFI_PS_PARAM_FAIL_OPERATION_NOT_SUPPORTED;
return -ENOTSUP;
}
return wifi_mgmt_api->set_power_save(dev, ps_params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS, wifi_set_power_save);
static int wifi_get_power_save_config(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_ps_config *ps_config = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_power_save_config == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (!data || len != sizeof(*ps_config)) {
return -EINVAL;
}
return wifi_mgmt_api->get_power_save_config(dev, ps_config);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_CONFIG, wifi_get_power_save_config);
static int wifi_set_twt(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_twt_params *twt_params = data;
struct wifi_iface_status info = { 0 };
if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_twt == NULL) {
twt_params->fail_reason =
WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (twt_params->operation == WIFI_TWT_TEARDOWN) {
return wifi_mgmt_api->set_twt(dev, twt_params);
}
if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
sizeof(struct wifi_iface_status))) {
twt_params->fail_reason =
WIFI_TWT_FAIL_UNABLE_TO_GET_IFACE_STATUS;
goto fail;
}
if (info.state != WIFI_STATE_COMPLETED) {
twt_params->fail_reason =
WIFI_TWT_FAIL_DEVICE_NOT_CONNECTED;
goto fail;
}
#ifdef CONFIG_WIFI_MGMT_TWT_CHECK_IP
if ((!net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) &&
(!net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface))) {
twt_params->fail_reason =
WIFI_TWT_FAIL_IP_NOT_ASSIGNED;
goto fail;
}
#else
NET_WARN("Check for valid IP address been disabled. "
"Device might be unreachable or might not receive traffic.\n");
#endif /* CONFIG_WIFI_MGMT_TWT_CHECK_IP */
if (info.link_mode < WIFI_6) {
twt_params->fail_reason =
WIFI_TWT_FAIL_PEER_NOT_HE_CAPAB;
goto fail;
}
if (!info.twt_capable) {
twt_params->fail_reason =
WIFI_TWT_FAIL_PEER_NOT_TWT_CAPAB;
goto fail;
}
return wifi_mgmt_api->set_twt(dev, twt_params);
fail:
return -ENOEXEC;
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_TWT, wifi_set_twt);
static int wifi_set_btwt(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_twt_params *twt_params = data;
struct wifi_iface_status info = { 0 };
if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_btwt == NULL) {
twt_params->fail_reason =
WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
sizeof(struct wifi_iface_status))) {
twt_params->fail_reason =
WIFI_TWT_FAIL_UNABLE_TO_GET_IFACE_STATUS;
goto fail;
}
return wifi_mgmt_api->set_btwt(dev, twt_params);
fail:
return -ENOEXEC;
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_BTWT, wifi_set_btwt);
void wifi_mgmt_raise_twt_event(struct net_if *iface, struct wifi_twt_params *twt_params)
{
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT,
iface, twt_params,
sizeof(struct wifi_twt_params));
}
static int wifi_reg_domain(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_reg_domain *reg_domain = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->reg_domain == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (!data || len != sizeof(*reg_domain)) {
return -EINVAL;
}
return wifi_mgmt_api->reg_domain(dev, reg_domain);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN, wifi_reg_domain);
void wifi_mgmt_raise_twt_sleep_state(struct net_if *iface,
int twt_sleep_state)
{
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT_SLEEP_STATE,
iface, &twt_sleep_state,
sizeof(twt_sleep_state));
}
static int wifi_mode(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_mode_info *mode_info = data;
if (dev == NULL) {
return -ENODEV;
}
if (wifi_mgmt_api == NULL || wifi_mgmt_api->mode == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->mode(dev, mode_info);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE, wifi_mode);
static int wifi_packet_filter(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_filter_info *filter_info = data;
if (dev == NULL) {
return -ENODEV;
}
if (wifi_mgmt_api == NULL || wifi_mgmt_api->filter == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->filter(dev, filter_info);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER, wifi_packet_filter);
static int wifi_channel(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_channel_info *channel_info = data;
if (dev == NULL) {
return -ENODEV;
}
if (wifi_mgmt_api == NULL || wifi_mgmt_api->channel == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->channel(dev, channel_info);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL, wifi_channel);
static int wifi_get_version(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_version *ver_params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_version == NULL) {
return -ENOTSUP;
}
return wifi_mgmt_api->get_version(dev, ver_params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_VERSION, wifi_get_version);
static int wifi_btm_query(uint32_t mgmt_request, struct net_if *iface, void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
uint8_t query_reason = *((uint8_t *)data);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->btm_query == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (query_reason >= WIFI_BTM_QUERY_REASON_UNSPECIFIED &&
query_reason <= WIFI_BTM_QUERY_REASON_LEAVING_ESS) {
return wifi_mgmt_api->btm_query(dev, query_reason);
}
return -EINVAL;
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_BTM_QUERY, wifi_btm_query);
static int wifi_get_connection_params(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_connect_req_params *conn_params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_conn_params == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->get_conn_params(dev, conn_params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONN_PARAMS, wifi_get_connection_params);
static int wifi_wps_config(uint32_t mgmt_request, struct net_if *iface, void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_wps_config_params *params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->wps_config == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->wps_config(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_WPS_CONFIG, wifi_wps_config);
static int wifi_set_rts_threshold(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
unsigned int *rts_threshold = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_rts_threshold == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (!data || len != sizeof(*rts_threshold)) {
return -EINVAL;
}
return wifi_mgmt_api->set_rts_threshold(dev, *rts_threshold);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD, wifi_set_rts_threshold);
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
static int wifi_dpp(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_dpp_params *params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->dpp_dispatch == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->dpp_dispatch(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_DPP, wifi_dpp);
#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
static int wifi_pmksa_flush(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
if (wifi_mgmt_api == NULL || wifi_mgmt_api->pmksa_flush == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->pmksa_flush(dev);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PMKSA_FLUSH, wifi_pmksa_flush);
static int wifi_get_rts_threshold(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
unsigned int *rts_threshold = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_rts_threshold == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
if (!data || len != sizeof(*rts_threshold)) {
return -EINVAL;
}
return wifi_mgmt_api->get_rts_threshold(dev, rts_threshold);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD_CONFIG, wifi_get_rts_threshold);
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
static int wifi_set_enterprise_creds(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_enterprise_creds_params *params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->enterprise_creds == NULL) {
return -ENOTSUP;
}
if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}
return wifi_mgmt_api->enterprise_creds(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_ENTERPRISE_CREDS, wifi_set_enterprise_creds);
#endif
#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface,
struct wifi_raw_scan_result *raw_scan_result)
{
if (raw_scan_result->frame_length > CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH) {
LOG_INF("raw scan result frame length = %d too big,"
"saving upto max raw scan length = %d",
raw_scan_result->frame_length,
CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH);
}
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_RAW_SCAN_RESULT,
iface, raw_scan_result,
sizeof(*raw_scan_result));
}
#endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
void wifi_mgmt_raise_disconnect_complete_event(struct net_if *iface,
int status)
{
struct wifi_status cnx_status = {
.status = status,
};
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_COMPLETE,
iface, &cnx_status,
sizeof(struct wifi_status));
}
void wifi_mgmt_raise_ap_enable_result_event(struct net_if *iface,
enum wifi_ap_status status)
{
struct wifi_status cnx_status = {
.status = status,
};
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_ENABLE_RESULT,
iface, &cnx_status,
sizeof(enum wifi_ap_status));
}
void wifi_mgmt_raise_ap_disable_result_event(struct net_if *iface,
enum wifi_ap_status status)
{
struct wifi_status cnx_status = {
.status = status,
};
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_DISABLE_RESULT,
iface, &cnx_status,
sizeof(enum wifi_ap_status));
}
void wifi_mgmt_raise_ap_sta_connected_event(struct net_if *iface,
struct wifi_ap_sta_info *sta_info)
{
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_STA_CONNECTED,
iface, sta_info,
sizeof(struct wifi_ap_sta_info));
}
void wifi_mgmt_raise_ap_sta_disconnected_event(struct net_if *iface,
struct wifi_ap_sta_info *sta_info)
{
net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_STA_DISCONNECTED,
iface, sta_info,
sizeof(struct wifi_ap_sta_info));
}
#ifdef CONFIG_WIFI_CREDENTIALS_CONNECT_STORED
#include <zephyr/net/wifi_credentials.h>
#if defined(CONFIG_WIFI_CREDENTIALS_STATIC)
BUILD_ASSERT(sizeof(CONFIG_WIFI_CREDENTIALS_STATIC_SSID) != 1,
"CONFIG_WIFI_CREDENTIALS_STATIC_SSID required");
#endif /* defined(CONFIG_WIFI_CREDENTIALS_STATIC) */
static int __stored_creds_to_params(struct wifi_credentials_personal *creds,
struct wifi_connect_req_params *params)
{
char *ssid = NULL;
char *psk = NULL;
int ret;
/* SSID */
ssid = (char *)k_malloc(creds->header.ssid_len + 1);
if (!ssid) {
LOG_ERR("Failed to allocate memory for SSID\n");
ret = -ENOMEM;
goto err_out;
}
memset(ssid, 0, creds->header.ssid_len + 1);
ret = snprintf(ssid, creds->header.ssid_len + 1, "%s", creds->header.ssid);
if (ret > creds->header.ssid_len) {
LOG_ERR("SSID string truncated\n");
ret = -EINVAL;
goto err_out;
}
params->ssid = ssid;
params->ssid_length = creds->header.ssid_len;
/* PSK (optional) */
if (creds->password_len > 0) {
psk = (char *)k_malloc(creds->password_len + 1);
if (!psk) {
LOG_ERR("Failed to allocate memory for PSK\n");
ret = -ENOMEM;
goto err_out;
}
memset(psk, 0, creds->password_len + 1);
ret = snprintf(psk, creds->password_len + 1, "%s", creds->password);
if (ret > creds->password_len) {
LOG_ERR("PSK string truncated\n");
ret = -EINVAL;
goto err_out;
}
params->psk = psk;
params->psk_length = creds->password_len;
}
/* Defaults */
params->security = creds->header.type;
/* If channel is set to 0 we default to ANY. 0 is not a valid Wi-Fi channel. */
params->channel = (creds->header.channel != 0) ? creds->header.channel : WIFI_CHANNEL_ANY;
params->timeout = (creds->header.timeout != 0)
? creds->header.timeout
: CONFIG_WIFI_CREDENTIALS_CONNECT_STORED_CONNECTION_TIMEOUT;
/* Security type (optional) */
if (creds->header.type > WIFI_SECURITY_TYPE_MAX) {
params->security = WIFI_SECURITY_TYPE_NONE;
}
if (creds->header.flags & WIFI_CREDENTIALS_FLAG_2_4GHz) {
params->band = WIFI_FREQ_BAND_2_4_GHZ;
} else if (creds->header.flags & WIFI_CREDENTIALS_FLAG_5GHz) {
params->band = WIFI_FREQ_BAND_5_GHZ;
} else {
params->band = WIFI_FREQ_BAND_UNKNOWN;
}
/* MFP setting (default: optional) */
if (creds->header.flags & WIFI_CREDENTIALS_FLAG_MFP_DISABLED) {
params->mfp = WIFI_MFP_DISABLE;
} else if (creds->header.flags & WIFI_CREDENTIALS_FLAG_MFP_REQUIRED) {
params->mfp = WIFI_MFP_REQUIRED;
} else {
params->mfp = WIFI_MFP_OPTIONAL;
}
return 0;
err_out:
if (ssid) {
k_free(ssid);
ssid = NULL;
}
if (psk) {
k_free(psk);
psk = NULL;
}
return ret;
}
static inline const char *wpa_supp_security_txt(enum wifi_security_type security)
{
switch (security) {
case WIFI_SECURITY_TYPE_NONE:
return "NONE";
case WIFI_SECURITY_TYPE_PSK:
return "WPA-PSK";
case WIFI_SECURITY_TYPE_PSK_SHA256:
return "WPA-PSK-SHA256";
case WIFI_SECURITY_TYPE_SAE:
return "SAE";
case WIFI_SECURITY_TYPE_UNKNOWN:
default:
return "UNKNOWN";
}
}
static int add_network_from_credentials_struct_personal(struct wifi_credentials_personal *creds,
struct net_if *iface)
{
int ret = 0;
struct wifi_connect_req_params cnx_params = {0};
if (__stored_creds_to_params(creds, &cnx_params)) {
ret = -ENOEXEC;
goto out;
}
if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params,
sizeof(struct wifi_connect_req_params))) {
LOG_ERR("Connection request failed\n");
return -ENOEXEC;
}
LOG_INF("Connection requested");
out:
if (cnx_params.psk) {
k_free((void *)cnx_params.psk);
}
if (cnx_params.ssid) {
k_free((void *)cnx_params.ssid);
}
return ret;
}
static void add_stored_network(void *cb_arg, const char *ssid, size_t ssid_len)
{
int ret = 0;
struct wifi_credentials_personal creds;
/* load stored data */
ret = wifi_credentials_get_by_ssid_personal_struct(ssid, ssid_len, &creds);
if (ret) {
LOG_ERR("Loading WiFi credentials failed for SSID [%.*s], len: %d, err: %d",
ssid_len, ssid, ssid_len, ret);
return;
}
add_network_from_credentials_struct_personal(&creds, (struct net_if *)cb_arg);
}
static int add_static_network_config(struct net_if *iface)
{
#if defined(CONFIG_WIFI_CREDENTIALS_STATIC)
struct wifi_credentials_personal creds = {
.header = {
.ssid_len = strlen(CONFIG_WIFI_CREDENTIALS_STATIC_SSID),
},
.password_len = strlen(CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD),
};
int ret = wifi_credentials_get_by_ssid_personal_struct(
CONFIG_WIFI_CREDENTIALS_STATIC_SSID, strlen(CONFIG_WIFI_CREDENTIALS_STATIC_SSID),
&creds);
if (!ret) {
LOG_WRN("Statically configured WiFi network was overridden by storage.");
return 0;
}
#if defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_OPEN)
creds.header.type = WIFI_SECURITY_TYPE_NONE;
#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_PSK)
creds.header.type = WIFI_SECURITY_TYPE_PSK;
#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_PSK_SHA256)
creds.header.type = WIFI_SECURITY_TYPE_PSK_SHA256;
#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_SAE)
creds.header.type = WIFI_SECURITY_TYPE_SAE;
#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_WPA_PSK)
creds.header.type = WIFI_SECURITY_TYPE_WPA_PSK;
#else
#error "invalid CONFIG_WIFI_CREDENTIALS_STATIC_TYPE"
#endif
memcpy(creds.header.ssid, CONFIG_WIFI_CREDENTIALS_STATIC_SSID,
strlen(CONFIG_WIFI_CREDENTIALS_STATIC_SSID));
memcpy(creds.password, CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD,
strlen(CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD));
LOG_DBG("Adding statically configured WiFi network [%s] to internal list.",
creds.header.ssid);
return add_network_from_credentials_struct_personal(&creds, iface);
#else
return 0;
#endif /* defined(CONFIG_WIFI_CREDENTIALS_STATIC) */
}
static int connect_stored_command(uint32_t mgmt_request, struct net_if *iface, void *data,
size_t len)
{
int ret = 0;
ret = add_static_network_config(iface);
if (ret) {
return ret;
}
wifi_credentials_for_each_ssid(add_stored_network, iface);
return ret;
};
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT_STORED, connect_stored_command);
#endif /* CONFIG_WIFI_CREDENTIALS_CONNECT_STORED */