| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 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 | */ | 
|  | 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 */ |