1 /*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "sco_connection.h"
18
19 #include <hci/hci_packets.h>
20 #include <log.h>
21
22 #include <vector>
23
24 using namespace rootcanal;
25 using namespace bluetooth::hci;
26
IsExtended()27 bool ScoConnectionParameters::IsExtended() {
28 uint16_t legacy = (uint16_t)SynchronousPacketTypeBits::HV1_ALLOWED |
29 (uint16_t)SynchronousPacketTypeBits::HV2_ALLOWED |
30 (uint16_t)SynchronousPacketTypeBits::HV3_ALLOWED;
31 uint16_t edr = (uint16_t)SynchronousPacketTypeBits::NO_2_EV3_ALLOWED |
32 (uint16_t)SynchronousPacketTypeBits::NO_3_EV3_ALLOWED |
33 (uint16_t)SynchronousPacketTypeBits::NO_2_EV5_ALLOWED |
34 (uint16_t)SynchronousPacketTypeBits::NO_3_EV5_ALLOWED;
35 return ((packet_type ^ edr) & ~legacy) != 0;
36 }
37
GetLinkParameters()38 std::optional<ScoLinkParameters> ScoConnectionParameters::GetLinkParameters() {
39 // Coding conversion.
40 uint8_t air_coding_to_air_mode[] = {
41 0x02, // CVSD
42 0x00, // u-law
43 0x01, // A-law
44 0x03, // transparent data
45 };
46
47 // Prioritize eSCO connections.
48 // Packets HV1, HV2, HV3 are tested in a second phase.
49 struct Packet {
50 unsigned length;
51 unsigned slots;
52
53 Packet(unsigned length, unsigned slots) : length(length), slots(slots) {}
54 };
55
56 std::vector<Packet> accepted_packets;
57 accepted_packets.push_back(Packet(0, 1)); // POLL/NULL
58
59 if (packet_type & (uint16_t)SynchronousPacketTypeBits::EV3_ALLOWED)
60 accepted_packets.push_back(Packet(30, 1));
61 if (packet_type & (uint16_t)SynchronousPacketTypeBits::EV4_ALLOWED)
62 accepted_packets.push_back(Packet(120, 3));
63 if (packet_type & (uint16_t)SynchronousPacketTypeBits::EV5_ALLOWED)
64 accepted_packets.push_back(Packet(180, 3));
65 if ((packet_type & (uint16_t)SynchronousPacketTypeBits::NO_2_EV3_ALLOWED) ==
66 0)
67 accepted_packets.push_back(Packet(60, 1));
68 if ((packet_type & (uint16_t)SynchronousPacketTypeBits::NO_3_EV3_ALLOWED) ==
69 0)
70 accepted_packets.push_back(Packet(360, 3));
71 if ((packet_type & (uint16_t)SynchronousPacketTypeBits::NO_2_EV5_ALLOWED) ==
72 0)
73 accepted_packets.push_back(Packet(90, 1));
74 if ((packet_type & (uint16_t)SynchronousPacketTypeBits::NO_3_EV5_ALLOWED) ==
75 0)
76 accepted_packets.push_back(Packet(540, 3));
77
78 // Ignore empty bandwidths for now.
79 if (transmit_bandwidth == 0 || receive_bandwidth == 0) {
80 LOG_WARN("eSCO transmissions with null bandwidths are not supported");
81 return {};
82 }
83
84 // Bandwidth usage of the optimal selection.
85 double best_bandwidth_usage = 1.0;
86 std::optional<ScoLinkParameters> best_parameters = {};
87
88 // Explore all packet combinations, select the valid one
89 // with smallest actual bandwidth usage.
90 for (auto tx : accepted_packets) {
91 if (tx.length == 0) continue;
92
93 unsigned tx_max_interval = (1600 * tx.length) / transmit_bandwidth;
94
95 for (auto rx : accepted_packets) {
96 if (rx.length == 0) continue;
97
98 LOG_INFO("Testing combination %u/%u : %u/%u", tx.length, tx.slots,
99 rx.length, rx.slots);
100
101 unsigned rx_max_interval = (1600 * rx.length) / receive_bandwidth;
102
103 // Choose the best interval satisfying both.
104 unsigned transmission_interval =
105 std::min(tx_max_interval, rx_max_interval);
106 transmission_interval -= transmission_interval % 2;
107 transmission_interval = std::min(transmission_interval, 254u);
108
109 LOG_INFO("Transmission interval: %u slots", transmission_interval);
110
111 // Compute retransmission window.
112 unsigned retransmission_window =
113 retransmission_effort ==
114 (uint8_t)RetransmissionEffort::NO_RETRANSMISSION
115 ? 0
116 : retransmission_effort ==
117 (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_POWER
118 ? rx.slots + tx.slots
119 : retransmission_effort ==
120 (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_LINK_QUALITY
121 ? 2 * (rx.slots + tx.slots)
122 : 0;
123
124 LOG_INFO("Retransmission window: %u slots", retransmission_window);
125
126 // Compute transmission window and validate latency.
127 unsigned transmission_window =
128 tx.slots + rx.slots + retransmission_window;
129
130 // Validate window.
131 if (transmission_window > transmission_interval)
132 // Oops
133 continue;
134
135 // Compute and validate latency.
136 unsigned latency = (transmission_window * 1250) / 2;
137
138 LOG_INFO("Latency: %u us (max %u us)", latency, max_latency * 1000u);
139
140 if (latency > (1000 * max_latency))
141 // Oops
142 continue;
143
144 // We got a valid configuration.
145 // Evaluate the actual bandwidth usage.
146 double bandwidth_usage =
147 (double)transmission_window / (double)transmission_interval;
148
149 if (bandwidth_usage <= best_bandwidth_usage) {
150 LOG_INFO("Valid combination!");
151
152 uint16_t tx_packet_length =
153 (transmit_bandwidth * transmission_interval + 1600 - 1) / 1600;
154 uint16_t rx_packet_length =
155 (receive_bandwidth * transmission_interval + 1600 - 1) / 1600;
156 uint8_t air_coding = voice_setting & 0x3;
157
158 best_bandwidth_usage = bandwidth_usage;
159 best_parameters = {
160 (uint8_t)transmission_interval,
161 (uint8_t)retransmission_window,
162 rx_packet_length,
163 tx_packet_length,
164 air_coding_to_air_mode[air_coding],
165 true,
166 };
167 }
168 }
169 }
170
171 if (best_parameters.has_value()) {
172 return best_parameters;
173 }
174
175 // Parameter negotiation for SCO connections:
176 // Check packet types and validate bandwidth and latency requirements.
177
178 if (retransmission_effort ==
179 (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_POWER ||
180 retransmission_effort ==
181 (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_LINK_QUALITY) {
182 LOG_WARN("SCO Retransmission effort must be None or Don't care");
183 return {};
184 }
185
186 uint8_t transmission_interval;
187 uint16_t packet_length;
188 uint8_t air_coding = voice_setting & 0x3;
189
190 if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV3_ALLOWED) {
191 transmission_interval = 6;
192 packet_length = 30;
193 } else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV2_ALLOWED) {
194 transmission_interval = 4;
195 packet_length = 20;
196 } else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV1_ALLOWED) {
197 transmission_interval = 2;
198 packet_length = 10;
199 } else {
200 LOG_WARN("No SCO packet type enabled");
201 return {};
202 }
203
204 best_parameters = {
205 transmission_interval,
206 0,
207 packet_length,
208 packet_length,
209 air_coding_to_air_mode[air_coding],
210 false,
211 };
212 return best_parameters;
213 }
214
NegotiateLinkParameters(ScoConnectionParameters const & peer)215 bool ScoConnection::NegotiateLinkParameters(
216 ScoConnectionParameters const& peer) {
217 if (peer.transmit_bandwidth != 0xffff &&
218 peer.transmit_bandwidth != parameters_.receive_bandwidth) {
219 LOG_WARN("Transmit bandwidth requirements cannot be met");
220 return false;
221 }
222
223 if (state_ == SCO_STATE_SENT_ESCO_CONNECTION_REQUEST &&
224 peer.receive_bandwidth != 0xffff &&
225 peer.receive_bandwidth != parameters_.transmit_bandwidth) {
226 LOG_WARN("Receive bandwidth requirements cannot be met");
227 return false;
228 }
229
230 // mask out the air coding format bits before comparison, as per 5.3 Vol
231 // 4E 6.12
232 if ((peer.voice_setting & ~0x3) != (parameters_.voice_setting & ~0x3)) {
233 LOG_WARN("Voice setting requirements cannot be met");
234 LOG_WARN("Remote voice setting: 0x%04x",
235 static_cast<unsigned>(parameters_.voice_setting));
236 LOG_WARN("Local voice setting: 0x%04x",
237 static_cast<unsigned>(peer.voice_setting));
238 return false;
239 }
240
241 uint16_t packet_type = (peer.packet_type & parameters_.packet_type) & 0x3f;
242 packet_type |= (peer.packet_type | parameters_.packet_type) & 0x3c0;
243
244 if (packet_type == 0x3c0) {
245 LOG_WARN("Packet type requirements cannot be met");
246 LOG_WARN("Remote packet type: 0x%04x",
247 static_cast<unsigned>(parameters_.packet_type));
248 LOG_WARN("Local packet type: 0x%04x",
249 static_cast<unsigned>(peer.packet_type));
250 return false;
251 }
252
253 uint16_t max_latency =
254 peer.max_latency == 0xffff ? parameters_.max_latency
255 : parameters_.max_latency == 0xffff
256 ? peer.max_latency
257 : std::min(peer.max_latency, parameters_.max_latency);
258
259 uint8_t retransmission_effort;
260 if (state_ == SCO_STATE_SENT_SCO_CONNECTION_REQUEST)
261 retransmission_effort = (uint8_t)RetransmissionEffort::NO_RETRANSMISSION;
262 else if (peer.retransmission_effort == parameters_.retransmission_effort ||
263 peer.retransmission_effort ==
264 (uint8_t)RetransmissionEffort::DO_NOT_CARE)
265 retransmission_effort = parameters_.retransmission_effort;
266 else if (parameters_.retransmission_effort ==
267 (uint8_t)RetransmissionEffort::DO_NOT_CARE)
268 retransmission_effort = peer.retransmission_effort;
269 else if (peer.retransmission_effort ==
270 (uint8_t)RetransmissionEffort::NO_RETRANSMISSION ||
271 parameters_.retransmission_effort ==
272 (uint8_t)RetransmissionEffort::NO_RETRANSMISSION) {
273 LOG_WARN("Retransmission effort requirements cannot be met");
274 LOG_WARN("Remote retransmission effort: 0x%02x",
275 static_cast<unsigned>(parameters_.retransmission_effort));
276 LOG_WARN("Local retransmission effort: 0x%04x",
277 static_cast<unsigned>(peer.retransmission_effort));
278 return false;
279 } else {
280 retransmission_effort = (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_POWER;
281 }
282
283 ScoConnectionParameters negotiated_parameters = {
284 parameters_.transmit_bandwidth,
285 parameters_.receive_bandwidth,
286 max_latency,
287 parameters_.voice_setting,
288 retransmission_effort,
289 packet_type};
290
291 auto link_parameters = negotiated_parameters.GetLinkParameters();
292 if (link_parameters.has_value()) {
293 link_parameters_ = link_parameters.value();
294 LOG_INFO("Negotiated link parameters for SCO connection:");
295 LOG_INFO(" Transmission interval: %u slots",
296 static_cast<unsigned>(link_parameters_.transmission_interval));
297 LOG_INFO(" Retransmission window: %u slots",
298 static_cast<unsigned>(link_parameters_.retransmission_window));
299 LOG_INFO(" RX packet length: %u bytes",
300 static_cast<unsigned>(link_parameters_.rx_packet_length));
301 LOG_INFO(" TX packet length: %u bytes",
302 static_cast<unsigned>(link_parameters_.tx_packet_length));
303 LOG_INFO(" Air mode: %u",
304 static_cast<unsigned>(link_parameters_.air_mode));
305 } else {
306 LOG_WARN("Failed to derive link parameters");
307 }
308 return link_parameters.has_value();
309 }
310
StartStream(std::function<AsyncTaskId ()> startStream)311 void ScoConnection::StartStream(std::function<AsyncTaskId()> startStream) {
312 ASSERT(!stream_handle_.has_value());
313 if (datapath_ == ScoDatapath::SPOOFED) {
314 stream_handle_ = startStream();
315 }
316 }
317
StopStream(std::function<void (AsyncTaskId)> stopStream)318 void ScoConnection::StopStream(std::function<void(AsyncTaskId)> stopStream) {
319 if (stream_handle_.has_value()) {
320 stopStream(*stream_handle_);
321 }
322 stream_handle_ = std::nullopt;
323 }
324