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 <cstddef>
26
27 #include "bt_common.h"
28 #include "bta_ag_api.h"
29 #include "bta_ag_int.h"
30 #include "bta_api.h"
31 #include "btm_api.h"
32 #include "device/include/controller.h"
33 #include "device/include/esco_parameters.h"
34 #include "osi/include/osi.h"
35 #include "utl.h"
36
37 /* Codec negotiation timeout */
38 #ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS
39 #define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000) /* 3 seconds */
40 #endif
41
42 static bool sco_allowed = true;
43 static RawAddress active_device_addr = {};
44
45 /* sco events */
46 enum {
47 BTA_AG_SCO_LISTEN_E, /* listen request */
48 BTA_AG_SCO_OPEN_E, /* open request */
49 BTA_AG_SCO_XFER_E, /* transfer request */
50 BTA_AG_SCO_CN_DONE_E, /* codec negotiation done */
51 BTA_AG_SCO_REOPEN_E, /* Retry with other codec when failed */
52 BTA_AG_SCO_CLOSE_E, /* close request */
53 BTA_AG_SCO_SHUTDOWN_E, /* shutdown request */
54 BTA_AG_SCO_CONN_OPEN_E, /* sco open */
55 BTA_AG_SCO_CONN_CLOSE_E, /* sco closed */
56 };
57
58 #define CASE_RETURN_STR(const) \
59 case const: \
60 return #const;
61
bta_ag_sco_evt_str(uint8_t event)62 static const char* bta_ag_sco_evt_str(uint8_t event) {
63 switch (event) {
64 CASE_RETURN_STR(BTA_AG_SCO_LISTEN_E)
65 CASE_RETURN_STR(BTA_AG_SCO_OPEN_E)
66 CASE_RETURN_STR(BTA_AG_SCO_XFER_E)
67 CASE_RETURN_STR(BTA_AG_SCO_CN_DONE_E)
68 CASE_RETURN_STR(BTA_AG_SCO_REOPEN_E)
69 CASE_RETURN_STR(BTA_AG_SCO_CLOSE_E)
70 CASE_RETURN_STR(BTA_AG_SCO_SHUTDOWN_E)
71 CASE_RETURN_STR(BTA_AG_SCO_CONN_OPEN_E)
72 CASE_RETURN_STR(BTA_AG_SCO_CONN_CLOSE_E)
73 default:
74 return "Unknown SCO Event";
75 }
76 }
77
bta_ag_sco_state_str(uint8_t state)78 static const char* bta_ag_sco_state_str(uint8_t state) {
79 switch (state) {
80 CASE_RETURN_STR(BTA_AG_SCO_SHUTDOWN_ST)
81 CASE_RETURN_STR(BTA_AG_SCO_LISTEN_ST)
82 CASE_RETURN_STR(BTA_AG_SCO_CODEC_ST)
83 CASE_RETURN_STR(BTA_AG_SCO_OPENING_ST)
84 CASE_RETURN_STR(BTA_AG_SCO_OPEN_CL_ST)
85 CASE_RETURN_STR(BTA_AG_SCO_OPEN_XFER_ST)
86 CASE_RETURN_STR(BTA_AG_SCO_OPEN_ST)
87 CASE_RETURN_STR(BTA_AG_SCO_CLOSING_ST)
88 CASE_RETURN_STR(BTA_AG_SCO_CLOSE_OP_ST)
89 CASE_RETURN_STR(BTA_AG_SCO_CLOSE_XFER_ST)
90 CASE_RETURN_STR(BTA_AG_SCO_SHUTTING_ST)
91 default:
92 return "Unknown SCO State";
93 }
94 }
95
96 /**
97 * Check if bd_addr is the current active device.
98 *
99 * @param bd_addr target device address
100 * @return True if bd_addr is the current active device, False otherwise or if
101 * no active device is set (i.e. active_device_addr is empty)
102 */
bta_ag_sco_is_active_device(const RawAddress & bd_addr)103 bool bta_ag_sco_is_active_device(const RawAddress& bd_addr) {
104 return !active_device_addr.IsEmpty() && active_device_addr == bd_addr;
105 }
106
107 static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local);
108
109 /*******************************************************************************
110 *
111 * Function bta_ag_sco_conn_cback
112 *
113 * Description BTM SCO connection callback.
114 *
115 *
116 * Returns void
117 *
118 ******************************************************************************/
bta_ag_sco_conn_cback(uint16_t sco_idx)119 static void bta_ag_sco_conn_cback(uint16_t sco_idx) {
120 uint16_t handle;
121 tBTA_AG_SCB* p_scb;
122
123 /* match callback to scb; first check current sco scb */
124 if (bta_ag_cb.sco.p_curr_scb != nullptr && bta_ag_cb.sco.p_curr_scb->in_use) {
125 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
126 }
127 /* then check for scb connected to this peer */
128 else {
129 /* Check if SLC is up */
130 handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx));
131 p_scb = bta_ag_scb_by_idx(handle);
132 if (p_scb && !p_scb->svc_conn) handle = 0;
133 }
134
135 if (handle != 0) {
136 do_in_bta_thread(FROM_HERE,
137 base::Bind(&bta_ag_sm_execute_by_handle, handle,
138 BTA_AG_SCO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
139 } else {
140 /* no match found; disconnect sco, init sco variables */
141 bta_ag_cb.sco.p_curr_scb = nullptr;
142 bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
143 BTM_RemoveSco(sco_idx);
144 }
145 }
146
147 /*******************************************************************************
148 *
149 * Function bta_ag_sco_disc_cback
150 *
151 * Description BTM SCO disconnection callback.
152 *
153 *
154 * Returns void
155 *
156 ******************************************************************************/
bta_ag_sco_disc_cback(uint16_t sco_idx)157 static void bta_ag_sco_disc_cback(uint16_t sco_idx) {
158 uint16_t handle = 0;
159
160 APPL_TRACE_DEBUG(
161 "bta_ag_sco_disc_cback(): sco_idx: 0x%x p_cur_scb: 0x%08x sco.state: "
162 "%d",
163 sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
164
165 APPL_TRACE_DEBUG(
166 "bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x in_use: %u sco_idx: 0x%x "
167 " sco state: %u",
168 &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx,
169 bta_ag_cb.scb[0].state);
170 APPL_TRACE_DEBUG(
171 "bta_ag_sco_disc_cback(): scb[1] addr: 0x%08x in_use: %u sco_idx: 0x%x "
172 " sco state: %u",
173 &bta_ag_cb.scb[1], bta_ag_cb.scb[1].in_use, bta_ag_cb.scb[1].sco_idx,
174 bta_ag_cb.scb[1].state);
175
176 /* match callback to scb */
177 if (bta_ag_cb.sco.p_curr_scb != nullptr && bta_ag_cb.sco.p_curr_scb->in_use) {
178 /* We only care about callbacks for the active SCO */
179 if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx) {
180 if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF) return;
181 }
182 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
183 }
184
185 if (handle != 0) {
186
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_bta_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 APPL_TRACE_DEBUG("%s: SCO index 0x%04x, status %d", __func__,
251 p_scb->sco_idx, status);
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,uint8_t event)342 static void bta_ag_cback_sco(tBTA_AG_SCB* p_scb, uint8_t 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)(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 APPL_TRACE_DEBUG(
363 "%s: BEFORE codec_updated=%d, codec_fallback=%d, "
364 "sco_codec=%d, peer_codec=%d, msbc_settings=%d, device=%s",
365 __func__, p_scb->codec_updated, p_scb->codec_fallback, p_scb->sco_codec,
366 p_scb->peer_codecs, p_scb->codec_msbc_settings,
367 p_scb->peer_addr.ToString().c_str());
368 tBTA_AG_PEER_CODEC esco_codec = BTA_AG_CODEC_CVSD;
369
370 if (!bta_ag_sco_is_active_device(p_scb->peer_addr)) {
371 LOG(WARNING) << __func__ << ": device " << p_scb->peer_addr
372 << " is not active, active_device=" << active_device_addr;
373 return;
374 }
375 /* Make sure this SCO handle is not already in use */
376 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) {
377 APPL_TRACE_ERROR("%s: device %s, index 0x%04x already in use!", __func__,
378 p_scb->peer_addr.ToString().c_str(), p_scb->sco_idx);
379 return;
380 }
381
382 if ((p_scb->sco_codec == BTA_AG_CODEC_MSBC) && !p_scb->codec_fallback)
383 esco_codec = BTA_AG_CODEC_MSBC;
384
385 if (p_scb->codec_fallback) {
386 p_scb->codec_fallback = false;
387 /* Force AG to send +BCS for the next audio connection. */
388 p_scb->codec_updated = true;
389 /* Reset mSBC settings to T2 for the next audio connection */
390 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
391 }
392
393 esco_codec_t codec_index = ESCO_CODEC_CVSD;
394 /* If WBS included, use CVSD by default, index is 0 for CVSD by
395 * initialization. If eSCO codec is mSBC, index is T2 or T1 */
396 if (esco_codec == BTA_AG_CODEC_MSBC) {
397 if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) {
398 codec_index = ESCO_CODEC_MSBC_T2;
399 } else {
400 codec_index = ESCO_CODEC_MSBC_T1;
401 }
402 }
403
404 /* Initialize eSCO parameters */
405 enh_esco_params_t params = esco_parameters_for_codec(codec_index);
406 /* For CVSD */
407 if (esco_codec == BTM_SCO_CODEC_CVSD) {
408 /* Use the applicable packet types
409 (3-EV3 not allowed due to errata 2363) */
410 params.packet_types =
411 p_bta_ag_cfg->sco_pkt_types | ESCO_PKT_TYPES_MASK_NO_3_EV3;
412 if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
413 (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
414 params.max_latency_ms = 10;
415 params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
416 }
417 }
418
419 /* If initiating, setup parameters to start SCO/eSCO connection */
420 if (is_orig) {
421 bta_ag_cb.sco.is_local = true;
422 /* Set eSCO Mode */
423 BTM_SetEScoMode(¶ms);
424 bta_ag_cb.sco.p_curr_scb = p_scb;
425 /* save the current codec as sco_codec can be updated while SCO is open. */
426 p_scb->inuse_codec = esco_codec;
427
428 /* tell sys to stop av if any */
429 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
430
431 /* Send pending commands to create SCO connection to peer */
432 bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
433 APPL_TRACE_API("%s: orig %d, inx 0x%04x, pkt types 0x%04x", __func__,
434 is_orig, p_scb->sco_idx, params.packet_types);
435 } else {
436 /* Not initiating, go to listen mode */
437 tBTM_STATUS status = BTM_CreateSco(
438 &p_scb->peer_addr, false, params.packet_types, &p_scb->sco_idx,
439 bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
440 if (status == BTM_CMD_STARTED) {
441 BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
442 }
443
444 APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
445 __func__, is_orig, p_scb->sco_idx, status,
446 params.packet_types);
447 }
448 APPL_TRACE_DEBUG(
449 "%s: AFTER codec_updated=%d, codec_fallback=%d, "
450 "sco_codec=%d, peer_codec=%d, msbc_settings=%d, device=%s",
451 __func__, p_scb->codec_updated, p_scb->codec_fallback, p_scb->sco_codec,
452 p_scb->peer_codecs, p_scb->codec_msbc_settings,
453 p_scb->peer_addr.ToString().c_str());
454 }
455
456 /*******************************************************************************
457 *
458 * Function bta_ag_create_pending_sco
459 *
460 * Description This Function is called after the pre-SCO vendor setup is
461 * done for the BTA to continue and send the HCI Commands for
462 * creating/accepting SCO connection with peer based on the
463 * is_local parameter.
464 *
465 * Returns void
466 *
467 ******************************************************************************/
bta_ag_create_pending_sco(tBTA_AG_SCB * p_scb,bool is_local)468 static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local) {
469 tBTA_AG_PEER_CODEC esco_codec = p_scb->inuse_codec;
470 enh_esco_params_t params = {};
471 bta_ag_cb.sco.p_curr_scb = p_scb;
472 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
473
474 /* Local device requested SCO connection to peer */
475 if (is_local) {
476 if (esco_codec == BTA_AG_CODEC_MSBC) {
477 if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) {
478 params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T2);
479 } else
480 params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T1);
481 } else {
482 params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
483 if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
484 (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
485 params.max_latency_ms = 10;
486 params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
487 }
488 }
489
490 /* Bypass voice settings if enhanced SCO setup command is supported */
491 if (!(controller_get_interface()
492 ->supports_enhanced_setup_synchronous_connection())) {
493 if (esco_codec == BTA_AG_CODEC_MSBC) {
494 BTM_WriteVoiceSettings(BTM_VOICE_SETTING_TRANS);
495 } else {
496 BTM_WriteVoiceSettings(BTM_VOICE_SETTING_CVSD);
497 }
498 }
499
500 if (BTM_CreateSco(&p_scb->peer_addr, true, params.packet_types,
501 &p_scb->sco_idx, bta_ag_sco_conn_cback,
502 bta_ag_sco_disc_cback) == BTM_CMD_STARTED) {
503 /* Initiating the connection, set the current sco handle */
504 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
505 }
506 APPL_TRACE_DEBUG("%s: initiated SCO connection", __func__);
507 } else {
508 /* Local device accepted SCO connection from peer */
509 params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
510 if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
511 (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
512 params.max_latency_ms = 10;
513 params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
514 }
515
516 BTM_EScoConnRsp(p_scb->sco_idx, HCI_SUCCESS, ¶ms);
517 APPL_TRACE_DEBUG("%s: listening for SCO connection", __func__);
518 }
519 }
520
521 /*******************************************************************************
522 *
523 * Function bta_ag_codec_negotiation_timer_cback
524 *
525 * Description
526 *
527 *
528 * Returns void
529 *
530 ******************************************************************************/
bta_ag_codec_negotiation_timer_cback(void * data)531 static void bta_ag_codec_negotiation_timer_cback(void* data) {
532 APPL_TRACE_DEBUG("%s", __func__);
533 tBTA_AG_SCB* p_scb = (tBTA_AG_SCB*)data;
534
535 /* Announce that codec negotiation failed. */
536 bta_ag_sco_codec_nego(p_scb, false);
537
538 /* call app callback */
539 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
540 }
541
542 /*******************************************************************************
543 *
544 * Function bta_ag_codec_negotiate
545 *
546 * Description Initiate codec negotiation by sending AT command.
547 * If not necessary, skip negotiation.
548 *
549 * Returns void
550 *
551 ******************************************************************************/
bta_ag_codec_negotiate(tBTA_AG_SCB * p_scb)552 void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb) {
553 APPL_TRACE_DEBUG("%s", __func__);
554 bta_ag_cb.sco.p_curr_scb = p_scb;
555
556 if ((p_scb->codec_updated || p_scb->codec_fallback) &&
557 (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
558 /* Change the power mode to Active until SCO open is completed. */
559 bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
560
561 /* Send +BCS to the peer */
562 bta_ag_send_bcs(p_scb);
563
564 /* Start timer to handle timeout */
565 alarm_set_on_mloop(p_scb->codec_negotiation_timer,
566 BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS,
567 bta_ag_codec_negotiation_timer_cback, p_scb);
568 } else {
569 /* use same codec type as previous SCO connection, skip codec negotiation */
570 APPL_TRACE_DEBUG(
571 "use same codec type as previous SCO connection,skip codec "
572 "negotiation");
573 bta_ag_sco_codec_nego(p_scb, true);
574 }
575 }
576
577 /*******************************************************************************
578 *
579 * Function bta_ag_sco_event
580 *
581 * Description
582 *
583 *
584 * Returns void
585 *
586 ******************************************************************************/
bta_ag_sco_event(tBTA_AG_SCB * p_scb,uint8_t event)587 static void bta_ag_sco_event(tBTA_AG_SCB* p_scb, uint8_t event) {
588 tBTA_AG_SCO_CB* p_sco = &bta_ag_cb.sco;
589 uint8_t previous_state = p_sco->state;
590 APPL_TRACE_EVENT("%s: index=0x%04x, device=%s, state=%s[%d], event=%s[%d]",
591 __func__, p_scb->sco_idx,
592 p_scb->peer_addr.ToString().c_str(),
593 bta_ag_sco_state_str(p_sco->state), p_sco->state,
594 bta_ag_sco_evt_str(event), event);
595
596 switch (p_sco->state) {
597 case BTA_AG_SCO_SHUTDOWN_ST:
598 switch (event) {
599 case BTA_AG_SCO_LISTEN_E:
600 /* create sco listen connection */
601 bta_ag_create_sco(p_scb, false);
602 p_sco->state = BTA_AG_SCO_LISTEN_ST;
603 break;
604
605 default:
606 APPL_TRACE_WARNING(
607 "%s: BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %s[%d]", __func__,
608 bta_ag_sco_evt_str(event), event);
609 break;
610 }
611 break;
612
613 case BTA_AG_SCO_LISTEN_ST:
614 switch (event) {
615 case BTA_AG_SCO_LISTEN_E:
616 /* create sco listen connection (Additional channel) */
617 bta_ag_create_sco(p_scb, false);
618 break;
619
620 case BTA_AG_SCO_OPEN_E:
621 /* remove listening connection */
622 bta_ag_remove_sco(p_scb, false);
623
624 /* start codec negotiation */
625 p_sco->state = BTA_AG_SCO_CODEC_ST;
626 bta_ag_codec_negotiate(p_scb);
627 break;
628
629 case BTA_AG_SCO_SHUTDOWN_E:
630 /* remove listening connection */
631 bta_ag_remove_sco(p_scb, false);
632
633 if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = nullptr;
634
635 /* If last SCO instance then finish shutting down */
636 if (!bta_ag_other_scb_open(p_scb)) {
637 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
638 }
639 break;
640
641 case BTA_AG_SCO_CLOSE_E:
642 /* remove listening connection */
643 /* Ignore the event. Keep listening SCO for the active SLC
644 */
645 APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %s[%d]",
646 __func__, bta_ag_sco_evt_str(event), event);
647 break;
648
649 case BTA_AG_SCO_CONN_CLOSE_E:
650 /* sco failed; create sco listen connection */
651 bta_ag_create_sco(p_scb, false);
652 p_sco->state = BTA_AG_SCO_LISTEN_ST;
653 break;
654
655 default:
656 APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %s[%d]",
657 __func__, bta_ag_sco_evt_str(event), event);
658 break;
659 }
660 break;
661
662 case BTA_AG_SCO_CODEC_ST:
663 switch (event) {
664 case BTA_AG_SCO_LISTEN_E:
665 /* create sco listen connection (Additional channel) */
666 bta_ag_create_sco(p_scb, false);
667 break;
668
669 case BTA_AG_SCO_CN_DONE_E:
670 /* create sco connection to peer */
671 bta_ag_create_sco(p_scb, true);
672 p_sco->state = BTA_AG_SCO_OPENING_ST;
673 break;
674
675 case BTA_AG_SCO_XFER_E:
676 /* save xfer scb */
677 p_sco->p_xfer_scb = p_scb;
678 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
679 break;
680
681 case BTA_AG_SCO_SHUTDOWN_E:
682 /* remove listening connection */
683 bta_ag_remove_sco(p_scb, false);
684
685 if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = nullptr;
686
687 /* If last SCO instance then finish shutting down */
688 if (!bta_ag_other_scb_open(p_scb)) {
689 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
690 }
691 break;
692
693 case BTA_AG_SCO_CLOSE_E:
694 /* sco open is not started yet. just go back to listening */
695 p_sco->state = BTA_AG_SCO_LISTEN_ST;
696 break;
697
698 case BTA_AG_SCO_CONN_CLOSE_E:
699 /* sco failed; create sco listen connection */
700 bta_ag_create_sco(p_scb, false);
701 p_sco->state = BTA_AG_SCO_LISTEN_ST;
702 break;
703
704 default:
705 APPL_TRACE_WARNING("%s: BTA_AG_SCO_CODEC_ST: Ignoring event %s[%d]",
706 __func__, bta_ag_sco_evt_str(event), event);
707 break;
708 }
709 break;
710
711 case BTA_AG_SCO_OPENING_ST:
712 switch (event) {
713 case BTA_AG_SCO_LISTEN_E:
714 /* second headset has now joined */
715 /* create sco listen connection (Additional channel) */
716 if (p_scb != p_sco->p_curr_scb) {
717 bta_ag_create_sco(p_scb, false);
718 }
719 break;
720
721 case BTA_AG_SCO_REOPEN_E:
722 /* start codec negotiation */
723 p_sco->state = BTA_AG_SCO_CODEC_ST;
724 bta_ag_codec_negotiate(p_scb);
725 break;
726
727 case BTA_AG_SCO_XFER_E:
728 /* save xfer scb */
729 p_sco->p_xfer_scb = p_scb;
730 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
731 break;
732
733 case BTA_AG_SCO_CLOSE_E:
734 p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
735 break;
736
737 case BTA_AG_SCO_SHUTDOWN_E:
738 /* If not opening scb, just close it */
739 if (p_scb != p_sco->p_curr_scb) {
740 /* remove listening connection */
741 bta_ag_remove_sco(p_scb, false);
742 } else
743 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
744
745 break;
746
747 case BTA_AG_SCO_CONN_OPEN_E:
748 p_sco->state = BTA_AG_SCO_OPEN_ST;
749 break;
750
751 case BTA_AG_SCO_CONN_CLOSE_E:
752 /* sco failed; create sco listen connection */
753 bta_ag_create_sco(p_scb, false);
754 p_sco->state = BTA_AG_SCO_LISTEN_ST;
755 break;
756
757 default:
758 APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPENING_ST: Ignoring event %s[%d]",
759 __func__, bta_ag_sco_evt_str(event), event);
760 break;
761 }
762 break;
763
764 case BTA_AG_SCO_OPEN_CL_ST:
765 switch (event) {
766 case BTA_AG_SCO_XFER_E:
767 /* save xfer scb */
768 p_sco->p_xfer_scb = p_scb;
769
770 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
771 break;
772
773 case BTA_AG_SCO_OPEN_E:
774 p_sco->state = BTA_AG_SCO_OPENING_ST;
775 break;
776
777 case BTA_AG_SCO_SHUTDOWN_E:
778 /* If not opening scb, just close it */
779 if (p_scb != p_sco->p_curr_scb) {
780 /* remove listening connection */
781 bta_ag_remove_sco(p_scb, false);
782 } else
783 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
784
785 break;
786
787 case BTA_AG_SCO_CONN_OPEN_E:
788 /* close sco connection */
789 bta_ag_remove_sco(p_scb, true);
790
791 p_sco->state = BTA_AG_SCO_CLOSING_ST;
792 break;
793
794 case BTA_AG_SCO_CONN_CLOSE_E:
795 /* sco failed; create sco listen connection */
796
797 p_sco->state = BTA_AG_SCO_LISTEN_ST;
798 break;
799
800 default:
801 APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_CL_ST: Ignoring event %s[%d]",
802 __func__, bta_ag_sco_evt_str(event), event);
803 break;
804 }
805 break;
806
807 case BTA_AG_SCO_OPEN_XFER_ST:
808 switch (event) {
809 case BTA_AG_SCO_CLOSE_E:
810 /* close sco connection */
811 bta_ag_remove_sco(p_scb, true);
812
813 p_sco->state = BTA_AG_SCO_CLOSING_ST;
814 break;
815
816 case BTA_AG_SCO_SHUTDOWN_E:
817 /* remove all connection */
818 bta_ag_remove_sco(p_scb, false);
819 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
820
821 break;
822
823 case BTA_AG_SCO_CONN_CLOSE_E:
824 /* closed sco; place in listen mode and
825 accept the transferred connection */
826 bta_ag_create_sco(p_scb, false); /* Back into listen mode */
827
828 /* Accept sco connection with xfer scb */
829 bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
830 p_sco->state = BTA_AG_SCO_OPENING_ST;
831 p_sco->p_curr_scb = p_sco->p_xfer_scb;
832 p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
833 p_sco->p_xfer_scb = nullptr;
834 break;
835
836 default:
837 APPL_TRACE_WARNING(
838 "%s: BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %s[%d]", __func__,
839 bta_ag_sco_evt_str(event), event);
840 break;
841 }
842 break;
843
844 case BTA_AG_SCO_OPEN_ST:
845 switch (event) {
846 case BTA_AG_SCO_LISTEN_E:
847 /* second headset has now joined */
848 /* create sco listen connection (Additional channel) */
849 if (p_scb != p_sco->p_curr_scb) {
850 bta_ag_create_sco(p_scb, false);
851 }
852 break;
853
854 case BTA_AG_SCO_XFER_E:
855 /* close current sco connection */
856 bta_ag_remove_sco(p_sco->p_curr_scb, true);
857
858 /* save xfer scb */
859 p_sco->p_xfer_scb = p_scb;
860
861 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
862 break;
863
864 case BTA_AG_SCO_CLOSE_E:
865 /* close sco connection if active */
866 if (bta_ag_remove_sco(p_scb, true)) {
867 p_sco->state = BTA_AG_SCO_CLOSING_ST;
868 }
869 break;
870
871 case BTA_AG_SCO_SHUTDOWN_E:
872 /* remove all listening connections */
873 bta_ag_remove_sco(p_scb, false);
874
875 /* If SCO was active on this scb, close it */
876 if (p_scb == p_sco->p_curr_scb) {
877 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
878 }
879 break;
880
881 case BTA_AG_SCO_CONN_CLOSE_E:
882 /* peer closed sco; create sco listen connection */
883 bta_ag_create_sco(p_scb, false);
884 p_sco->state = BTA_AG_SCO_LISTEN_ST;
885 break;
886
887 default:
888 APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_ST: Ignoring event %s[%d]",
889 __func__, bta_ag_sco_evt_str(event), event);
890 break;
891 }
892 break;
893
894 case BTA_AG_SCO_CLOSING_ST:
895 switch (event) {
896 case BTA_AG_SCO_LISTEN_E:
897 /* create sco listen connection (Additional channel) */
898 if (p_scb != p_sco->p_curr_scb) {
899 bta_ag_create_sco(p_scb, false);
900 }
901 break;
902
903 case BTA_AG_SCO_OPEN_E:
904 p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
905 break;
906
907 case BTA_AG_SCO_XFER_E:
908 /* save xfer scb */
909 p_sco->p_xfer_scb = p_scb;
910
911 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
912 break;
913
914 case BTA_AG_SCO_SHUTDOWN_E:
915 /* If not closing scb, just close it */
916 if (p_scb != p_sco->p_curr_scb) {
917 /* remove listening connection */
918 bta_ag_remove_sco(p_scb, false);
919 } else
920 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
921
922 break;
923
924 case BTA_AG_SCO_CONN_CLOSE_E:
925 /* peer closed sco; create sco listen connection */
926 bta_ag_create_sco(p_scb, false);
927
928 p_sco->state = BTA_AG_SCO_LISTEN_ST;
929 break;
930
931 default:
932 APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSING_ST: Ignoring event %s[%d]",
933 __func__, bta_ag_sco_evt_str(event), event);
934 break;
935 }
936 break;
937
938 case BTA_AG_SCO_CLOSE_OP_ST:
939 switch (event) {
940 case BTA_AG_SCO_CLOSE_E:
941 p_sco->state = BTA_AG_SCO_CLOSING_ST;
942 break;
943
944 case BTA_AG_SCO_SHUTDOWN_E:
945 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
946 break;
947
948 case BTA_AG_SCO_CONN_CLOSE_E:
949 /* start codec negotiation */
950 p_sco->state = BTA_AG_SCO_CODEC_ST;
951 bta_ag_codec_negotiate(p_scb);
952 break;
953
954 case BTA_AG_SCO_LISTEN_E:
955 /* create sco listen connection (Additional channel) */
956 if (p_scb != p_sco->p_curr_scb) {
957 bta_ag_create_sco(p_scb, false);
958 }
959 break;
960
961 default:
962 APPL_TRACE_WARNING(
963 "%s: BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %s[%d]", __func__,
964 bta_ag_sco_evt_str(event), event);
965 break;
966 }
967 break;
968
969 case BTA_AG_SCO_CLOSE_XFER_ST:
970 switch (event) {
971 case BTA_AG_SCO_CONN_OPEN_E:
972 /* close sco connection so headset can be transferred
973 Probably entered this state from "opening state" */
974 bta_ag_remove_sco(p_scb, true);
975 break;
976
977 case BTA_AG_SCO_CLOSE_E:
978 /* clear xfer scb */
979 p_sco->p_xfer_scb = nullptr;
980
981 p_sco->state = BTA_AG_SCO_CLOSING_ST;
982 break;
983
984 case BTA_AG_SCO_SHUTDOWN_E:
985 /* clear xfer scb */
986 p_sco->p_xfer_scb = nullptr;
987
988 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
989 break;
990
991 case BTA_AG_SCO_CONN_CLOSE_E: {
992 /* closed sco; place old sco in listen mode,
993 take current sco out of listen, and
994 create originating sco for current */
995 bta_ag_create_sco(p_scb, false);
996 bta_ag_remove_sco(p_sco->p_xfer_scb, false);
997
998 /* start codec negotiation */
999 p_sco->state = BTA_AG_SCO_CODEC_ST;
1000 tBTA_AG_SCB* p_cn_scb = p_sco->p_xfer_scb;
1001 p_sco->p_xfer_scb = nullptr;
1002 bta_ag_codec_negotiate(p_cn_scb);
1003 break;
1004 }
1005
1006 default:
1007 APPL_TRACE_WARNING(
1008 "%s: BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %s[%d]", __func__,
1009 bta_ag_sco_evt_str(event), event);
1010 break;
1011 }
1012 break;
1013
1014 case BTA_AG_SCO_SHUTTING_ST:
1015 switch (event) {
1016 case BTA_AG_SCO_CONN_OPEN_E:
1017 /* close sco connection; wait for conn close event */
1018 bta_ag_remove_sco(p_scb, true);
1019 break;
1020
1021 case BTA_AG_SCO_CONN_CLOSE_E:
1022 /* If last SCO instance then finish shutting down */
1023 if (!bta_ag_other_scb_open(p_scb)) {
1024 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1025 } else /* Other instance is still listening */
1026 {
1027 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1028 }
1029
1030 /* If SCO closed for other HS which is not being disconnected,
1031 then create listen sco connection for it as scb still open */
1032 if (bta_ag_scb_open(p_scb)) {
1033 bta_ag_create_sco(p_scb, false);
1034 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1035 }
1036
1037 if (p_scb == p_sco->p_curr_scb) {
1038 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1039 p_sco->p_curr_scb = nullptr;
1040 }
1041 break;
1042
1043 case BTA_AG_SCO_LISTEN_E:
1044 /* create sco listen connection (Additional channel) */
1045 if (p_scb != p_sco->p_curr_scb) {
1046 bta_ag_create_sco(p_scb, false);
1047 }
1048 break;
1049
1050 case BTA_AG_SCO_SHUTDOWN_E:
1051 if (!bta_ag_other_scb_open(p_scb)) {
1052 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1053 } else /* Other instance is still listening */
1054 {
1055 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1056 }
1057
1058 if (p_scb == p_sco->p_curr_scb) {
1059 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1060 p_sco->p_curr_scb = nullptr;
1061 }
1062 break;
1063
1064 default:
1065 APPL_TRACE_WARNING(
1066 "%s: BTA_AG_SCO_SHUTTING_ST: Ignoring event %s[%d]", __func__,
1067 bta_ag_sco_evt_str(event), event);
1068 break;
1069 }
1070 break;
1071
1072 default:
1073 break;
1074 }
1075 if (p_sco->state != previous_state) {
1076 APPL_TRACE_EVENT(
1077 "%s: SCO_state_change: [%s(0x%02x)]->[%s(0x%02x)] "
1078 "after event [%s(0x%02x)]",
1079 __func__, bta_ag_sco_state_str(previous_state), previous_state,
1080 bta_ag_sco_state_str(p_sco->state), p_sco->state,
1081 bta_ag_sco_evt_str(event), event);
1082 }
1083 }
1084
1085 /*******************************************************************************
1086 *
1087 * Function bta_ag_sco_is_open
1088 *
1089 * Description Check if sco is open for this scb.
1090 *
1091 *
1092 * Returns true if sco open for this scb, false otherwise.
1093 *
1094 ******************************************************************************/
bta_ag_sco_is_open(tBTA_AG_SCB * p_scb)1095 bool bta_ag_sco_is_open(tBTA_AG_SCB* p_scb) {
1096 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
1097 (bta_ag_cb.sco.p_curr_scb == p_scb));
1098 }
1099
1100 /*******************************************************************************
1101 *
1102 * Function bta_ag_sco_is_opening
1103 *
1104 * Description Check if sco is in Opening state.
1105 *
1106 *
1107 * Returns true if sco is in Opening state for this scb, false
1108 * otherwise.
1109 *
1110 ******************************************************************************/
bta_ag_sco_is_opening(tBTA_AG_SCB * p_scb)1111 bool bta_ag_sco_is_opening(tBTA_AG_SCB* p_scb) {
1112 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
1113 (bta_ag_cb.sco.p_curr_scb == p_scb));
1114 }
1115
1116 /*******************************************************************************
1117 *
1118 * Function bta_ag_sco_listen
1119 *
1120 * Description
1121 *
1122 *
1123 * Returns void
1124 *
1125 ******************************************************************************/
bta_ag_sco_listen(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1126 void bta_ag_sco_listen(tBTA_AG_SCB* p_scb,
1127 UNUSED_ATTR const tBTA_AG_DATA& data) {
1128 LOG(INFO) << __func__ << ": " << p_scb->peer_addr;
1129 bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
1130 }
1131
1132 /*******************************************************************************
1133 *
1134 * Function bta_ag_sco_open
1135 *
1136 * Description
1137 *
1138 *
1139 * Returns void
1140 *
1141 ******************************************************************************/
bta_ag_sco_open(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1142 void bta_ag_sco_open(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
1143 if (!sco_allowed) {
1144 LOG(INFO) << __func__ << ": not opening sco, by policy";
1145 return;
1146 }
1147 /* if another scb using sco, this is a transfer */
1148 if (bta_ag_cb.sco.p_curr_scb && bta_ag_cb.sco.p_curr_scb != p_scb) {
1149 LOG(INFO) << __func__ << ": tranfer " << bta_ag_cb.sco.p_curr_scb->peer_addr
1150 << " -> " << p_scb->peer_addr;
1151 bta_ag_sco_event(p_scb, BTA_AG_SCO_XFER_E);
1152 } else {
1153 /* else it is an open */
1154 LOG(INFO) << __func__ << ": open " << p_scb->peer_addr;
1155 bta_ag_sco_event(p_scb, BTA_AG_SCO_OPEN_E);
1156 }
1157 }
1158
1159 /*******************************************************************************
1160 *
1161 * Function bta_ag_sco_close
1162 *
1163 * Description
1164 *
1165 *
1166 * Returns void
1167 *
1168 ******************************************************************************/
bta_ag_sco_close(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1169 void bta_ag_sco_close(tBTA_AG_SCB* p_scb,
1170 UNUSED_ATTR const tBTA_AG_DATA& data) {
1171 /* if scb is in use */
1172 /* sco_idx is not allocated in SCO_CODEC_ST, still need to move to listen
1173 * state. */
1174 if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) ||
1175 (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST)) {
1176 APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
1177 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1178 }
1179 }
1180
1181 /*******************************************************************************
1182 *
1183 * Function bta_ag_sco_codec_nego
1184 *
1185 * Description Handles result of eSCO codec negotiation
1186 *
1187 *
1188 * Returns void
1189 *
1190 ******************************************************************************/
bta_ag_sco_codec_nego(tBTA_AG_SCB * p_scb,bool result)1191 void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result) {
1192 if (result) {
1193 /* Subsequent SCO connection will skip codec negotiation */
1194 APPL_TRACE_DEBUG("%s: Succeeded for index 0x%04x, device %s", __func__,
1195 p_scb->sco_idx, p_scb->peer_addr.ToString().c_str());
1196 p_scb->codec_updated = false;
1197 bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
1198 } else {
1199 /* codec negotiation failed */
1200 APPL_TRACE_ERROR("%s: Failed for index 0x%04x, device %s", __func__,
1201 p_scb->sco_idx, p_scb->peer_addr.ToString().c_str());
1202 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1203 }
1204 }
1205
1206 /*******************************************************************************
1207 *
1208 * Function bta_ag_sco_shutdown
1209 *
1210 * Description
1211 *
1212 *
1213 * Returns void
1214 *
1215 ******************************************************************************/
bta_ag_sco_shutdown(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1216 void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb,
1217 UNUSED_ATTR const tBTA_AG_DATA& data) {
1218 bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
1219 }
1220
1221 /*******************************************************************************
1222 *
1223 * Function bta_ag_sco_conn_open
1224 *
1225 * Description
1226 *
1227 *
1228 * Returns void
1229 *
1230 ******************************************************************************/
bta_ag_sco_conn_open(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1231 void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb,
1232 UNUSED_ATTR const tBTA_AG_DATA& data) {
1233 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
1234
1235 bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1236
1237 /* call app callback */
1238 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
1239
1240 /* reset to mSBC T2 settings as the preferred */
1241 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1242 }
1243
1244 /*******************************************************************************
1245 *
1246 * Function bta_ag_sco_conn_close
1247 *
1248 * Description
1249 *
1250 *
1251 * Returns void
1252 *
1253 ******************************************************************************/
bta_ag_sco_conn_close(tBTA_AG_SCB * p_scb,UNUSED_ATTR const tBTA_AG_DATA & data)1254 void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb,
1255 UNUSED_ATTR const tBTA_AG_DATA& data) {
1256 /* clear current scb */
1257 bta_ag_cb.sco.p_curr_scb = nullptr;
1258 p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1259
1260 /* codec_fallback is set when AG is initiator and connection failed for mSBC.
1261 * OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */
1262 if (p_scb->svc_conn &&
1263 (p_scb->codec_fallback ||
1264 (p_scb->sco_codec == BTM_SCO_CODEC_MSBC &&
1265 p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1))) {
1266 bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
1267 } else {
1268 /* Indicate if the closing of audio is because of transfer */
1269 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
1270
1271 bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1272
1273 /* if av got suspended by this call, let it resume. */
1274 /* In case call stays alive regardless of sco, av should not be affected. */
1275 if (((p_scb->call_ind == BTA_AG_CALL_INACTIVE) &&
1276 (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE)) ||
1277 (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)) {
1278 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1279 }
1280
1281 /* call app callback */
1282 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
1283 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1284 }
1285 }
1286
1287 /*******************************************************************************
1288 *
1289 * Function bta_ag_sco_conn_rsp
1290 *
1291 * Description Process the SCO connection request
1292 *
1293 *
1294 * Returns void
1295 *
1296 ******************************************************************************/
bta_ag_sco_conn_rsp(tBTA_AG_SCB * p_scb,tBTM_ESCO_CONN_REQ_EVT_DATA * p_data)1297 void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb,
1298 tBTM_ESCO_CONN_REQ_EVT_DATA* p_data) {
1299 bta_ag_cb.sco.is_local = false;
1300
1301 APPL_TRACE_DEBUG("%s: eSCO %d, state %d", __func__,
1302 controller_get_interface()
1303 ->supports_enhanced_setup_synchronous_connection(),
1304 bta_ag_cb.sco.state);
1305
1306 if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST ||
1307 bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
1308 bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST) {
1309 /* tell sys to stop av if any */
1310 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1311 /* When HS initiated SCO, it cannot be WBS. */
1312 }
1313
1314 /* If SCO open was initiated from HS, it must be CVSD */
1315 p_scb->inuse_codec = BTA_AG_CODEC_NONE;
1316 /* Send pending commands to create SCO connection to peer */
1317 bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
1318 }
1319
bta_ag_set_sco_allowed(bool value)1320 void bta_ag_set_sco_allowed(bool value) {
1321 sco_allowed = value;
1322 APPL_TRACE_DEBUG(sco_allowed ? "sco now allowed" : "sco now not allowed");
1323 }
1324
bta_ag_get_active_device()1325 const RawAddress& bta_ag_get_active_device() { return active_device_addr; }
1326
bta_clear_active_device()1327 void bta_clear_active_device() { active_device_addr = RawAddress::kEmpty; }
1328
bta_ag_api_set_active_device(const RawAddress & new_active_device)1329 void bta_ag_api_set_active_device(const RawAddress& new_active_device) {
1330 if (new_active_device.IsEmpty()) {
1331 APPL_TRACE_ERROR("%s: empty device", __func__);
1332 return;
1333 }
1334 active_device_addr = new_active_device;
1335 }
1336