1 /******************************************************************************
2 *
3 * Copyright 2004-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 for managing the SCO connection used in AG.
22 *
23 ******************************************************************************/
24
25 #include <base/bind.h>
26 #include <cstdint>
27
28 #include "bt_target.h" // Must be first to define build configuration
29 #include "bt_trace.h" // Legacy trace logging
30
31 #include "bta/ag/bta_ag_int.h"
32 #include "device/include/controller.h"
33 #include "device/include/esco_parameters.h"
34 #include "main/shim/dumpsys.h"
35 #include "osi/include/log.h"
36 #include "osi/include/osi.h" // UNUSED_ATTR
37 #include "stack/btm/btm_sco.h"
38 #include "stack/include/btm_api.h"
39 #include "stack/include/btu.h" // do_in_main_thread
40 #include "types/raw_address.h"
41
42 /* Codec negotiation timeout */
43 #ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS
44 #define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000) /* 3 seconds */
45 #endif
46
47 static bool sco_allowed = true;
48 static RawAddress active_device_addr = {};
49
50 /* sco events */
51 enum {
52 BTA_AG_SCO_LISTEN_E, /* listen request */
53 BTA_AG_SCO_OPEN_E, /* open request */
54 BTA_AG_SCO_XFER_E, /* transfer request */
55 BTA_AG_SCO_CN_DONE_E, /* codec negotiation done */
56 BTA_AG_SCO_REOPEN_E, /* Retry with other codec when failed */
57 BTA_AG_SCO_CLOSE_E, /* close request */
58 BTA_AG_SCO_SHUTDOWN_E, /* shutdown request */
59 BTA_AG_SCO_CONN_OPEN_E, /* sco open */
60 BTA_AG_SCO_CONN_CLOSE_E, /* sco closed */
61 };
62
63 #define CASE_RETURN_STR(const) \
64 case const: \
65 return #const;
66
bta_ag_sco_evt_str(uint8_t event)67 static const char* bta_ag_sco_evt_str(uint8_t event) {
68 switch (event) {
69 CASE_RETURN_STR(BTA_AG_SCO_LISTEN_E)
70 CASE_RETURN_STR(BTA_AG_SCO_OPEN_E)
71 CASE_RETURN_STR(BTA_AG_SCO_XFER_E)
72 CASE_RETURN_STR(BTA_AG_SCO_CN_DONE_E)
73 CASE_RETURN_STR(BTA_AG_SCO_REOPEN_E)
74 CASE_RETURN_STR(BTA_AG_SCO_CLOSE_E)
75 CASE_RETURN_STR(BTA_AG_SCO_SHUTDOWN_E)
76 CASE_RETURN_STR(BTA_AG_SCO_CONN_OPEN_E)
77 CASE_RETURN_STR(BTA_AG_SCO_CONN_CLOSE_E)
78 default:
79 return "Unknown SCO Event";
80 }
81 }
82
bta_ag_sco_state_str(uint8_t state)83 static const char* bta_ag_sco_state_str(uint8_t state) {
84 switch (state) {
85 CASE_RETURN_STR(BTA_AG_SCO_SHUTDOWN_ST)
86 CASE_RETURN_STR(BTA_AG_SCO_LISTEN_ST)
87 CASE_RETURN_STR(BTA_AG_SCO_CODEC_ST)
88 CASE_RETURN_STR(BTA_AG_SCO_OPENING_ST)
89 CASE_RETURN_STR(BTA_AG_SCO_OPEN_CL_ST)
90 CASE_RETURN_STR(BTA_AG_SCO_OPEN_XFER_ST)
91 CASE_RETURN_STR(BTA_AG_SCO_OPEN_ST)
92 CASE_RETURN_STR(BTA_AG_SCO_CLOSING_ST)
93 CASE_RETURN_STR(BTA_AG_SCO_CLOSE_OP_ST)
94 CASE_RETURN_STR(BTA_AG_SCO_CLOSE_XFER_ST)
95 CASE_RETURN_STR(BTA_AG_SCO_SHUTTING_ST)
96 default:
97 return "Unknown SCO State";
98 }
99 }
100
101 /**
102 * Check if bd_addr is the current active device.
103 *
104 * @param bd_addr target device address
105 * @return True if bd_addr is the current active device, False otherwise or if
106 * no active device is set (i.e. active_device_addr is empty)
107 */
bta_ag_sco_is_active_device(const RawAddress & bd_addr)108 bool bta_ag_sco_is_active_device(const RawAddress& bd_addr) {
109 return !active_device_addr.IsEmpty() && active_device_addr == bd_addr;
110 }
111
112 static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local);
113
114 /*******************************************************************************
115 *
116 * Function bta_ag_sco_conn_cback
117 *
118 * Description BTM SCO connection callback.
119 *
120 *
121 * Returns void
122 *
123 ******************************************************************************/
bta_ag_sco_conn_cback(uint16_t sco_idx)124 static void bta_ag_sco_conn_cback(uint16_t sco_idx) {
125 uint16_t handle;
126 tBTA_AG_SCB* p_scb;
127
128 /* match callback to scb; first check current sco scb */
129 if (bta_ag_cb.sco.p_curr_scb != nullptr && bta_ag_cb.sco.p_curr_scb->in_use) {
130 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
131 }
132 /* then check for scb connected to this peer */
133 else {
134 /* Check if SLC is up */
135 handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx));
136 p_scb = bta_ag_scb_by_idx(handle);
137 if (p_scb && !p_scb->svc_conn) handle = 0;
138 }
139
140 if (handle != 0) {
141 do_in_main_thread(FROM_HERE,
142 base::Bind(&bta_ag_sm_execute_by_handle, handle,
143 BTA_AG_SCO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
144 } else {
145 /* no match found; disconnect sco, init sco variables */
146 bta_ag_cb.sco.p_curr_scb = nullptr;
147 bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
148 BTM_RemoveSco(sco_idx);
149 }
150 }
151
152 /*******************************************************************************
153 *
154 * Function bta_ag_sco_disc_cback
155 *
156 * Description BTM SCO disconnection callback.
157 *
158 *
159 * Returns void
160 *
161 ******************************************************************************/
bta_ag_sco_disc_cback(uint16_t sco_idx)162 static void bta_ag_sco_disc_cback(uint16_t sco_idx) {
163 uint16_t handle = 0;
164
165 LOG_DEBUG(
166 "sco_idx: 0x%x sco.state:%s", sco_idx,
167 sco_state_text(static_cast<tSCO_STATE>(bta_ag_cb.sco.state)).c_str());
168 LOG_DEBUG(
169 " scb[0] in_use:%s sco_idx: 0x%x sco state:%s",
170 logbool(bta_ag_cb.scb[0].in_use).c_str(), bta_ag_cb.scb[0].sco_idx,
171 sco_state_text(static_cast<tSCO_STATE>(bta_ag_cb.scb[0].state)).c_str());
172 LOG_DEBUG(
173 " scb[1] in_use:%s sco_idx:0x%x sco state:%s",
174 logbool(bta_ag_cb.scb[1].in_use).c_str(), bta_ag_cb.scb[1].sco_idx,
175 sco_state_text(static_cast<tSCO_STATE>(bta_ag_cb.scb[1].state)).c_str());
176
177 /* match callback to scb */
178 if (bta_ag_cb.sco.p_curr_scb != nullptr && bta_ag_cb.sco.p_curr_scb->in_use) {
179 /* We only care about callbacks for the active SCO */
180 if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx) {
181 if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF) return;
182 }
183 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
184 }
185
186 if (handle != 0) {
187 /* Restore settings */
188 if (bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC) {
189 /* Bypass vendor specific and voice settings if enhanced eSCO supported */
190 if (!(controller_get_interface()
191 ->supports_enhanced_setup_synchronous_connection())) {
192 BTM_WriteVoiceSettings(BTM_VOICE_SETTING_CVSD);
193 }
194
195 /* If SCO open was initiated by AG and failed for mSBC T2, try mSBC T1
196 * 'Safe setting' first. If T1 also fails, try CVSD */
197 if (bta_ag_sco_is_opening(bta_ag_cb.sco.p_curr_scb)) {
198 bta_ag_cb.sco.p_curr_scb->state = BTA_AG_SCO_CODEC_ST;
199 if (bta_ag_cb.sco.p_curr_scb->codec_msbc_settings ==
200 BTA_AG_SCO_MSBC_SETTINGS_T2) {
201 APPL_TRACE_WARNING(
202 "%s: eSCO/SCO failed to open, falling back to mSBC T1 settings",
203 __func__);
204 bta_ag_cb.sco.p_curr_scb->codec_msbc_settings =
205 BTA_AG_SCO_MSBC_SETTINGS_T1;
206 } else {
207 APPL_TRACE_WARNING(
208 "%s: eSCO/SCO failed to open, falling back to CVSD", __func__);
209 bta_ag_cb.sco.p_curr_scb->codec_fallback = true;
210 }
211 }
212 } else if (bta_ag_sco_is_opening(bta_ag_cb.sco.p_curr_scb)) {
213 APPL_TRACE_ERROR("%s: eSCO/SCO failed to open, no more fall back",
214 __func__);
215 }
216
217 bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
218
219 do_in_main_thread(FROM_HERE,
220 base::Bind(&bta_ag_sm_execute_by_handle, handle,
221 BTA_AG_SCO_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
222 } else {
223 /* no match found */
224 APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback");
225
226 /* sco could be closed after scb dealloc'ed */
227 if (bta_ag_cb.sco.p_curr_scb != nullptr) {
228 bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
229 bta_ag_cb.sco.p_curr_scb = nullptr;
230 bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
231 }
232 }
233 }
234
235 /*******************************************************************************
236 *
237 * Function bta_ag_remove_sco
238 *
239 * Description Removes the specified SCO from the system.
240 * If only_active is true, then SCO is only removed if
241 * connected
242 *
243 * Returns bool - true if SCO removal was started
244 *
245 ******************************************************************************/
bta_ag_remove_sco(tBTA_AG_SCB * p_scb,bool only_active)246 static bool bta_ag_remove_sco(tBTA_AG_SCB* p_scb, bool only_active) {
247 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) {
248 if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx) {
249 tBTM_STATUS status = BTM_RemoveSco(p_scb->sco_idx);
250 LOG_DEBUG("Removed SCO index:0x%04x status:%s", p_scb->sco_idx,
251 btm_status_text(status).c_str());
252 if (status == BTM_CMD_STARTED) {
253 /* SCO is connected; set current control block */
254 bta_ag_cb.sco.p_curr_scb = p_scb;
255 return true;
256 } else if ((status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR)) {
257 /* If no connection reset the SCO handle */
258 p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
259 }
260 }
261 }
262 return false;
263 }
264
265 /*******************************************************************************
266 *
267 * Function bta_ag_esco_connreq_cback
268 *
269 * Description BTM eSCO connection requests and eSCO change requests
270 * Only the connection requests are processed by BTA.
271 *
272 * Returns void
273 *
274 ******************************************************************************/
bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event,tBTM_ESCO_EVT_DATA * p_data)275 static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event,
276 tBTM_ESCO_EVT_DATA* p_data) {
277 /* Only process connection requests */
278 if (event == BTM_ESCO_CONN_REQ_EVT) {
279 uint16_t sco_inx = p_data->conn_evt.sco_inx;
280 const RawAddress* remote_bda = BTM_ReadScoBdAddr(sco_inx);
281 tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(bta_ag_idx_by_bdaddr(remote_bda));
282 if (remote_bda && bta_ag_sco_is_active_device(*remote_bda) && p_scb &&
283 p_scb->svc_conn) {
284 p_scb->sco_idx = sco_inx;
285
286 /* If no other SCO active, allow this one */
287 if (!bta_ag_cb.sco.p_curr_scb) {
288 APPL_TRACE_EVENT("%s: Accept Conn Request (sco_inx 0x%04x)", __func__,
289 sco_inx);
290 bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
291
292 bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST;
293 bta_ag_cb.sco.p_curr_scb = p_scb;
294 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
295 } else {
296 /* Begin a transfer: Close current SCO before responding */
297 APPL_TRACE_DEBUG("bta_ag_esco_connreq_cback: Begin XFER");
298 bta_ag_cb.sco.p_xfer_scb = p_scb;
299 bta_ag_cb.sco.conn_data = p_data->conn_evt;
300 bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST;
301
302 if (!bta_ag_remove_sco(bta_ag_cb.sco.p_curr_scb, true)) {
303 APPL_TRACE_ERROR(
304 "%s: Nothing to remove,so accept Conn Request(sco_inx 0x%04x)",
305 __func__, sco_inx);
306 bta_ag_cb.sco.p_xfer_scb = nullptr;
307 bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST;
308
309 bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
310 }
311 }
312 } else {
313 LOG(WARNING) << __func__
314 << ": reject incoming SCO connection, remote_bda="
315 << (remote_bda ? *remote_bda : RawAddress::kEmpty)
316 << ", active_bda=" << active_device_addr << ", current_bda="
317 << (p_scb ? p_scb->peer_addr : RawAddress::kEmpty);
318 BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES,
319 (enh_esco_params_t*)nullptr);
320 }
321 } else if (event == BTM_ESCO_CHG_EVT) {
322 /* Received a change in the esco link */
323 APPL_TRACE_EVENT(
324 "%s: eSCO change event (inx %d): rtrans %d, "
325 "rxlen %d, txlen %d, txint %d",
326 __func__, p_data->chg_evt.sco_inx, p_data->chg_evt.retrans_window,
327 p_data->chg_evt.rx_pkt_len, p_data->chg_evt.tx_pkt_len,
328 p_data->chg_evt.tx_interval);
329 }
330 }
331
332 /*******************************************************************************
333 *
334 * Function bta_ag_cback_sco
335 *
336 * Description Call application callback function with SCO event.
337 *
338 *
339 * Returns void
340 *
341 ******************************************************************************/
bta_ag_cback_sco(tBTA_AG_SCB * p_scb,tBTA_AG_EVT event)342 static void bta_ag_cback_sco(tBTA_AG_SCB* p_scb, tBTA_AG_EVT event) {
343 tBTA_AG_HDR sco = {};
344 sco.handle = bta_ag_scb_to_idx(p_scb);
345 sco.app_id = p_scb->app_id;
346 /* call close cback */
347 (*bta_ag_cb.p_cback)(static_cast<tBTA_AG_EVT>(event), (tBTA_AG*)&sco);
348 }
349
350 /*******************************************************************************
351 *
352 * Function bta_ag_create_sco
353 *
354 * Description Create a SCO connection for a given control block
355 * p_scb : Pointer to the target AG control block
356 * is_orig : Whether to initiate or listen for SCO connection
357 *
358 * Returns void
359 *
360 ******************************************************************************/
bta_ag_create_sco(tBTA_AG_SCB * p_scb,bool is_orig)361 static void bta_ag_create_sco(tBTA_AG_SCB* p_scb, bool is_orig) {
362 LOG_DEBUG("BEFORE %s", p_scb->ToString().c_str());
363 tBTA_AG_PEER_CODEC esco_codec = BTA_AG_CODEC_CVSD;
364
365 if (!bta_ag_sco_is_active_device(p_scb->peer_addr)) {
366 LOG(WARNING) << __func__ << ": device " << p_scb->peer_addr
367 << " is not active, active_device=" << active_device_addr;
368 if (bta_ag_cb.sco.p_curr_scb != nullptr &&
369 bta_ag_cb.sco.p_curr_scb->in_use && p_scb == bta_ag_cb.sco.p_curr_scb) {
370 do_in_main_thread(
371 FROM_HERE, base::Bind(&bta_ag_sm_execute, p_scb, BTA_AG_SCO_CLOSE_EVT,
372 tBTA_AG_DATA::kEmpty));
373 }
374 return;
375 }
376 /* Make sure this SCO handle is not already in use */
377 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) {
378 APPL_TRACE_ERROR("%s: device %s, index 0x%04x already in use!", __func__,
379 p_scb->peer_addr.ToString().c_str(), p_scb->sco_idx);
380 return;
381 }
382
383 #if (DISABLE_WBS == FALSE)
384 if ((p_scb->sco_codec == BTA_AG_CODEC_MSBC) && !p_scb->codec_fallback)
385 esco_codec = BTA_AG_CODEC_MSBC;
386 #endif
387
388 if (p_scb->codec_fallback) {
389 p_scb->codec_fallback = false;
390 /* Force AG to send +BCS for the next audio connection. */
391 p_scb->codec_updated = true;
392 /* Reset mSBC settings to T2 for the next audio connection */
393 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
394 }
395
396 /* Initialize eSCO parameters */
397 enh_esco_params_t params = {};
398 /* If WBS included, use CVSD by default, index is 0 for CVSD by
399 * initialization. If eSCO codec is mSBC, index is T2 or T1 */
400 if (esco_codec == BTA_AG_CODEC_MSBC) {
401 if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) {
402 params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T2);
403 } else {
404 params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T1);
405 }
406 } else {
407 if (p_scb->features & BTA_AG_PEER_FEAT_ESCO_S4 &&
408 (p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4)) {
409 // HFP >=1.7 eSCO
410 params = esco_parameters_for_codec(ESCO_CODEC_CVSD_S4);
411 } else {
412 // HFP <=1.6 eSCO
413 params = esco_parameters_for_codec(ESCO_CODEC_CVSD_S3);
414 }
415 }
416
417 /* If initiating, setup parameters to start SCO/eSCO connection */
418 if (is_orig) {
419 bta_ag_cb.sco.is_local = true;
420 /* Set eSCO Mode */
421 BTM_SetEScoMode(¶ms);
422 bta_ag_cb.sco.p_curr_scb = p_scb;
423 /* save the current codec as sco_codec can be updated while SCO is open. */
424 p_scb->inuse_codec = esco_codec;
425
426 /* tell sys to stop av if any */
427 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
428
429 /* Send pending commands to create SCO connection to peer */
430 bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
431 LOG_DEBUG("Initiating AG SCO inx 0x%04x, pkt types 0x%04x", p_scb->sco_idx,
432 params.packet_types);
433 } else {
434 /* Not initiating, go to listen mode */
435 tBTM_STATUS btm_status = BTM_CreateSco(
436 &p_scb->peer_addr, false, params.packet_types, &p_scb->sco_idx,
437 bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
438 if (btm_status == BTM_CMD_STARTED) {
439 BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
440 }
441 LOG_DEBUG("Listening AG SCO inx 0x%04x status:%s pkt types 0x%04x",
442 p_scb->sco_idx, btm_status_text(btm_status).c_str(),
443 params.packet_types);
444 }
445 LOG_DEBUG("AFTER %s", p_scb->ToString().c_str());
446 }
447
448 /*******************************************************************************
449 *
450 * Function bta_ag_create_pending_sco
451 *
452 * Description This Function is called after the pre-SCO vendor setup is
453 * done for the BTA to continue and send the HCI Commands for
454 * creating/accepting SCO connection with peer based on the
455 * is_local parameter.
456 *
457 * Returns void
458 *
459 ******************************************************************************/
bta_ag_create_pending_sco(tBTA_AG_SCB * p_scb,bool is_local)460 static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local) {
461 tBTA_AG_PEER_CODEC esco_codec = p_scb->inuse_codec;
462 enh_esco_params_t params = {};
463 bta_ag_cb.sco.p_curr_scb = p_scb;
464 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
465
466 /* Local device requested SCO connection to peer */
467 if (is_local) {
468 if (esco_codec == BTA_AG_CODEC_MSBC) {
469 if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) {
470 params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T2);
471 } else {
472 params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T1);
473 }
474 } else {
475 if (p_scb->features & BTA_AG_PEER_FEAT_ESCO_S4 &&
476 (p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4)) {
477 // HFP >=1.7 eSCO
478 params = esco_parameters_for_codec(ESCO_CODEC_CVSD_S4);
479 } else {
480 // HFP <=1.6 eSCO
481 params = esco_parameters_for_codec(ESCO_CODEC_CVSD_S3);
482 }
483 }
484
485 /* Bypass voice settings if enhanced SCO setup command is supported */
486 if (!(controller_get_interface()
487 ->supports_enhanced_setup_synchronous_connection())) {
488 if (esco_codec == BTA_AG_CODEC_MSBC) {
489 BTM_WriteVoiceSettings(BTM_VOICE_SETTING_TRANS);
490 } else {
491 BTM_WriteVoiceSettings(BTM_VOICE_SETTING_CVSD);
492 }
493 }
494
495 if (BTM_CreateSco(&p_scb->peer_addr, true, params.packet_types,
496 &p_scb->sco_idx, bta_ag_sco_conn_cback,
497 bta_ag_sco_disc_cback) == BTM_CMD_STARTED) {
498 /* Initiating the connection, set the current sco handle */
499 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
500 }
501 APPL_TRACE_DEBUG("%s: initiated SCO connection", __func__);
502 } else {
503 // Local device accepted SCO connection from peer(HF)
504 // Because HF devices usually do not send AT+BAC and +BCS command,
505 // and there is no plan to implement corresponding command handlers,
506 // so we only accept CVSD connection from HF no matter what's
507 // requested.
508 if (p_scb->features & BTA_AG_PEER_FEAT_ESCO_S4 &&
509 (p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4)) {
510 // HFP >=1.7 eSCO
511 params = esco_parameters_for_codec(ESCO_CODEC_CVSD_S4);
512 } else {
513 // HFP <=1.6 eSCO
514 params = esco_parameters_for_codec(ESCO_CODEC_CVSD_S3);
515 }
516
517 BTM_EScoConnRsp(p_scb->sco_idx, HCI_SUCCESS, ¶ms);
518 APPL_TRACE_DEBUG("%s: listening for SCO connection", __func__);
519 }
520 }
521
522 /*******************************************************************************
523 *
524 * Function bta_ag_codec_negotiation_timer_cback
525 *
526 * Description
527 *
528 *
529 * Returns void
530 *
531 ******************************************************************************/
bta_ag_codec_negotiation_timer_cback(void * data)532 static void bta_ag_codec_negotiation_timer_cback(void* data) {
533 LOG_WARN("Codec negotiation timeout");
534 tBTA_AG_SCB* p_scb = (tBTA_AG_SCB*)data;
535
536 /* Announce that codec negotiation failed. */
537 bta_ag_sco_codec_nego(p_scb, false);
538
539 /* call app callback */
540 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
541 }
542
543 /*******************************************************************************
544 *
545 * Function bta_ag_codec_negotiate
546 *
547 * Description Initiate codec negotiation by sending AT command.
548 * If not necessary, skip negotiation.
549 *
550 * Returns void
551 *
552 ******************************************************************************/
bta_ag_codec_negotiate(tBTA_AG_SCB * p_scb)553 void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb) {
554 bta_ag_cb.sco.p_curr_scb = p_scb;
555 uint8_t* p_rem_feat = BTM_ReadRemoteFeatures(p_scb->peer_addr);
556 bool sdp_wbs_support = p_scb->peer_sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
557
558 if (p_rem_feat == nullptr) {
559 LOG_WARN("Skip codec negotiation, failed to read remote features");
560 bta_ag_sco_codec_nego(p_scb, false);
561 return;
562 }
563
564 // Workaround for misbehaving HFs, which indicate which one is not support on
565 // Transparent Synchronous Data in Remote Supported Features, WBS in SDP and
566 // and Codec Negotiation in BRSF. Fluoride will assume CVSD codec by default.
567 // In Sony XAV AX100 car kit and Sony MW600 Headset case, which indicate
568 // Transparent Synchronous Data and WBS support, but no codec negotiation
569 // support, using mSBC codec can result background noise or no audio.
570 // In Skullcandy JIB case, which indicate WBS and codec negotiation support,
571 // but no Transparent Synchronous Data support, using mSBC codec can result
572 // SCO setup fail by Firmware reject.
573 if (!HCI_LMP_TRANSPNT_SUPPORTED(p_rem_feat) || !sdp_wbs_support ||
574 !(p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
575 LOG_INFO("Assume CVSD by default due to mask mismatch");
576 p_scb->sco_codec = UUID_CODEC_CVSD;
577 }
578
579 if ((p_scb->codec_updated || p_scb->codec_fallback) &&
580 (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
581 LOG_INFO("Starting codec negotiation");
582 /* Change the power mode to Active until SCO open is completed. */
583 bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
584
585 /* Send +BCS to the peer */
586 bta_ag_send_bcs(p_scb);
587
588 /* Start timer to handle timeout */
589 alarm_set_on_mloop(p_scb->codec_negotiation_timer,
590 BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS,
591 bta_ag_codec_negotiation_timer_cback, p_scb);
592 } else {
593 /* use same codec type as previous SCO connection, skip codec negotiation */
594 LOG_INFO("Skip codec negotiation, using the same codec");
595 bta_ag_sco_codec_nego(p_scb, true);
596 }
597 }
598
bta_ag_sco_event(tBTA_AG_SCB * p_scb,uint8_t event)599 static void bta_ag_sco_event(tBTA_AG_SCB* p_scb, uint8_t event) {
600 tBTA_AG_SCO_CB* p_sco = &bta_ag_cb.sco;
601 uint8_t previous_state = p_sco->state;
602 LOG_INFO("device:%s index:0x%04x state:%s[%d] event:%s[%d]",
603 PRIVATE_ADDRESS(p_scb->peer_addr), p_scb->sco_idx,
604 bta_ag_sco_state_str(p_sco->state), p_sco->state,
605 bta_ag_sco_evt_str(event), event);
606
607 switch (p_sco->state) {
608 case BTA_AG_SCO_SHUTDOWN_ST:
609 switch (event) {
610 case BTA_AG_SCO_LISTEN_E:
611 /* create sco listen connection */
612 bta_ag_create_sco(p_scb, false);
613 p_sco->state = BTA_AG_SCO_LISTEN_ST;
614 break;
615
616 default:
617 LOG_WARN("BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %s[%d]",
618 bta_ag_sco_evt_str(event), event);
619 break;
620 }
621 break;
622
623 case BTA_AG_SCO_LISTEN_ST:
624 switch (event) {
625 case BTA_AG_SCO_LISTEN_E:
626 /* create sco listen connection (Additional channel) */
627 bta_ag_create_sco(p_scb, false);
628 break;
629
630 case BTA_AG_SCO_OPEN_E:
631 /* remove listening connection */
632 bta_ag_remove_sco(p_scb, false);
633
634 #if (DISABLE_WBS == FALSE)
635 /* start codec negotiation */
636 p_sco->state = BTA_AG_SCO_CODEC_ST;
637 bta_ag_codec_negotiate(p_scb);
638 #else
639 bta_ag_create_sco(p_scb, true);
640 p_sco->state = BTA_AG_SCO_OPENING_ST;
641 #endif
642 break;
643
644 case BTA_AG_SCO_SHUTDOWN_E:
645 /* remove listening connection */
646 bta_ag_remove_sco(p_scb, false);
647
648 if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = nullptr;
649
650 /* If last SCO instance then finish shutting down */
651 if (!bta_ag_other_scb_open(p_scb)) {
652 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
653 }
654 break;
655
656 case BTA_AG_SCO_CLOSE_E:
657 /* remove listening connection */
658 /* Ignore the event. Keep listening SCO for the active SLC */
659 LOG_WARN("BTA_AG_SCO_LISTEN_ST: Ignoring event %s[%d]",
660 bta_ag_sco_evt_str(event), event);
661 break;
662
663 case BTA_AG_SCO_CONN_CLOSE_E:
664 /* sco failed; create sco listen connection */
665 bta_ag_create_sco(p_scb, false);
666 p_sco->state = BTA_AG_SCO_LISTEN_ST;
667 break;
668
669 default:
670 LOG_WARN("BTA_AG_SCO_LISTEN_ST: Ignoring event %s[%d]",
671 bta_ag_sco_evt_str(event), event);
672 break;
673 }
674 break;
675
676 case BTA_AG_SCO_CODEC_ST:
677 switch (event) {
678 case BTA_AG_SCO_LISTEN_E:
679 /* create sco listen connection (Additional channel) */
680 bta_ag_create_sco(p_scb, false);
681 break;
682
683 case BTA_AG_SCO_CN_DONE_E:
684 /* create sco connection to peer */
685 bta_ag_create_sco(p_scb, true);
686 p_sco->state = BTA_AG_SCO_OPENING_ST;
687 break;
688
689 case BTA_AG_SCO_XFER_E:
690 /* save xfer scb */
691 p_sco->p_xfer_scb = p_scb;
692 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
693 break;
694
695 case BTA_AG_SCO_SHUTDOWN_E:
696 /* remove listening connection */
697 bta_ag_remove_sco(p_scb, false);
698
699 if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = nullptr;
700
701 /* If last SCO instance then finish shutting down */
702 if (!bta_ag_other_scb_open(p_scb)) {
703 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
704 }
705 break;
706
707 case BTA_AG_SCO_CLOSE_E:
708 /* sco open is not started yet. just go back to listening */
709 p_sco->state = BTA_AG_SCO_LISTEN_ST;
710 break;
711
712 case BTA_AG_SCO_CONN_CLOSE_E:
713 /* sco failed; create sco listen connection */
714 bta_ag_create_sco(p_scb, false);
715 p_sco->state = BTA_AG_SCO_LISTEN_ST;
716 break;
717
718 default:
719 LOG_WARN("BTA_AG_SCO_CODEC_ST: Ignoring event %s[%d]",
720 bta_ag_sco_evt_str(event), event);
721 break;
722 }
723 break;
724
725 case BTA_AG_SCO_OPENING_ST:
726 switch (event) {
727 case BTA_AG_SCO_LISTEN_E:
728 /* second headset has now joined */
729 /* create sco listen connection (Additional channel) */
730 if (p_scb != p_sco->p_curr_scb) {
731 bta_ag_create_sco(p_scb, false);
732 }
733 break;
734
735 #if (DISABLE_WBS == FALSE)
736 case BTA_AG_SCO_REOPEN_E:
737 /* start codec negotiation */
738 p_sco->state = BTA_AG_SCO_CODEC_ST;
739 bta_ag_codec_negotiate(p_scb);
740 break;
741 #endif
742
743 case BTA_AG_SCO_XFER_E:
744 /* save xfer scb */
745 p_sco->p_xfer_scb = p_scb;
746 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
747 break;
748
749 case BTA_AG_SCO_CLOSE_E:
750 p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
751 break;
752
753 case BTA_AG_SCO_SHUTDOWN_E:
754 /* If not opening scb, just close it */
755 if (p_scb != p_sco->p_curr_scb) {
756 /* remove listening connection */
757 bta_ag_remove_sco(p_scb, false);
758 } else
759 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
760
761 break;
762
763 case BTA_AG_SCO_CONN_OPEN_E:
764 p_sco->state = BTA_AG_SCO_OPEN_ST;
765 break;
766
767 case BTA_AG_SCO_CONN_CLOSE_E:
768 /* sco failed; create sco listen connection */
769 bta_ag_create_sco(p_scb, false);
770 p_sco->state = BTA_AG_SCO_LISTEN_ST;
771 break;
772
773 default:
774 LOG_WARN("BTA_AG_SCO_OPENING_ST: Ignoring event %s[%d]",
775 bta_ag_sco_evt_str(event), event);
776 break;
777 }
778 break;
779
780 case BTA_AG_SCO_OPEN_CL_ST:
781 switch (event) {
782 case BTA_AG_SCO_XFER_E:
783 /* save xfer scb */
784 p_sco->p_xfer_scb = p_scb;
785
786 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
787 break;
788
789 case BTA_AG_SCO_OPEN_E:
790 p_sco->state = BTA_AG_SCO_OPENING_ST;
791 break;
792
793 case BTA_AG_SCO_SHUTDOWN_E:
794 /* If not opening scb, just close it */
795 if (p_scb != p_sco->p_curr_scb) {
796 /* remove listening connection */
797 bta_ag_remove_sco(p_scb, false);
798 } else
799 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
800
801 break;
802
803 case BTA_AG_SCO_CONN_OPEN_E:
804 /* close sco connection */
805 bta_ag_remove_sco(p_scb, true);
806
807 p_sco->state = BTA_AG_SCO_CLOSING_ST;
808 break;
809
810 case BTA_AG_SCO_CONN_CLOSE_E:
811 /* sco failed; create sco listen connection */
812
813 p_sco->state = BTA_AG_SCO_LISTEN_ST;
814 break;
815
816 default:
817 LOG_WARN("BTA_AG_SCO_OPEN_CL_ST: Ignoring event %s[%d]",
818 bta_ag_sco_evt_str(event), event);
819 break;
820 }
821 break;
822
823 case BTA_AG_SCO_OPEN_XFER_ST:
824 switch (event) {
825 case BTA_AG_SCO_CLOSE_E:
826 /* close sco connection */
827 bta_ag_remove_sco(p_scb, true);
828
829 p_sco->state = BTA_AG_SCO_CLOSING_ST;
830 break;
831
832 case BTA_AG_SCO_SHUTDOWN_E:
833 /* remove all connection */
834 bta_ag_remove_sco(p_scb, false);
835 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
836
837 break;
838
839 case BTA_AG_SCO_CONN_CLOSE_E:
840 /* closed sco; place in listen mode and
841 accept the transferred connection */
842 bta_ag_create_sco(p_scb, false); /* Back into listen mode */
843
844 /* Accept sco connection with xfer scb */
845 bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
846 p_sco->state = BTA_AG_SCO_OPENING_ST;
847 p_sco->p_curr_scb = p_sco->p_xfer_scb;
848 p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
849 p_sco->p_xfer_scb = nullptr;
850 break;
851
852 default:
853 LOG_WARN("BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %s[%d]",
854 bta_ag_sco_evt_str(event), event);
855 break;
856 }
857 break;
858
859 case BTA_AG_SCO_OPEN_ST:
860 switch (event) {
861 case BTA_AG_SCO_LISTEN_E:
862 /* second headset has now joined */
863 /* create sco listen connection (Additional channel) */
864 if (p_scb != p_sco->p_curr_scb) {
865 bta_ag_create_sco(p_scb, false);
866 }
867 break;
868
869 case BTA_AG_SCO_XFER_E:
870 /* close current sco connection */
871 bta_ag_remove_sco(p_sco->p_curr_scb, true);
872
873 /* save xfer scb */
874 p_sco->p_xfer_scb = p_scb;
875
876 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
877 break;
878
879 case BTA_AG_SCO_CLOSE_E:
880 /* close sco connection if active */
881 if (bta_ag_remove_sco(p_scb, true)) {
882 p_sco->state = BTA_AG_SCO_CLOSING_ST;
883 }
884 break;
885
886 case BTA_AG_SCO_SHUTDOWN_E:
887 /* remove all listening connections */
888 bta_ag_remove_sco(p_scb, false);
889
890 /* If SCO was active on this scb, close it */
891 if (p_scb == p_sco->p_curr_scb) {
892 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
893 }
894 break;
895
896 case BTA_AG_SCO_CONN_CLOSE_E:
897 /* peer closed sco; create sco listen connection */
898 bta_ag_create_sco(p_scb, false);
899 p_sco->state = BTA_AG_SCO_LISTEN_ST;
900 break;
901
902 default:
903 LOG_WARN("BTA_AG_SCO_OPEN_ST: Ignoring event %s[%d]",
904 bta_ag_sco_evt_str(event), event);
905 break;
906 }
907 break;
908
909 case BTA_AG_SCO_CLOSING_ST:
910 switch (event) {
911 case BTA_AG_SCO_LISTEN_E:
912 /* create sco listen connection (Additional channel) */
913 if (p_scb != p_sco->p_curr_scb) {
914 bta_ag_create_sco(p_scb, false);
915 }
916 break;
917
918 case BTA_AG_SCO_OPEN_E:
919 p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
920 break;
921
922 case BTA_AG_SCO_XFER_E:
923 /* save xfer scb */
924 p_sco->p_xfer_scb = p_scb;
925
926 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
927 break;
928
929 case BTA_AG_SCO_SHUTDOWN_E:
930 /* If not closing scb, just close it */
931 if (p_scb != p_sco->p_curr_scb) {
932 /* remove listening connection */
933 bta_ag_remove_sco(p_scb, false);
934 } else
935 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
936
937 break;
938
939 case BTA_AG_SCO_CONN_CLOSE_E:
940 /* peer closed sco; create sco listen connection */
941 bta_ag_create_sco(p_scb, false);
942
943 p_sco->state = BTA_AG_SCO_LISTEN_ST;
944 break;
945
946 default:
947 LOG_WARN("BTA_AG_SCO_CLOSING_ST: Ignoring event %s[%d]",
948 bta_ag_sco_evt_str(event), event);
949 break;
950 }
951 break;
952
953 case BTA_AG_SCO_CLOSE_OP_ST:
954 switch (event) {
955 case BTA_AG_SCO_CLOSE_E:
956 p_sco->state = BTA_AG_SCO_CLOSING_ST;
957 break;
958
959 case BTA_AG_SCO_SHUTDOWN_E:
960 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
961 break;
962
963 case BTA_AG_SCO_CONN_CLOSE_E:
964 /* start codec negotiation */
965 p_sco->state = BTA_AG_SCO_CODEC_ST;
966 bta_ag_codec_negotiate(p_scb);
967 break;
968
969 case BTA_AG_SCO_LISTEN_E:
970 /* create sco listen connection (Additional channel) */
971 if (p_scb != p_sco->p_curr_scb) {
972 bta_ag_create_sco(p_scb, false);
973 }
974 break;
975
976 default:
977 LOG_WARN("BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %s[%d]",
978 bta_ag_sco_evt_str(event), event);
979 break;
980 }
981 break;
982
983 case BTA_AG_SCO_CLOSE_XFER_ST:
984 switch (event) {
985 case BTA_AG_SCO_CONN_OPEN_E:
986 /* close sco connection so headset can be transferred
987 Probably entered this state from "opening state" */
988 bta_ag_remove_sco(p_scb, true);
989 break;
990
991 case BTA_AG_SCO_CLOSE_E:
992 /* clear xfer scb */
993 p_sco->p_xfer_scb = nullptr;
994
995 p_sco->state = BTA_AG_SCO_CLOSING_ST;
996 break;
997
998 case BTA_AG_SCO_SHUTDOWN_E:
999 /* clear xfer scb */
1000 p_sco->p_xfer_scb = nullptr;
1001
1002 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1003 break;
1004
1005 case BTA_AG_SCO_CONN_CLOSE_E: {
1006 /* closed sco; place old sco in listen mode,
1007 take current sco out of listen, and
1008 create originating sco for current */
1009 bta_ag_create_sco(p_scb, false);
1010 bta_ag_remove_sco(p_sco->p_xfer_scb, false);
1011
1012 #if (DISABLE_WBS == FALSE)
1013 /* start codec negotiation */
1014 p_sco->state = BTA_AG_SCO_CODEC_ST;
1015 tBTA_AG_SCB* p_cn_scb = p_sco->p_xfer_scb;
1016 p_sco->p_xfer_scb = nullptr;
1017 bta_ag_codec_negotiate(p_cn_scb);
1018 #else
1019 /* create sco connection to peer */
1020 bta_ag_create_sco(p_sco->p_xfer_scb, true);
1021 p_sco->p_xfer_scb = nullptr;
1022 p_sco->state = BTA_AG_SCO_OPENING_ST;
1023 #endif
1024 break;
1025 }
1026
1027 default:
1028 LOG_WARN(" BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %s[%d]",
1029 bta_ag_sco_evt_str(event), event);
1030 break;
1031 }
1032 break;
1033
1034 case BTA_AG_SCO_SHUTTING_ST:
1035 switch (event) {
1036 case BTA_AG_SCO_CONN_OPEN_E:
1037 /* close sco connection; wait for conn close event */
1038 bta_ag_remove_sco(p_scb, true);
1039 break;
1040
1041 case BTA_AG_SCO_CONN_CLOSE_E:
1042 /* If last SCO instance then finish shutting down */
1043 if (!bta_ag_other_scb_open(p_scb)) {
1044 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1045 } else /* Other instance is still listening */
1046 {
1047 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1048 }
1049
1050 /* If SCO closed for other HS which is not being disconnected,
1051 then create listen sco connection for it as scb still open */
1052 if (bta_ag_scb_open(p_scb)) {
1053 bta_ag_create_sco(p_scb, false);
1054 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1055 }
1056
1057 if (p_scb == p_sco->p_curr_scb) {
1058 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1059 p_sco->p_curr_scb = nullptr;
1060 }
1061 break;
1062
1063 case BTA_AG_SCO_LISTEN_E:
1064 /* create sco listen connection (Additional channel) */
1065 if (p_scb != p_sco->p_curr_scb) {
1066 bta_ag_create_sco(p_scb, false);
1067 }
1068 break;
1069
1070 case BTA_AG_SCO_SHUTDOWN_E:
1071 if (!bta_ag_other_scb_open(p_scb)) {
1072 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1073 } else /* Other instance is still listening */
1074 {
1075 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1076 }
1077
1078 if (p_scb == p_sco->p_curr_scb) {
1079 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1080 p_sco->p_curr_scb = nullptr;
1081 }
1082 break;
1083
1084 default:
1085 LOG_WARN("BTA_AG_SCO_SHUTTING_ST: Ignoring event %s[%d]",
1086 bta_ag_sco_evt_str(event), event);
1087 break;
1088 }
1089 break;
1090
1091 default:
1092 break;
1093 }
1094 if (p_sco->state != previous_state) {
1095 LOG_WARN(
1096 "SCO_state_change: [%s(0x%02x)]->[%s(0x%02x)] "
1097 "after event [%s(0x%02x)]",
1098 bta_ag_sco_state_str(previous_state), previous_state,
1099 bta_ag_sco_state_str(p_sco->state), p_sco->state,
1100 bta_ag_sco_evt_str(event), event);
1101 }
1102 }
1103
1104 /*******************************************************************************
1105 *
1106 * Function bta_ag_sco_is_open
1107 *
1108 * Description Check if sco is open for this scb.
1109 *
1110 *
1111 * Returns true if sco open for this scb, false otherwise.
1112 *
1113 ******************************************************************************/
bta_ag_sco_is_open(tBTA_AG_SCB * p_scb)1114 bool bta_ag_sco_is_open(tBTA_AG_SCB* p_scb) {
1115 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
1116 (bta_ag_cb.sco.p_curr_scb == p_scb));
1117 }
1118
1119 /*******************************************************************************
1120 *
1121 * Function bta_ag_sco_is_opening
1122 *
1123 * Description Check if sco is in Opening state.
1124 *
1125 *
1126 * Returns true if sco is in Opening state for this scb, false
1127 * otherwise.
1128 *
1129 ******************************************************************************/
bta_ag_sco_is_opening(tBTA_AG_SCB * p_scb)1130 bool bta_ag_sco_is_opening(tBTA_AG_SCB* p_scb) {
1131 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
1132 (bta_ag_cb.sco.p_curr_scb == p_scb));
1133 }
1134
1135 /*******************************************************************************
1136 *
1137 * Function bta_ag_sco_listen
1138 *
1139 * Description
1140 *
1141 *
1142 * Returns void
1143 *
1144 ******************************************************************************/
bta_ag_sco_listen(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1145 void bta_ag_sco_listen(tBTA_AG_SCB* p_scb,
1146 UNUSED_ATTR const tBTA_AG_DATA& data) {
1147 LOG(INFO) << __func__ << ": " << p_scb->peer_addr;
1148 bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
1149 }
1150
1151 /*******************************************************************************
1152 *
1153 * Function bta_ag_sco_open
1154 *
1155 * Description
1156 *
1157 *
1158 * Returns void
1159 *
1160 ******************************************************************************/
bta_ag_sco_open(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1161 void bta_ag_sco_open(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
1162 if (!sco_allowed) {
1163 LOG(INFO) << __func__ << ": not opening sco, by policy";
1164 return;
1165 }
1166 /* if another scb using sco, this is a transfer */
1167 if (bta_ag_cb.sco.p_curr_scb && bta_ag_cb.sco.p_curr_scb != p_scb) {
1168 LOG(INFO) << __func__ << ": transfer "
1169 << bta_ag_cb.sco.p_curr_scb->peer_addr << " -> "
1170 << p_scb->peer_addr;
1171 bta_ag_sco_event(p_scb, BTA_AG_SCO_XFER_E);
1172 } else {
1173 /* else it is an open */
1174 LOG(INFO) << __func__ << ": open " << p_scb->peer_addr;
1175 bta_ag_sco_event(p_scb, BTA_AG_SCO_OPEN_E);
1176 }
1177 }
1178
1179 /*******************************************************************************
1180 *
1181 * Function bta_ag_sco_close
1182 *
1183 * Description
1184 *
1185 *
1186 * Returns void
1187 *
1188 ******************************************************************************/
bta_ag_sco_close(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1189 void bta_ag_sco_close(tBTA_AG_SCB* p_scb,
1190 UNUSED_ATTR const tBTA_AG_DATA& data) {
1191 /* if scb is in use */
1192 /* sco_idx is not allocated in SCO_CODEC_ST, still need to move to listen
1193 * state. */
1194 if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) ||
1195 (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST)) {
1196 APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
1197 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1198 }
1199 }
1200
1201 /*******************************************************************************
1202 *
1203 * Function bta_ag_sco_codec_nego
1204 *
1205 * Description Handles result of eSCO codec negotiation
1206 *
1207 *
1208 * Returns void
1209 *
1210 ******************************************************************************/
bta_ag_sco_codec_nego(tBTA_AG_SCB * p_scb,bool result)1211 void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result) {
1212 if (result) {
1213 /* Subsequent SCO connection will skip codec negotiation */
1214 LOG_INFO("Succeeded for index 0x%04x, device %s", p_scb->sco_idx,
1215 p_scb->peer_addr.ToString().c_str());
1216 p_scb->codec_updated = false;
1217 bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
1218 } else {
1219 /* codec negotiation failed */
1220 LOG_INFO("Failed for index 0x%04x, device %s", p_scb->sco_idx,
1221 p_scb->peer_addr.ToString().c_str());
1222 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1223 }
1224 }
1225
1226 /*******************************************************************************
1227 *
1228 * Function bta_ag_sco_shutdown
1229 *
1230 * Description
1231 *
1232 *
1233 * Returns void
1234 *
1235 ******************************************************************************/
bta_ag_sco_shutdown(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1236 void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb,
1237 UNUSED_ATTR const tBTA_AG_DATA& data) {
1238 bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
1239 }
1240
1241 /*******************************************************************************
1242 *
1243 * Function bta_ag_sco_conn_open
1244 *
1245 * Description
1246 *
1247 *
1248 * Returns void
1249 *
1250 ******************************************************************************/
bta_ag_sco_conn_open(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1251 void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb,
1252 UNUSED_ATTR const tBTA_AG_DATA& data) {
1253 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
1254
1255 bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1256
1257 /* call app callback */
1258 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
1259
1260 /* reset to mSBC T2 settings as the preferred */
1261 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1262 }
1263
1264 /*******************************************************************************
1265 *
1266 * Function bta_ag_sco_conn_close
1267 *
1268 * Description
1269 *
1270 *
1271 * Returns void
1272 *
1273 ******************************************************************************/
bta_ag_sco_conn_close(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1274 void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb,
1275 UNUSED_ATTR const tBTA_AG_DATA& data) {
1276 /* clear current scb */
1277 bta_ag_cb.sco.p_curr_scb = nullptr;
1278 p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1279
1280 /* codec_fallback is set when AG is initiator and connection failed for mSBC.
1281 * OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */
1282 if (p_scb->svc_conn &&
1283 (p_scb->codec_fallback ||
1284 (p_scb->sco_codec == BTM_SCO_CODEC_MSBC &&
1285 p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1))) {
1286 bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
1287 } else {
1288 /* Indicate if the closing of audio is because of transfer */
1289 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
1290
1291 bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1292
1293 /* if av got suspended by this call, let it resume. */
1294 /* In case call stays alive regardless of sco, av should not be affected. */
1295 if (((p_scb->call_ind == BTA_AG_CALL_INACTIVE) &&
1296 (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE)) ||
1297 (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)) {
1298 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1299 }
1300
1301 /* call app callback */
1302 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
1303 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1304 }
1305 }
1306
1307 /*******************************************************************************
1308 *
1309 * Function bta_ag_sco_conn_rsp
1310 *
1311 * Description Process the SCO connection request
1312 *
1313 *
1314 * Returns void
1315 *
1316 ******************************************************************************/
bta_ag_sco_conn_rsp(tBTA_AG_SCB * p_scb,tBTM_ESCO_CONN_REQ_EVT_DATA * p_data)1317 void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb,
1318 tBTM_ESCO_CONN_REQ_EVT_DATA* p_data) {
1319 bta_ag_cb.sco.is_local = false;
1320
1321 APPL_TRACE_DEBUG("%s: eSCO %d, state %d", __func__,
1322 controller_get_interface()
1323 ->supports_enhanced_setup_synchronous_connection(),
1324 bta_ag_cb.sco.state);
1325
1326 if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST ||
1327 bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
1328 bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST) {
1329 /* tell sys to stop av if any */
1330 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1331 /* When HS initiated SCO, it cannot be WBS. */
1332 }
1333
1334 /* If SCO open was initiated from HS, it must be CVSD */
1335 p_scb->inuse_codec = BTA_AG_CODEC_NONE;
1336 /* Send pending commands to create SCO connection to peer */
1337 bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
1338 }
1339
bta_ag_set_sco_allowed(bool value)1340 void bta_ag_set_sco_allowed(bool value) {
1341 sco_allowed = value;
1342 APPL_TRACE_DEBUG(sco_allowed ? "sco now allowed" : "sco now not allowed");
1343 }
1344
bta_ag_get_active_device()1345 const RawAddress& bta_ag_get_active_device() { return active_device_addr; }
1346
bta_clear_active_device()1347 void bta_clear_active_device() { active_device_addr = RawAddress::kEmpty; }
1348
bta_ag_api_set_active_device(const RawAddress & new_active_device)1349 void bta_ag_api_set_active_device(const RawAddress& new_active_device) {
1350 if (new_active_device.IsEmpty()) {
1351 APPL_TRACE_ERROR("%s: empty device", __func__);
1352 return;
1353 }
1354 active_device_addr = new_active_device;
1355 }
1356