Home | History | Annotate | Line # | Download | only in wpa_supplicant
      1 /*
      2  * wpa_supplicant - TWT
      3  * Copyright (c) 2003-2016, Jouni Malinen <j (at) 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  */
     29 int 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  */
    106 int 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