• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params);
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, &params);
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