• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 <bluetooth/log.h>
18 #include <poll.h>
19 #include <sys/socket.h>
20 #include <unistd.h>
21 
22 #include <vector>
23 
24 #include "btm_sco_hfp_hal.h"
25 #include "common/init_flags.h"
26 #include "hci/controller_interface.h"
27 #include "main/shim/entry.h"
28 #include "os/log.h"
29 #include "osi/include/properties.h"
30 #include "stack/include/hcimsgs.h"
31 #include "stack/include/sdpdefs.h"
32 
33 using namespace bluetooth;
34 using bluetooth::legacy::hci::GetInterface;
35 
36 namespace hfp_hal_interface {
37 namespace {
38 bool offload_supported = false;
39 bool offload_enabled = false;
40 
41 typedef struct cached_codec_info {
42   struct bt_codec inner;
43   size_t pkt_size;
44 } cached_codec_info;
45 
46 std::vector<cached_codec_info> cached_codecs;
47 
48 #define RETRY_ON_INTR(fn) \
49   do {                    \
50   } while ((fn) == -1 && errno == EINTR)
51 
52 #define MGMT_EV_SIZE_MAX 1024
53 #define MGMT_PKT_HDR_SIZE 6
54 struct mgmt_pkt {
55   uint16_t opcode;
56   uint16_t index;
57   uint16_t len;
58   uint8_t data[MGMT_EV_SIZE_MAX];
59 } __attribute__((packed));
60 
61 #define MGMT_EV_COMMAND_COMPLETE 0x1
62 
63 struct mgmt_ev_cmd_complete {
64   uint16_t opcode;
65   uint8_t status;
66   uint8_t data[];
67 } __attribute__((packed));
68 
69 #define MGMT_OP_GET_SCO_CODEC_CAPABILITIES 0x0100
70 #define MGMT_SCO_CODEC_CVSD 0x1
71 #define MGMT_SCO_CODEC_MSBC_TRANSPARENT 0x2
72 #define MGMT_SCO_CODEC_MSBC 0x3
73 
74 struct mgmt_cp_get_codec_capabilities {
75   uint16_t hci_dev;
76 } __attribute__((packed));
77 
78 struct mgmt_rp_get_codec_capabilities {
79   uint16_t hci_dev;
80   uint8_t transparent_wbs_supported;
81   uint8_t hci_data_path_id;
82   uint32_t wbs_pkt_len;
83 } __attribute__((packed));
84 
85 #define MGMT_POLL_TIMEOUT_MS 2000
86 
cache_codec_capabilities(struct mgmt_rp_get_codec_capabilities * rp)87 void cache_codec_capabilities(struct mgmt_rp_get_codec_capabilities* rp) {
88   const uint8_t kCodecMsbc = 0x5;
89 
90   // TODO(b/323087725): Query the codec capabilities and fill in c.inner.data.
91   // The capabilities are not used currently so it's safe to keep this for a
92   // while.
93 
94   // CVSD is mandatory in HFP.
95   cached_codecs.push_back({
96       .inner = {.codec = codec::CVSD},
97   });
98 
99   // No need to check GetLocalSupportedBrEdrCodecIds. Some legacy devices don't
100   // even support HCI command Read Local Supported Codecs so WBS quirk is more
101   // reliable.
102   if (rp->transparent_wbs_supported) {
103     cached_codecs.push_back({
104         .inner = {.codec = codec::MSBC_TRANSPARENT},
105         .pkt_size = rp->wbs_pkt_len,
106     });
107   }
108 
109   auto codecs =
110       bluetooth::shim::GetController()->GetLocalSupportedBrEdrCodecIds();
111   if (std::find(codecs.begin(), codecs.end(), kCodecMsbc) != codecs.end()) {
112     offload_supported = true;
113     cached_codecs.push_back({
114         .inner = {.codec = codec::MSBC, .data_path = rp->hci_data_path_id},
115         .pkt_size = rp->wbs_pkt_len,
116     });
117   }
118 
119   for (const auto& c : cached_codecs) {
120     log::info("Caching HFP codec {}, data path {}, data len {}, pkt_size {}",
121               (uint64_t)c.inner.codec, c.inner.data_path, c.inner.data.size(),
122               c.pkt_size);
123   }
124 }
125 
126 struct sockaddr_hci {
127   sa_family_t hci_family;
128   unsigned short hci_dev;
129   unsigned short hci_channel;
130 };
131 
132 constexpr uint8_t BTPROTO_HCI = 1;
133 constexpr uint16_t HCI_CHANNEL_CONTROL = 3;
134 constexpr uint16_t HCI_DEV_NONE = 0xffff;
135 
btsocket_open_mgmt(uint16_t hci)136 int btsocket_open_mgmt(uint16_t hci) {
137   int fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_NONBLOCK, BTPROTO_HCI);
138   if (fd < 0) {
139     log::debug("Failed to open BT socket.");
140     return -errno;
141   }
142 
143   struct sockaddr_hci addr = {
144       .hci_family = AF_BLUETOOTH,
145       .hci_dev = HCI_DEV_NONE,
146       .hci_channel = HCI_CHANNEL_CONTROL,
147   };
148 
149   int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
150   if (ret < 0) {
151     log::debug("Failed to bind BT socket.");
152     close(fd);
153     return -errno;
154   }
155 
156   return fd;
157 }
158 
mgmt_get_codec_capabilities(int fd,uint16_t hci)159 int mgmt_get_codec_capabilities(int fd, uint16_t hci) {
160   struct mgmt_pkt ev;
161   ev.opcode = MGMT_OP_GET_SCO_CODEC_CAPABILITIES;
162   ev.index = HCI_DEV_NONE;
163   ev.len = sizeof(struct mgmt_cp_get_codec_capabilities);
164 
165   struct mgmt_cp_get_codec_capabilities* cp =
166       reinterpret_cast<struct mgmt_cp_get_codec_capabilities*>(ev.data);
167   cp->hci_dev = hci;
168 
169   int ret;
170 
171   struct pollfd writable[1];
172   writable[0].fd = fd;
173   writable[0].events = POLLOUT;
174 
175   do {
176     ret = poll(writable, 1, MGMT_POLL_TIMEOUT_MS);
177     if (ret > 0) {
178       RETRY_ON_INTR(ret = write(fd, &ev, MGMT_PKT_HDR_SIZE + ev.len));
179       if (ret < 0) {
180         log::debug("Failed to call MGMT_OP_GET_SCO_CODEC_CAPABILITIES: {}",
181                    -errno);
182         return -errno;
183       };
184       break;
185     }
186   } while (ret > 0);
187 
188   if (ret <= 0) {
189     log::debug("Failed waiting for mgmt socket to be writable.");
190     return -1;
191   }
192 
193   struct pollfd fds[1];
194 
195   fds[0].fd = fd;
196   fds[0].events = POLLIN;
197 
198   do {
199     ret = poll(fds, 1, MGMT_POLL_TIMEOUT_MS);
200     if (ret > 0) {
201       if (fds[0].revents & POLLIN) {
202         RETRY_ON_INTR(ret = read(fd, &ev, sizeof(ev)));
203         if (ret < 0) {
204           log::debug("Failed to read mgmt socket: {}", -errno);
205           return -errno;
206         }
207 
208         if (ev.opcode == MGMT_EV_COMMAND_COMPLETE) {
209           struct mgmt_ev_cmd_complete* cc =
210               reinterpret_cast<struct mgmt_ev_cmd_complete*>(ev.data);
211           if (cc->opcode == MGMT_OP_GET_SCO_CODEC_CAPABILITIES &&
212               cc->status == 0) {
213             struct mgmt_rp_get_codec_capabilities* rp =
214                 reinterpret_cast<struct mgmt_rp_get_codec_capabilities*>(
215                     cc->data);
216             if (rp->hci_dev == hci) {
217               cache_codec_capabilities(rp);
218               return 0;
219             }
220           }
221         }
222       }
223     } else if (ret == 0) {
224       log::debug("Timeout while waiting for codec capabilities response.");
225       ret = -1;
226     }
227   } while (ret > 0);
228 
229   return ret;
230 }
231 
232 #define MGMT_OP_NOTIFY_SCO_CONNECTION_CHANGE 0x0101
233 struct mgmt_cp_notify_sco_connection_change {
234   uint16_t hci_dev;
235   uint8_t addr[6];
236   uint8_t addr_type;
237   uint8_t connected;
238   uint8_t codec;
239 } __attribute__((packed));
240 
mgmt_notify_sco_connection_change(int fd,int hci,RawAddress device,bool is_connected,int codec)241 int mgmt_notify_sco_connection_change(int fd, int hci, RawAddress device,
242                                       bool is_connected, int codec) {
243   struct mgmt_pkt ev;
244   ev.opcode = MGMT_OP_NOTIFY_SCO_CONNECTION_CHANGE;
245   ev.index = HCI_DEV_NONE;
246   ev.len = sizeof(struct mgmt_cp_notify_sco_connection_change);
247 
248   struct mgmt_cp_notify_sco_connection_change* cp =
249       reinterpret_cast<struct mgmt_cp_notify_sco_connection_change*>(ev.data);
250 
251   cp->hci_dev = hci;
252   cp->connected = is_connected;
253   cp->codec = codec;
254   memcpy(cp->addr, device.address, sizeof(cp->addr));
255   cp->addr_type = 0;
256 
257   int ret;
258 
259   struct pollfd writable[1];
260   writable[0].fd = fd;
261   writable[0].events = POLLOUT;
262 
263   do {
264     ret = poll(writable, 1, MGMT_POLL_TIMEOUT_MS);
265     if (ret > 0) {
266       RETRY_ON_INTR(ret = write(fd, &ev, MGMT_PKT_HDR_SIZE + ev.len));
267       if (ret < 0) {
268         log::error("Failed to call MGMT_OP_NOTIFY_SCO_CONNECTION_CHANGE: {}",
269                    -errno);
270         return -errno;
271       };
272       break;
273     }
274   } while (ret > 0);
275 
276   if (ret <= 0) {
277     log::debug("Failed waiting for mgmt socket to be writable.");
278     return -1;
279   }
280 
281   return 0;
282 }
283 }  // namespace
284 
init()285 void init() {
286   int hci = bluetooth::common::InitFlags::GetAdapterIndex();
287   int fd = btsocket_open_mgmt(hci);
288   if (fd < 0) {
289     log::error("Failed to open mgmt channel, error= {}.", fd);
290     return;
291   }
292 
293   int ret = mgmt_get_codec_capabilities(fd, hci);
294   if (ret) {
295     log::error("Failed to get codec capabilities with error = {}.", ret);
296   } else {
297     log::info("Successfully queried SCO codec capabilities.");
298   }
299 
300   close(fd);
301 }
302 
303 // Check if the specified coding format is supported by the adapter.
is_coding_format_supported(esco_coding_format_t coding_format)304 bool is_coding_format_supported(esco_coding_format_t coding_format) {
305   if (coding_format != ESCO_CODING_FORMAT_TRANSPNT &&
306       coding_format != ESCO_CODING_FORMAT_MSBC) {
307     log::warn("Unsupported coding format to query: {}", coding_format);
308     return false;
309   }
310 
311   for (cached_codec_info c : cached_codecs) {
312     if (c.inner.codec == MSBC_TRANSPARENT &&
313         coding_format == ESCO_CODING_FORMAT_TRANSPNT) {
314       return true;
315     }
316     if (c.inner.codec == MSBC && coding_format == ESCO_CODING_FORMAT_MSBC) {
317       return true;
318     }
319   }
320 
321   return false;
322 }
323 
324 // Check if wideband speech is supported on local device
get_wbs_supported()325 bool get_wbs_supported() {
326   return is_coding_format_supported(ESCO_CODING_FORMAT_TRANSPNT) ||
327          is_coding_format_supported(ESCO_CODING_FORMAT_MSBC);
328 }
329 
330 // Check if super-wideband speech is supported on local device
get_swb_supported()331 bool get_swb_supported() {
332   // We only support SWB via transparent mode.
333   return is_coding_format_supported(ESCO_CODING_FORMAT_TRANSPNT);
334 }
335 
336 // Checks the supported codecs
get_codec_capabilities(uint64_t codecs)337 bt_codecs get_codec_capabilities(uint64_t codecs) {
338   bt_codecs codec_list = {.offload_capable = offload_supported};
339 
340   for (auto c : cached_codecs) {
341     if (c.inner.codec & codecs) {
342       codec_list.codecs.push_back(c.inner);
343     }
344   }
345 
346   return codec_list;
347 }
348 
349 // Check if hardware offload is supported
get_offload_supported()350 bool get_offload_supported() { return offload_supported; }
351 
352 // Check if hardware offload is enabled
get_offload_enabled()353 bool get_offload_enabled() { return offload_supported && offload_enabled; }
354 
355 // Set offload enable/disable
enable_offload(bool enable)356 bool enable_offload(bool enable) {
357   if (!offload_supported && enable) {
358     log::error("Cannot enable SCO-offload since it is not supported.");
359     return false;
360   }
361   offload_enabled = enable;
362   return true;
363 }
364 
get_single_codec(int codec,bt_codec ** out)365 static bool get_single_codec(int codec, bt_codec** out) {
366   for (cached_codec_info& c : cached_codecs) {
367     if (c.inner.codec == codec) {
368       *out = &c.inner;
369       return true;
370     }
371   }
372 
373   return false;
374 }
375 
376 constexpr uint8_t OFFLOAD_DATAPATH = 0x01;
377 
378 // Notify the codec datapath to lower layer for offload mode
set_codec_datapath(int codec_uuid)379 void set_codec_datapath(int codec_uuid) {
380   bool found;
381   bt_codec* codec;
382   uint8_t codec_id;
383 
384   if (codec_uuid == UUID_CODEC_LC3 && get_offload_enabled()) {
385     log::error("Offload path for LC3 is not implemented.");
386     return;
387   }
388 
389   switch (codec_uuid) {
390     case UUID_CODEC_CVSD:
391       codec_id = codec::CVSD;
392       break;
393     case UUID_CODEC_MSBC:
394       codec_id = get_offload_enabled() ? codec::MSBC : codec::MSBC_TRANSPARENT;
395       break;
396     case UUID_CODEC_LC3:
397       codec_id = get_offload_enabled() ? codec::LC3 : codec::MSBC_TRANSPARENT;
398       break;
399     default:
400       log::warn("Unsupported codec ({}). Won't set datapath.", codec_uuid);
401       return;
402   }
403 
404   found = get_single_codec(codec_id, &codec);
405   if (!found) {
406     log::error(
407         "Failed to find codec config for codec ({}). Won't set datapath.",
408         codec_uuid);
409     return;
410   }
411 
412   log::info("Configuring datapath for codec ({})", codec_uuid);
413   if (codec->codec == codec::MSBC && !get_offload_enabled()) {
414     log::error(
415         "Tried to configure offload data path for format ({}) with offload "
416         "disabled. Won't set datapath.",
417         codec_uuid);
418     return;
419   }
420 
421   if (get_offload_enabled()) {
422     std::vector<uint8_t> data;
423     switch (codec_uuid) {
424       case UUID_CODEC_CVSD:
425         data = {0x00};
426         break;
427       case UUID_CODEC_MSBC:
428         data = {0x01};
429         break;
430       default:
431         break;
432     }
433 
434     GetInterface().ConfigureDataPath(hci_data_direction_t::CONTROLLER_TO_HOST,
435                                      OFFLOAD_DATAPATH, data);
436     GetInterface().ConfigureDataPath(hci_data_direction_t::HOST_TO_CONTROLLER,
437                                      OFFLOAD_DATAPATH, data);
438   }
439 }
440 
get_packet_size(int codec)441 size_t get_packet_size(int codec) {
442   for (const cached_codec_info& c : cached_codecs) {
443     if (c.inner.codec == codec) {
444       return c.pkt_size;
445     }
446   }
447 
448   return kDefaultPacketSize;
449 }
450 
notify_sco_connection_change(RawAddress device,bool is_connected,int codec)451 void notify_sco_connection_change(RawAddress device, bool is_connected,
452                                   int codec) {
453   int hci = bluetooth::common::InitFlags::GetAdapterIndex();
454   int fd = btsocket_open_mgmt(hci);
455   if (fd < 0) {
456     log::error("Failed to open mgmt channel, error= {}.", fd);
457     return;
458   }
459 
460   if (codec == codec::LC3) {
461     log::error("Offload path for LC3 is not implemented.");
462     return;
463   }
464 
465   int converted_codec;
466 
467   switch (codec) {
468     case codec::MSBC:
469       converted_codec = MGMT_SCO_CODEC_MSBC;
470       break;
471     case codec::MSBC_TRANSPARENT:
472       converted_codec = MGMT_SCO_CODEC_MSBC_TRANSPARENT;
473       break;
474     default:
475       converted_codec = MGMT_SCO_CODEC_CVSD;
476   }
477 
478   int ret = mgmt_notify_sco_connection_change(fd, hci, device, is_connected,
479                                               converted_codec);
480   if (ret) {
481     log::error(
482         "Failed to notify HAL of connection change: hci {}, device {}, "
483         "connected {}, codec {}",
484         hci, device, is_connected, codec);
485   } else {
486     log::info(
487         "Notified HAL of connection change: hci {}, device {}, connected {}, "
488         "codec {}",
489         hci, device, is_connected, codec);
490   }
491 
492   close(fd);
493 }
494 
update_esco_parameters(enh_esco_params_t * p_parms)495 void update_esco_parameters(enh_esco_params_t* p_parms) {
496   if (get_offload_enabled()) {
497     p_parms->input_transport_unit_size = 0x01;
498     p_parms->output_transport_unit_size = 0x01;
499   } else {
500     p_parms->input_transport_unit_size = 0x00;
501     p_parms->output_transport_unit_size = 0x00;
502   }
503 }
504 }  // namespace hfp_hal_interface
505