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