From e1ab06a6ab1d9eb3d55dad298e4f8cb6b4a01152 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 26 Dec 2023 21:27:32 +0530 Subject: [PATCH 1/4] wifi: Fix duplication Use a common set of events and then add specific ones as per the configuration. Signed-off-by: Chaitanya Tata --- subsys/net/l2/wifi/wifi_shell.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index c7899635105214..592b4a898d76bd 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -30,19 +30,17 @@ LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF); #define WIFI_SHELL_MODULE "wifi" +#define WIFI_SHELL_MGMT_EVENTS_COMMON (NET_EVENT_WIFI_SCAN_DONE |\ + NET_EVENT_WIFI_CONNECT_RESULT |\ + NET_EVENT_WIFI_DISCONNECT_RESULT | \ + NET_EVENT_WIFI_TWT |\ + NET_EVENT_WIFI_RAW_SCAN_RESULT) + #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY -#define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_RAW_SCAN_RESULT | \ - NET_EVENT_WIFI_SCAN_DONE | \ - NET_EVENT_WIFI_CONNECT_RESULT | \ - NET_EVENT_WIFI_DISCONNECT_RESULT | \ - NET_EVENT_WIFI_TWT) +#define WIFI_SHELL_MGMT_EVENTS (WIFI_SHELL_MGMT_EVENTS_COMMON) #else -#define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_SCAN_RESULT | \ - NET_EVENT_WIFI_SCAN_DONE | \ - NET_EVENT_WIFI_CONNECT_RESULT | \ - NET_EVENT_WIFI_DISCONNECT_RESULT | \ - NET_EVENT_WIFI_TWT | \ - NET_EVENT_WIFI_RAW_SCAN_RESULT) +#define WIFI_SHELL_MGMT_EVENTS (WIFI_SHELL_MGMT_EVENTS_COMMON |\ + NET_EVENT_WIFI_SCAN_RESULT) #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY */ static struct { From 622fb2a9f5291c979f93e8a5c1c7aa625bc4cf30 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Mon, 25 Dec 2023 20:09:45 +0530 Subject: [PATCH 2/4] wifi: ap: Add status events These events communicate the status of AP mode operations (enable or disable) with few pre-defined enumerations. Signed-off-by: Chaitanya Tata --- include/zephyr/net/wifi_mgmt.h | 47 +++++++++++++++++++++++++++++++++ subsys/net/l2/wifi/wifi_mgmt.c | 24 +++++++++++++++++ subsys/net/l2/wifi/wifi_shell.c | 41 +++++++++++++++++++++++++--- 3 files changed, 108 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index babf67722c1575..0897bdd5715dce 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -180,6 +180,10 @@ enum net_event_wifi_cmd { NET_EVENT_WIFI_CMD_RAW_SCAN_RESULT, /** Disconnect complete */ NET_EVENT_WIFI_CMD_DISCONNECT_COMPLETE, + /** AP mode enable result */ + NET_EVENT_WIFI_CMD_AP_ENABLE_RESULT, + /** AP mode disable result */ + NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT, }; #define NET_EVENT_WIFI_SCAN_RESULT \ @@ -209,6 +213,12 @@ enum net_event_wifi_cmd { #define NET_EVENT_WIFI_DISCONNECT_COMPLETE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_DISCONNECT_COMPLETE) +#define NET_EVENT_WIFI_AP_ENABLE_RESULT \ + (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_ENABLE_RESULT) + +#define NET_EVENT_WIFI_AP_DISABLE_RESULT \ + (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT) + /** * @brief Wi-Fi structure to uniquely identify a band-channel pair */ @@ -351,12 +361,35 @@ enum wifi_disconn_reason { WIFI_REASON_DISCONN_INACTIVITY, }; +/** Wi-Fi AP mode result codes. To be overlaid on top of \ref wifi_status + * in the AP mode enable or disable result event for detailed status. + */ +enum wifi_ap_status { + /** AP mode enable or disable successful */ + WIFI_STATUS_AP_SUCCESS = 0, + /** AP mode enable or disable failed - generic failure */ + WIFI_STATUS_AP_FAIL, + /** AP mode enable failed - channel not supported */ + WIFI_STATUS_AP_CHANNEL_NOT_SUPPORTED, + /** AP mode enable failed - channel not allowed */ + WIFI_STATUS_AP_CHANNEL_NOT_ALLOWED, + /** AP mode enable failed - SSID not allowed */ + WIFI_STATUS_AP_SSID_NOT_ALLOWED, + /** AP mode enable failed - authentication type not supported */ + WIFI_STATUS_AP_AUTH_TYPE_NOT_SUPPORTED, + /** AP mode enable failed - operation not supported */ + WIFI_STATUS_AP_OP_NOT_SUPPORTED, + /** AP mode enable failed - operation not permitted */ + WIFI_STATUS_AP_OP_NOT_PERMITTED, +}; + /** Generic Wi-Fi status for commands and events */ struct wifi_status { union { int status; enum wifi_conn_status conn_status; enum wifi_disconn_reason disconn_reason; + enum wifi_ap_status ap_status; }; }; @@ -802,6 +835,20 @@ void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface, */ void wifi_mgmt_raise_disconnect_complete_event(struct net_if *iface, int status); +/** Wi-Fi management AP mode enable result event + * + * @param iface Network interface + * @param status AP mode enable result status + */ +void wifi_mgmt_raise_ap_enable_result_event(struct net_if *iface, enum wifi_ap_status status); + +/** Wi-Fi management AP mode disable result event + * + * @param iface Network interface + * @param status AP mode disable result status + */ +void wifi_mgmt_raise_ap_disable_result_event(struct net_if *iface, enum wifi_ap_status status); + /** * @} */ diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 1a866d4c47cf73..21a426d794db90 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -707,3 +707,27 @@ void wifi_mgmt_raise_disconnect_complete_event(struct net_if *iface, 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)); +} diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 592b4a898d76bd..9b078a5f7b2748 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -34,7 +34,9 @@ LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF); NET_EVENT_WIFI_CONNECT_RESULT |\ NET_EVENT_WIFI_DISCONNECT_RESULT | \ NET_EVENT_WIFI_TWT |\ - NET_EVENT_WIFI_RAW_SCAN_RESULT) + NET_EVENT_WIFI_RAW_SCAN_RESULT |\ + NET_EVENT_WIFI_AP_ENABLE_RESULT |\ + NET_EVENT_WIFI_AP_DISABLE_RESULT) #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY #define WIFI_SHELL_MGMT_EVENTS (WIFI_SHELL_MGMT_EVENTS_COMMON) @@ -301,6 +303,32 @@ static void handle_wifi_twt_event(struct net_mgmt_event_callback *cb) } } +static void handle_wifi_ap_enable_result(struct net_mgmt_event_callback *cb) +{ + const struct wifi_status *status = + (const struct wifi_status *)cb->info; + + if (status->status) { + print(context.sh, SHELL_WARNING, + "AP enable request failed (%d)\n", status->status); + } else { + print(context.sh, SHELL_NORMAL, "AP enabled\n"); + } +} + +static void handle_wifi_ap_disable_result(struct net_mgmt_event_callback *cb) +{ + const struct wifi_status *status = + (const struct wifi_status *)cb->info; + + if (status->status) { + print(context.sh, SHELL_WARNING, + "AP disable request failed (%d)\n", status->status); + } else { + print(context.sh, SHELL_NORMAL, "AP disabled\n"); + } +} + static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface) { @@ -325,6 +353,12 @@ static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, handle_wifi_raw_scan_result(cb); break; #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ + case NET_EVENT_WIFI_AP_ENABLE_RESULT: + handle_wifi_ap_enable_result(cb); + break; + case NET_EVENT_WIFI_AP_DISABLE_RESULT: + handle_wifi_ap_disable_result(cb); + break; default: break; } @@ -1113,7 +1147,7 @@ static int cmd_wifi_ap_enable(const struct shell *sh, size_t argc, return -ENOEXEC; } - shell_fprintf(sh, SHELL_NORMAL, "AP mode enabled\n"); + shell_fprintf(sh, SHELL_NORMAL, "AP mode enable requested\n"); return 0; } @@ -1130,8 +1164,7 @@ static int cmd_wifi_ap_disable(const struct shell *sh, size_t argc, return -ENOEXEC; } - shell_fprintf(sh, SHELL_NORMAL, "AP mode disabled\n"); - + shell_fprintf(sh, SHELL_NORMAL, "AP mode disable requested\n"); return 0; } From 1b2df933d943a2c6f97aeceb1c9ad879f4381320 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 26 Dec 2023 21:17:51 +0530 Subject: [PATCH 3/4] wifi: ap: Add client side events These are helpful to track clients being added and deleted. Applications can actions based on these events. Signed-off-by: Chaitanya Tata --- include/zephyr/net/wifi_mgmt.h | 38 +++++++++++++++++++++++++++++++++ subsys/net/l2/wifi/wifi_mgmt.c | 16 ++++++++++++++ subsys/net/l2/wifi/wifi_shell.c | 32 ++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 0897bdd5715dce..78800f451e76bb 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -184,6 +184,10 @@ enum net_event_wifi_cmd { NET_EVENT_WIFI_CMD_AP_ENABLE_RESULT, /** AP mode disable result */ NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT, + /** STA connected to AP */ + NET_EVENT_WIFI_CMD_AP_STA_CONNECTED, + /** STA disconnected from AP */ + NET_EVENT_WIFI_CMD_AP_STA_DISCONNECTED, }; #define NET_EVENT_WIFI_SCAN_RESULT \ @@ -219,6 +223,12 @@ enum net_event_wifi_cmd { #define NET_EVENT_WIFI_AP_DISABLE_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT) +#define NET_EVENT_WIFI_AP_STA_CONNECTED \ + (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_STA_CONNECTED) + +#define NET_EVENT_WIFI_AP_STA_DISCONNECTED \ + (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_STA_DISCONNECTED) + /** * @brief Wi-Fi structure to uniquely identify a band-channel pair */ @@ -568,6 +578,18 @@ struct wifi_raw_scan_result { }; #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ +/** AP mode - connected STA details */ +struct wifi_ap_sta_info { + /** Link mode, see enum wifi_link_mode */ + enum wifi_link_mode link_mode; + /** MAC address */ + uint8_t mac[WIFI_MAC_ADDR_LEN]; + /** MAC address length */ + uint8_t mac_length; + /** is TWT capable ? */ + bool twt_capable; +}; + /* for use in max info size calculations */ union wifi_mgmt_events { struct wifi_scan_result scan_result; @@ -577,6 +599,7 @@ union wifi_mgmt_events { struct wifi_raw_scan_result raw_scan_result; #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ struct wifi_twt_params twt_params; + struct wifi_ap_sta_info ap_sta_info; }; /** Wi-Fi mode setup */ @@ -849,6 +872,21 @@ void wifi_mgmt_raise_ap_enable_result_event(struct net_if *iface, enum wifi_ap_s */ void wifi_mgmt_raise_ap_disable_result_event(struct net_if *iface, enum wifi_ap_status status); +/** Wi-Fi management AP mode STA connected event + * + * @param iface Network interface + * @param sta_info STA information + */ +void wifi_mgmt_raise_ap_sta_connected_event(struct net_if *iface, + struct wifi_ap_sta_info *sta_info); + +/** Wi-Fi management AP mode STA disconnected event + * @param iface Network interface + * @param sta_info STA information + */ +void wifi_mgmt_raise_ap_sta_disconnected_event(struct net_if *iface, + struct wifi_ap_sta_info *sta_info); + /** * @} */ diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 21a426d794db90..6e0cb761dbf758 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -731,3 +731,19 @@ void wifi_mgmt_raise_ap_disable_result_event(struct net_if *iface, 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)); +} diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 9b078a5f7b2748..64f9f8a29b9d75 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -36,7 +36,9 @@ LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF); NET_EVENT_WIFI_TWT |\ NET_EVENT_WIFI_RAW_SCAN_RESULT |\ NET_EVENT_WIFI_AP_ENABLE_RESULT |\ - NET_EVENT_WIFI_AP_DISABLE_RESULT) + NET_EVENT_WIFI_AP_DISABLE_RESULT |\ + NET_EVENT_WIFI_AP_STA_CONNECTED |\ + NET_EVENT_WIFI_AP_STA_DISCONNECTED) #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY #define WIFI_SHELL_MGMT_EVENTS (WIFI_SHELL_MGMT_EVENTS_COMMON) @@ -329,6 +331,28 @@ static void handle_wifi_ap_disable_result(struct net_mgmt_event_callback *cb) } } +static void handle_wifi_ap_sta_connected(struct net_mgmt_event_callback *cb) +{ + const struct wifi_ap_sta_info *sta_info = + (const struct wifi_ap_sta_info *)cb->info; + uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")]; + + print(context.sh, SHELL_NORMAL, "Station connected: %s\n", + net_sprint_ll_addr_buf(sta_info->mac, WIFI_MAC_ADDR_LEN, + mac_string_buf, sizeof(mac_string_buf))); +} + +static void handle_wifi_ap_sta_disconnected(struct net_mgmt_event_callback *cb) +{ + const struct wifi_ap_sta_info *sta_info = + (const struct wifi_ap_sta_info *)cb->info; + uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")]; + + print(context.sh, SHELL_NORMAL, "Station disconnected: %s\n", + net_sprint_ll_addr_buf(sta_info->mac, WIFI_MAC_ADDR_LEN, + mac_string_buf, sizeof(mac_string_buf))); +} + static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface) { @@ -359,6 +383,12 @@ static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, case NET_EVENT_WIFI_AP_DISABLE_RESULT: handle_wifi_ap_disable_result(cb); break; + case NET_EVENT_WIFI_AP_STA_CONNECTED: + handle_wifi_ap_sta_connected(cb); + break; + case NET_EVENT_WIFI_AP_STA_DISCONNECTED: + handle_wifi_ap_sta_disconnected(cb); + break; default: break; } From 37466bc9b65ed487a041c8f9181826db4f962549 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 27 Dec 2023 00:06:45 +0530 Subject: [PATCH 4/4] wifi: shell: Add a shell command to list stations In AP mode maintain the database of connected stations based on the Wi-Fi management events and dump the list. Signed-off-by: Chaitanya Tata --- subsys/net/l2/wifi/Kconfig | 8 +++ subsys/net/l2/wifi/wifi_shell.c | 90 +++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/subsys/net/l2/wifi/Kconfig b/subsys/net/l2/wifi/Kconfig index 134448aa57f472..2816be56d746d3 100644 --- a/subsys/net/l2/wifi/Kconfig +++ b/subsys/net/l2/wifi/Kconfig @@ -64,6 +64,14 @@ config WIFI_MGMT_SCAN_CHAN_MAX_MANUAL There are approximately 100 channels allocated across the three supported bands. The default of 3 allows the 3 most common channels (2.4GHz: 1, 6, 11) to be specified. +config WIFI_SHELL_MAX_AP_STA + int "Maximum number of APs and STAs that can be managed in Wi-Fi shell" + range 1 5 + default 1 + help + This option defines the maximum number of APs and STAs that can be managed + in Wi-Fi shell. + config WIFI_NM bool "Wi-Fi Network manager support" help diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 64f9f8a29b9d75..ec85008229159b 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -25,6 +25,7 @@ LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF); #include #include #include +#include #include "net_private.h" @@ -65,6 +66,13 @@ static uint32_t scan_result; static struct net_mgmt_event_callback wifi_shell_mgmt_cb; +static K_MUTEX_DEFINE(wifi_ap_sta_list_lock); +struct wifi_ap_sta_node { + bool valid; + struct wifi_ap_sta_info sta_info; +}; +static struct wifi_ap_sta_node sta_list[CONFIG_WIFI_SHELL_MAX_AP_STA]; + #define print(sh, level, fmt, ...) \ do { \ if (sh) { \ @@ -329,6 +337,10 @@ static void handle_wifi_ap_disable_result(struct net_mgmt_event_callback *cb) } else { print(context.sh, SHELL_NORMAL, "AP disabled\n"); } + + k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER); + memset(&sta_list, 0, sizeof(sta_list)); + k_mutex_unlock(&wifi_ap_sta_list_lock); } static void handle_wifi_ap_sta_connected(struct net_mgmt_event_callback *cb) @@ -336,10 +348,25 @@ static void handle_wifi_ap_sta_connected(struct net_mgmt_event_callback *cb) const struct wifi_ap_sta_info *sta_info = (const struct wifi_ap_sta_info *)cb->info; uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")]; + int i; print(context.sh, SHELL_NORMAL, "Station connected: %s\n", net_sprint_ll_addr_buf(sta_info->mac, WIFI_MAC_ADDR_LEN, mac_string_buf, sizeof(mac_string_buf))); + + k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER); + for (i = 0; i < CONFIG_WIFI_SHELL_MAX_AP_STA; i++) { + if (!sta_list[i].valid) { + sta_list[i].sta_info = *sta_info; + sta_list[i].valid = true; + break; + } + } + if (i == CONFIG_WIFI_SHELL_MAX_AP_STA) { + print(context.sh, SHELL_WARNING, "No space to store station info: " + "Increase CONFIG_WIFI_SHELL_MAX_AP_STA\n"); + } + k_mutex_unlock(&wifi_ap_sta_list_lock); } static void handle_wifi_ap_sta_disconnected(struct net_mgmt_event_callback *cb) @@ -351,6 +378,20 @@ static void handle_wifi_ap_sta_disconnected(struct net_mgmt_event_callback *cb) print(context.sh, SHELL_NORMAL, "Station disconnected: %s\n", net_sprint_ll_addr_buf(sta_info->mac, WIFI_MAC_ADDR_LEN, mac_string_buf, sizeof(mac_string_buf))); + + k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER); + for (int i = 0; i < CONFIG_WIFI_SHELL_MAX_AP_STA; i++) { + if (!sta_list[i].valid) { + continue; + } + + if (!memcmp(sta_list[i].sta_info.mac, sta_info->mac, + WIFI_MAC_ADDR_LEN)) { + sta_list[i].valid = false; + break; + } + } + k_mutex_unlock(&wifi_ap_sta_list_lock); } static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb, @@ -1170,6 +1211,8 @@ static int cmd_wifi_ap_enable(const struct shell *sh, size_t argc, context.sh = sh; + k_mutex_init(&wifi_ap_sta_list_lock); + ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, iface, &cnx_params, sizeof(struct wifi_connect_req_params)); if (ret) { @@ -1198,6 +1241,49 @@ static int cmd_wifi_ap_disable(const struct shell *sh, size_t argc, return 0; } +static int cmd_wifi_ap_stations(const struct shell *sh, size_t argc, + char *argv[]) +{ + size_t id = 1; + + ARG_UNUSED(argv); + ARG_UNUSED(argc); + + shell_fprintf(sh, SHELL_NORMAL, "AP stations:\n"); + shell_fprintf(sh, SHELL_NORMAL, "============\n"); + + k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER); + for (int i = 0; i < CONFIG_WIFI_SHELL_MAX_AP_STA; i++) { + struct wifi_ap_sta_info *sta; + uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")]; + + if (!sta_list[i].valid) { + continue; + } + + sta = &sta_list[i].sta_info; + + shell_fprintf(sh, SHELL_NORMAL, "Station %zu:\n", id++); + shell_fprintf(sh, SHELL_NORMAL, "==========\n"); + shell_fprintf(sh, SHELL_NORMAL, "MAC: %s\n", + net_sprint_ll_addr_buf(sta->mac, + WIFI_MAC_ADDR_LEN, + mac_string_buf, + sizeof(mac_string_buf))); + shell_fprintf(sh, SHELL_NORMAL, "Link mode: %s\n", + wifi_link_mode_txt(sta->link_mode)); + shell_fprintf(sh, SHELL_NORMAL, "TWT: %s\n", + sta->twt_capable ? "Supported" : "Not supported"); + } + + if (id == 1) { + shell_fprintf(sh, SHELL_NORMAL, "No stations connected\n"); + } + k_mutex_unlock(&wifi_ap_sta_list_lock); + + return 0; +} + static int cmd_wifi_reg_domain(const struct shell *sh, size_t argc, char *argv[]) @@ -1676,6 +1762,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap, ": 0:Disable, 1:Optional, 2:Required.\n", cmd_wifi_ap_enable, 2, 4), + SHELL_CMD_ARG(stations, NULL, + "List stations connected to the AP", + cmd_wifi_ap_stations, + 1, 0), SHELL_SUBCMD_SET_END );