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