diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index 303a61270ad..e81a96aa00c 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -398,6 +398,8 @@ enum wifi_ps_param_type { WIFI_PS_PARAM_WAKEUP_MODE, /** Power save mode. */ WIFI_PS_PARAM_MODE, + /** Power save exit strategy. */ + WIFI_PS_PARAM_EXIT_STRATEGY, /** Power save timeout. */ WIFI_PS_PARAM_TIMEOUT, }; @@ -413,6 +415,24 @@ enum wifi_ps_wakeup_mode { /** Helper function to get user-friendly ps wakeup mode name. */ const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode); +/** + * Wi-Fi power save exit strategy + */ +enum wifi_ps_exit_strategy { + /** PS-Poll frame based */ + WIFI_PS_EXIT_CUSTOM_ALGO = 0, + /** QoS NULL frame based */ + WIFI_PS_EXIT_EVERY_TIM, + + /** Last value */ + WIFI_PS_EXIT_LAST, + /** Maximum value */ + WIFI_PS_EXIT_MAX = WIFI_PS_EXIT_LAST - 1, +}; + +/** Helper function to get user-friendly ps exit strategy name. */ +const char * const wifi_ps_exit_strategy_txt(enum wifi_ps_exit_strategy ps_exit_strategy); + /** Wi-Fi power save error codes. */ enum wifi_config_ps_param_fail_reason { /** Unspecified error */ @@ -429,6 +449,8 @@ enum wifi_config_ps_param_fail_reason { WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED, /** Listen interval out of range */ WIFI_PS_PARAM_LISTEN_INTERVAL_RANGE_INVALID, + /** Invalid exit strategy */ + WIFI_PS_PARAM_FAIL_INVALID_EXIT_STRATEGY, }; /** @cond INTERNAL_HIDDEN */ diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 06638167690..d51979b6881 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -482,6 +482,8 @@ struct wifi_ps_params { enum wifi_ps_param_type type; /** Wi-Fi power save fail reason */ enum wifi_config_ps_param_fail_reason fail_reason; + /** Wi-Fi power save exit strategy */ + enum wifi_ps_exit_strategy exit_strategy; }; /** Wi-Fi TWT parameters */ diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 7974059625e..6e4ce100f43 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -235,6 +235,18 @@ const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode) } } +const char * const 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"; + } +} + static const struct wifi_mgmt_ops *const get_wifi_api(struct net_if *iface) { const struct device *dev = net_if_get_device(iface); @@ -515,6 +527,13 @@ static int wifi_set_power_save(uint32_t mgmt_request, struct net_if *iface, 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; diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 77d23fd5c0e..c5dc2d8edc0 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -915,6 +915,9 @@ static int cmd_wifi_ps(const struct shell *sh, size_t argc, char *argv[]) PR("PS timeout: disabled\n"); } + shell_fprintf(sh, SHELL_NORMAL, "PS exit strategy: %s\n", + wifi_ps_exit_strategy_txt(config.ps_params.exit_strategy)); + if (config.num_twt_flows == 0) { PR("No TWT flows\n"); } else { @@ -1482,6 +1485,40 @@ static int cmd_wifi_ps_wakeup_mode(const struct shell *sh, size_t argc, char *ar return 0; } +static int cmd_wifi_ps_exit_strategy(const struct shell *sh, size_t argc, + char *argv[]) +{ + struct net_if *iface = net_if_get_first_wifi(); + struct wifi_ps_params params = { 0 }; + + context.sh = sh; + + if (!strncmp(argv[1], "tim", 3)) { + params.exit_strategy = WIFI_PS_EXIT_EVERY_TIM; + } else if (!strncmp(argv[1], "custom", 6)) { + params.exit_strategy = WIFI_PS_EXIT_CUSTOM_ALGO; + } else { + shell_fprintf(sh, SHELL_WARNING, "Invalid argument\n"); + shell_fprintf(sh, SHELL_INFO, "Valid argument : / \n"); + return -ENOEXEC; + } + + params.type = WIFI_PS_PARAM_EXIT_STRATEGY; + + if (net_mgmt(NET_REQUEST_WIFI_PS, iface, ¶ms, sizeof(params))) { + shell_fprintf(sh, SHELL_WARNING, + "Setting PS exit strategy to %s failed..Reason :%s\n", + wifi_ps_exit_strategy_txt(params.exit_strategy), + wifi_ps_get_config_err_code_str(params.fail_reason)); + return -ENOEXEC; + } + + shell_fprintf(sh, SHELL_NORMAL, "%s\n", + wifi_ps_exit_strategy_txt(params.exit_strategy)); + + return 0; +} + void parse_mode_args_to_params(const struct shell *sh, int argc, char *argv[], struct wifi_mode_info *mode, bool *do_mode_oper) @@ -1977,6 +2014,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands, cmd_wifi_ps_wakeup_mode, 2, 0), + SHELL_CMD_ARG(ps_exit_strategy, + NULL, + " : Set PS exit strategy to Every TIM\n" + " : Set PS exit strategy to Custom", + cmd_wifi_ps_exit_strategy, + 2, + 0), SHELL_SUBCMD_SET_END );