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