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