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