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