• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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