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