1 /******************************************************************************
2 *
3 * Copyright 2000-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains functions that handle SCO connections. This includes
22 * operations such as connect, disconnect, change supported packet types.
23 *
24 ******************************************************************************/
25
26 #include <base/strings/stringprintf.h>
27 #include <cstdint>
28 #include <string>
29
30 #include "device/include/controller.h"
31 #include "device/include/esco_parameters.h"
32 #include "osi/include/log.h"
33 #include "osi/include/osi.h"
34 #include "stack/btm/btm_sec.h"
35 #include "stack/btm/security_device_record.h"
36 #include "stack/include/acl_api.h"
37 #include "stack/include/btm_api.h"
38 #include "stack/include/btm_api_types.h"
39 #include "stack/include/hci_error_code.h"
40 #include "stack/include/hcimsgs.h"
41 #include "types/class_of_device.h"
42 #include "types/raw_address.h"
43
44 extern tBTM_CB btm_cb;
45
46 namespace {
47 constexpr char kBtmLogTag[] = "SCO";
48
GetLegacyHciInterface()49 const bluetooth::legacy::hci::Interface& GetLegacyHciInterface() {
50 return bluetooth::legacy::hci::GetInterface();
51 }
52
53 }; // namespace
54
55 /******************************************************************************/
56 /* L O C A L D A T A D E F I N I T I O N S */
57 /******************************************************************************/
58
59 #define BTM_SCO_PKT_TYPE_MASK \
60 (HCI_PKT_TYPES_MASK_HV1 | HCI_PKT_TYPES_MASK_HV2 | HCI_PKT_TYPES_MASK_HV3)
61
62 /* MACROs to convert from SCO packet types mask to ESCO and back */
63 #define BTM_SCO_PKT_TYPE_MASK \
64 (HCI_PKT_TYPES_MASK_HV1 | HCI_PKT_TYPES_MASK_HV2 | HCI_PKT_TYPES_MASK_HV3)
65
66 /* Mask defining only the SCO types of an esco packet type */
67 #define BTM_ESCO_PKT_TYPE_MASK \
68 (ESCO_PKT_TYPES_MASK_HV1 | ESCO_PKT_TYPES_MASK_HV2 | ESCO_PKT_TYPES_MASK_HV3)
69
70 #define BTM_ESCO_2_SCO(escotype) \
71 ((uint16_t)(((escotype)&BTM_ESCO_PKT_TYPE_MASK) << 5))
72
73 /* Define masks for supported and exception 2.0 SCO packet types
74 */
75 #define BTM_SCO_SUPPORTED_PKTS_MASK \
76 (ESCO_PKT_TYPES_MASK_HV1 | ESCO_PKT_TYPES_MASK_HV2 | \
77 ESCO_PKT_TYPES_MASK_HV3 | ESCO_PKT_TYPES_MASK_EV3 | \
78 ESCO_PKT_TYPES_MASK_EV4 | ESCO_PKT_TYPES_MASK_EV5)
79
80 #define BTM_SCO_EXCEPTION_PKTS_MASK \
81 (ESCO_PKT_TYPES_MASK_NO_2_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV3 | \
82 ESCO_PKT_TYPES_MASK_NO_2_EV5 | ESCO_PKT_TYPES_MASK_NO_3_EV5)
83
84 /******************************************************************************/
85 /* L O C A L F U N C T I O N P R O T O T Y P E S */
86 /******************************************************************************/
87
88 static uint16_t btm_sco_voice_settings_to_legacy(enh_esco_params_t* p_parms);
89
90 /*******************************************************************************
91 *
92 * Function btm_sco_flush_sco_data
93 *
94 * Description This function is called to flush the SCO data for this
95 * channel.
96 *
97 * Returns void
98 *
99 ******************************************************************************/
btm_sco_flush_sco_data(UNUSED_ATTR uint16_t sco_inx)100 static void btm_sco_flush_sco_data(UNUSED_ATTR uint16_t sco_inx) {}
101
102 /*******************************************************************************
103 *
104 * Function btm_esco_conn_rsp
105 *
106 * Description This function is called upon receipt of an (e)SCO connection
107 * request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject
108 * the request. Parameters used to negotiate eSCO links.
109 * If p_parms is NULL, then default values are used.
110 * If the link type of the incoming request is SCO, then only
111 * the tx_bw, max_latency, content format, and packet_types are
112 * valid. The hci_status parameter should be
113 * ([0x0] to accept, [0x0d..0x0f] to reject)
114 *
115 * Returns void
116 *
117 ******************************************************************************/
btm_esco_conn_rsp(uint16_t sco_inx,uint8_t hci_status,const RawAddress & bda,enh_esco_params_t * p_parms)118 static void btm_esco_conn_rsp(uint16_t sco_inx, uint8_t hci_status,
119 const RawAddress& bda,
120 enh_esco_params_t* p_parms) {
121 tSCO_CONN* p_sco = NULL;
122
123 if (BTM_MAX_SCO_LINKS == 0) return;
124
125 if (sco_inx < BTM_MAX_SCO_LINKS) p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
126
127 /* Reject the connect request if refused by caller or wrong state */
128 if (hci_status != HCI_SUCCESS || p_sco == NULL) {
129 if (p_sco) {
130 p_sco->state = (p_sco->state == SCO_ST_W4_CONN_RSP) ? SCO_ST_LISTENING
131 : SCO_ST_UNUSED;
132 }
133 if (!btm_cb.sco_cb.esco_supported) {
134 btsnd_hcic_reject_conn(bda, hci_status);
135 } else {
136 btsnd_hcic_reject_esco_conn(bda, hci_status);
137 }
138 } else {
139 /* Connection is being accepted */
140 p_sco->state = SCO_ST_CONNECTING;
141 enh_esco_params_t* p_setup = &p_sco->esco.setup;
142 /* If parameters not specified use the default */
143 if (p_parms) {
144 *p_setup = *p_parms;
145 } else {
146 /* Use the last setup passed thru BTM_SetEscoMode (or defaults) */
147 *p_setup = btm_cb.sco_cb.def_esco_parms;
148 }
149
150 /* Use Enhanced Synchronous commands if supported */
151 if (controller_get_interface()
152 ->supports_enhanced_setup_synchronous_connection()) {
153 /* Use the saved SCO routing */
154 p_setup->input_data_path = p_setup->output_data_path =
155 btm_cb.sco_cb.sco_route;
156
157 BTM_TRACE_DEBUG(
158 "%s: txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, "
159 "pkt 0x%04x, path %u",
160 __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
161 p_setup->max_latency_ms, p_setup->retransmission_effort,
162 p_setup->packet_types, p_setup->input_data_path);
163
164 btsnd_hcic_enhanced_accept_synchronous_connection(bda, p_setup);
165
166 } else {
167 /* Use legacy command if enhanced SCO setup is not supported */
168 uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
169 btsnd_hcic_accept_esco_conn(
170 bda, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
171 p_setup->max_latency_ms, voice_content_format,
172 p_setup->retransmission_effort, p_setup->packet_types);
173 }
174 }
175 }
176
177 /*******************************************************************************
178 *
179 * Function btm_route_sco_data
180 *
181 * Description Route received SCO data.
182 *
183 * Returns void
184 *
185 ******************************************************************************/
btm_route_sco_data(BT_HDR * p_msg)186 void btm_route_sco_data(BT_HDR* p_msg) {
187 osi_free(p_msg);
188 }
189
190 /*******************************************************************************
191 *
192 * Function btm_send_connect_request
193 *
194 * Description This function is called to respond to SCO connect
195 * indications
196 *
197 * Returns void
198 *
199 ******************************************************************************/
btm_send_connect_request(uint16_t acl_handle,enh_esco_params_t * p_setup)200 static tBTM_STATUS btm_send_connect_request(uint16_t acl_handle,
201 enh_esco_params_t* p_setup) {
202 /* Send connect request depending on version of spec */
203 if (!btm_cb.sco_cb.esco_supported) {
204 LOG(INFO) << __func__ << ": sending non-eSCO request for handle="
205 << unsigned(acl_handle);
206 btsnd_hcic_add_SCO_conn(acl_handle, BTM_ESCO_2_SCO(p_setup->packet_types));
207 } else {
208 uint16_t temp_packet_types =
209 (p_setup->packet_types &
210 static_cast<uint16_t>(BTM_SCO_SUPPORTED_PKTS_MASK) &
211 btm_cb.btm_sco_pkt_types_supported);
212
213 /* OR in any exception packet types */
214 temp_packet_types |=
215 ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
216 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
217
218 /* Finally, remove EDR eSCO if the remote device doesn't support it */
219 /* UPF25: Only SCO was brought up in this case */
220 const RawAddress bd_addr = acl_address_from_handle(acl_handle);
221 if (bd_addr != RawAddress::kEmpty) {
222 if (!sco_peer_supports_esco_2m_phy(bd_addr)) {
223 BTM_TRACE_DEBUG("BTM Remote does not support 2-EDR eSCO");
224 temp_packet_types |=
225 (ESCO_PKT_TYPES_MASK_NO_2_EV3 | ESCO_PKT_TYPES_MASK_NO_2_EV5);
226 }
227 if (!sco_peer_supports_esco_3m_phy(bd_addr)) {
228 BTM_TRACE_DEBUG("BTM Remote does not support 3-EDR eSCO");
229 temp_packet_types |=
230 (ESCO_PKT_TYPES_MASK_NO_3_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV5);
231 }
232
233 /* Check to see if BR/EDR Secure Connections is being used
234 ** If so, we cannot use SCO-only packet types (HFP 1.7)
235 */
236 const bool local_supports_sc =
237 controller_get_interface()->supports_secure_connections();
238 const bool remote_supports_sc =
239 BTM_PeerSupportsSecureConnections(bd_addr);
240
241 if (local_supports_sc && remote_supports_sc) {
242 temp_packet_types &= ~(BTM_SCO_PKT_TYPE_MASK);
243 if (temp_packet_types == 0) {
244 LOG_ERROR(
245 "SCO connection cannot support any packet types for "
246 "acl_handle:0x%04x",
247 acl_handle);
248 return BTM_WRONG_MODE;
249 }
250 LOG_DEBUG(
251 "Both local and remote controllers support SCO secure connections "
252 "handle:0x%04x pkt_types:0x%04x",
253 acl_handle, temp_packet_types);
254
255 } else if (!local_supports_sc && !remote_supports_sc) {
256 LOG_DEBUG(
257 "Both local and remote controllers do not support secure "
258 "connections for handle:0x%04x",
259 acl_handle);
260 } else if (remote_supports_sc) {
261 LOG_DEBUG(
262 "Only remote controller supports secure connections for "
263 "handle:0x%04x",
264 acl_handle);
265 } else {
266 LOG_DEBUG(
267 "Only local controller supports secure connections for "
268 "handle:0x%04x",
269 acl_handle);
270 }
271 } else {
272 LOG_ERROR("Received SCO connect from unknown peer:%s",
273 PRIVATE_ADDRESS(bd_addr));
274 }
275
276 /* Save the previous types in case command fails */
277 uint16_t saved_packet_types = p_setup->packet_types;
278 p_setup->packet_types = temp_packet_types;
279
280 /* Use Enhanced Synchronous commands if supported */
281 if (controller_get_interface()
282 ->supports_enhanced_setup_synchronous_connection()) {
283 LOG_INFO("Sending enhanced SCO connect request over handle:0x%04x",
284 acl_handle);
285 /* Use the saved SCO routing */
286 p_setup->input_data_path = p_setup->output_data_path =
287 btm_cb.sco_cb.sco_route;
288 LOG(INFO) << __func__ << std::hex << ": enhanced parameter list"
289 << " txbw=0x" << unsigned(p_setup->transmit_bandwidth)
290 << ", rxbw=0x" << unsigned(p_setup->receive_bandwidth)
291 << ", latency_ms=0x" << unsigned(p_setup->max_latency_ms)
292 << ", retransmit_effort=0x"
293 << unsigned(p_setup->retransmission_effort) << ", pkt_type=0x"
294 << unsigned(p_setup->packet_types) << ", path=0x"
295 << unsigned(p_setup->input_data_path);
296 btsnd_hcic_enhanced_set_up_synchronous_connection(acl_handle, p_setup);
297 p_setup->packet_types = saved_packet_types;
298 } else { /* Use older command */
299 LOG_INFO("Sending eSCO connect request over handle:0x%04x", acl_handle);
300 uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
301 LOG(INFO) << __func__ << std::hex << ": legacy parameter list"
302 << " txbw=0x" << unsigned(p_setup->transmit_bandwidth)
303 << ", rxbw=0x" << unsigned(p_setup->receive_bandwidth)
304 << ", latency_ms=0x" << unsigned(p_setup->max_latency_ms)
305 << ", retransmit_effort=0x"
306 << unsigned(p_setup->retransmission_effort)
307 << ", voice_content_format=0x" << unsigned(voice_content_format)
308 << ", pkt_type=0x" << unsigned(p_setup->packet_types);
309 btsnd_hcic_setup_esco_conn(
310 acl_handle, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
311 p_setup->max_latency_ms, voice_content_format,
312 p_setup->retransmission_effort, p_setup->packet_types);
313 }
314 }
315
316 return (BTM_CMD_STARTED);
317 }
318
319 /*******************************************************************************
320 *
321 * Function BTM_CreateSco
322 *
323 * Description This function is called to create an SCO connection. If the
324 * "is_orig" flag is true, the connection will be originated,
325 * otherwise BTM will wait for the other side to connect.
326 *
327 * NOTE: If BTM_IGNORE_SCO_PKT_TYPE is passed in the pkt_types
328 * parameter the default packet types is used.
329 *
330 * Returns BTM_UNKNOWN_ADDR if the ACL connection is not up
331 * BTM_BUSY if another SCO being set up to
332 * the same BD address
333 * BTM_NO_RESOURCES if the max SCO limit has been reached
334 * BTM_CMD_STARTED if the connection establishment is started.
335 * In this case, "*p_sco_inx" is filled in
336 * with the sco index used for the connection.
337 *
338 ******************************************************************************/
BTM_CreateSco(const RawAddress * remote_bda,bool is_orig,uint16_t pkt_types,uint16_t * p_sco_inx,tBTM_SCO_CB * p_conn_cb,tBTM_SCO_CB * p_disc_cb)339 tBTM_STATUS BTM_CreateSco(const RawAddress* remote_bda, bool is_orig,
340 uint16_t pkt_types, uint16_t* p_sco_inx,
341 tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) {
342 enh_esco_params_t* p_setup;
343 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
344 uint16_t xx;
345 uint16_t acl_handle = HCI_INVALID_HANDLE;
346 *p_sco_inx = BTM_INVALID_SCO_INDEX;
347
348 if (BTM_MAX_SCO_LINKS == 0) {
349 return BTM_NO_RESOURCES;
350 }
351
352 /* If originating, ensure that there is an ACL connection to the BD Address */
353
354 if (is_orig) {
355 if (!remote_bda) {
356 LOG(ERROR) << __func__ << ": remote_bda is null";
357 return BTM_ILLEGAL_VALUE;
358 }
359 acl_handle = BTM_GetHCIConnHandle(*remote_bda, BT_TRANSPORT_BR_EDR);
360 if (acl_handle == HCI_INVALID_HANDLE) {
361 LOG(ERROR) << __func__ << ": cannot find ACL handle for remote device "
362 << remote_bda;
363 return BTM_UNKNOWN_ADDR;
364 }
365 }
366
367 if (remote_bda) {
368 /* If any SCO is being established to the remote BD address, refuse this */
369 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
370 if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
371 (p->state == SCO_ST_PEND_UNPARK)) &&
372 (p->esco.data.bd_addr == *remote_bda)) {
373 LOG(ERROR) << __func__ << ": a sco connection is already going on for "
374 << *remote_bda << ", at state " << unsigned(p->state);
375 return BTM_BUSY;
376 }
377 }
378 } else {
379 /* Support only 1 wildcard BD address at a time */
380 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
381 if ((p->state == SCO_ST_LISTENING) && (!p->rem_bd_known)) {
382 LOG(ERROR)
383 << __func__
384 << ": remote_bda is null and not known and we are still listening";
385 return BTM_BUSY;
386 }
387 }
388 }
389
390 /* Try to find an unused control block, and kick off the SCO establishment */
391 for (xx = 0, p = &btm_cb.sco_cb.sco_db[0]; xx < BTM_MAX_SCO_LINKS;
392 xx++, p++) {
393 if (p->state == SCO_ST_UNUSED) {
394 if (remote_bda) {
395 if (is_orig) {
396 // can not create SCO link if in park mode
397 tBTM_PM_STATE state;
398 if (BTM_ReadPowerMode(*remote_bda, &state)) {
399 if (state == BTM_PM_ST_SNIFF || state == BTM_PM_ST_PARK ||
400 state == BTM_PM_ST_PENDING) {
401 LOG(INFO) << __func__ << ": " << *remote_bda
402 << " in sniff, park or pending mode "
403 << unsigned(state);
404 if (!BTM_SetLinkPolicyActiveMode(*remote_bda)) {
405 LOG_WARN("Unable to set link policy active");
406 }
407 p->state = SCO_ST_PEND_UNPARK;
408 }
409 } else {
410 LOG(ERROR) << __func__ << ": failed to read power mode for "
411 << *remote_bda;
412 }
413 }
414 p->esco.data.bd_addr = *remote_bda;
415 p->rem_bd_known = true;
416 } else
417 p->rem_bd_known = false;
418
419 p_setup = &p->esco.setup;
420 *p_setup = btm_cb.sco_cb.def_esco_parms;
421
422 /* Determine the packet types */
423 p_setup->packet_types = pkt_types & BTM_SCO_SUPPORTED_PKTS_MASK &
424 btm_cb.btm_sco_pkt_types_supported;
425 /* OR in any exception packet types */
426 if (controller_get_interface()->get_bt_version()->hci_version >=
427 HCI_PROTO_VERSION_2_0) {
428 p_setup->packet_types |=
429 (pkt_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
430 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK);
431 }
432
433 p->p_conn_cb = p_conn_cb;
434 p->p_disc_cb = p_disc_cb;
435 p->hci_handle = HCI_INVALID_HANDLE;
436 p->is_orig = is_orig;
437
438 if (p->state != SCO_ST_PEND_UNPARK) {
439 if (is_orig) {
440 /* If role change is in progress, do not proceed with SCO setup
441 * Wait till role change is complete */
442 if (!acl_is_switch_role_idle(*remote_bda, BT_TRANSPORT_BR_EDR)) {
443 BTM_TRACE_API("Role Change is in progress for ACL handle 0x%04x",
444 acl_handle);
445 p->state = SCO_ST_PEND_ROLECHANGE;
446 }
447 }
448 }
449
450 if (p->state != SCO_ST_PEND_UNPARK &&
451 p->state != SCO_ST_PEND_ROLECHANGE) {
452 if (is_orig) {
453 LOG_DEBUG("Initiating (e)SCO link for ACL handle:0x%04x", acl_handle);
454
455 if ((btm_send_connect_request(acl_handle, p_setup)) !=
456 BTM_CMD_STARTED) {
457 LOG(ERROR) << __func__ << ": failed to send connect request for "
458 << *remote_bda;
459 return (BTM_NO_RESOURCES);
460 }
461
462 p->state = SCO_ST_CONNECTING;
463 } else {
464 LOG_DEBUG("Listening for (e)SCO on ACL handle:0x%04x", acl_handle);
465 p->state = SCO_ST_LISTENING;
466 }
467 }
468
469 *p_sco_inx = xx;
470 LOG_DEBUG("SCO connection successfully requested");
471 if (p->state == SCO_ST_CONNECTING) {
472 BTM_LogHistory(
473 kBtmLogTag, *remote_bda, "Connecting",
474 base::StringPrintf("local initiated acl:0x%04x", acl_handle));
475 }
476 return BTM_CMD_STARTED;
477 }
478 }
479
480 /* If here, all SCO blocks in use */
481 LOG(ERROR) << __func__ << ": all SCO control blocks are in use";
482 return BTM_NO_RESOURCES;
483 }
484
485 /*******************************************************************************
486 *
487 * Function btm_sco_chk_pend_unpark
488 *
489 * Description This function is called by BTIF when there is a mode change
490 * event to see if there are SCO commands waiting for the
491 * unpark.
492 *
493 * Returns void
494 *
495 ******************************************************************************/
btm_sco_chk_pend_unpark(tHCI_STATUS hci_status,uint16_t hci_handle)496 void btm_sco_chk_pend_unpark(tHCI_STATUS hci_status, uint16_t hci_handle) {
497 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
498 for (uint16_t xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
499 uint16_t acl_handle =
500 BTM_GetHCIConnHandle(p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR);
501 if ((p->state == SCO_ST_PEND_UNPARK) && (acl_handle == hci_handle)) {
502 LOG(INFO) << __func__ << ": " << p->esco.data.bd_addr
503 << " unparked, sending connection request, acl_handle="
504 << unsigned(acl_handle)
505 << ", hci_status=" << unsigned(hci_status);
506 if (btm_send_connect_request(acl_handle, &p->esco.setup) ==
507 BTM_CMD_STARTED) {
508 p->state = SCO_ST_CONNECTING;
509 } else {
510 LOG(ERROR) << __func__ << ": failed to send connection request for "
511 << p->esco.data.bd_addr;
512 }
513 }
514 }
515 }
516
517 /*******************************************************************************
518 *
519 * Function btm_sco_chk_pend_rolechange
520 *
521 * Description This function is called by BTIF when there is a role change
522 * event to see if there are SCO commands waiting for the role
523 * change.
524 *
525 * Returns void
526 *
527 ******************************************************************************/
btm_sco_chk_pend_rolechange(uint16_t hci_handle)528 void btm_sco_chk_pend_rolechange(uint16_t hci_handle) {
529 uint16_t xx;
530 uint16_t acl_handle;
531 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
532
533 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
534 if ((p->state == SCO_ST_PEND_ROLECHANGE) &&
535 ((acl_handle = BTM_GetHCIConnHandle(
536 p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle))
537
538 {
539 BTM_TRACE_API(
540 "btm_sco_chk_pend_rolechange -> (e)SCO Link for ACL handle 0x%04x",
541 acl_handle);
542
543 if ((btm_send_connect_request(acl_handle, &p->esco.setup)) ==
544 BTM_CMD_STARTED)
545 p->state = SCO_ST_CONNECTING;
546 }
547 }
548 }
549
550 /*******************************************************************************
551 *
552 * Function btm_sco_disc_chk_pend_for_modechange
553 *
554 * Description This function is called by btm when there is a mode change
555 * event to see if there are SCO disconnect commands waiting
556 * for the mode change.
557 *
558 * Returns void
559 *
560 ******************************************************************************/
btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle)561 void btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle) {
562 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
563
564 LOG_DEBUG(
565 "Checking for SCO pending mode change events hci_handle:0x%04x "
566 "p->state:%s",
567 hci_handle, sco_state_text(p->state).c_str());
568
569 for (uint16_t xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
570 if ((p->state == SCO_ST_PEND_MODECHANGE) &&
571 (BTM_GetHCIConnHandle(p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) ==
572 hci_handle)
573
574 {
575 LOG_DEBUG("Removing SCO Link handle 0x%04x", p->hci_handle);
576 BTM_RemoveSco(xx);
577 }
578 }
579 }
580
581 /*******************************************************************************
582 *
583 * Function btm_sco_conn_req
584 *
585 * Description This function is called by BTU HCIF when an SCO connection
586 * request is received from a remote.
587 *
588 * Returns void
589 *
590 ******************************************************************************/
btm_sco_conn_req(const RawAddress & bda,const DEV_CLASS & dev_class,uint8_t link_type)591 void btm_sco_conn_req(const RawAddress& bda, const DEV_CLASS& dev_class,
592 uint8_t link_type) {
593 tSCO_CB* p_sco = &btm_cb.sco_cb;
594 tSCO_CONN* p = &p_sco->sco_db[0];
595 tBTM_ESCO_CONN_REQ_EVT_DATA evt_data = {};
596
597 for (uint16_t sco_index = 0; sco_index < BTM_MAX_SCO_LINKS;
598 sco_index++, p++) {
599 /*
600 * If the sco state is in the SCO_ST_CONNECTING state, we still need
601 * to return accept sco to avoid race conditon for sco creation
602 */
603 bool rem_bd_matches = p->rem_bd_known && p->esco.data.bd_addr == bda;
604 if (((p->state == SCO_ST_CONNECTING) && rem_bd_matches) ||
605 ((p->state == SCO_ST_LISTENING) &&
606 (rem_bd_matches || !p->rem_bd_known))) {
607 /* If this was a wildcard, it is not one any more */
608 p->rem_bd_known = true;
609 p->esco.data.link_type = link_type;
610 p->state = SCO_ST_W4_CONN_RSP;
611 p->esco.data.bd_addr = bda;
612
613 /* If no callback, auto-accept the connection if packet types match */
614 if (!p->esco.p_esco_cback) {
615 /* If requesting eSCO reject if default parameters are SCO only */
616 if ((link_type == BTM_LINK_TYPE_ESCO &&
617 !(p_sco->def_esco_parms.packet_types & BTM_ESCO_LINK_ONLY_MASK) &&
618 ((p_sco->def_esco_parms.packet_types &
619 BTM_SCO_EXCEPTION_PKTS_MASK) == BTM_SCO_EXCEPTION_PKTS_MASK))
620
621 /* Reject request if SCO is desired but no SCO packets delected */
622 ||
623 (link_type == BTM_LINK_TYPE_SCO &&
624 !(p_sco->def_esco_parms.packet_types & BTM_SCO_LINK_ONLY_MASK))) {
625 btm_esco_conn_rsp(sco_index, HCI_ERR_HOST_REJECT_RESOURCES, bda,
626 nullptr);
627 } else {
628 /* Accept the request */
629 btm_esco_conn_rsp(sco_index, HCI_SUCCESS, bda, nullptr);
630 }
631 } else {
632 /* Notify upper layer of connect indication */
633 evt_data.bd_addr = bda;
634 memcpy(evt_data.dev_class, dev_class, DEV_CLASS_LEN);
635 evt_data.link_type = link_type;
636 evt_data.sco_inx = sco_index;
637 tBTM_ESCO_EVT_DATA btm_esco_evt_data = {};
638 btm_esco_evt_data.conn_evt = evt_data;
639 p->esco.p_esco_cback(BTM_ESCO_CONN_REQ_EVT, &btm_esco_evt_data);
640 }
641
642 return;
643 }
644 }
645
646 /* TCS usage */
647 if (btm_cb.sco_cb.app_sco_ind_cb) {
648 /* Now, try to find an unused control block */
649 uint16_t sco_index;
650 for (sco_index = 0, p = &btm_cb.sco_cb.sco_db[0];
651 sco_index < BTM_MAX_SCO_LINKS; sco_index++, p++) {
652 if (p->state == SCO_ST_UNUSED) {
653 p->is_orig = false;
654 p->state = SCO_ST_LISTENING;
655
656 p->esco.data.link_type = link_type;
657 p->esco.data.bd_addr = bda;
658 p->rem_bd_known = true;
659 break;
660 }
661 }
662 if (sco_index < BTM_MAX_SCO_LINKS) {
663 btm_cb.sco_cb.app_sco_ind_cb(sco_index);
664 return;
665 }
666 }
667
668 /* If here, no one wants the SCO connection. Reject it */
669 BTM_TRACE_WARNING("%s: rejecting SCO for %s", __func__,
670 bda.ToString().c_str());
671 btm_esco_conn_rsp(BTM_MAX_SCO_LINKS, HCI_ERR_HOST_REJECT_RESOURCES, bda,
672 nullptr);
673 }
674
675 /*******************************************************************************
676 *
677 * Function btm_sco_connected
678 *
679 * Description This function is called by BTIF when an (e)SCO connection
680 * is connected.
681 *
682 * Returns void
683 *
684 ******************************************************************************/
btm_sco_connected(tHCI_STATUS hci_status,const RawAddress & bda,uint16_t hci_handle,tBTM_ESCO_DATA * p_esco_data)685 void btm_sco_connected(tHCI_STATUS hci_status, const RawAddress& bda,
686 uint16_t hci_handle, tBTM_ESCO_DATA* p_esco_data) {
687 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
688 uint16_t xx;
689 bool spt = false;
690 tBTM_CHG_ESCO_PARAMS parms = {};
691
692 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
693 if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
694 (p->state == SCO_ST_W4_CONN_RSP)) &&
695 (p->rem_bd_known) && (p->esco.data.bd_addr == bda)) {
696 if (hci_status != HCI_SUCCESS) {
697 /* Report the error if originator, otherwise remain in Listen mode */
698 if (p->is_orig) {
699 LOG_DEBUG("SCO initiating connection failed handle:0x%04x reason:%s",
700 hci_handle, hci_error_code_text(hci_status).c_str());
701 switch (hci_status) {
702 case HCI_ERR_ROLE_SWITCH_PENDING:
703 /* If role switch is pending, we need try again after role switch
704 * is complete */
705 p->state = SCO_ST_PEND_ROLECHANGE;
706 break;
707 case HCI_ERR_LMP_ERR_TRANS_COLLISION:
708 /* Avoid calling disconnect callback because of sco creation race
709 */
710 break;
711 default: /* Notify client about SCO failure */
712 p->state = SCO_ST_UNUSED;
713 (*p->p_disc_cb)(xx);
714 }
715 BTM_LogHistory(
716 kBtmLogTag, bda, "Connection failed",
717 base::StringPrintf(
718 "locally_initiated reason:%s",
719 hci_reason_code_text(static_cast<tHCI_REASON>(hci_status))
720 .c_str()));
721 } else {
722 LOG_DEBUG("SCO terminating connection failed handle:0x%04x reason:%s",
723 hci_handle, hci_error_code_text(hci_status).c_str());
724 if (p->state == SCO_ST_CONNECTING) {
725 p->state = SCO_ST_UNUSED;
726 (*p->p_disc_cb)(xx);
727 } else
728 p->state = SCO_ST_LISTENING;
729 BTM_LogHistory(
730 kBtmLogTag, bda, "Connection failed",
731 base::StringPrintf(
732 "remote_initiated reason:%s",
733 hci_reason_code_text(static_cast<tHCI_REASON>(hci_status))
734 .c_str()));
735 }
736 return;
737 }
738
739 BTM_LogHistory(
740 kBtmLogTag, bda, "Connection created",
741 base::StringPrintf("sco_idx:%hu handle:0x%04x ", xx, hci_handle));
742
743 if (p->state == SCO_ST_LISTENING) spt = true;
744
745 p->state = SCO_ST_CONNECTED;
746 p->hci_handle = hci_handle;
747
748 if (hci_status == HCI_SUCCESS) {
749 BTM_LogHistory(kBtmLogTag, bda, "Connection success",
750 base::StringPrintf("handle:0x%04x %s", hci_handle,
751 (spt) ? "listener" : "initiator"));
752 } else {
753 BTM_LogHistory(
754 kBtmLogTag, bda, "Connection failed",
755 base::StringPrintf(
756 "reason:%s",
757 hci_reason_code_text(static_cast<tHCI_REASON>(hci_status))
758 .c_str()));
759 }
760
761 if (!btm_cb.sco_cb.esco_supported) {
762 p->esco.data.link_type = BTM_LINK_TYPE_SCO;
763 if (spt) {
764 parms.packet_types = p->esco.setup.packet_types;
765 /* Keep the other parameters the same for SCO */
766 parms.max_latency_ms = p->esco.setup.max_latency_ms;
767 parms.retransmission_effort = p->esco.setup.retransmission_effort;
768
769 BTM_ChangeEScoLinkParms(xx, &parms);
770 }
771 } else {
772 if (p_esco_data) p->esco.data = *p_esco_data;
773 }
774
775 (*p->p_conn_cb)(xx);
776
777 return;
778 }
779 }
780 }
781
782 /*******************************************************************************
783 *
784 * Function BTM_RemoveSco
785 *
786 * Description This function is called to remove a specific SCO connection.
787 *
788 * Returns status of the operation
789 *
790 ******************************************************************************/
BTM_RemoveSco(uint16_t sco_inx)791 tBTM_STATUS BTM_RemoveSco(uint16_t sco_inx) {
792 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx];
793 tBTM_PM_STATE state = BTM_PM_ST_INVALID;
794
795 BTM_TRACE_DEBUG("%s", __func__);
796
797 if (BTM_MAX_SCO_LINKS == 0) {
798 return BTM_NO_RESOURCES;
799 }
800
801 /* Validity check */
802 if ((sco_inx >= BTM_MAX_SCO_LINKS) || (p->state == SCO_ST_UNUSED))
803 return (BTM_UNKNOWN_ADDR);
804
805 /* If no HCI handle, simply drop the connection and return */
806 if (p->hci_handle == HCI_INVALID_HANDLE || p->state == SCO_ST_PEND_UNPARK) {
807 p->hci_handle = HCI_INVALID_HANDLE;
808 p->state = SCO_ST_UNUSED;
809 p->esco.p_esco_cback = NULL; /* Deregister the eSCO event callback */
810 return (BTM_SUCCESS);
811 }
812
813 if (BTM_ReadPowerMode(p->esco.data.bd_addr, &state) &&
814 (state == BTM_PM_ST_PENDING)) {
815 BTM_TRACE_DEBUG("%s: BTM_PM_ST_PENDING for ACL mapped with SCO Link 0x%04x",
816 __func__, p->hci_handle);
817 p->state = SCO_ST_PEND_MODECHANGE;
818 return (BTM_CMD_STARTED);
819 }
820
821 tSCO_STATE old_state = p->state;
822 p->state = SCO_ST_DISCONNECTING;
823
824 GetLegacyHciInterface().Disconnect(p->Handle(), HCI_ERR_PEER_USER);
825
826 LOG_DEBUG("Disconnecting link sco_handle:0x%04x peer:%s", p->Handle(),
827 PRIVATE_ADDRESS(p->esco.data.bd_addr));
828 BTM_LogHistory(
829 kBtmLogTag, p->esco.data.bd_addr, "Disconnecting",
830 base::StringPrintf("local initiated handle:0x%04x previous_state:%s",
831 p->Handle(), sco_state_text(old_state).c_str()));
832 return (BTM_CMD_STARTED);
833 }
834
BTM_RemoveSco(const RawAddress & bda)835 void BTM_RemoveSco(const RawAddress& bda) {
836 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
837 uint16_t xx;
838
839 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
840 if (p->rem_bd_known && p->esco.data.bd_addr == bda) {
841 BTM_RemoveSco(xx);
842 }
843 }
844 }
845
846 /*******************************************************************************
847 *
848 * Function btm_sco_removed
849 *
850 * Description This function is called by lower layers when an
851 * disconnect is received.
852 *
853 * Returns true if the link is known about, else false
854 *
855 ******************************************************************************/
btm_sco_removed(uint16_t hci_handle,tHCI_REASON reason)856 bool btm_sco_removed(uint16_t hci_handle, tHCI_REASON reason) {
857 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
858 uint16_t xx;
859
860 p = &btm_cb.sco_cb.sco_db[0];
861 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
862 if ((p->state != SCO_ST_UNUSED) && (p->state != SCO_ST_LISTENING) &&
863 (p->hci_handle == hci_handle)) {
864 btm_sco_flush_sco_data(xx);
865
866 p->state = SCO_ST_UNUSED;
867 p->hci_handle = HCI_INVALID_HANDLE;
868 p->rem_bd_known = false;
869 p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
870 (*p->p_disc_cb)(xx);
871 LOG_DEBUG("Disconnected SCO link handle:%hu reason:%s", hci_handle,
872 hci_reason_code_text(reason).c_str());
873 return true;
874 }
875 }
876 return false;
877 }
878
btm_sco_on_esco_connect_request(const RawAddress & bda,const bluetooth::types::ClassOfDevice & cod)879 void btm_sco_on_esco_connect_request(
880 const RawAddress& bda, const bluetooth::types::ClassOfDevice& cod) {
881 LOG_DEBUG("Remote ESCO connect request remote:%s cod:%s",
882 PRIVATE_ADDRESS(bda), cod.ToString().c_str());
883 btm_sco_conn_req(bda, cod.cod, BTM_LINK_TYPE_ESCO);
884 }
885
btm_sco_on_sco_connect_request(const RawAddress & bda,const bluetooth::types::ClassOfDevice & cod)886 void btm_sco_on_sco_connect_request(
887 const RawAddress& bda, const bluetooth::types::ClassOfDevice& cod) {
888 LOG_DEBUG("Remote SCO connect request remote:%s cod:%s", PRIVATE_ADDRESS(bda),
889 cod.ToString().c_str());
890 btm_sco_conn_req(bda, cod.cod, BTM_LINK_TYPE_SCO);
891 }
892
btm_sco_on_disconnected(uint16_t hci_handle,tHCI_REASON reason)893 void btm_sco_on_disconnected(uint16_t hci_handle, tHCI_REASON reason) {
894 tSCO_CONN* p_sco = btm_cb.sco_cb.get_sco_connection_from_handle(hci_handle);
895 if (p_sco == nullptr) {
896 LOG_ERROR("Unable to find sco connection");
897 return;
898 }
899
900 if (!p_sco->is_active()) {
901 LOG_ERROR("Connection is not active handle:0x%04x reason:%s", hci_handle,
902 hci_reason_code_text(reason).c_str());
903 return;
904 }
905
906 if (p_sco->state == SCO_ST_LISTENING) {
907 LOG_ERROR("Connection is in listening state handle:0x%04x reason:%s",
908 hci_handle, hci_reason_code_text(reason).c_str());
909 return;
910 }
911
912 const RawAddress bd_addr(p_sco->esco.data.bd_addr);
913
914 p_sco->state = SCO_ST_UNUSED;
915 p_sco->hci_handle = HCI_INVALID_HANDLE;
916 p_sco->rem_bd_known = false;
917 p_sco->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
918 (*p_sco->p_disc_cb)(btm_cb.sco_cb.get_index(p_sco));
919 LOG_DEBUG("Disconnected SCO link handle:%hu reason:%s", hci_handle,
920 hci_reason_code_text(reason).c_str());
921 BTM_LogHistory(kBtmLogTag, bd_addr, "Disconnected",
922 base::StringPrintf("handle:0x%04x reason:%s", hci_handle,
923 hci_reason_code_text(reason).c_str()));
924 }
925
926 /*******************************************************************************
927 *
928 * Function btm_sco_acl_removed
929 *
930 * Description This function is called when an ACL connection is
931 * removed. If the BD address is NULL, it is assumed that
932 * the local device is down, and all SCO links are removed.
933 * If a specific BD address is passed, only SCO connections
934 * to that BD address are removed.
935 *
936 * Returns void
937 *
938 ******************************************************************************/
btm_sco_acl_removed(const RawAddress * bda)939 void btm_sco_acl_removed(const RawAddress* bda) {
940 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
941 uint16_t xx;
942
943 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
944 if (p->state != SCO_ST_UNUSED) {
945 if ((!bda) || (p->esco.data.bd_addr == *bda && p->rem_bd_known)) {
946 btm_sco_flush_sco_data(xx);
947
948 p->state = SCO_ST_UNUSED;
949 p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
950 (*p->p_disc_cb)(xx);
951 }
952 }
953 }
954 }
955
956 /*******************************************************************************
957 *
958 * Function BTM_ReadScoBdAddr
959 *
960 * Description This function is read the remote BD Address for a specific
961 * SCO connection,
962 *
963 * Returns pointer to BD address or NULL if not known
964 *
965 ******************************************************************************/
BTM_ReadScoBdAddr(uint16_t sco_inx)966 const RawAddress* BTM_ReadScoBdAddr(uint16_t sco_inx) {
967 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx];
968
969 /* Validity check */
970 if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->rem_bd_known))
971 return &(p->esco.data.bd_addr);
972 else
973 return (NULL);
974 }
975
976 /*******************************************************************************
977 *
978 * Function BTM_SetEScoMode
979 *
980 * Description This function sets up the negotiated parameters for SCO or
981 * eSCO, and sets as the default mode used for outgoing calls
982 * to BTM_CreateSco. It does not change any currently active
983 * (e)SCO links.
984 * Note: Incoming (e)SCO connections will always use packet
985 * types supported by the controller. If eSCO is not
986 * desired the feature should be disabled in the
987 * controller's feature mask.
988 *
989 * Returns BTM_SUCCESS if the successful.
990 * BTM_BUSY if there are one or more active (e)SCO links.
991 *
992 ******************************************************************************/
BTM_SetEScoMode(enh_esco_params_t * p_parms)993 tBTM_STATUS BTM_SetEScoMode(enh_esco_params_t* p_parms) {
994 ASSERT_LOG(p_parms != nullptr, "eSCO parameters must have a value");
995 enh_esco_params_t* p_def = &btm_cb.sco_cb.def_esco_parms;
996
997 if (btm_cb.sco_cb.esco_supported) {
998 *p_def = *p_parms;
999 LOG_DEBUG(
1000 "Setting eSCO mode parameters txbw:0x%08x rxbw:0x%08x max_lat:0x%04x"
1001 " pkt:0x%04x rtx_effort:0x%02x",
1002 p_def->transmit_bandwidth, p_def->receive_bandwidth,
1003 p_def->max_latency_ms, p_def->packet_types,
1004 p_def->retransmission_effort);
1005 } else {
1006 /* Load defaults for SCO only */
1007 *p_def = esco_parameters_for_codec(SCO_CODEC_CVSD_D1);
1008 LOG_WARN("eSCO not supported so setting SCO parameters instead");
1009 LOG_DEBUG(
1010 "Setting SCO mode parameters txbw:0x%08x rxbw:0x%08x max_lat:0x%04x"
1011 " pkt:0x%04x rtx_effort:0x%02x",
1012 p_def->transmit_bandwidth, p_def->receive_bandwidth,
1013 p_def->max_latency_ms, p_def->packet_types,
1014 p_def->retransmission_effort);
1015 }
1016 return BTM_SUCCESS;
1017 }
1018
1019 /*******************************************************************************
1020 *
1021 * Function BTM_RegForEScoEvts
1022 *
1023 * Description This function registers a SCO event callback with the
1024 * specified instance. It should be used to received
1025 * connection indication events and change of link parameter
1026 * events.
1027 *
1028 * Returns BTM_SUCCESS if the successful.
1029 * BTM_ILLEGAL_VALUE if there is an illegal sco_inx
1030 * BTM_MODE_UNSUPPORTED if controller version is not BT1.2 or
1031 * later or does not support eSCO.
1032 *
1033 ******************************************************************************/
BTM_RegForEScoEvts(uint16_t sco_inx,tBTM_ESCO_CBACK * p_esco_cback)1034 tBTM_STATUS BTM_RegForEScoEvts(uint16_t sco_inx,
1035 tBTM_ESCO_CBACK* p_esco_cback) {
1036 if (BTM_MAX_SCO_LINKS == 0) {
1037 return BTM_MODE_UNSUPPORTED;
1038 }
1039
1040 if (!btm_cb.sco_cb.esco_supported) {
1041 btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = NULL;
1042 return (BTM_MODE_UNSUPPORTED);
1043 }
1044
1045 if (sco_inx < BTM_MAX_SCO_LINKS &&
1046 btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_UNUSED) {
1047 btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = p_esco_cback;
1048 return (BTM_SUCCESS);
1049 }
1050 return (BTM_ILLEGAL_VALUE);
1051 }
1052
1053 /*******************************************************************************
1054 *
1055 * Function BTM_ChangeEScoLinkParms
1056 *
1057 * Description This function requests renegotiation of the parameters on
1058 * the current eSCO Link. If any of the changes are accepted
1059 * by the controllers, the BTM_ESCO_CHG_EVT event is sent in
1060 * the tBTM_ESCO_CBACK function with the current settings of
1061 * the link. The callback is registered through the call to
1062 * BTM_SetEScoMode.
1063 *
1064 * Note: If called over a SCO link (including 1.1 controller),
1065 * a change packet type request is sent out instead.
1066 *
1067 * Returns BTM_CMD_STARTED if command is successfully initiated.
1068 * BTM_NO_RESOURCES - not enough resources to initiate command.
1069 * BTM_WRONG_MODE if no connection with a peer device or bad
1070 * sco_inx.
1071 *
1072 ******************************************************************************/
BTM_ChangeEScoLinkParms(uint16_t sco_inx,tBTM_CHG_ESCO_PARAMS * p_parms)1073 tBTM_STATUS BTM_ChangeEScoLinkParms(uint16_t sco_inx,
1074 tBTM_CHG_ESCO_PARAMS* p_parms) {
1075 if (BTM_MAX_SCO_LINKS == 0) {
1076 return BTM_WRONG_MODE;
1077 }
1078
1079 /* Make sure sco handle is valid and on an active link */
1080 if (sco_inx >= BTM_MAX_SCO_LINKS ||
1081 btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_CONNECTED)
1082 return (BTM_WRONG_MODE);
1083
1084 tSCO_CONN* p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
1085 enh_esco_params_t* p_setup = &p_sco->esco.setup;
1086
1087 /* Save the previous types in case command fails */
1088 uint16_t saved_packet_types = p_setup->packet_types;
1089
1090 /* If SCO connection OR eSCO not supported just send change packet types */
1091 if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO ||
1092 !btm_cb.sco_cb.esco_supported) {
1093 p_setup->packet_types =
1094 p_parms->packet_types &
1095 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_LINK_ONLY_MASK);
1096
1097 BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__,
1098 p_sco->hci_handle, p_setup->packet_types);
1099
1100 BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__,
1101 p_sco->hci_handle, p_setup->packet_types);
1102
1103 btsnd_hcic_change_conn_type(p_sco->hci_handle,
1104 BTM_ESCO_2_SCO(p_setup->packet_types));
1105 } else /* eSCO is supported and the link type is eSCO */
1106 {
1107 uint16_t temp_packet_types =
1108 (p_parms->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
1109 btm_cb.btm_sco_pkt_types_supported);
1110
1111 /* OR in any exception packet types */
1112 temp_packet_types |=
1113 ((p_parms->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
1114 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
1115 p_setup->packet_types = temp_packet_types;
1116
1117 BTM_TRACE_API("%s -> eSCO Link for handle 0x%04x", __func__,
1118 p_sco->hci_handle);
1119 BTM_TRACE_API(
1120 " txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x",
1121 p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
1122 p_parms->max_latency_ms, p_parms->retransmission_effort,
1123 temp_packet_types);
1124
1125 /* Use Enhanced Synchronous commands if supported */
1126 if (controller_get_interface()
1127 ->supports_enhanced_setup_synchronous_connection()) {
1128 /* Use the saved SCO routing */
1129 p_setup->input_data_path = p_setup->output_data_path =
1130 btm_cb.sco_cb.sco_route;
1131
1132 btsnd_hcic_enhanced_set_up_synchronous_connection(p_sco->hci_handle,
1133 p_setup);
1134 p_setup->packet_types = saved_packet_types;
1135 } else { /* Use older command */
1136 uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
1137 /* When changing an existing link, only change latency, retrans, and
1138 * pkts */
1139 btsnd_hcic_setup_esco_conn(p_sco->hci_handle, p_setup->transmit_bandwidth,
1140 p_setup->receive_bandwidth,
1141 p_parms->max_latency_ms, voice_content_format,
1142 p_parms->retransmission_effort,
1143 p_setup->packet_types);
1144 }
1145
1146 BTM_TRACE_API(
1147 "%s: txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x",
1148 __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
1149 p_parms->max_latency_ms, p_parms->retransmission_effort,
1150 temp_packet_types);
1151 }
1152
1153 return (BTM_CMD_STARTED);
1154 }
1155
1156 /*******************************************************************************
1157 *
1158 * Function BTM_EScoConnRsp
1159 *
1160 * Description This function is called upon receipt of an (e)SCO connection
1161 * request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject
1162 * the request. Parameters used to negotiate eSCO links.
1163 * If p_parms is NULL, then values set through BTM_SetEScoMode
1164 * are used.
1165 * If the link type of the incoming request is SCO, then only
1166 * the tx_bw, max_latency, content format, and packet_types are
1167 * valid. The hci_status parameter should be
1168 * ([0x0] to accept, [0x0d..0x0f] to reject)
1169 *
1170 *
1171 * Returns void
1172 *
1173 ******************************************************************************/
BTM_EScoConnRsp(uint16_t sco_inx,uint8_t hci_status,enh_esco_params_t * p_parms)1174 void BTM_EScoConnRsp(uint16_t sco_inx, uint8_t hci_status,
1175 enh_esco_params_t* p_parms) {
1176 if (sco_inx < BTM_MAX_SCO_LINKS &&
1177 btm_cb.sco_cb.sco_db[sco_inx].state == SCO_ST_W4_CONN_RSP) {
1178 btm_esco_conn_rsp(sco_inx, hci_status,
1179 btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr, p_parms);
1180 }
1181 }
1182
1183 /*******************************************************************************
1184 *
1185 * Function btm_esco_proc_conn_chg
1186 *
1187 * Description This function is called by BTIF when an SCO connection
1188 * is changed.
1189 *
1190 * Returns void
1191 *
1192 ******************************************************************************/
btm_esco_proc_conn_chg(uint8_t status,uint16_t handle,uint8_t tx_interval,uint8_t retrans_window,uint16_t rx_pkt_len,uint16_t tx_pkt_len)1193 void btm_esco_proc_conn_chg(uint8_t status, uint16_t handle,
1194 uint8_t tx_interval, uint8_t retrans_window,
1195 uint16_t rx_pkt_len, uint16_t tx_pkt_len) {
1196 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1197 tBTM_CHG_ESCO_EVT_DATA data;
1198 uint16_t xx;
1199
1200 BTM_TRACE_EVENT("btm_esco_proc_conn_chg -> handle 0x%04x, status 0x%02x",
1201 handle, status);
1202
1203 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1204 if (p->state == SCO_ST_CONNECTED && handle == p->hci_handle) {
1205 /* If upper layer wants notification */
1206 if (p->esco.p_esco_cback) {
1207 data.bd_addr = p->esco.data.bd_addr;
1208 data.hci_status = status;
1209 data.sco_inx = xx;
1210 data.rx_pkt_len = p->esco.data.rx_pkt_len = rx_pkt_len;
1211 data.tx_pkt_len = p->esco.data.tx_pkt_len = tx_pkt_len;
1212 data.tx_interval = p->esco.data.tx_interval = tx_interval;
1213 data.retrans_window = p->esco.data.retrans_window = retrans_window;
1214
1215 tBTM_ESCO_EVT_DATA btm_esco_evt_data;
1216 btm_esco_evt_data.chg_evt = data;
1217 (*p->esco.p_esco_cback)(BTM_ESCO_CHG_EVT, &btm_esco_evt_data);
1218 }
1219 return;
1220 }
1221 }
1222 }
1223
1224 /*******************************************************************************
1225 *
1226 * Function btm_is_sco_active
1227 *
1228 * Description This function is called to see if a SCO handle is already in
1229 * use.
1230 *
1231 * Returns bool
1232 *
1233 ******************************************************************************/
btm_is_sco_active(uint16_t handle)1234 bool btm_is_sco_active(uint16_t handle) {
1235 uint16_t xx;
1236 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1237
1238 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1239 if (handle == p->hci_handle && p->state == SCO_ST_CONNECTED) return (true);
1240 }
1241 return (false);
1242 }
1243
1244 /*******************************************************************************
1245 *
1246 * Function BTM_GetNumScoLinks
1247 *
1248 * Description This function returns the number of active sco links.
1249 *
1250 * Returns uint8_t
1251 *
1252 ******************************************************************************/
BTM_GetNumScoLinks(void)1253 uint8_t BTM_GetNumScoLinks(void) {
1254 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1255 uint16_t xx;
1256 uint8_t num_scos = 0;
1257
1258 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1259 switch (p->state) {
1260 case SCO_ST_W4_CONN_RSP:
1261 case SCO_ST_CONNECTING:
1262 case SCO_ST_CONNECTED:
1263 case SCO_ST_DISCONNECTING:
1264 case SCO_ST_PEND_UNPARK:
1265 num_scos++;
1266 break;
1267 default:
1268 break;
1269 }
1270 }
1271 return (num_scos);
1272 }
1273
1274 /*******************************************************************************
1275 *
1276 * Function BTM_IsScoActiveByBdaddr
1277 *
1278 * Description This function is called to see if a SCO connection is active
1279 * for a bd address.
1280 *
1281 * Returns bool
1282 *
1283 ******************************************************************************/
BTM_IsScoActiveByBdaddr(const RawAddress & remote_bda)1284 bool BTM_IsScoActiveByBdaddr(const RawAddress& remote_bda) {
1285 uint8_t xx;
1286 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1287
1288 /* If any SCO is being established to the remote BD address, refuse this */
1289 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1290 if (p->esco.data.bd_addr == remote_bda && p->state == SCO_ST_CONNECTED) {
1291 return (true);
1292 }
1293 }
1294 return (false);
1295 }
1296
1297 /*******************************************************************************
1298 *
1299 * Function btm_sco_voice_settings_2_legacy
1300 *
1301 * Description This function is called to convert the Enhanced eSCO
1302 * parameters into voice setting parameter mask used
1303 * for legacy setup synchronous connection HCI commands
1304 *
1305 * Returns UINT16 - 16-bit mask for voice settings
1306 *
1307 * HCI_INP_CODING_LINEAR 0x0000 (0000000000)
1308 * HCI_INP_CODING_U_LAW 0x0100 (0100000000)
1309 * HCI_INP_CODING_A_LAW 0x0200 (1000000000)
1310 * HCI_INP_CODING_MASK 0x0300 (1100000000)
1311 *
1312 * HCI_INP_DATA_FMT_1S_COMPLEMENT 0x0000 (0000000000)
1313 * HCI_INP_DATA_FMT_2S_COMPLEMENT 0x0040 (0001000000)
1314 * HCI_INP_DATA_FMT_SIGN_MAGNITUDE 0x0080 (0010000000)
1315 * HCI_INP_DATA_FMT_UNSIGNED 0x00c0 (0011000000)
1316 * HCI_INP_DATA_FMT_MASK 0x00c0 (0011000000)
1317 *
1318 * HCI_INP_SAMPLE_SIZE_8BIT 0x0000 (0000000000)
1319 * HCI_INP_SAMPLE_SIZE_16BIT 0x0020 (0000100000)
1320 * HCI_INP_SAMPLE_SIZE_MASK 0x0020 (0000100000)
1321 *
1322 * HCI_INP_LINEAR_PCM_BIT_POS_MASK 0x001c (0000011100)
1323 * HCI_INP_LINEAR_PCM_BIT_POS_OFFS 2
1324 *
1325 * HCI_AIR_CODING_FORMAT_CVSD 0x0000 (0000000000)
1326 * HCI_AIR_CODING_FORMAT_U_LAW 0x0001 (0000000001)
1327 * HCI_AIR_CODING_FORMAT_A_LAW 0x0002 (0000000010)
1328 * HCI_AIR_CODING_FORMAT_TRANSPNT 0x0003 (0000000011)
1329 * HCI_AIR_CODING_FORMAT_MASK 0x0003 (0000000011)
1330 *
1331 * default (0001100000)
1332 * HCI_DEFAULT_VOICE_SETTINGS (HCI_INP_CODING_LINEAR \
1333 * | HCI_INP_DATA_FMT_2S_COMPLEMENT \
1334 * | HCI_INP_SAMPLE_SIZE_16BIT \
1335 * | HCI_AIR_CODING_FORMAT_CVSD)
1336 *
1337 ******************************************************************************/
btm_sco_voice_settings_to_legacy(enh_esco_params_t * p_params)1338 static uint16_t btm_sco_voice_settings_to_legacy(enh_esco_params_t* p_params) {
1339 uint16_t voice_settings = 0;
1340
1341 /* Convert Input Coding Format: If no uLaw or aLAW then Linear will be used
1342 * (0) */
1343 if (p_params->input_coding_format.coding_format == ESCO_CODING_FORMAT_ULAW)
1344 voice_settings |= HCI_INP_CODING_U_LAW;
1345 else if (p_params->input_coding_format.coding_format ==
1346 ESCO_CODING_FORMAT_ALAW)
1347 voice_settings |= HCI_INP_CODING_A_LAW;
1348 /* else default value of '0 is good 'Linear' */
1349
1350 /* Convert Input Data Format. Use 2's Compliment as the default */
1351 switch (p_params->input_pcm_data_format) {
1352 case ESCO_PCM_DATA_FORMAT_1_COMP:
1353 /* voice_settings |= HCI_INP_DATA_FMT_1S_COMPLEMENT; value is '0'
1354 * already */
1355 break;
1356
1357 case ESCO_PCM_DATA_FORMAT_SIGN:
1358 voice_settings |= HCI_INP_DATA_FMT_SIGN_MAGNITUDE;
1359 break;
1360
1361 case ESCO_PCM_DATA_FORMAT_UNSIGN:
1362 voice_settings |= HCI_INP_DATA_FMT_UNSIGNED;
1363 break;
1364
1365 default: /* 2's Compliment */
1366 voice_settings |= HCI_INP_DATA_FMT_2S_COMPLEMENT;
1367 break;
1368 }
1369
1370 /* Convert Over the Air Coding. Use CVSD as the default */
1371 switch (p_params->transmit_coding_format.coding_format) {
1372 case ESCO_CODING_FORMAT_ULAW:
1373 voice_settings |= HCI_AIR_CODING_FORMAT_U_LAW;
1374 break;
1375
1376 case ESCO_CODING_FORMAT_ALAW:
1377 voice_settings |= HCI_AIR_CODING_FORMAT_A_LAW;
1378 break;
1379
1380 case ESCO_CODING_FORMAT_MSBC:
1381 voice_settings |= HCI_AIR_CODING_FORMAT_TRANSPNT;
1382 break;
1383
1384 default: /* CVSD (0) */
1385 break;
1386 }
1387
1388 /* Convert PCM payload MSB position (0000011100) */
1389 voice_settings |= (uint16_t)(((p_params->input_pcm_payload_msb_position & 0x7)
1390 << HCI_INP_LINEAR_PCM_BIT_POS_OFFS));
1391
1392 /* Convert Input Sample Size (0000011100) */
1393 if (p_params->input_coded_data_size == 16)
1394 voice_settings |= HCI_INP_SAMPLE_SIZE_16BIT;
1395 else /* Use 8 bit for all others */
1396 voice_settings |= HCI_INP_SAMPLE_SIZE_8BIT;
1397
1398 BTM_TRACE_DEBUG("%s: voice setting for legacy 0x%03x", __func__,
1399 voice_settings);
1400
1401 return (voice_settings);
1402 }
1403