1 /******************************************************************************
2 *
3 * Copyright (C) 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 <stddef.h>
26 #include "bta_api.h"
27 #include "bta_ag_api.h"
28 #include "bta_ag_co.h"
29 #if (BTM_SCO_HCI_INCLUDED == TRUE )
30 #include "bta_dm_co.h"
31 #endif
32 #include "bta_ag_int.h"
33 #include "btm_api.h"
34 #include "bt_common.h"
35 #include "utl.h"
36
37 #ifndef BTA_AG_SCO_DEBUG
38 #define BTA_AG_SCO_DEBUG FALSE
39 #endif
40
41 /* Codec negotiation timeout */
42 #ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS
43 #define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000) /* 3 seconds */
44 #endif
45
46 extern fixed_queue_t *btu_bta_alarm_queue;
47
48 #if BTA_AG_SCO_DEBUG == TRUE
49 static char *bta_ag_sco_evt_str(UINT8 event);
50 static char *bta_ag_sco_state_str(UINT8 state);
51 #endif
52
53 #define BTA_AG_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
54 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
55 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
56 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
57
58 /* sco events */
59 enum
60 {
61 BTA_AG_SCO_LISTEN_E, /* listen request */
62 BTA_AG_SCO_OPEN_E, /* open request */
63 BTA_AG_SCO_XFER_E, /* transfer request */
64 #if (BTM_WBS_INCLUDED == TRUE )
65 BTA_AG_SCO_CN_DONE_E, /* codec negotiation done */
66 BTA_AG_SCO_REOPEN_E, /* Retry with other codec when failed */
67 #endif
68 BTA_AG_SCO_CLOSE_E, /* close request */
69 BTA_AG_SCO_SHUTDOWN_E, /* shutdown request */
70 BTA_AG_SCO_CONN_OPEN_E, /* sco open */
71 BTA_AG_SCO_CONN_CLOSE_E, /* sco closed */
72 BTA_AG_SCO_CI_DATA_E /* SCO data ready */
73 };
74
75 #if (BTM_WBS_INCLUDED == TRUE )
76 #define BTA_AG_NUM_CODECS 3
77 #define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */
78 #define BTA_AG_ESCO_SETTING_IDX_T1 1 /* eSCO setting for mSBC T1 */
79 #define BTA_AG_ESCO_SETTING_IDX_T2 2 /* eSCO setting for mSBC T2 */
80
81 static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
82 {
83 /* CVSD */
84 {
85 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
86 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
87 0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
88 BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
89 (BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
90 BTM_SCO_PKT_TYPES_MASK_HV2 +
91 BTM_SCO_PKT_TYPES_MASK_HV3 +
92 BTM_SCO_PKT_TYPES_MASK_EV3 +
93 BTM_SCO_PKT_TYPES_MASK_EV4 +
94 BTM_SCO_PKT_TYPES_MASK_EV5 +
95 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
96 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
97 BTM_ESCO_RETRANS_POWER /* Retransmission effort */
98 },
99 /* mSBC T1 */
100 {
101 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec), 8000 */
102 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec), 8000 */
103 8, /* 8 ms */
104 BTM_VOICE_SETTING_TRANS, /* Inp Linear, Transparent, 2s Comp, 16bit */
105 (BTM_SCO_PKT_TYPES_MASK_EV3 | /* Packet Types : EV3 + NO_2_EV3 */
106 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
107 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
108 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 |
109 BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 ),
110 BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
111 },
112 /* mSBC T2*/
113 {
114 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec), 8000 */
115 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec), 8000 */
116 13, /* 13 ms */
117 BTM_VOICE_SETTING_TRANS, /* Inp Linear, Transparent, 2s Comp, 16bit */
118 (BTM_SCO_PKT_TYPES_MASK_EV3 | /* Packet Types : EV3 + 2-EV3 */
119 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
120 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
121 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
122 BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
123 }
124 };
125 #else
126 /* WBS not included, CVSD by default */
127 static const tBTM_ESCO_PARAMS bta_ag_esco_params =
128 {
129 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
130 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
131 0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
132 0x0060, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
133 (BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
134 BTM_SCO_PKT_TYPES_MASK_HV2 +
135 BTM_SCO_PKT_TYPES_MASK_HV3 +
136 BTM_SCO_PKT_TYPES_MASK_EV3 +
137 BTM_SCO_PKT_TYPES_MASK_EV4 +
138 BTM_SCO_PKT_TYPES_MASK_EV5 +
139 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
140 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
141 BTM_ESCO_RETRANS_POWER /* Retransmission effort */
142 };
143 #endif
144
145 /*******************************************************************************
146 **
147 ** Function bta_ag_sco_conn_cback
148 **
149 ** Description BTM SCO connection callback.
150 **
151 **
152 ** Returns void
153 **
154 *******************************************************************************/
bta_ag_sco_conn_cback(UINT16 sco_idx)155 static void bta_ag_sco_conn_cback(UINT16 sco_idx)
156 {
157 UINT16 handle;
158 tBTA_AG_SCB *p_scb;
159
160 /* match callback to scb; first check current sco scb */
161 if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
162 {
163 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
164 }
165 /* then check for scb connected to this peer */
166 else
167 {
168 /* Check if SLC is up */
169 handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx));
170 p_scb = bta_ag_scb_by_idx(handle);
171 if(p_scb && !p_scb->svc_conn)
172 handle = 0;
173 }
174
175 if (handle != 0) {
176 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
177 p_buf->event = BTA_AG_SCO_OPEN_EVT;
178 p_buf->layer_specific = handle;
179 bta_sys_sendmsg(p_buf);
180 } else {
181 /* no match found; disconnect sco, init sco variables */
182 bta_ag_cb.sco.p_curr_scb = NULL;
183 bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
184 BTM_RemoveSco(sco_idx);
185 }
186 }
187
188 /*******************************************************************************
189 **
190 ** Function bta_ag_sco_disc_cback
191 **
192 ** Description BTM SCO disconnection callback.
193 **
194 **
195 ** Returns void
196 **
197 *******************************************************************************/
bta_ag_sco_disc_cback(UINT16 sco_idx)198 static void bta_ag_sco_disc_cback(UINT16 sco_idx)
199 {
200 UINT16 handle = 0;
201
202 APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): sco_idx: 0x%x p_cur_scb: 0x%08x sco.state: %d", sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
203
204 APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x in_use: %u sco_idx: 0x%x sco state: %u",
205 &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx, bta_ag_cb.scb[0].state);
206 APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): scb[1] addr: 0x%08x in_use: %u sco_idx: 0x%x sco state: %u",
207 &bta_ag_cb.scb[1], bta_ag_cb.scb[1].in_use, bta_ag_cb.scb[1].sco_idx, bta_ag_cb.scb[1].state);
208
209 /* match callback to scb */
210 if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
211 {
212 /* We only care about callbacks for the active SCO */
213 if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx)
214 {
215 if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF)
216 return;
217 }
218 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
219 }
220
221 if (handle != 0)
222 {
223 #if (BTM_SCO_HCI_INCLUDED == TRUE )
224 tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE);
225 APPL_TRACE_DEBUG("bta_ag_sco_disc_cback sco close config status = %d", status);
226 /* SCO clean up here */
227 bta_dm_sco_co_close();
228 #endif
229
230 #if (BTM_WBS_INCLUDED == TRUE )
231 /* Restore settings */
232 if(bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC)
233 {
234 /* set_sco_codec(BTM_SCO_CODEC_NONE); we should get a close */
235 BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
236
237 /* If SCO open was initiated by AG and failed for mSBC, then attempt
238 mSBC with T1 settings i.e. 'Safe Settings'. If this fails, then switch to CVSD */
239 if (bta_ag_sco_is_opening (bta_ag_cb.sco.p_curr_scb))
240 {
241 if (bta_ag_cb.sco.p_curr_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2)
242 {
243 APPL_TRACE_DEBUG("Fallback to mSBC T1 settings");
244 bta_ag_cb.sco.p_curr_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T1;
245 }
246 else
247 {
248 APPL_TRACE_DEBUG("Fallback to CVSD settings");
249 bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE;
250 }
251 }
252 }
253
254 bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
255 #endif
256
257 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
258 p_buf->event = BTA_AG_SCO_CLOSE_EVT;
259 p_buf->layer_specific = handle;
260 bta_sys_sendmsg(p_buf);
261 } else {
262 /* no match found */
263 APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback");
264
265 /* sco could be closed after scb dealloc'ed */
266 if (bta_ag_cb.sco.p_curr_scb != NULL)
267 {
268 bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
269 bta_ag_cb.sco.p_curr_scb = NULL;
270 bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
271 }
272 }
273 }
274 #if (BTM_SCO_HCI_INCLUDED == TRUE )
275 /*******************************************************************************
276 **
277 ** Function bta_ag_sco_read_cback
278 **
279 ** Description Callback function is the callback function for incoming
280 ** SCO data over HCI.
281 **
282 ** Returns void
283 **
284 *******************************************************************************/
bta_ag_sco_read_cback(UINT16 sco_inx,BT_HDR * p_data,tBTM_SCO_DATA_FLAG status)285 static void bta_ag_sco_read_cback (UINT16 sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status)
286 {
287 if (status != BTM_SCO_DATA_CORRECT)
288 {
289 APPL_TRACE_DEBUG("bta_ag_sco_read_cback: status(%d)", status);
290 }
291
292 /* Callout function must free the data. */
293 bta_dm_sco_co_in_data (p_data, status);
294 }
295 #endif
296 /*******************************************************************************
297 **
298 ** Function bta_ag_remove_sco
299 **
300 ** Description Removes the specified SCO from the system.
301 ** If only_active is TRUE, then SCO is only removed if connected
302 **
303 ** Returns BOOLEAN - TRUE if Sco removal was started
304 **
305 *******************************************************************************/
bta_ag_remove_sco(tBTA_AG_SCB * p_scb,BOOLEAN only_active)306 static BOOLEAN bta_ag_remove_sco(tBTA_AG_SCB *p_scb, BOOLEAN only_active)
307 {
308 BOOLEAN removed_started = FALSE;
309 tBTM_STATUS status;
310
311 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
312 {
313 if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx)
314 {
315 status = BTM_RemoveSco(p_scb->sco_idx);
316
317 APPL_TRACE_DEBUG("ag remove sco: inx 0x%04x, status:0x%x", p_scb->sco_idx, status);
318
319 if (status == BTM_CMD_STARTED)
320 {
321 /* Sco is connected; set current control block */
322 bta_ag_cb.sco.p_curr_scb = p_scb;
323
324 removed_started = TRUE;
325 }
326 /* If no connection reset the sco handle */
327 else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
328 {
329 p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
330 }
331 }
332 }
333 return removed_started;
334 }
335
336
337 /*******************************************************************************
338 **
339 ** Function bta_ag_esco_connreq_cback
340 **
341 ** Description BTM eSCO connection requests and eSCO change requests
342 ** Only the connection requests are processed by BTA.
343 **
344 ** Returns void
345 **
346 *******************************************************************************/
bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event,tBTM_ESCO_EVT_DATA * p_data)347 static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
348 {
349 tBTA_AG_SCB *p_scb;
350 UINT16 handle;
351 UINT16 sco_inx = p_data->conn_evt.sco_inx;
352
353 /* Only process connection requests */
354 if (event == BTM_ESCO_CONN_REQ_EVT)
355 {
356 if ((handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_inx))) != 0 &&
357 ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) && p_scb->svc_conn)
358 {
359 p_scb->sco_idx = sco_inx;
360
361 /* If no other SCO active, allow this one */
362 if (!bta_ag_cb.sco.p_curr_scb)
363 {
364 APPL_TRACE_EVENT("bta_ag_esco_connreq_cback: Accept Conn Request (sco_inx 0x%04x)", sco_inx);
365 bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
366
367 bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST;
368 bta_ag_cb.sco.p_curr_scb = p_scb;
369 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
370 }
371 else /* Begin a transfer: Close current SCO before responding */
372 {
373 APPL_TRACE_DEBUG("bta_ag_esco_connreq_cback: Begin XFER");
374 bta_ag_cb.sco.p_xfer_scb = p_scb;
375 bta_ag_cb.sco.conn_data = p_data->conn_evt;
376 bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST;
377
378 if (!bta_ag_remove_sco(bta_ag_cb.sco.p_curr_scb, TRUE))
379 {
380 APPL_TRACE_ERROR("bta_ag_esco_connreq_cback: Nothing to remove so accept Conn Request (sco_inx 0x%04x)", sco_inx);
381 bta_ag_cb.sco.p_xfer_scb = NULL;
382 bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST;
383
384 bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
385 }
386 }
387 }
388 /* If error occurred send reject response immediately */
389 else
390 {
391 APPL_TRACE_WARNING("no scb for bta_ag_esco_connreq_cback or no resources");
392 BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL);
393 }
394 }
395 /* Received a change in the esco link */
396 else if (event == BTM_ESCO_CHG_EVT)
397 {
398 APPL_TRACE_EVENT("eSCO change event (inx %d): rtrans %d, rxlen %d, txlen %d, txint %d",
399 p_data->chg_evt.sco_inx,
400 p_data->chg_evt.retrans_window, p_data->chg_evt.rx_pkt_len,
401 p_data->chg_evt.tx_pkt_len, p_data->chg_evt.tx_interval);
402 }
403 }
404
405 /*******************************************************************************
406 **
407 ** Function bta_ag_cback_sco
408 **
409 ** Description Call application callback function with SCO event.
410 **
411 **
412 ** Returns void
413 **
414 *******************************************************************************/
bta_ag_cback_sco(tBTA_AG_SCB * p_scb,UINT8 event)415 static void bta_ag_cback_sco(tBTA_AG_SCB *p_scb, UINT8 event)
416 {
417 tBTA_AG_HDR sco;
418
419 sco.handle = bta_ag_scb_to_idx(p_scb);
420 sco.app_id = p_scb->app_id;
421
422 /* call close cback */
423 (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &sco);
424 }
425
426 /*******************************************************************************
427 **
428 ** Function bta_ag_create_sco
429 **
430 ** Description
431 **
432 **
433 ** Returns void
434 **
435 *******************************************************************************/
bta_ag_create_sco(tBTA_AG_SCB * p_scb,BOOLEAN is_orig)436 static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
437 {
438 tBTM_STATUS status;
439 UINT8 *p_bd_addr = NULL;
440 tBTM_ESCO_PARAMS params;
441 #if (BTM_WBS_INCLUDED == TRUE )
442 tBTA_AG_PEER_CODEC esco_codec = BTM_SCO_CODEC_CVSD;
443 int codec_index = 0;
444 #endif
445 #if (BTM_SCO_HCI_INCLUDED == TRUE )
446 tBTM_SCO_ROUTE_TYPE sco_route;
447 tBTA_CODEC_INFO codec_info = {BTA_SCO_CODEC_PCM};
448 UINT32 pcm_sample_rate;
449 #endif
450
451 /* Make sure this sco handle is not already in use */
452 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
453 {
454 APPL_TRACE_WARNING("bta_ag_create_sco: Index 0x%04x Already In Use!",
455 p_scb->sco_idx);
456 return;
457 }
458
459 #if (BTM_WBS_INCLUDED == TRUE )
460 if ((p_scb->sco_codec == BTM_SCO_CODEC_MSBC) &&
461 !p_scb->codec_fallback &&
462 !p_scb->retry_with_sco_only)
463 esco_codec = BTM_SCO_CODEC_MSBC;
464
465 if (p_scb->codec_fallback)
466 {
467 p_scb->codec_fallback = FALSE;
468
469 /* Force AG to send +BCS for the next audio connection. */
470 p_scb->codec_updated = TRUE;
471 }
472
473 /* If WBS included, use CVSD by default, index is 0 for CVSD by initialization */
474 /* If eSCO codec is mSBC, index is T2 or T1 */
475 if (esco_codec == BTM_SCO_CODEC_MSBC)
476 {
477 if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2)
478 {
479 codec_index = BTA_AG_ESCO_SETTING_IDX_T2;
480 }
481 else
482 {
483 codec_index = BTA_AG_ESCO_SETTING_IDX_T1;
484 }
485 }
486
487 params = bta_ag_esco_params[codec_index];
488 #else
489 /* When WBS is not included, use CVSD by default */
490 params = bta_ag_esco_params;
491 #endif
492
493 if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */
494 params = bta_ag_cb.sco.params;
495
496 if(!bta_ag_cb.sco.param_updated)
497 {
498 #if (BTM_WBS_INCLUDED == TRUE)
499 if (esco_codec == BTM_SCO_CODEC_CVSD) /* For CVSD */
500 #endif
501 {
502 /* Use the application packet types (5 slot EV packets not allowed) */
503 params.packet_types = p_bta_ag_cfg->sco_pkt_types |
504 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
505 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
506 }
507 }
508
509 /* if initiating set current scb and peer bd addr */
510 if (is_orig)
511 {
512 /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
513 /* Need to find out from SIG if HSP can use eSCO; for now use SCO */
514 if (p_scb->conn_service == BTA_AG_HFP && p_scb->peer_version >= HFP_VERSION_1_5 && !p_scb->retry_with_sco_only)
515 {
516
517 BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms);
518 /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
519 if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
520 ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_AG_NO_EDR_ESCO))
521 {
522 #if (BTM_WBS_INCLUDED == TRUE )
523 if (esco_codec != BTA_AG_CODEC_MSBC)
524 {
525 p_scb->retry_with_sco_only = TRUE;
526 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
527 }
528 else /* Do not use SCO when using mSBC */
529 {
530 p_scb->retry_with_sco_only = FALSE;
531 APPL_TRACE_API("Setting retry_with_sco_only to FALSE");
532 }
533 #else
534 p_scb->retry_with_sco_only = TRUE;
535 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
536 #endif
537 }
538 }
539 else
540 {
541 if(p_scb->retry_with_sco_only)
542 APPL_TRACE_API("retrying with SCO only");
543 p_scb->retry_with_sco_only = FALSE;
544
545 BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms);
546 }
547
548 bta_ag_cb.sco.p_curr_scb = p_scb;
549
550 /* tell sys to stop av if any */
551 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
552
553 #if (BTM_WBS_INCLUDED == TRUE )
554 /* Allow any platform specific pre-SCO set up to take place */
555 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP,
556 esco_codec);
557
558 /* This setting may not be necessary */
559 /* To be verified with stable 2049 boards */
560 if (esco_codec == BTA_AG_CODEC_MSBC)
561 BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS);
562 else
563 BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
564 /* save the current codec because sco_codec can be updated while SCO is open. */
565 p_scb->inuse_codec = esco_codec;
566 #else
567 /* Allow any platform specific pre-SCO set up to take place */
568 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP);
569 #endif
570
571 #if (BTM_SCO_HCI_INCLUDED == TRUE )
572 #if (BTM_WBS_INCLUDED == TRUE)
573 if (esco_codec == BTA_AG_CODEC_MSBC)
574 pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_16K;
575 else
576 #endif
577 pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
578
579 sco_route = bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id);
580 #endif
581
582
583 #if (BTM_SCO_HCI_INCLUDED == TRUE )
584 /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
585 BTM_ConfigScoPath(sco_route, bta_ag_sco_read_cback, NULL, TRUE);
586 #endif
587 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
588 }
589 else
590 p_scb->retry_with_sco_only = FALSE;
591
592 p_bd_addr = p_scb->peer_addr;
593
594 status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
595 &p_scb->sco_idx, bta_ag_sco_conn_cback,
596 bta_ag_sco_disc_cback);
597 if (status == BTM_CMD_STARTED)
598 {
599 if (!is_orig)
600 {
601 BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
602 }
603 else /* Initiating the connection, set the current sco handle */
604 {
605 bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
606 }
607 }
608
609 APPL_TRACE_API("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
610 is_orig, p_scb->sco_idx, status, params.packet_types);
611 }
612
613 #if (BTM_WBS_INCLUDED == TRUE )
614 /*******************************************************************************
615 **
616 ** Function bta_ag_attempt_msbc_safe_settings
617 **
618 ** Description Checks if ESCO connection needs to be attempted using mSBC T1(safe) settings
619 **
620 **
621 ** Returns TRUE if T1 settings has to be used, FALSE otherwise
622 **
623 *******************************************************************************/
bta_ag_attempt_msbc_safe_settings(tBTA_AG_SCB * p_scb)624 BOOLEAN bta_ag_attempt_msbc_safe_settings(tBTA_AG_SCB *p_scb)
625 {
626 if (p_scb->svc_conn && p_scb->sco_codec == BTM_SCO_CODEC_MSBC &&
627 p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1)
628 return TRUE;
629 else
630 return FALSE;
631 }
632
633 /*******************************************************************************
634 **
635 ** Function bta_ag_codec_negotiation_timer_cback
636 **
637 ** Description
638 **
639 **
640 ** Returns void
641 **
642 *******************************************************************************/
bta_ag_codec_negotiation_timer_cback(void * data)643 static void bta_ag_codec_negotiation_timer_cback(void *data)
644 {
645 tBTA_AG_SCB *p_scb = (tBTA_AG_SCB *)data;
646
647 /* Announce that codec negotiation failed. */
648 bta_ag_sco_codec_nego(p_scb, FALSE);
649
650 /* call app callback */
651 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
652 }
653
654 /*******************************************************************************
655 **
656 ** Function bta_ag_codec_negotiate
657 **
658 ** Description Initiate codec negotiation by sending AT command.
659 ** If not necessary, skip negotiation.
660 **
661 ** Returns void
662 **
663 *******************************************************************************/
bta_ag_codec_negotiate(tBTA_AG_SCB * p_scb)664 void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb)
665 {
666 bta_ag_cb.sco.p_curr_scb = p_scb;
667
668 if ((p_scb->codec_updated || p_scb->codec_fallback ||
669 bta_ag_attempt_msbc_safe_settings(p_scb)) &&
670 (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC))
671 {
672 /* Change the power mode to Active until sco open is completed. */
673 bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
674
675 /* Send +BCS to the peer */
676 bta_ag_send_bcs(p_scb, NULL);
677
678 /* Start timer to handle timeout */
679 alarm_set_on_queue(p_scb->codec_negotiation_timer,
680 BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS,
681 bta_ag_codec_negotiation_timer_cback,
682 p_scb,
683 btu_bta_alarm_queue);
684 }
685 else
686 {
687 /* use same codec type as previous SCO connection, skip codec negotiation */
688 APPL_TRACE_DEBUG("use same codec type as previous SCO connection,skip codec negotiation");
689 bta_ag_sco_codec_nego(p_scb, TRUE);
690 }
691 }
692 #endif /* (BTM_WBS_INCLUDED == TRUE ) */
693
694 /*******************************************************************************
695 **
696 ** Function bta_ag_sco_event
697 **
698 ** Description
699 **
700 **
701 ** Returns void
702 **
703 *******************************************************************************/
bta_ag_sco_event(tBTA_AG_SCB * p_scb,UINT8 event)704 static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event)
705 {
706 tBTA_AG_SCO_CB *p_sco = &bta_ag_cb.sco;
707 #if (BTM_WBS_INCLUDED == TRUE )
708 tBTA_AG_SCB *p_cn_scb = NULL; /* For codec negotiation */
709 #endif
710 #if (BTM_SCO_HCI_INCLUDED == TRUE )
711 BT_HDR *p_buf;
712 #endif
713 #if BTA_AG_SCO_DEBUG == TRUE
714 UINT8 in_state = p_sco->state;
715
716 APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)",
717 p_scb->sco_idx,
718 p_sco->state, bta_ag_sco_state_str(p_sco->state),
719 event, bta_ag_sco_evt_str(event));
720 #else
721 APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d, Event %d",
722 p_scb->sco_idx, p_sco->state, event);
723 #endif
724
725 #if (BTM_SCO_HCI_INCLUDED == TRUE )
726 if (event == BTA_AG_SCO_CI_DATA_E)
727 {
728 while (TRUE)
729 {
730 bta_dm_sco_co_out_data(&p_buf);
731 if (p_buf)
732 {
733 if (p_sco->state == BTA_AG_SCO_OPEN_ST)
734 BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf);
735 else
736 osi_free(p_buf);
737 }
738 else
739 break;
740 }
741
742 return;
743 }
744 #endif
745
746 switch (p_sco->state)
747 {
748 case BTA_AG_SCO_SHUTDOWN_ST:
749 switch (event)
750 {
751 case BTA_AG_SCO_LISTEN_E:
752 /* 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("BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d", event);
759 break;
760 }
761 break;
762
763 case BTA_AG_SCO_LISTEN_ST:
764 switch (event)
765 {
766 case BTA_AG_SCO_LISTEN_E:
767 /* create sco listen connection (Additional channel) */
768 bta_ag_create_sco(p_scb, FALSE);
769 break;
770
771 case BTA_AG_SCO_OPEN_E:
772 /* remove listening connection */
773 bta_ag_remove_sco(p_scb, FALSE);
774
775 #if (BTM_WBS_INCLUDED == TRUE )
776 /* start codec negotiation */
777 p_sco->state = BTA_AG_SCO_CODEC_ST;
778 p_cn_scb = p_scb;
779 #else
780 /* create sco connection to peer */
781 bta_ag_create_sco(p_scb, TRUE);
782 p_sco->state = BTA_AG_SCO_OPENING_ST;
783 #endif
784 break;
785
786 case BTA_AG_SCO_SHUTDOWN_E:
787 /* remove listening connection */
788 bta_ag_remove_sco(p_scb, FALSE);
789
790 if (p_scb == p_sco->p_curr_scb)
791 p_sco->p_curr_scb = NULL;
792
793 /* If last SCO instance then finish shutting down */
794 if (!bta_ag_other_scb_open(p_scb))
795 {
796 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
797 }
798 break;
799
800 case BTA_AG_SCO_CLOSE_E:
801 /* remove listening connection */
802 /* Ignore the event. We need to keep listening SCO for the active SLC */
803 APPL_TRACE_WARNING("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
804 break;
805
806 case BTA_AG_SCO_CONN_CLOSE_E:
807 /* sco failed; create sco listen connection */
808 bta_ag_create_sco(p_scb, FALSE);
809 p_sco->state = BTA_AG_SCO_LISTEN_ST;
810 break;
811
812 default:
813 APPL_TRACE_WARNING("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
814 break;
815 }
816 break;
817
818 #if (BTM_WBS_INCLUDED == TRUE )
819 case BTA_AG_SCO_CODEC_ST:
820 switch (event)
821 {
822 case BTA_AG_SCO_LISTEN_E:
823 /* create sco listen connection (Additional channel) */
824 bta_ag_create_sco(p_scb, FALSE);
825 break;
826
827 case BTA_AG_SCO_CN_DONE_E:
828 /* create sco connection to peer */
829 bta_ag_create_sco(p_scb, TRUE);
830 p_sco->state = BTA_AG_SCO_OPENING_ST;
831 break;
832
833 case BTA_AG_SCO_XFER_E:
834 /* save xfer scb */
835 p_sco->p_xfer_scb = p_scb;
836 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
837 break;
838
839 case BTA_AG_SCO_SHUTDOWN_E:
840 /* remove listening connection */
841 bta_ag_remove_sco(p_scb, FALSE);
842
843 if (p_scb == p_sco->p_curr_scb)
844 p_sco->p_curr_scb = NULL;
845
846 /* If last SCO instance then finish shutting down */
847 if (!bta_ag_other_scb_open(p_scb))
848 {
849 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
850 }
851 break;
852
853 case BTA_AG_SCO_CLOSE_E:
854 /* sco open is not started yet. just go back to listening */
855 p_sco->state = BTA_AG_SCO_LISTEN_ST;
856 break;
857
858 case BTA_AG_SCO_CONN_CLOSE_E:
859 /* sco failed; create sco listen connection */
860 bta_ag_create_sco(p_scb, FALSE);
861 p_sco->state = BTA_AG_SCO_LISTEN_ST;
862 break;
863
864 default:
865 APPL_TRACE_WARNING("BTA_AG_SCO_CODEC_ST: Ignoring event %d", event);
866 break;
867 }
868 break;
869 #endif
870
871 case BTA_AG_SCO_OPENING_ST:
872 switch (event)
873 {
874 case BTA_AG_SCO_LISTEN_E:
875 /* second headset has now joined */
876 /* create sco listen connection (Additional channel) */
877 if (p_scb != p_sco->p_curr_scb)
878 {
879 bta_ag_create_sco(p_scb, FALSE);
880 }
881 break;
882
883 #if (BTM_WBS_INCLUDED == TRUE)
884 case BTA_AG_SCO_REOPEN_E:
885 /* start codec negotiation */
886 p_sco->state = BTA_AG_SCO_CODEC_ST;
887 p_cn_scb = p_scb;
888 break;
889 #endif
890
891 case BTA_AG_SCO_XFER_E:
892 /* save xfer scb */
893 p_sco->p_xfer_scb = p_scb;
894 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
895 break;
896
897 case BTA_AG_SCO_CLOSE_E:
898 p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
899 break;
900
901 case BTA_AG_SCO_SHUTDOWN_E:
902 /* If not opening scb, just close it */
903 if (p_scb != p_sco->p_curr_scb)
904 {
905 /* remove listening connection */
906 bta_ag_remove_sco(p_scb, FALSE);
907 }
908 else
909 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
910
911 break;
912
913 case BTA_AG_SCO_CONN_OPEN_E:
914 p_sco->state = BTA_AG_SCO_OPEN_ST;
915 break;
916
917 case BTA_AG_SCO_CONN_CLOSE_E:
918 /* sco failed; create sco listen connection */
919 bta_ag_create_sco(p_scb, FALSE);
920 p_sco->state = BTA_AG_SCO_LISTEN_ST;
921 break;
922
923 default:
924 APPL_TRACE_WARNING("BTA_AG_SCO_OPENING_ST: Ignoring event %d", event);
925 break;
926 }
927 break;
928
929 case BTA_AG_SCO_OPEN_CL_ST:
930 switch (event)
931 {
932 case BTA_AG_SCO_XFER_E:
933 /* save xfer scb */
934 p_sco->p_xfer_scb = p_scb;
935
936 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
937 break;
938
939 case BTA_AG_SCO_OPEN_E:
940 p_sco->state = BTA_AG_SCO_OPENING_ST;
941 break;
942
943 case BTA_AG_SCO_SHUTDOWN_E:
944 /* If not opening scb, just close it */
945 if (p_scb != p_sco->p_curr_scb)
946 {
947 /* remove listening connection */
948 bta_ag_remove_sco(p_scb, FALSE);
949 }
950 else
951 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
952
953 break;
954
955 case BTA_AG_SCO_CONN_OPEN_E:
956 /* close sco connection */
957 bta_ag_remove_sco(p_scb, TRUE);
958
959 p_sco->state = BTA_AG_SCO_CLOSING_ST;
960 break;
961
962 case BTA_AG_SCO_CONN_CLOSE_E:
963 /* sco failed; create sco listen connection */
964
965 p_sco->state = BTA_AG_SCO_LISTEN_ST;
966 break;
967
968 default:
969 APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d", event);
970 break;
971 }
972 break;
973
974 case BTA_AG_SCO_OPEN_XFER_ST:
975 switch (event)
976 {
977 case BTA_AG_SCO_CLOSE_E:
978 /* close sco connection */
979 bta_ag_remove_sco(p_scb, TRUE);
980
981 p_sco->state = BTA_AG_SCO_CLOSING_ST;
982 break;
983
984 case BTA_AG_SCO_SHUTDOWN_E:
985 /* remove all connection */
986 bta_ag_remove_sco(p_scb, FALSE);
987 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
988
989 break;
990
991 case BTA_AG_SCO_CONN_CLOSE_E:
992 /* closed sco; place in listen mode and
993 accept the transferred connection */
994 bta_ag_create_sco(p_scb, FALSE); /* Back into listen mode */
995
996 /* Accept sco connection with xfer scb */
997 bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
998 p_sco->state = BTA_AG_SCO_OPENING_ST;
999 p_sco->p_curr_scb = p_sco->p_xfer_scb;
1000 p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
1001 p_sco->p_xfer_scb = NULL;
1002 break;
1003
1004 default:
1005 APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d", event);
1006 break;
1007 }
1008 break;
1009
1010 case BTA_AG_SCO_OPEN_ST:
1011 switch (event)
1012 {
1013 case BTA_AG_SCO_LISTEN_E:
1014 /* second headset has now joined */
1015 /* create sco listen connection (Additional channel) */
1016 if (p_scb != p_sco->p_curr_scb)
1017 {
1018 bta_ag_create_sco(p_scb, FALSE);
1019 }
1020 break;
1021
1022 case BTA_AG_SCO_XFER_E:
1023 /* close current sco connection */
1024 bta_ag_remove_sco(p_sco->p_curr_scb, TRUE);
1025
1026 /* save xfer scb */
1027 p_sco->p_xfer_scb = p_scb;
1028
1029 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
1030 break;
1031
1032 case BTA_AG_SCO_CLOSE_E:
1033 /* close sco connection if active */
1034 if (bta_ag_remove_sco(p_scb, TRUE))
1035 {
1036 p_sco->state = BTA_AG_SCO_CLOSING_ST;
1037 }
1038 break;
1039
1040 case BTA_AG_SCO_SHUTDOWN_E:
1041 /* remove all listening connections */
1042 bta_ag_remove_sco(p_scb, FALSE);
1043
1044 /* If SCO was active on this scb, close it */
1045 if (p_scb == p_sco->p_curr_scb)
1046 {
1047 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1048 }
1049 break;
1050
1051 case BTA_AG_SCO_CONN_CLOSE_E:
1052 /* peer closed sco; create sco listen connection */
1053 bta_ag_create_sco(p_scb, FALSE);
1054 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1055 break;
1056
1057 default:
1058 APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_ST: Ignoring event %d", event);
1059 break;
1060 }
1061 break;
1062
1063 case BTA_AG_SCO_CLOSING_ST:
1064 switch (event)
1065 {
1066 case BTA_AG_SCO_LISTEN_E:
1067 /* create sco listen connection (Additional channel) */
1068 if (p_scb != p_sco->p_curr_scb)
1069 {
1070 bta_ag_create_sco(p_scb, FALSE);
1071 }
1072 break;
1073
1074 case BTA_AG_SCO_OPEN_E:
1075 p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
1076 break;
1077
1078 case BTA_AG_SCO_XFER_E:
1079 /* save xfer scb */
1080 p_sco->p_xfer_scb = p_scb;
1081
1082 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
1083 break;
1084
1085 case BTA_AG_SCO_SHUTDOWN_E:
1086 /* If not closing scb, just close it */
1087 if (p_scb != p_sco->p_curr_scb)
1088 {
1089 /* remove listening connection */
1090 bta_ag_remove_sco(p_scb, FALSE);
1091 }
1092 else
1093 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1094
1095 break;
1096
1097 case BTA_AG_SCO_CONN_CLOSE_E:
1098 /* peer closed sco; create sco listen connection */
1099 bta_ag_create_sco(p_scb, FALSE);
1100
1101 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1102 break;
1103
1104 default:
1105 APPL_TRACE_WARNING("BTA_AG_SCO_CLOSING_ST: Ignoring event %d", event);
1106 break;
1107 }
1108 break;
1109
1110 case BTA_AG_SCO_CLOSE_OP_ST:
1111 switch (event)
1112 {
1113 case BTA_AG_SCO_CLOSE_E:
1114 p_sco->state = BTA_AG_SCO_CLOSING_ST;
1115 break;
1116
1117 case BTA_AG_SCO_SHUTDOWN_E:
1118 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1119 break;
1120
1121 case BTA_AG_SCO_CONN_CLOSE_E:
1122 #if (BTM_WBS_INCLUDED == TRUE )
1123 /* start codec negotiation */
1124 p_sco->state = BTA_AG_SCO_CODEC_ST;
1125 p_cn_scb = p_scb;
1126 #else
1127 /* open sco connection */
1128 bta_ag_create_sco(p_scb, TRUE);
1129 p_sco->state = BTA_AG_SCO_OPENING_ST;
1130 #endif
1131 break;
1132
1133 case BTA_AG_SCO_LISTEN_E:
1134 /* create sco listen connection (Additional channel) */
1135 if (p_scb != p_sco->p_curr_scb)
1136 {
1137 bta_ag_create_sco(p_scb, FALSE);
1138 }
1139 break;
1140
1141 default:
1142 APPL_TRACE_WARNING("BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d", event);
1143 break;
1144 }
1145 break;
1146
1147 case BTA_AG_SCO_CLOSE_XFER_ST:
1148 switch (event)
1149 {
1150 case BTA_AG_SCO_CONN_OPEN_E:
1151 /* close sco connection so headset can be transferred
1152 Probably entered this state from "opening state" */
1153 bta_ag_remove_sco(p_scb, TRUE);
1154 break;
1155
1156 case BTA_AG_SCO_CLOSE_E:
1157 /* clear xfer scb */
1158 p_sco->p_xfer_scb = NULL;
1159
1160 p_sco->state = BTA_AG_SCO_CLOSING_ST;
1161 break;
1162
1163 case BTA_AG_SCO_SHUTDOWN_E:
1164 /* clear xfer scb */
1165 p_sco->p_xfer_scb = NULL;
1166
1167 p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1168 break;
1169
1170 case BTA_AG_SCO_CONN_CLOSE_E:
1171 /* closed sco; place old sco in listen mode,
1172 take current sco out of listen, and
1173 create originating sco for current */
1174 bta_ag_create_sco(p_scb, FALSE);
1175 bta_ag_remove_sco(p_sco->p_xfer_scb, FALSE);
1176
1177 #if (BTM_WBS_INCLUDED == TRUE )
1178 /* start codec negotiation */
1179 p_sco->state = BTA_AG_SCO_CODEC_ST;
1180 p_cn_scb = p_sco->p_xfer_scb;
1181 p_sco->p_xfer_scb = NULL;
1182 #else
1183 /* create sco connection to peer */
1184 bta_ag_create_sco(p_sco->p_xfer_scb, TRUE);
1185 p_sco->p_xfer_scb = NULL;
1186 p_sco->state = BTA_AG_SCO_OPENING_ST;
1187 #endif
1188 break;
1189
1190 default:
1191 APPL_TRACE_WARNING("BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d", event);
1192 break;
1193 }
1194 break;
1195
1196 case BTA_AG_SCO_SHUTTING_ST:
1197 switch (event)
1198 {
1199 case BTA_AG_SCO_CONN_OPEN_E:
1200 /* close sco connection; wait for conn close event */
1201 bta_ag_remove_sco(p_scb, TRUE);
1202 break;
1203
1204 case BTA_AG_SCO_CONN_CLOSE_E:
1205 /* If last SCO instance then finish shutting down */
1206 if (!bta_ag_other_scb_open(p_scb))
1207 {
1208 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1209 }
1210 else /* Other instance is still listening */
1211 {
1212 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1213 }
1214
1215 /* If SCO closed for other HS which is not being disconnected,
1216 then create listen sco connection for it as scb still open */
1217 if (bta_ag_scb_open(p_scb))
1218 {
1219 bta_ag_create_sco(p_scb, FALSE);
1220 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1221 }
1222
1223 if (p_scb == p_sco->p_curr_scb)
1224 {
1225 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1226 p_sco->p_curr_scb = NULL;
1227 }
1228 break;
1229
1230 case BTA_AG_SCO_LISTEN_E:
1231 /* create sco listen connection (Additional channel) */
1232 if (p_scb != p_sco->p_curr_scb)
1233 {
1234 bta_ag_create_sco(p_scb, FALSE);
1235 }
1236 break;
1237
1238 case BTA_AG_SCO_SHUTDOWN_E:
1239 if (!bta_ag_other_scb_open(p_scb))
1240 {
1241 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1242 }
1243 else /* Other instance is still listening */
1244 {
1245 p_sco->state = BTA_AG_SCO_LISTEN_ST;
1246 }
1247
1248 if (p_scb == p_sco->p_curr_scb)
1249 {
1250 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1251 p_sco->p_curr_scb = NULL;
1252 }
1253 break;
1254
1255 default:
1256 APPL_TRACE_WARNING("BTA_AG_SCO_SHUTTING_ST: Ignoring event %d", event);
1257 break;
1258 }
1259 break;
1260
1261 default:
1262 break;
1263 }
1264 #if BTA_AG_SCO_DEBUG == TRUE
1265 if (p_sco->state != in_state)
1266 {
1267 APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
1268 bta_ag_sco_state_str(in_state),
1269 bta_ag_sco_state_str(p_sco->state),
1270 bta_ag_sco_evt_str(event));
1271 }
1272 #endif
1273
1274 #if (BTM_WBS_INCLUDED == TRUE )
1275 if (p_cn_scb)
1276 {
1277 bta_ag_codec_negotiate(p_cn_scb);
1278 }
1279 #endif
1280 }
1281
1282 /*******************************************************************************
1283 **
1284 ** Function bta_ag_sco_is_open
1285 **
1286 ** Description Check if sco is open for this scb.
1287 **
1288 **
1289 ** Returns TRUE if sco open for this scb, FALSE otherwise.
1290 **
1291 *******************************************************************************/
bta_ag_sco_is_open(tBTA_AG_SCB * p_scb)1292 BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb)
1293 {
1294 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
1295 (bta_ag_cb.sco.p_curr_scb == p_scb));
1296 }
1297
1298 /*******************************************************************************
1299 **
1300 ** Function bta_ag_sco_is_opening
1301 **
1302 ** Description Check if sco is in Opening state.
1303 **
1304 **
1305 ** Returns TRUE if sco is in Opening state for this scb, FALSE otherwise.
1306 **
1307 *******************************************************************************/
bta_ag_sco_is_opening(tBTA_AG_SCB * p_scb)1308 BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb)
1309 {
1310 #if (BTM_WBS_INCLUDED == TRUE )
1311 return (((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) ||
1312 (bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST)) &&
1313 (bta_ag_cb.sco.p_curr_scb == p_scb));
1314 #else
1315 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
1316 (bta_ag_cb.sco.p_curr_scb == p_scb));
1317 #endif
1318 }
1319
1320 /*******************************************************************************
1321 **
1322 ** Function bta_ag_sco_listen
1323 **
1324 ** Description
1325 **
1326 **
1327 ** Returns void
1328 **
1329 *******************************************************************************/
bta_ag_sco_listen(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1330 void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1331 {
1332 UNUSED(p_data);
1333 bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
1334 }
1335
1336 /*******************************************************************************
1337 **
1338 ** Function bta_ag_sco_open
1339 **
1340 ** Description
1341 **
1342 **
1343 ** Returns void
1344 **
1345 *******************************************************************************/
bta_ag_sco_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1346 void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1347 {
1348 UINT8 event;
1349 UNUSED(p_data);
1350
1351 /* if another scb using sco, this is a transfer */
1352 if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb)
1353 {
1354 event = BTA_AG_SCO_XFER_E;
1355 }
1356 /* else it is an open */
1357 else
1358 {
1359 event = BTA_AG_SCO_OPEN_E;
1360 }
1361
1362 bta_ag_sco_event(p_scb, event);
1363 }
1364
1365 /*******************************************************************************
1366 **
1367 ** Function bta_ag_sco_close
1368 **
1369 ** Description
1370 **
1371 **
1372 ** Returns void
1373 **
1374 *******************************************************************************/
bta_ag_sco_close(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1375 void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1376 {
1377 UNUSED(p_data);
1378
1379 /* if scb is in use */
1380 #if (BTM_WBS_INCLUDED == TRUE )
1381 /* sco_idx is not allocated in SCO_CODEC_ST, we still need to move to listening state. */
1382 if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) || (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
1383 #else
1384 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
1385 #endif
1386 {
1387 APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
1388 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1389 }
1390 }
1391
1392 #if (BTM_WBS_INCLUDED == TRUE )
1393
1394 /*******************************************************************************
1395 **
1396 ** Function bta_ag_sco_codec_nego
1397 **
1398 ** Description
1399 **
1400 **
1401 ** Returns void
1402 **
1403 *******************************************************************************/
bta_ag_sco_codec_nego(tBTA_AG_SCB * p_scb,BOOLEAN result)1404 void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result)
1405 {
1406 if(result == TRUE)
1407 {
1408 /* Subsequent sco connection will skip codec negotiation */
1409 p_scb->codec_updated = FALSE;
1410
1411 bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
1412 }
1413 else /* codec negotiation failed */
1414 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1415 }
1416 #endif
1417
1418 /*******************************************************************************
1419 **
1420 ** Function bta_ag_sco_shutdown
1421 **
1422 ** Description
1423 **
1424 **
1425 ** Returns void
1426 **
1427 *******************************************************************************/
bta_ag_sco_shutdown(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1428 void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1429 {
1430 UNUSED(p_data);
1431
1432 bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
1433 }
1434
1435 /*******************************************************************************
1436 **
1437 ** Function bta_ag_sco_conn_open
1438 **
1439 ** Description
1440 **
1441 **
1442 ** Returns void
1443 **
1444 *******************************************************************************/
bta_ag_sco_conn_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1445 void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1446 {
1447 UNUSED(p_data);
1448
1449 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
1450
1451 bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1452
1453 #if (BTM_WBS_INCLUDED == TRUE)
1454 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON,
1455 p_scb->inuse_codec);
1456 #else
1457 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON);
1458 #endif
1459
1460 #if (BTM_SCO_HCI_INCLUDED == TRUE )
1461 /* open SCO codec if SCO is routed through transport */
1462 bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT);
1463 #endif
1464
1465 /* call app callback */
1466 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
1467
1468 p_scb->retry_with_sco_only = FALSE;
1469 #if (BTM_WBS_INCLUDED == TRUE)
1470 /* reset to mSBC T2 settings as the preferred */
1471 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1472 #endif
1473 }
1474
1475 /*******************************************************************************
1476 **
1477 ** Function bta_ag_sco_conn_close
1478 **
1479 ** Description
1480 **
1481 **
1482 ** Returns void
1483 **
1484 *******************************************************************************/
bta_ag_sco_conn_close(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1485 void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1486 {
1487 UINT16 handle = bta_ag_scb_to_idx(p_scb);
1488 UNUSED(p_data);
1489
1490 /* clear current scb */
1491 bta_ag_cb.sco.p_curr_scb = NULL;
1492 p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1493
1494 #if (BTM_WBS_INCLUDED == TRUE)
1495 /* codec_fallback is set when AG is initiator and connection failed for mSBC. */
1496 /* OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */
1497 if ((p_scb->codec_fallback && p_scb->svc_conn) ||
1498 bta_ag_attempt_msbc_safe_settings(p_scb))
1499 {
1500 bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
1501 }
1502 else if (p_scb->retry_with_sco_only && p_scb->svc_conn)
1503 {
1504 /* retry_with_sco_only is set when AG is initiator and connection failed for eSCO */
1505 bta_ag_create_sco(p_scb, TRUE);
1506 }
1507 #else
1508 /* retry_with_sco_only, will be set only when AG is initiator
1509 ** and AG is first trying to establish an eSCO connection */
1510 if (p_scb->retry_with_sco_only && p_scb->svc_conn)
1511 {
1512 bta_ag_create_sco(p_scb, TRUE);
1513 }
1514 #endif
1515 else
1516 {
1517 sco_state_t sco_state = bta_ag_cb.sco.p_xfer_scb ? SCO_STATE_OFF_TRANSFER : SCO_STATE_OFF;
1518 #if (BTM_WBS_INCLUDED == TRUE)
1519 /* Indicate if the closing of audio is because of transfer */
1520 bta_ag_co_audio_state(handle, p_scb->app_id, sco_state, p_scb->inuse_codec);
1521 #else
1522 /* Indicate if the closing of audio is because of transfer */
1523 bta_ag_co_audio_state(handle, p_scb->app_id, sco_state);
1524 #endif
1525 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
1526
1527 bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1528
1529 /* if av got suspended by this call, let it resume. */
1530 /* In case call stays alive regardless of sco, av should not be affected. */
1531 if(((p_scb->call_ind == BTA_AG_CALL_INACTIVE) && (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
1532 || (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END))
1533 {
1534 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1535 }
1536
1537 /* call app callback */
1538 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
1539 #if (BTM_WBS_INCLUDED == TRUE)
1540 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1541 #endif
1542 }
1543 p_scb->retry_with_sco_only = FALSE;
1544 }
1545
1546 /*******************************************************************************
1547 **
1548 ** Function bta_ag_sco_conn_rsp
1549 **
1550 ** Description Process the SCO connection request
1551 **
1552 **
1553 ** Returns void
1554 **
1555 *******************************************************************************/
bta_ag_sco_conn_rsp(tBTA_AG_SCB * p_scb,tBTM_ESCO_CONN_REQ_EVT_DATA * p_data)1556 void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
1557 {
1558 tBTM_ESCO_PARAMS resp;
1559 UINT8 hci_status = HCI_SUCCESS;
1560 #if (BTM_SCO_HCI_INCLUDED == TRUE )
1561 tBTA_CODEC_INFO codec_info = {BTA_SCO_CODEC_PCM};
1562 UINT32 pcm_sample_rate;
1563 #endif
1564
1565 if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST ||
1566 bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
1567 bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST)
1568 {
1569 /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */
1570 if (bta_ag_cb.sco.param_updated)
1571 {
1572 resp = bta_ag_cb.sco.params;
1573 }
1574 else
1575 {
1576 resp.rx_bw = BTM_64KBITS_RATE;
1577 resp.tx_bw = BTM_64KBITS_RATE;
1578 resp.max_latency = 10;
1579 resp.voice_contfmt = 0x60;
1580 resp.retrans_effort = BTM_ESCO_RETRANS_POWER;
1581
1582 if (p_data->link_type == BTM_LINK_TYPE_SCO)
1583 {
1584 resp.packet_types = (BTM_SCO_LINK_ONLY_MASK |
1585 BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
1586 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
1587 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
1588 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
1589 }
1590 else /* Allow controller to use all types available except 5-slot EDR */
1591 {
1592 resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
1593 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
1594 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
1595 }
1596 }
1597
1598 /* tell sys to stop av if any */
1599 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1600
1601 #if (BTM_WBS_INCLUDED == FALSE )
1602 /* Allow any platform specific pre-SCO set up to take place */
1603 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP);
1604 #else
1605 /* When HS initiated SCO, it cannot be WBS. */
1606 /* Allow any platform specific pre-SCO set up to take place */
1607 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP,
1608 BTA_AG_CODEC_CVSD);
1609 #endif
1610
1611 #if (BTM_SCO_HCI_INCLUDED == TRUE )
1612 pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
1613
1614 /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
1615 BTM_ConfigScoPath(bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id),
1616 bta_ag_sco_read_cback, NULL, TRUE);
1617 #endif
1618 }
1619 else
1620 hci_status = HCI_ERR_HOST_REJECT_DEVICE;
1621
1622 #if (BTM_WBS_INCLUDED == TRUE )
1623 /* If SCO open was initiated from HS, it must be CVSD */
1624 p_scb->inuse_codec = BTA_AG_CODEC_NONE;
1625 #endif
1626
1627 BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
1628 }
1629
1630 /*******************************************************************************
1631 **
1632 ** Function bta_ag_ci_sco_data
1633 **
1634 ** Description Process the SCO data ready callin event
1635 **
1636 **
1637 ** Returns void
1638 **
1639 *******************************************************************************/
bta_ag_ci_sco_data(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1640 void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1641 {
1642 UNUSED(p_scb);
1643 UNUSED(p_data);
1644
1645 #if (BTM_SCO_HCI_INCLUDED == TRUE )
1646 bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
1647 #endif
1648 }
1649
1650 /*******************************************************************************
1651 **
1652 ** Function bta_ag_set_esco_param
1653 **
1654 ** Description Update esco parameters from script wrapper.
1655 **
1656 **
1657 ** Returns void
1658 **
1659 *******************************************************************************/
bta_ag_set_esco_param(BOOLEAN set_reset,tBTM_ESCO_PARAMS * param)1660 void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param)
1661 {
1662 if(set_reset == FALSE) /* reset the parameters to default */
1663 {
1664 bta_ag_cb.sco.param_updated = FALSE;
1665 APPL_TRACE_DEBUG("bta_ag_set_esco_param : Resetting ESCO parameters to default");
1666 }
1667 else
1668 {
1669 bta_ag_cb.sco.param_updated = TRUE;
1670 bta_ag_cb.sco.params = *param;
1671 APPL_TRACE_DEBUG("bta_ag_set_esco_param : Setting ESCO parameters");
1672 }
1673 }
1674
1675 /*******************************************************************************
1676 ** Debugging functions
1677 *******************************************************************************/
1678
1679 #if BTA_AG_SCO_DEBUG == TRUE
bta_ag_sco_evt_str(UINT8 event)1680 static char *bta_ag_sco_evt_str(UINT8 event)
1681 {
1682 switch (event)
1683 {
1684 case BTA_AG_SCO_LISTEN_E:
1685 return "Listen Request";
1686 case BTA_AG_SCO_OPEN_E:
1687 return "Open Request";
1688 case BTA_AG_SCO_XFER_E:
1689 return "Transfer Request";
1690 #if (BTM_WBS_INCLUDED == TRUE )
1691 case BTA_AG_SCO_CN_DONE_E:
1692 return "Codec Negotiation Done";
1693 case BTA_AG_SCO_REOPEN_E:
1694 return "Reopen Request";
1695 #endif
1696 case BTA_AG_SCO_CLOSE_E:
1697 return "Close Request";
1698 case BTA_AG_SCO_SHUTDOWN_E:
1699 return "Shutdown Request";
1700 case BTA_AG_SCO_CONN_OPEN_E:
1701 return "Opened";
1702 case BTA_AG_SCO_CONN_CLOSE_E:
1703 return "Closed";
1704 case BTA_AG_SCO_CI_DATA_E :
1705 return "Sco Data";
1706 default:
1707 return "Unknown SCO Event";
1708 }
1709 }
1710
bta_ag_sco_state_str(UINT8 state)1711 static char *bta_ag_sco_state_str(UINT8 state)
1712 {
1713 switch (state)
1714 {
1715 case BTA_AG_SCO_SHUTDOWN_ST:
1716 return "Shutdown";
1717 case BTA_AG_SCO_LISTEN_ST:
1718 return "Listening";
1719 #if (BTM_WBS_INCLUDED == TRUE )
1720 case BTA_AG_SCO_CODEC_ST:
1721 return "Codec Negotiation";
1722 #endif
1723 case BTA_AG_SCO_OPENING_ST:
1724 return "Opening";
1725 case BTA_AG_SCO_OPEN_CL_ST:
1726 return "Open while closing";
1727 case BTA_AG_SCO_OPEN_XFER_ST:
1728 return "Opening while Transferring";
1729 case BTA_AG_SCO_OPEN_ST:
1730 return "Open";
1731 case BTA_AG_SCO_CLOSING_ST:
1732 return "Closing";
1733 case BTA_AG_SCO_CLOSE_OP_ST:
1734 return "Close while Opening";
1735 case BTA_AG_SCO_CLOSE_XFER_ST:
1736 return "Close while Transferring";
1737 case BTA_AG_SCO_SHUTTING_ST:
1738 return "Shutting Down";
1739 default:
1740 return "Unknown SCO State";
1741 }
1742 }
1743
1744 #endif
1745