Skip to content

Commit 951d60d

Browse files
muahmed-silabskartben
authored andcommitted
drivers: wifi: siwx91x: Add support for TWT
- Implemented `siwx91x_set_twt_setup` and `siwx91x_set_twt_teardown` for handling TWT setup and teardown requests. - Added validation for TWT parameters, including negotiation type, device state, and operation type. - Integrated TWT functionality into the `wifi_mgmt_ops` structure for seamless management via the Zephyr Wi-Fi API. Signed-off-by: Muzaffar Ahmed <[email protected]>
1 parent 8b934dc commit 951d60d

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

drivers/wifi/siwx91x/siwx91x_wifi.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ LOG_MODULE_REGISTER(siwx91x_wifi);
2828

2929
NET_BUF_POOL_FIXED_DEFINE(siwx91x_tx_pool, 1, _NET_ETH_MAX_FRAME_SIZE, 0, NULL);
3030

31+
enum {
32+
REQUEST_TWT = 0,
33+
SUGGEST_TWT = 1,
34+
DEMAND_TWT = 2,
35+
};
36+
3137
static int siwx91x_sl_to_z_mode(sl_wifi_interface_t interface)
3238
{
3339
switch (interface) {
@@ -1067,6 +1073,137 @@ static int siwx91x_dev_init(const struct device *dev)
10671073
return 0;
10681074
}
10691075

1076+
static int siwx91x_convert_z_sl_twt_req_type(enum wifi_twt_setup_cmd z_req_cmd)
1077+
{
1078+
switch (z_req_cmd) {
1079+
case WIFI_TWT_SETUP_CMD_REQUEST:
1080+
return REQUEST_TWT;
1081+
case WIFI_TWT_SETUP_CMD_SUGGEST:
1082+
return SUGGEST_TWT;
1083+
case WIFI_TWT_SETUP_CMD_DEMAND:
1084+
return DEMAND_TWT;
1085+
default:
1086+
return -EINVAL;
1087+
}
1088+
}
1089+
1090+
static int siwx91x_set_twt_setup(struct wifi_twt_params *params)
1091+
{
1092+
sl_status_t status;
1093+
int twt_req_type = siwx91x_convert_z_sl_twt_req_type(params->setup_cmd);
1094+
1095+
sl_wifi_twt_request_t twt_req = {
1096+
.wake_duration_unit = 0,
1097+
.wake_int_mantissa = params->setup.twt_mantissa,
1098+
.un_announced_twt = !params->setup.announce,
1099+
.wake_duration = params->setup.twt_wake_interval,
1100+
.triggered_twt = params->setup.trigger,
1101+
.wake_int_exp = params->setup.twt_exponent,
1102+
.implicit_twt = 1,
1103+
.twt_flow_id = params->flow_id,
1104+
.twt_enable = 1,
1105+
.req_type = twt_req_type,
1106+
};
1107+
1108+
if (twt_req_type < 0) {
1109+
params->fail_reason = WIFI_TWT_FAIL_CMD_EXEC_FAIL;
1110+
return -EINVAL;
1111+
}
1112+
1113+
if (!params->setup.twt_info_disable) {
1114+
params->fail_reason = WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
1115+
return -ENOTSUP;
1116+
}
1117+
1118+
if (params->setup.responder) {
1119+
params->fail_reason = WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
1120+
return -ENOTSUP;
1121+
}
1122+
1123+
/* implicit -> won't do renegotiation
1124+
* explicit -> must do renegotiation for each session
1125+
*/
1126+
if (!params->setup.implicit) {
1127+
/* explicit twt is not supported */
1128+
params->fail_reason = WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
1129+
return -ENOTSUP;
1130+
}
1131+
1132+
if (params->setup.twt_wake_interval > 255 * 256) {
1133+
twt_req.wake_duration_unit = 1;
1134+
twt_req.wake_duration = params->setup.twt_wake_interval / 256;
1135+
} else {
1136+
twt_req.wake_duration_unit = 0;
1137+
twt_req.wake_duration = params->setup.twt_wake_interval / 1024;
1138+
}
1139+
1140+
status = sl_wifi_enable_target_wake_time(&twt_req);
1141+
if (status != SL_STATUS_OK) {
1142+
params->fail_reason = WIFI_TWT_FAIL_CMD_EXEC_FAIL;
1143+
params->resp_status = WIFI_TWT_RESP_NOT_RECEIVED;
1144+
return -EINVAL;
1145+
}
1146+
1147+
return 0;
1148+
}
1149+
1150+
static int siwx91x_set_twt_teardown(struct wifi_twt_params *params)
1151+
{
1152+
sl_status_t status;
1153+
sl_wifi_twt_request_t twt_req = { };
1154+
1155+
twt_req.twt_enable = 0;
1156+
1157+
if (params->teardown.teardown_all) {
1158+
twt_req.twt_flow_id = 0xFF;
1159+
} else {
1160+
twt_req.twt_flow_id = params->flow_id;
1161+
}
1162+
1163+
status = sl_wifi_disable_target_wake_time(&twt_req);
1164+
if (status != SL_STATUS_OK) {
1165+
params->fail_reason = WIFI_TWT_FAIL_CMD_EXEC_FAIL;
1166+
params->teardown_status = WIFI_TWT_TEARDOWN_FAILED;
1167+
return -EINVAL;
1168+
}
1169+
1170+
params->teardown_status = WIFI_TWT_TEARDOWN_SUCCESS;
1171+
1172+
return 0;
1173+
}
1174+
1175+
static int siwx91x_set_twt(const struct device *dev, struct wifi_twt_params *params)
1176+
{
1177+
sl_wifi_interface_t interface = sl_wifi_get_default_interface();
1178+
struct siwx91x_dev *sidev = dev->data;
1179+
1180+
__ASSERT(params, "params cannot be a NULL");
1181+
1182+
if (FIELD_GET(SIWX91X_INTERFACE_MASK, interface) != SL_WIFI_CLIENT_INTERFACE) {
1183+
params->fail_reason = WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
1184+
return -ENOTSUP;
1185+
}
1186+
1187+
if (sidev->state != WIFI_STATE_DISCONNECTED && sidev->state != WIFI_STATE_INACTIVE &&
1188+
sidev->state != WIFI_STATE_COMPLETED) {
1189+
LOG_ERR("Command given in invalid state");
1190+
return -EBUSY;
1191+
}
1192+
1193+
if (params->negotiation_type != WIFI_TWT_INDIVIDUAL) {
1194+
params->fail_reason = WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
1195+
return -ENOTSUP;
1196+
}
1197+
1198+
if (params->operation == WIFI_TWT_SETUP) {
1199+
return siwx91x_set_twt_setup(params);
1200+
} else if (params->operation == WIFI_TWT_TEARDOWN) {
1201+
return siwx91x_set_twt_teardown(params);
1202+
}
1203+
params->fail_reason = WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
1204+
return -ENOTSUP;
1205+
}
1206+
10701207
static const struct wifi_mgmt_ops siwx91x_mgmt = {
10711208
.scan = siwx91x_scan,
10721209
.connect = siwx91x_connect,
@@ -1076,6 +1213,7 @@ static const struct wifi_mgmt_ops siwx91x_mgmt = {
10761213
.ap_sta_disconnect = siwx91x_ap_sta_disconnect,
10771214
.iface_status = siwx91x_status,
10781215
.mode = siwx91x_mode,
1216+
.set_twt = siwx91x_set_twt,
10791217
#if defined(CONFIG_NET_STATISTICS_WIFI)
10801218
.get_stats = siwx91x_stats,
10811219
#endif

0 commit comments

Comments
 (0)