Skip to content

Commit

Permalink
samples: wifi: twt: Add support for TWT setup
Browse files Browse the repository at this point in the history
Establish TWT with AP if AP is TWT capable and teardown after waiting
for a few sevice periods.

Implements SHEL-1654 partially.

Signed-off-by: Chiranjeevi Srikakulapu <chiranjeevi.srikakulapu@nordicsemi.no>
  • Loading branch information
chiranjeevi2776 authored and carlescufi committed Aug 22, 2023
1 parent 3c17ef6 commit 4a8332f
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 3 deletions.
25 changes: 25 additions & 0 deletions samples/wifi/twt/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,29 @@ config TWT_SAMPLE_PASSWORD
help
Specify the Password to connect

config TWT_TRIGGER_ENABLE
bool "Enable trigger mode"
help
STA expects AP to send triggers for start of every service period.
default y

config TWT_ANNOUNCED_MODE
bool "Enable announced mode"
help
STA announces its wakeup to AP for every service period start.
default y

config TWT_WAKE_INTERVAL
int "TWT awake interval"
help
The period where STA is awake and does data transfer, interval should be in us.
default 65000

config TWT_INTERVAL
int "TWT service interval"
help
The period for TWT that includes both wake and sleep durations, interval should be in us.
Please note higher intervals can be rejected by AP or cause interoperability issues.
default 524000

endmenu
13 changes: 13 additions & 0 deletions samples/wifi/twt/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,19 @@ Testing
[00:00:07.720,245] <inf> sta: MFP: UNKNOWN
[00:00:07.720,245] <inf> sta: RSSI: -57
[00:00:07.720,245] <inf> sta: Static IP address:
[00:01:14.217,224] <inf> twt: == TWT negotiated parameters ==
[00:01:14.217,224] <inf> twt: TWT Dialog token: 1
[00:01:14.217,224] <inf> twt: TWT flow ID: 1
[00:01:14.217,254] <inf> twt: TWT negotiation type: TWT individual negotiation
[00:01:14.217,285] <inf> twt: TWT responder: true
[00:01:14.217,315] <inf> twt: TWT implicit: true
[00:01:14.217,315] <inf> twt: TWT announce: true
[00:01:14.217,346] <inf> twt: TWT trigger: true
[00:01:14.217,376] <inf> twt: TWT wake interval: 65024 us
[00:01:14.217,376] <inf> twt: TWT interval: 524000 us
[00:01:14.217,376] <inf> twt: ========================
[00:01:14.439,270] <inf> twt: TWT Setup Success
[00:01:17.061,767] <inf> twt: TWT teardown success
Power management testing
************************
Expand Down
2 changes: 2 additions & 0 deletions samples/wifi/twt/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ CONFIG_WPA_SUPP=y
# CONFIG_TWT_STA_KEY_MGMT_WPA3=y
CONFIG_TWT_SAMPLE_SSID="Myssid"
CONFIG_TWT_SAMPLE_PASSWORD="Mypassword"
#CONFIG_TWT_TRIGGER_ENABLE=n
#CONFIG_TWT_ANNOUNCED_MODE=n

# System settings
CONFIG_NEWLIB_LIBC=y
Expand Down
174 changes: 171 additions & 3 deletions samples/wifi/twt/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ LOG_MODULE_REGISTER(twt, CONFIG_LOG_DEFAULT_LEVEL);
#define WIFI_SHELL_MODULE "wifi"

#define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_CONNECT_RESULT | \
NET_EVENT_WIFI_DISCONNECT_RESULT)
NET_EVENT_WIFI_DISCONNECT_RESULT| \
NET_EVENT_WIFI_TWT)

#define MAX_SSID_LEN 32
#define DHCP_TIMEOUT 70
#define CONNECTION_TIMEOUT 100
#define STATUS_POLLING_MS 300
#define TWT_RESP_TIMEOUT_S 20

static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
static struct net_mgmt_event_callback net_shell_mgmt_cb;
Expand All @@ -52,6 +54,77 @@ static struct {
};
} context;

static bool twt_supported, twt_resp_received;

static int wait_for_twt_resp_received(void)
{
int i, timeout_polls = (TWT_RESP_TIMEOUT_S * 1000) / STATUS_POLLING_MS;

for (i = 0; i < timeout_polls; i++) {
k_sleep(K_MSEC(STATUS_POLLING_MS));
if (twt_resp_received) {
return 1;
}
}

return 0;
}

static int setup_twt(void)
{
struct net_if *iface = net_if_get_first_wifi();
struct wifi_twt_params params = { 0 };
int ret;

params.operation = WIFI_TWT_SETUP;
params.negotiation_type = WIFI_TWT_INDIVIDUAL;
params.setup_cmd = WIFI_TWT_SETUP_CMD_REQUEST;
params.dialog_token = 1;
params.flow_id = 1;
params.setup.responder = 0;
params.setup.trigger = IS_ENABLED(CONFIG_TWT_TRIGGER_ENABLE);
params.setup.implicit = 1;
params.setup.announce = IS_ENABLED(CONFIG_TWT_ANNOUNCED_MODE);
params.setup.twt_wake_interval = CONFIG_TWT_WAKE_INTERVAL;
params.setup.twt_interval = CONFIG_TWT_INTERVAL;

ret = net_mgmt(NET_REQUEST_WIFI_TWT, iface, &params, sizeof(params));
if (ret) {
LOG_INF("TWT setup failed: %d", ret);
return ret;
}

LOG_INF("TWT setup requested");

return 0;
}

