1/*
2 * wpa_supplicant - TWT
3 * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "includes.h"
10
11#include "utils/common.h"
12#include "wpa_supplicant_i.h"
13#include "driver_i.h"
14
15
16#ifdef CONFIG_TESTING_OPTIONS
17
18/**
19 * wpas_twt_send_setup - Send TWT Setup frame (Request) to our AP
20 * @wpa_s: Pointer to wpa_supplicant
21 * @dtok: Dialog token
22 * @exponent: Wake-interval exponent
23 * @mantissa: Wake-interval mantissa
24 * @min_twt: Minimum TWT wake duration in units of 256 usec
25 * @setup_cmd: 0 == request, 1 == suggest, etc.  Table 9-297
26 * Returns: 0 in case of success, negative error code otherwise
27 *
28 */
29int wpas_twt_send_setup(struct wpa_supplicant *wpa_s, u8 dtok, int exponent,
30			int mantissa, u8 min_twt, int setup_cmd, u64 twt,
31			bool requestor, bool trigger, bool implicit,
32			bool flow_type, u8 flow_id, bool protection,
33			u8 twt_channel, u8 control)
34{
35	struct wpabuf *buf;
36	u16 req_type = 0;
37	int ret = 0;
38
39	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
40		wpa_printf(MSG_DEBUG,
41			   "TWT: No connection - cannot send TWT Setup frame");
42		return -ENOTCONN;
43	}
44
45	/* 3 = Action category + Action code + Dialog token */
46	/* 17 = TWT element */
47	buf = wpabuf_alloc(3 + 17);
48	if (!buf) {
49		wpa_printf(MSG_DEBUG,
50			   "TWT: Failed to allocate TWT Setup frame (Request)");
51		return -ENOMEM;
52	}
53
54	wpa_printf(MSG_DEBUG,
55		   "TWT: Setup request, dtok: %d  exponent: %d  mantissa: %d  min-twt: %d",
56		   dtok, exponent, mantissa, min_twt);
57
58	wpabuf_put_u8(buf, WLAN_ACTION_S1G);
59	wpabuf_put_u8(buf, S1G_ACT_TWT_SETUP);
60	wpabuf_put_u8(buf, dtok);
61
62	wpabuf_put_u8(buf, WLAN_EID_TWT);
63	wpabuf_put_u8(buf, 15); /* len */
64
65	wpabuf_put_u8(buf, control);
66
67	if (requestor)
68		req_type |= BIT(0); /* This STA is a TWT Requesting STA */
69	/* TWT Setup Command field */
70	req_type |= (setup_cmd & 0x7) << 1;
71	if (trigger)
72		req_type |= BIT(4); /* TWT SP includes trigger frames */
73	if (implicit)
74		req_type |= BIT(5); /* Implicit TWT */
75	if (flow_type)
76		req_type |= BIT(6); /* Flow Type: Unannounced TWT */
77	req_type |= (flow_id & 0x7) << 7;
78	req_type |= (exponent & 0x1f) << 10; /* TWT Wake Interval Exponent */
79	if (protection)
80		req_type |= BIT(15);
81	wpabuf_put_le16(buf, req_type);
82	wpabuf_put_le64(buf, twt);
83	wpabuf_put_u8(buf, min_twt); /* Nominal Minimum TWT Wake Duration */
84	wpabuf_put_le16(buf, mantissa); /* TWT Wake Interval Mantissa */
85	wpabuf_put_u8(buf, twt_channel); /* TWT Channel */
86
87	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
88				wpa_s->own_addr, wpa_s->bssid,
89				wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
90		wpa_printf(MSG_DEBUG, "TWT: Failed to send TWT Setup Request");
91		ret = -ECANCELED;
92	}
93
94	wpabuf_free(buf);
95	return ret;
96}
97
98
99/**
100 * wpas_twt_send_teardown - Send TWT teardown request to our AP
101 * @wpa_s: Pointer to wpa_supplicant
102 * @flags: The byte that goes inside the TWT Teardown element
103 * Returns: 0 in case of success, negative error code otherwise
104 *
105 */
106int wpas_twt_send_teardown(struct wpa_supplicant *wpa_s, u8 flags)
107{
108	struct wpabuf *buf;
109	int ret = 0;
110
111	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
112		wpa_printf(MSG_DEBUG,
113			   "TWT: No connection - cannot send TWT Teardown frame");
114		return -ENOTCONN;
115	}
116
117	/* 3 = Action category + Action code + flags */
118	buf = wpabuf_alloc(3);
119	if (!buf) {
120		wpa_printf(MSG_DEBUG,
121			   "TWT: Failed to allocate TWT Teardown frame");
122		return -ENOMEM;
123	}
124
125	wpa_printf(MSG_DEBUG, "TWT: Teardown request, flags: 0x%x", flags);
126
127	wpabuf_put_u8(buf, WLAN_ACTION_S1G);
128	wpabuf_put_u8(buf, S1G_ACT_TWT_TEARDOWN);
129	wpabuf_put_u8(buf, flags);
130
131	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
132				wpa_s->own_addr, wpa_s->bssid,
133				wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
134		wpa_printf(MSG_DEBUG, "TWT: Failed to send TWT Teardown frame");
135		ret = -ECANCELED;
136	}
137
138	wpabuf_free(buf);
139	return ret;
140}
141
142#endif /* CONFIG_TESTING_OPTIONS */
143