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