1 /******************************************************************************
2  *
3  *  Copyright (c) 2014 The Android Open Source Project
4  *  Copyright (C) 2004-2012 Broadcom Corporation
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 
20 #include "bta_hf_client_int.h"
21 #include <bt_trace.h>
22 #include <string.h>
23 #include "bt_utils.h"
24 
25 #define BTA_HF_CLIENT_NO_EDR_ESCO  (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
26                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
27                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
28                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
29 
30 static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
31         /* SCO CVSD */
32         {
33                 .rx_bw = BTM_64KBITS_RATE,
34                 .tx_bw = BTM_64KBITS_RATE,
35                 .max_latency = 10,
36                 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
37                 .packet_types = (BTM_SCO_LINK_ONLY_MASK          |
38                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
39                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
40                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
41                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
42                  .retrans_effort = BTM_ESCO_RETRANS_POWER,
43         },
44         /* ESCO CVSD */
45         {
46                 .rx_bw = BTM_64KBITS_RATE,
47                 .tx_bw = BTM_64KBITS_RATE,
48                 .max_latency = 10,
49                 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
50                 /* Allow controller to use all types available except 5-slot EDR */
51                 .packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
52                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
53                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
54                 .retrans_effort = BTM_ESCO_RETRANS_POWER,
55         },
56         /* ESCO mSBC */
57         {
58                 .rx_bw = BTM_64KBITS_RATE,
59                 .tx_bw = BTM_64KBITS_RATE,
60                 .max_latency = 13,
61                 .voice_contfmt = BTM_VOICE_SETTING_TRANS,
62                 /* Packet Types : EV3 + 2-EV3               */
63                 .packet_types = (BTM_SCO_PKT_TYPES_MASK_EV3  |
64                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
65                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
66                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
67                 .retrans_effort = BTM_ESCO_RETRANS_QUALITY,
68         }
69 };
70 
71 enum
72 {
73     BTA_HF_CLIENT_SCO_LISTEN_E,
74     BTA_HF_CLIENT_SCO_OPEN_E,          /* open request */
75     BTA_HF_CLIENT_SCO_CLOSE_E,         /* close request */
76     BTA_HF_CLIENT_SCO_SHUTDOWN_E,      /* shutdown request */
77     BTA_HF_CLIENT_SCO_CONN_OPEN_E,     /* sco opened */
78     BTA_HF_CLIENT_SCO_CONN_CLOSE_E,    /* sco closed */
79 };
80 
81 /*******************************************************************************
82 **
83 ** Function         bta_hf_client_remove_sco
84 **
85 ** Description      Removes the specified SCO from the system.
86 **                  If only_active is TRUE, then SCO is only removed if connected
87 **
88 ** Returns          BOOLEAN   - TRUE if Sco removal was started
89 **
90 *******************************************************************************/
bta_hf_client_sco_remove(BOOLEAN only_active)91 static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active)
92 {
93     BOOLEAN     removed_started = FALSE;
94     tBTM_STATUS status;
95 
96     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active);
97 
98     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
99     {
100         status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx);
101 
102         APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status);
103 
104         if (status == BTM_CMD_STARTED)
105         {
106             removed_started = TRUE;
107         }
108         /* If no connection reset the sco handle */
109         else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
110         {
111             bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
112         }
113     }
114     return removed_started;
115 }
116 
117 /*******************************************************************************
118 **
119 ** Function         bta_hf_client_cback_sco
120 **
121 ** Description      Call application callback function with SCO event.
122 **
123 **
124 ** Returns          void
125 **
126 *******************************************************************************/
bta_hf_client_cback_sco(UINT8 event)127 void bta_hf_client_cback_sco(UINT8 event)
128 {
129     tBTA_HF_CLIENT    evt;
130 
131     memset(&evt, 0, sizeof(evt));
132 
133     /* call app cback */
134     (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT *) &evt);
135 }
136 
137 /*******************************************************************************
138 **
139 ** Function         bta_hf_client_sco_conn_rsp
140 **
141 ** Description      Process the SCO connection request
142 **
143 **
144 ** Returns          void
145 **
146 *******************************************************************************/
bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA * p_data)147 static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
148 {
149     tBTM_ESCO_PARAMS    resp;
150     UINT8               hci_status = HCI_SUCCESS;
151 
152     APPL_TRACE_DEBUG("%s", __FUNCTION__);
153 
154     if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST)
155     {
156         if (p_data->link_type == BTM_LINK_TYPE_SCO)
157         {
158             resp = bta_hf_client_esco_params[0];
159         }
160         else
161         {
162             resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
163         }
164 
165         /* tell sys to stop av if any */
166         bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
167     }
168     else
169     {
170         hci_status = HCI_ERR_HOST_REJECT_DEVICE;
171     }
172 
173     BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
174 }
175 
176 /*******************************************************************************
177 **
178 ** Function         bta_hf_client_sco_connreq_cback
179 **
180 ** Description      BTM eSCO connection requests and eSCO change requests
181 **                  Only the connection requests are processed by BTA.
182 **
183 ** Returns          void
184 **
185 *******************************************************************************/
bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event,tBTM_ESCO_EVT_DATA * p_data)186 static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
187 {
188     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event);
189 
190     if (event != BTM_ESCO_CONN_REQ_EVT)
191     {
192         return;
193     }
194 
195     /* TODO check remote bdaddr, should allow connect only from device with
196      * active SLC  */
197 
198     bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx;
199 
200     bta_hf_client_sco_conn_rsp(&p_data->conn_evt);
201 
202     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
203 }
204 
205 /*******************************************************************************
206 **
207 ** Function         bta_hf_client_sco_conn_cback
208 **
209 ** Description      BTM SCO connection callback.
210 **
211 **
212 ** Returns          void
213 **
214 *******************************************************************************/
bta_hf_client_sco_conn_cback(UINT16 sco_idx)215 static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
216 {
217     BT_HDR  *p_buf;
218     UINT8 *rem_bd;
219 
220     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
221 
222     rem_bd = BTM_ReadScoBdAddr(sco_idx);
223 
224     if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
225             bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx)
226     {
227         if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
228         {
229             p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
230             p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
231             bta_sys_sendmsg(p_buf);
232         }
233     }
234     /* no match found; disconnect sco, init sco variables */
235     else
236     {
237         bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
238         BTM_RemoveSco(sco_idx);
239     }
240 }
241 
242 /*******************************************************************************
243 **
244 ** Function         bta_hf_client_sco_disc_cback
245 **
246 ** Description      BTM SCO disconnection callback.
247 **
248 **
249 ** Returns          void
250 **
251 *******************************************************************************/
bta_hf_client_sco_disc_cback(UINT16 sco_idx)252 static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
253 {
254     BT_HDR  *p_buf;
255 
256     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
257 
258     if (bta_hf_client_cb.scb.sco_idx == sco_idx)
259     {
260         if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
261         {
262             p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
263             p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
264             bta_sys_sendmsg(p_buf);
265         }
266     }
267 }
268 
269 /*******************************************************************************
270 **
271 ** Function         bta_hf_client_create_sco
272 **
273 ** Description
274 **
275 **
276 ** Returns          void
277 **
278 *******************************************************************************/
bta_hf_client_sco_create(BOOLEAN is_orig)279 static void bta_hf_client_sco_create(BOOLEAN is_orig)
280 {
281     tBTM_STATUS       status;
282     UINT8            *p_bd_addr = NULL;
283     tBTM_ESCO_PARAMS params;
284 
285     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
286 
287     /* Make sure this sco handle is not already in use */
288     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
289     {
290         APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
291                             bta_hf_client_cb.scb.sco_idx);
292         return;
293     }
294 
295     params = bta_hf_client_esco_params[1];
296 
297     /* if initiating set current scb and peer bd addr */
298     if (is_orig)
299     {
300         /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
301         if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only)
302         {
303             BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
304             /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
305             if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
306                ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO))
307             {
308                 bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
309                 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
310             }
311         }
312         else
313         {
314             if(bta_hf_client_cb.scb.retry_with_sco_only)
315                 APPL_TRACE_API("retrying with SCO only");
316             bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
317 
318             BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
319         }
320 
321         /* tell sys to stop av if any */
322         bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
323     }
324     else
325     {
326         bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
327     }
328 
329     p_bd_addr = bta_hf_client_cb.scb.peer_addr;
330 
331     status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
332                            &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
333                            bta_hf_client_sco_disc_cback);
334     if (status == BTM_CMD_STARTED && !is_orig)
335     {
336         if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback))
337             APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
338     }
339 
340     APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
341                       __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
342                       status, params.packet_types);
343 }
344 
345 
346 /*******************************************************************************
347 **
348 ** Function         bta_hf_client_sco_event
349 **
350 ** Description      Handle SCO events
351 **
352 **
353 ** Returns          void
354 **
355 *******************************************************************************/
bta_hf_client_sco_event(UINT8 event)356 static void bta_hf_client_sco_event(UINT8 event)
357 {
358     APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
359                         bta_hf_client_cb.scb.sco_state, event);
360 
361     switch (bta_hf_client_cb.scb.sco_state)
362     {
363         case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
364             switch (event)
365             {
366                 case BTA_HF_CLIENT_SCO_LISTEN_E:
367                     /* create sco listen connection */
368                     bta_hf_client_sco_create(FALSE);
369                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
370                     break;
371 
372                 default:
373                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
374                     break;
375             }
376             break;
377 
378         case BTA_HF_CLIENT_SCO_LISTEN_ST:
379             switch (event)
380             {
381                 case BTA_HF_CLIENT_SCO_LISTEN_E:
382                     /* create sco listen connection (Additional channel) */
383                     bta_hf_client_sco_create(FALSE);
384                     break;
385 
386                 case BTA_HF_CLIENT_SCO_OPEN_E:
387                     /* remove listening connection */
388                     bta_hf_client_sco_remove(FALSE);
389 
390                     /* create sco connection to peer */
391                     bta_hf_client_sco_create(TRUE);
392                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
393                     break;
394 
395                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
396                     /* remove listening connection */
397                     bta_hf_client_sco_remove(FALSE);
398 
399                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
400                     break;
401 
402                 case BTA_HF_CLIENT_SCO_CLOSE_E:
403                     /* remove listening connection */
404                     /* Ignore the event. We need to keep listening SCO for the active SLC */
405                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
406                     break;
407 
408                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
409                     /* sco failed; create sco listen connection */
410                     bta_hf_client_sco_create(FALSE);
411                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
412                     break;
413 
414                 default:
415                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
416                     break;
417             }
418             break;
419 
420         case BTA_HF_CLIENT_SCO_OPENING_ST:
421             switch (event)
422             {
423                 case BTA_HF_CLIENT_SCO_CLOSE_E:
424                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
425                     break;
426 
427                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
428                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
429                     break;
430 
431                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
432                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
433                     break;
434 
435                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
436                     /* sco failed; create sco listen connection */
437                     bta_hf_client_sco_create(FALSE);
438                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
439                     break;
440 
441                 default:
442                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
443                     break;
444             }
445             break;
446 
447         case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
448             switch (event)
449             {
450                 case BTA_HF_CLIENT_SCO_OPEN_E:
451                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
452                     break;
453 
454                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
455                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
456                     break;
457 
458                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
459                     /* close sco connection */
460                     bta_hf_client_sco_remove(TRUE);
461 
462                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
463                     break;
464 
465                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
466                     /* sco failed; create sco listen connection */
467 
468                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
469                     break;
470 
471                 default:
472                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
473                     break;
474             }
475             break;
476 
477         case BTA_HF_CLIENT_SCO_OPEN_ST:
478             switch (event)
479             {
480                 case BTA_HF_CLIENT_SCO_CLOSE_E:
481                     /* close sco connection if active */
482                     if (bta_hf_client_sco_remove(TRUE))
483                     {
484                         bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
485                     }
486                     break;
487 
488                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
489                     /* remove all listening connections */
490                     bta_hf_client_sco_remove(FALSE);
491 
492                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
493                     break;
494 
495                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
496                     /* peer closed sco; create sco listen connection */
497                     bta_hf_client_sco_create(FALSE);
498                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
499                     break;
500 
501                 default:
502                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
503                     break;
504             }
505             break;
506 
507         case BTA_HF_CLIENT_SCO_CLOSING_ST:
508             switch (event)
509             {
510                 case BTA_HF_CLIENT_SCO_OPEN_E:
511                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
512                     break;
513 
514                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
515                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
516                     break;
517 
518                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
519                     /* peer closed sco; create sco listen connection */
520                     bta_hf_client_sco_create(FALSE);
521 
522                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
523                     break;
524 
525                 default:
526                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
527                     break;
528             }
529             break;
530 
531         case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
532             switch (event)
533             {
534                 case BTA_HF_CLIENT_SCO_CLOSE_E:
535                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
536                     break;
537 
538                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
539                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
540                     break;
541 
542                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
543                     /* open sco connection */
544                     bta_hf_client_sco_create(TRUE);
545                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
546                     break;
547 
548                 default:
549                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
550                     break;
551             }
552             break;
553 
554         case BTA_HF_CLIENT_SCO_SHUTTING_ST:
555             switch (event)
556             {
557                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
558                     /* close sco connection; wait for conn close event */
559                     bta_hf_client_sco_remove(TRUE);
560                     break;
561 
562                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
563                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
564                     break;
565 
566                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
567                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
568                     break;
569 
570                 default:
571                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
572                     break;
573             }
574             break;
575 
576         default:
577             break;
578     }
579 }
580 
581 /*******************************************************************************
582 **
583 ** Function         bta_hf_client_sco_listen
584 **
585 ** Description      Initialize SCO listener
586 **
587 **
588 ** Returns          void
589 **
590 *******************************************************************************/
bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA * p_data)591 void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
592 {
593     UNUSED(p_data);
594 
595     APPL_TRACE_DEBUG("%s", __FUNCTION__);
596 
597     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
598 }
599 
600 /*******************************************************************************
601 **
602 ** Function         bta_hf_client_sco_shutdown
603 **
604 ** Description
605 **
606 **
607 ** Returns          void
608 **
609 *******************************************************************************/
bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA * p_data)610 void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
611 {
612     UNUSED(p_data);
613 
614     APPL_TRACE_DEBUG("%s", __FUNCTION__);
615 
616     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
617 }
618 
619 /*******************************************************************************
620 **
621 ** Function         bta_hf_client_sco_conn_open
622 **
623 ** Description
624 **
625 **
626 ** Returns          void
627 **
628 *******************************************************************************/
bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA * p_data)629 void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
630 {
631     UNUSED(p_data);
632 
633     APPL_TRACE_DEBUG("%s", __FUNCTION__);
634 
635     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
636 
637     bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
638 
639     if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC)
640     {
641         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
642     }
643     else
644     {
645         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
646     }
647 
648     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
649 }
650 
651 /*******************************************************************************
652 **
653 ** Function         bta_hf_client_sco_conn_close
654 **
655 ** Description
656 **
657 **
658 ** Returns          void
659 **
660 *******************************************************************************/
bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA * p_data)661 void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
662 {
663     APPL_TRACE_DEBUG("%s", __FUNCTION__);
664 
665     /* clear current scb */
666     bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
667 
668     /* retry_with_sco_only, will be set only when initiator
669     ** and HFClient is first trying to establish an eSCO connection */
670     if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn)
671     {
672         bta_hf_client_sco_create(TRUE);
673     }
674     else
675     {
676         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
677 
678         bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
679 
680         bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
681 
682         /* call app callback */
683         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
684 
685         if (bta_hf_client_cb.scb.sco_close_rfc == TRUE)
686         {
687             bta_hf_client_cb.scb.sco_close_rfc = FALSE;
688             bta_hf_client_rfc_do_close(p_data);
689         }
690     }
691     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
692 }
693 
694 /*******************************************************************************
695 **
696 ** Function         bta_hf_client_sco_open
697 **
698 ** Description
699 **
700 **
701 ** Returns          void
702 **
703 *******************************************************************************/
bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA * p_data)704 void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
705 {
706     UNUSED(p_data);
707 
708     APPL_TRACE_DEBUG("%s", __FUNCTION__);
709 
710     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
711 }
712 
713 /*******************************************************************************
714 **
715 ** Function         bta_hf_client_sco_close
716 **
717 ** Description
718 **
719 **
720 ** Returns          void
721 **
722 *******************************************************************************/
bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA * p_data)723 void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
724 {
725     UNUSED(p_data);
726 
727     APPL_TRACE_DEBUG("%s  0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
728 
729     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
730     {
731         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
732     }
733 }
734