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