static int teardown_twt(void)
{
struct net_if *iface = net_if_get_first_wifi();
struct wifi_twt_params params = { 0 };
int ret;

params.operation = WIFI_TWT_TEARDOWN;
params.negotiation_type = WIFI_TWT_INDIVIDUAL;
params.setup_cmd = WIFI_TWT_TEARDOWN;
params.dialog_token = 1;
params.flow_id = 1;

ret = net_mgmt(NET_REQUEST_WIFI_TWT, iface, &params, sizeof(params));
if (ret) {
LOG_ERR("%s with %s failed, reason : %s",
wifi_twt_operation2str[params.operation],
wifi_twt_negotiation_type2str[params.negotiation_type],
get_twt_err_code_str(params.fail_reason));
return ret;
}

LOG_INF("TWT teardown success");

return 0;
}

static int cmd_wifi_status(void)
{
struct net_if *iface = net_if_get_default();
Expand Down Expand Up @@ -86,7 +159,12 @@ static int cmd_wifi_status(void)
LOG_INF("MFP: %s", wifi_mfp_txt(status.mfp));
LOG_INF("RSSI: %d", status.rssi);
LOG_INF("TWT: %s", status.twt_capable ? "Supported" : "Not supported");

if (status.twt_capable) {
twt_supported = 1;
}
}

return 0;
}

Expand Down Expand Up @@ -131,6 +209,63 @@ static void handle_wifi_disconnect_result(struct net_mgmt_event_callback *cb)
cmd_wifi_status();
}

static void print_twt_params(uint8_t dialog_token, uint8_t flow_id,
enum wifi_twt_negotiation_type negotiation_type,
bool responder, bool implicit, bool announce,
bool trigger, uint32_t twt_wake_interval,
uint64_t twt_interval)
{
LOG_INF("TWT Dialog token: %d",
dialog_token);
LOG_INF("TWT flow ID: %d",
flow_id);
LOG_INF("TWT negotiation type: %s",
wifi_twt_negotiation_type2str[negotiation_type]);
LOG_INF("TWT responder: %s",
responder ? "true" : "false");
LOG_INF("TWT implicit: %s",
implicit ? "true" : "false");
LOG_INF("TWT announce: %s",
announce ? "true" : "false");
LOG_INF("TWT trigger: %s",
trigger ? "true" : "false");
LOG_INF("TWT wake interval: %d us",
twt_wake_interval);
LOG_INF("TWT interval: %lld us",
twt_interval);
LOG_INF("========================");
}

static void handle_wifi_twt_event(struct net_mgmt_event_callback *cb)
{
const struct wifi_twt_params *resp =
(const struct wifi_twt_params *)cb->info;

if (resp->operation == WIFI_TWT_TEARDOWN) {
LOG_INF("TWT teardown received for flow ID %d\n",
resp->flow_id);
return;
}

if (resp->resp_status == WIFI_TWT_RESP_RECEIVED) {
twt_resp_received = 1;
LOG_INF("TWT response: %s",
wifi_twt_setup_cmd2str[resp->setup_cmd]);
LOG_INF("== TWT negotiated parameters ==");
print_twt_params(resp->dialog_token,
resp->flow_id,
resp->negotiation_type,
resp->setup.responder,
resp->setup.implicit,
resp->setup.announce,
resp->setup.trigger,
resp->setup.twt_wake_interval,
resp->setup.twt_interval);
} else {
LOG_INF("TWT response timed out\n");
}
}

static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event, struct net_if *iface)
{
Expand All @@ -141,6 +276,9 @@ static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb,
case NET_EVENT_WIFI_DISCONNECT_RESULT:
handle_wifi_disconnect_result(cb);
break;
case NET_EVENT_WIFI_TWT:
handle_wifi_twt_event(cb);
break;
default:
break;
}
Expand Down Expand Up @@ -248,7 +386,6 @@ int main(void)
CONFIG_NET_CONFIG_MY_IPV4_GW);

while (1) {

wifi_connect();

for (i = 0; i < CONNECTION_TIMEOUT; i++) {
Expand All @@ -258,8 +395,39 @@ int main(void)
break;
}
}

if (context.connected) {
k_sleep(K_FOREVER);
int ret;

k_sleep(K_SECONDS(2));

if (!twt_supported) {
LOG_INF("AP is not TWT capable, exiting the sample\n");
return 1;
}

LOG_INF("AP is TWT capable, establishing TWT");

ret = setup_twt();
if (ret) {
LOG_ERR("Failed to establish TWT flow: %d\n", ret);
return 1;
}

if (wait_for_twt_resp_received()) {
LOG_INF("TWT Setup success");
} else {
LOG_INF("TWT Setup timed out\n");
}

/* Wait for few service periods before tearing down */
k_sleep(K_USEC(5 * CONFIG_TWT_INTERVAL));
ret = teardown_twt();
if (ret) {
LOG_ERR("Failed to teardown TWT flow: %d\n", ret);
return 1;
}
return 0;
} else if (!context.connect_result) {
LOG_ERR("Connection Timed Out");
}
Expand Down

0 comments on commit 4a8332f

Please sign in to comment.