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