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     UINT8 *rem_bd;
218 
219     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
220 
221     rem_bd = BTM_ReadScoBdAddr(sco_idx);
222 
223     if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
224             bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx)
225     {
226         BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
227         p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
228         p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
229         bta_sys_sendmsg(p_buf);
230     }
231     /* no match found; disconnect sco, init sco variables */
232     else
233     {
234         bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
235         BTM_RemoveSco(sco_idx);
236     }
237 }
238 
239 /*******************************************************************************
240 **
241 ** Function         bta_hf_client_sco_disc_cback
242 **
243 ** Description      BTM SCO disconnection callback.
244 **
245 **
246 ** Returns          void
247 **
248 *******************************************************************************/
bta_hf_client_sco_disc_cback(UINT16 sco_idx)249 static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
250 {
251     APPL_TRACE_DEBUG("%s %d", __func__, sco_idx);
252 
253     if (bta_hf_client_cb.scb.sco_idx == sco_idx) {
254         BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
255         p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
256         p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
257         bta_sys_sendmsg(p_buf);
258     }
259 }
260 
261 /*******************************************************************************
262 **
263 ** Function         bta_hf_client_create_sco
264 **
265 ** Description
266 **
267 **
268 ** Returns          void
269 **
270 *******************************************************************************/
bta_hf_client_sco_create(BOOLEAN is_orig)271 static void bta_hf_client_sco_create(BOOLEAN is_orig)
272 {
273     tBTM_STATUS       status;
274     UINT8            *p_bd_addr = NULL;
275     tBTM_ESCO_PARAMS params;
276 
277     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
278 
279     /* Make sure this sco handle is not already in use */
280     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
281     {
282         APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
283                             bta_hf_client_cb.scb.sco_idx);
284         return;
285     }
286 
287     params = bta_hf_client_esco_params[1];
288 
289     /* if initiating set current scb and peer bd addr */
290     if (is_orig)
291     {
292         /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
293         if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only)
294         {
295             BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
296             /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
297             if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
298                ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO))
299             {
300                 bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
301                 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
302             }
303         }
304         else
305         {
306             if(bta_hf_client_cb.scb.retry_with_sco_only)
307                 APPL_TRACE_API("retrying with SCO only");
308             bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
309 
310             BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
311         }
312 
313         /* tell sys to stop av if any */
314         bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
315     }
316     else
317     {
318         bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
319     }
320 
321     p_bd_addr = bta_hf_client_cb.scb.peer_addr;
322 
323     status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
324                            &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
325                            bta_hf_client_sco_disc_cback);
326     if (status == BTM_CMD_STARTED && !is_orig)
327     {
328         if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback))
329             APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
330     }
331 
332     APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
333                       __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
334                       status, params.packet_types);
335 }
336 
337 
338 /*******************************************************************************
339 **
340 ** Function         bta_hf_client_sco_event
341 **
342 ** Description      Handle SCO events
343 **
344 **
345 ** Returns          void
346 **
347 *******************************************************************************/
bta_hf_client_sco_event(UINT8 event)348 static void bta_hf_client_sco_event(UINT8 event)
349 {
350     APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
351                         bta_hf_client_cb.scb.sco_state, event);
352 
353     switch (bta_hf_client_cb.scb.sco_state)
354     {
355         case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
356             switch (event)
357             {
358                 case BTA_HF_CLIENT_SCO_LISTEN_E:
359                     /* create sco listen connection */
360                     bta_hf_client_sco_create(FALSE);
361                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
362                     break;
363 
364                 default:
365                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
366                     break;
367             }
368             break;
369 
370         case BTA_HF_CLIENT_SCO_LISTEN_ST:
371             switch (event)
372             {
373                 case BTA_HF_CLIENT_SCO_LISTEN_E:
374                     /* create sco listen connection (Additional channel) */
375                     bta_hf_client_sco_create(FALSE);
376                     break;
377 
378                 case BTA_HF_CLIENT_SCO_OPEN_E:
379                     /* remove listening connection */
380                     bta_hf_client_sco_remove(FALSE);
381 
382                     /* create sco connection to peer */
383                     bta_hf_client_sco_create(TRUE);
384                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
385                     break;
386 
387                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
388                     /* remove listening connection */
389                     bta_hf_client_sco_remove(FALSE);
390 
391                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
392                     break;
393 
394                 case BTA_HF_CLIENT_SCO_CLOSE_E:
395                     /* remove listening connection */
396                     /* Ignore the event. We need to keep listening SCO for the active SLC */
397                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
398                     break;
399 
400                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
401                     /* sco failed; create sco listen connection */
402                     bta_hf_client_sco_create(FALSE);
403                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
404                     break;
405 
406                 default:
407                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
408                     break;
409             }
410             break;
411 
412         case BTA_HF_CLIENT_SCO_OPENING_ST:
413             switch (event)
414             {
415                 case BTA_HF_CLIENT_SCO_CLOSE_E:
416                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
417                     break;
418 
419                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
420                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
421                     break;
422 
423                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
424                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
425                     break;
426 
427                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
428                     /* sco failed; create sco listen connection */
429                     bta_hf_client_sco_create(FALSE);
430                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
431                     break;
432 
433                 default:
434                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
435                     break;
436             }
437             break;
438 
439         case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
440             switch (event)
441             {
442                 case BTA_HF_CLIENT_SCO_OPEN_E:
443                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
444                     break;
445 
446                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
447                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
448                     break;
449 
450                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
451                     /* close sco connection */
452                     bta_hf_client_sco_remove(TRUE);
453 
454                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
455                     break;
456 
457                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
458                     /* sco failed; create sco listen connection */
459 
460                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
461                     break;
462 
463                 default:
464                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
465                     break;
466             }
467             break;
468 
469         case BTA_HF_CLIENT_SCO_OPEN_ST:
470             switch (event)
471             {
472                 case BTA_HF_CLIENT_SCO_CLOSE_E:
473                     /* close sco connection if active */
474                     if (bta_hf_client_sco_remove(TRUE))
475                     {
476                         bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
477                     }
478                     break;
479 
480                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
481                     /* remove all listening connections */
482                     bta_hf_client_sco_remove(FALSE);
483 
484                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
485                     break;
486 
487                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
488                     /* peer closed sco; create sco listen connection */
489                     bta_hf_client_sco_create(FALSE);
490                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
491                     break;
492 
493                 default:
494                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
495                     break;
496             }
497             break;
498 
499         case BTA_HF_CLIENT_SCO_CLOSING_ST:
500             switch (event)
501             {
502                 case BTA_HF_CLIENT_SCO_OPEN_E:
503                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
504                     break;
505 
506                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
507                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
508                     break;
509 
510                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
511                     /* peer closed sco; create sco listen connection */
512                     bta_hf_client_sco_create(FALSE);
513 
514                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
515                     break;
516 
517                 default:
518                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
519                     break;
520             }
521             break;
522 
523         case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
524             switch (event)
525             {
526                 case BTA_HF_CLIENT_SCO_CLOSE_E:
527                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
528                     break;
529 
530                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
531                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
532                     break;
533 
534                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
535                     /* open sco connection */
536                     bta_hf_client_sco_create(TRUE);
537                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
538                     break;
539 
540                 default:
541                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
542                     break;
543             }
544             break;
545 
546         case BTA_HF_CLIENT_SCO_SHUTTING_ST:
547             switch (event)
548             {
549                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
550                     /* close sco connection; wait for conn close event */
551                     bta_hf_client_sco_remove(TRUE);
552                     break;
553 
554                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
555                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
556                     break;
557 
558                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
559                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
560                     break;
561 
562                 default:
563                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
564                     break;
565             }
566             break;
567 
568         default:
569             break;
570     }
571 }
572 
573 /*******************************************************************************
574 **
575 ** Function         bta_hf_client_sco_listen
576 **
577 ** Description      Initialize SCO listener
578 **
579 **
580 ** Returns          void
581 **
582 *******************************************************************************/
bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA * p_data)583 void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
584 {
585     UNUSED(p_data);
586 
587     APPL_TRACE_DEBUG("%s", __FUNCTION__);
588 
589     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
590 }
591 
592 /*******************************************************************************
593 **
594 ** Function         bta_hf_client_sco_shutdown
595 **
596 ** Description
597 **
598 **
599 ** Returns          void
600 **
601 *******************************************************************************/
bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA * p_data)602 void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
603 {
604     UNUSED(p_data);
605 
606     APPL_TRACE_DEBUG("%s", __FUNCTION__);
607 
608     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
609 }
610 
611 /*******************************************************************************
612 **
613 ** Function         bta_hf_client_sco_conn_open
614 **
615 ** Description
616 **
617 **
618 ** Returns          void
619 **
620 *******************************************************************************/
bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA * p_data)621 void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
622 {
623     UNUSED(p_data);
624 
625     APPL_TRACE_DEBUG("%s", __FUNCTION__);
626 
627     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
628 
629     bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
630 
631     if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC)
632     {
633         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
634     }
635     else
636     {
637         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
638     }
639 
640     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
641 }
642 
643 /*******************************************************************************
644 **
645 ** Function         bta_hf_client_sco_conn_close
646 **
647 ** Description
648 **
649 **
650 ** Returns          void
651 **
652 *******************************************************************************/
bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA * p_data)653 void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
654 {
655     APPL_TRACE_DEBUG("%s", __FUNCTION__);
656 
657     /* clear current scb */
658     bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
659 
660     /* retry_with_sco_only, will be set only when initiator
661     ** and HFClient is first trying to establish an eSCO connection */
662     if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn)
663     {
664         bta_hf_client_sco_create(TRUE);
665     }
666     else
667     {
668         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
669 
670         bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
671 
672         bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
673 
674         /* call app callback */
675         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
676 
677         if (bta_hf_client_cb.scb.sco_close_rfc == TRUE)
678         {
679             bta_hf_client_cb.scb.sco_close_rfc = FALSE;
680             bta_hf_client_rfc_do_close(p_data);
681         }
682     }
683     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
684 }
685 
686 /*******************************************************************************
687 **
688 ** Function         bta_hf_client_sco_open
689 **
690 ** Description
691 **
692 **
693 ** Returns          void
694 **
695 *******************************************************************************/
bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA * p_data)696 void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
697 {
698     UNUSED(p_data);
699 
700     APPL_TRACE_DEBUG("%s", __FUNCTION__);
701 
702     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
703 }
704 
705 /*******************************************************************************
706 **
707 ** Function         bta_hf_client_sco_close
708 **
709 ** Description
710 **
711 **
712 ** Returns          void
713 **
714 *******************************************************************************/
bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA * p_data)715 void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
716 {
717     UNUSED(p_data);
718 
719     APPL_TRACE_DEBUG("%s  0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
720 
721     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
722     {
723         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
724     }
725 }
726