1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*****************************************************************************
8  *
9  *  Filename:      btc_avk.c
10  *
11  *  Description:   AV implementation
12  *
13  *****************************************************************************/
14 #include "common/bt_target.h"
15 #include <string.h>
16 #include "common/bt_trace.h"
17 #include "common/bt_defs.h"
18 #include "osi/allocator.h"
19 #include "stack/btu.h"
20 #include "bta/bta_av_api.h"
21 #include "btc/btc_dm.h"
22 #include "btc/btc_common.h"
23 #include "btc/btc_manage.h"
24 #include "btc_av.h"
25 #include "btc_avrc.h"
26 #include "btc/btc_util.h"
27 #include "btc/btc_profile_queue.h"
28 #include "btc_a2dp.h"
29 #include "btc_a2dp_control.h"
30 #include "btc_a2dp_sink.h"
31 #include "btc_a2dp_source.h"
32 #include "esp_a2dp_api.h"
33 #include "osi/alarm.h"
34 
35 #if BTC_AV_INCLUDED
36 
37 // global variable to inidcate avrc is initialized with a2dp
38 bool g_av_with_rc;
39 // global variable to indicate a2dp is initialized
40 bool g_a2dp_on_init;
41 // global variable to indicate a2dp is deinitialized
42 bool g_a2dp_on_deinit;
43 // global variable to indicate a2dp source deinitialization is ongoing
44 bool g_a2dp_source_ongoing_deinit;
45 // global variable to indicate a2dp sink deinitialization is ongoing
46 bool g_a2dp_sink_ongoing_deinit;
47 
48 
49 /*****************************************************************************
50 **  Constants & Macros
51 ******************************************************************************/
52 #define BTC_AV_SERVICE_NAME "Advanced Audio"
53 
54 #define BTC_TIMEOUT_AV_OPEN_ON_RC_SECS  2
55 
56 typedef enum {
57     BTC_AV_STATE_IDLE = 0x0,
58     BTC_AV_STATE_OPENING,
59     BTC_AV_STATE_OPENED,
60     BTC_AV_STATE_STARTED,
61     BTC_AV_STATE_CLOSING
62 } btc_av_state_t;
63 
64 /* Should not need dedicated suspend state as actual actions are no
65    different than open state. Suspend flags are needed however to prevent
66    media task from trying to restart stream during remote suspend or while
67    we are in the process of a local suspend */
68 
69 #define BTC_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1
70 #define BTC_AV_FLAG_REMOTE_SUSPEND        0x2
71 #define BTC_AV_FLAG_PENDING_START         0x4
72 #define BTC_AV_FLAG_PENDING_STOP          0x8
73 
74 /*****************************************************************************
75 **  Local type definitions
76 ******************************************************************************/
77 
78 typedef struct {
79     int service_id;
80     tBTA_AV_HNDL bta_handle;
81     bt_bdaddr_t peer_bda;
82     btc_sm_handle_t sm_handle;
83     UINT8 flags;
84     tBTA_AV_EDR edr;
85     UINT8   peer_sep;  /* sep type of peer device */
86 #if BTC_AV_SRC_INCLUDED
87     osi_alarm_t *tle_av_open_on_rc;
88 #endif /* BTC_AV_SRC_INCLUDED */
89 } btc_av_cb_t;
90 
91 typedef struct {
92     bt_bdaddr_t target_bda;
93     uint16_t uuid;
94 } btc_av_connect_req_t;
95 
96 typedef struct {
97     bt_bdaddr_t target_bda;
98 } btc_av_disconn_req_t;
99 
100 /*****************************************************************************
101 **  Static variables
102 ******************************************************************************/
103 
104 #if A2D_DYNAMIC_MEMORY == FALSE
105 static btc_av_cb_t btc_av_cb = {0};
106 #else
107 static btc_av_cb_t *btc_av_cb_ptr = NULL;
108 #define btc_av_cb (*btc_av_cb_ptr)
109 #endif ///A2D_DYNAMIC_MEMORY == FALSE
110 
111 /* both interface and media task needs to be ready to alloc incoming request */
112 #define CHECK_BTAV_INIT() do \
113 { \
114     assert (btc_av_cb.sm_handle != NULL); \
115 } while (0)
116 
117 
118 /* Helper macro to avoid code duplication in the state machine handlers */
119 #define CHECK_RC_EVENT(e, d) \
120     case BTA_AV_RC_OPEN_EVT: \
121     case BTA_AV_RC_CLOSE_EVT: \
122     case BTA_AV_REMOTE_CMD_EVT: \
123     case BTA_AV_VENDOR_CMD_EVT: \
124     case BTA_AV_META_MSG_EVT: \
125     case BTA_AV_RC_FEAT_EVT: \
126     case BTA_AV_REMOTE_RSP_EVT: \
127     { \
128          btc_rc_handler(e, d);\
129     }break; \
130 
131 static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *data);
132 static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *data);
133 static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *data);
134 static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *data);
135 static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *data);
136 static void clean_up(int service_id);
137 
138 #if BTC_AV_SRC_INCLUDED
139 static bt_status_t btc_a2d_src_init(void);
140 static bt_status_t btc_a2d_src_connect(bt_bdaddr_t *remote_bda);
141 static void btc_a2d_src_deinit(void);
142 #endif /* BTC_AV_SRC_INCLUDED */
143 
144 #if BTC_AV_SINK_INCLUDED
145 static bt_status_t btc_a2d_sink_init(void);
146 static bt_status_t btc_a2d_sink_connect(bt_bdaddr_t *remote_bda);
147 static void btc_a2d_sink_deinit(void);
148 #endif /* BTC_AV_SINK_INCLUDED */
149 
150 static const btc_sm_handler_t btc_av_state_handlers[] = {
151     btc_av_state_idle_handler,
152     btc_av_state_opening_handler,
153     btc_av_state_opened_handler,
154     btc_av_state_started_handler,
155     btc_av_state_closing_handler
156 };
157 
158 static void btc_av_event_free_data(btc_sm_event_t event, void *p_data);
159 
160 /*************************************************************************
161 ** Extern functions
162 *************************************************************************/
163 
164 extern tBTA_AV_CO_FUNCTS bta_av_a2d_cos;
165 extern tBTA_AVRC_CO_FUNCTS bta_avrc_cos;
166 /*****************************************************************************
167 ** Local helper functions
168 ******************************************************************************/
btc_a2d_cb_to_app(esp_a2d_cb_event_t event,esp_a2d_cb_param_t * param)169 static inline void btc_a2d_cb_to_app(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
170 {
171     esp_a2d_cb_t btc_a2d_cb = (esp_a2d_cb_t)btc_profile_cb_get(BTC_PID_A2DP);
172     if (btc_a2d_cb) {
173         btc_a2d_cb(event, param);
174     }
175 }
176 
dump_av_sm_state_name(btc_av_state_t state)177 UNUSED_ATTR static const char *dump_av_sm_state_name(btc_av_state_t state)
178 {
179     switch (state) {
180         CASE_RETURN_STR(BTC_AV_STATE_IDLE)
181         CASE_RETURN_STR(BTC_AV_STATE_OPENING)
182         CASE_RETURN_STR(BTC_AV_STATE_OPENED)
183         CASE_RETURN_STR(BTC_AV_STATE_STARTED)
184         CASE_RETURN_STR(BTC_AV_STATE_CLOSING)
185     default: return "UNKNOWN_STATE";
186     }
187 }
188 
dump_av_sm_event_name(btc_av_sm_event_t event)189 UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event)
190 {
191     switch ((int)event) {
192         CASE_RETURN_STR(BTA_AV_ENABLE_EVT)
193         CASE_RETURN_STR(BTA_AV_REGISTER_EVT)
194         CASE_RETURN_STR(BTA_AV_OPEN_EVT)
195         CASE_RETURN_STR(BTA_AV_CLOSE_EVT)
196         CASE_RETURN_STR(BTA_AV_START_EVT)
197         CASE_RETURN_STR(BTA_AV_STOP_EVT)
198         CASE_RETURN_STR(BTA_AV_PROTECT_REQ_EVT)
199         CASE_RETURN_STR(BTA_AV_PROTECT_RSP_EVT)
200         CASE_RETURN_STR(BTA_AV_RC_OPEN_EVT)
201         CASE_RETURN_STR(BTA_AV_RC_CLOSE_EVT)
202         CASE_RETURN_STR(BTA_AV_REMOTE_CMD_EVT)
203         CASE_RETURN_STR(BTA_AV_REMOTE_RSP_EVT)
204         CASE_RETURN_STR(BTA_AV_VENDOR_CMD_EVT)
205         CASE_RETURN_STR(BTA_AV_VENDOR_RSP_EVT)
206         CASE_RETURN_STR(BTA_AV_RECONFIG_EVT)
207         CASE_RETURN_STR(BTA_AV_SUSPEND_EVT)
208         CASE_RETURN_STR(BTA_AV_PENDING_EVT)
209         CASE_RETURN_STR(BTA_AV_META_MSG_EVT)
210         CASE_RETURN_STR(BTA_AV_REJECT_EVT)
211         CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
212         CASE_RETURN_STR(BTC_SM_ENTER_EVT)
213         CASE_RETURN_STR(BTC_SM_EXIT_EVT)
214         CASE_RETURN_STR(BTC_AV_CONNECT_REQ_EVT)
215         CASE_RETURN_STR(BTC_AV_DISCONNECT_REQ_EVT)
216         CASE_RETURN_STR(BTC_AV_START_STREAM_REQ_EVT)
217         CASE_RETURN_STR(BTC_AV_STOP_STREAM_REQ_EVT)
218         CASE_RETURN_STR(BTC_AV_SUSPEND_STREAM_REQ_EVT)
219         CASE_RETURN_STR(BTC_AV_SINK_CONFIG_REQ_EVT)
220     default: return "UNKNOWN_EVENT";
221     }
222 }
223 
224 /****************************************************************************
225 **  Local helper functions
226 *****************************************************************************/
227 #if BTC_AV_SRC_INCLUDED
228 /*******************************************************************************
229 **
230 ** Function         btc_initiate_av_open_tmr_hdlr
231 **
232 ** Description      Timer to trigger AV open if the remote headset establishes
233 **                  RC connection w/o AV connection. The timer is needed to IOP
234 **                  with headsets that do establish AV after RC connection.
235 **
236 ** Returns          void
237 **
238 *******************************************************************************/
btc_initiate_av_open_tmr_hdlr(void * arg)239 static void btc_initiate_av_open_tmr_hdlr(void *arg)
240 {
241     UNUSED(arg);
242     BD_ADDR peer_addr;
243     btc_av_connect_req_t connect_req;
244     /* is there at least one RC connection - There should be */
245     if (btc_rc_get_connected_peer(peer_addr)) {
246         BTC_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
247         /* In case of AVRCP connection request, we will initiate SRC connection */
248         memcpy(connect_req.target_bda.address, peer_addr, sizeof(bt_bdaddr_t));
249         connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
250         btc_dispatch_sm_event(BTC_AV_CONNECT_REQ_EVT, &connect_req, sizeof(btc_av_connect_req_t));
251     } else {
252         BTC_TRACE_ERROR("%s No connected RC peers", __FUNCTION__);
253     }
254 }
255 #endif /* BTC_AV_SRC_INCLUDED */
256 
257 /*****************************************************************************
258 **  Static functions
259 ******************************************************************************/
btc_report_connection_state(esp_a2d_connection_state_t state,bt_bdaddr_t * bd_addr,int disc_rsn)260 static void btc_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr, int disc_rsn)
261 {
262     // todo: add callback for SRC
263     esp_a2d_cb_param_t param;
264     memset(&param, 0, sizeof(esp_a2d_cb_param_t));
265 
266     param.conn_stat.state = state;
267     if (bd_addr) {
268         memcpy(param.conn_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
269     }
270     if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
271         param.conn_stat.disc_rsn = (disc_rsn == 0) ? ESP_A2D_DISC_RSN_NORMAL :
272                                    ESP_A2D_DISC_RSN_ABNORMAL;
273     }
274     btc_a2d_cb_to_app(ESP_A2D_CONNECTION_STATE_EVT, &param);
275 }
276 
btc_report_audio_state(esp_a2d_audio_state_t state,bt_bdaddr_t * bd_addr)277 static void btc_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_addr)
278 {
279     // todo: add callback for SRC
280     esp_a2d_cb_param_t param;
281     memset(&param, 0, sizeof(esp_a2d_cb_param_t));
282 
283     param.audio_stat.state = state;
284     if (bd_addr) {
285         memcpy(param.audio_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
286     }
287     btc_a2d_cb_to_app(ESP_A2D_AUDIO_STATE_EVT, &param);
288 }
289 
290 /*****************************************************************************
291 **
292 ** Function     btc_av_state_idle_handler
293 **
294 ** Description  State managing disconnected AV link
295 **
296 ** Returns      TRUE if event was processed, FALSE otherwise
297 **
298 *******************************************************************************/
299 
btc_av_state_idle_handler(btc_sm_event_t event,void * p_data)300 static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
301 {
302     BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
303               dump_av_sm_event_name(event), btc_av_cb.flags);
304 
305     switch (event) {
306     case BTC_SM_ENTER_EVT:
307         /* clear the peer_bda */
308         memset(&btc_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t));
309         btc_av_cb.flags = 0;
310         btc_av_cb.edr = 0;
311         btc_a2dp_on_idle();
312         break;
313 
314     case BTC_SM_EXIT_EVT:
315         break;
316 
317     case BTA_AV_ENABLE_EVT:
318         break;
319 
320     case BTA_AV_REGISTER_EVT:
321         btc_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl;
322         break;
323 
324     case BTA_AV_PENDING_EVT:
325     case BTC_AV_CONNECT_REQ_EVT: {
326         if (event == BTC_AV_CONNECT_REQ_EVT) {
327             memcpy(&btc_av_cb.peer_bda, &((btc_av_connect_req_t *)p_data)->target_bda,
328                    sizeof(bt_bdaddr_t));
329             if (g_av_with_rc) {
330                 BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
331                         TRUE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid);
332             } else {
333                 BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
334                         FALSE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid);
335             }
336         } else if (event == BTA_AV_PENDING_EVT) {
337             bdcpy(btc_av_cb.peer_bda.address, ((tBTA_AV *)p_data)->pend.bd_addr);
338             UINT16 uuid = (btc_av_cb.service_id == BTA_A2DP_SOURCE_SERVICE_ID) ? UUID_SERVCLASS_AUDIO_SOURCE :
339                 UUID_SERVCLASS_AUDIO_SINK;
340             if (g_av_with_rc) {
341                 BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
342                         TRUE, BTA_SEC_AUTHENTICATE, uuid);
343             } else {
344                 BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
345                        FALSE, BTA_SEC_AUTHENTICATE, uuid);
346             }
347         }
348         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENING);
349     } break;
350 
351     case BTC_AV_DISCONNECT_REQ_EVT:
352         BTC_TRACE_WARNING("No Link At All.");
353         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0);
354         break;
355 
356     case BTA_AV_RC_OPEN_EVT:
357         /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
358          * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
359          * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
360          * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
361          * headsets, as some headsets initiate the AVRC connection first and then
362          * immediately initiate the AV connection
363          *
364          * TODO: We may need to do this only on an AVRCP Play. FixMe
365          */
366 #if BTC_AV_SRC_INCLUDED
367         BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
368         btc_av_cb.tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
369         osi_alarm_set(btc_av_cb.tle_av_open_on_rc, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
370 #endif /* BTC_AV_SRC_INCLUDED */
371         btc_rc_handler(event, p_data);
372         break;
373 
374     case BTA_AV_REMOTE_CMD_EVT:
375     case BTA_AV_VENDOR_CMD_EVT:
376     case BTA_AV_META_MSG_EVT:
377     case BTA_AV_RC_FEAT_EVT:
378     case BTA_AV_REMOTE_RSP_EVT:
379         btc_rc_handler(event, (tBTA_AV *)p_data);
380         break;
381 
382     case BTA_AV_RC_CLOSE_EVT:
383 #if BTC_AV_SRC_INCLUDED
384         if (btc_av_cb.tle_av_open_on_rc) {
385             osi_alarm_free(btc_av_cb.tle_av_open_on_rc);
386             btc_av_cb.tle_av_open_on_rc = NULL;
387         }
388 #endif /* BTC_AV_SRC_INCLUDED */
389         btc_rc_handler(event, p_data);
390         break;
391 
392     default:
393         BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
394                  dump_av_sm_event_name(event));
395         return FALSE;
396     }
397 
398     return TRUE;
399 }
400 /*****************************************************************************
401 **
402 ** Function        btc_av_state_opening_handler
403 **
404 ** Description     Intermediate state managing events during establishment
405 **                 of avdtp channel
406 **
407 ** Returns         TRUE if event was processed, FALSE otherwise
408 **
409 *******************************************************************************/
410 
btc_av_state_opening_handler(btc_sm_event_t event,void * p_data)411 static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
412 {
413     BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
414               dump_av_sm_event_name(event), btc_av_cb.flags);
415 
416     switch (event) {
417     case BTC_SM_ENTER_EVT:
418         /* inform the application that we are entering connecting state */
419         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btc_av_cb.peer_bda), 0);
420         break;
421 
422     case BTC_SM_EXIT_EVT:
423         break;
424 
425     case BTA_AV_REJECT_EVT:
426         BTC_TRACE_WARNING(" Received  BTA_AV_REJECT_EVT \n");
427         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0);
428         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
429         break;
430 
431     case BTA_AV_OPEN_EVT: {
432         tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
433         esp_a2d_connection_state_t conn_stat;
434         btc_sm_state_t av_state;
435         BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status,
436                         p_bta_data->open.edr, p_bta_data->open.sep);
437 
438         if (p_bta_data->open.status == BTA_AV_SUCCESS) {
439             btc_av_cb.edr = p_bta_data->open.edr;
440             btc_av_cb.peer_sep = p_bta_data->open.sep;
441 
442             conn_stat = ESP_A2D_CONNECTION_STATE_CONNECTED;
443             av_state = BTC_AV_STATE_OPENED;
444         } else {
445             BTC_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n", p_bta_data->open.status);
446 
447             conn_stat = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
448             av_state = BTC_AV_STATE_IDLE;
449         }
450         /* inform the application of the event */
451         btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), 0);
452         /* change state to open/idle based on the status */
453         btc_sm_change_state(btc_av_cb.sm_handle, av_state);
454 
455         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
456             /* if queued PLAY command,  send it now */
457             /* necessary to add this?
458             btc_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
459                                              (p_bta_data->open.status == BTA_AV_SUCCESS));
460             */
461         } else if (btc_av_cb.peer_sep == AVDT_TSEP_SRC &&
462                    (p_bta_data->open.status == BTA_AV_SUCCESS)) {
463             /* Bring up AVRCP connection too if AVRC Initialized */
464             if(g_av_with_rc) {
465                 BTA_AvOpenRc(btc_av_cb.bta_handle);
466             } else {
467                 BTC_TRACE_WARNING("AVRC not Init, not using it.");
468             }
469         }
470         btc_queue_advance();
471     } break;
472 
473     case BTC_AV_SINK_CONFIG_REQ_EVT: {
474         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
475             esp_a2d_cb_param_t param;
476             memcpy(param.audio_cfg.remote_bda, &btc_av_cb.peer_bda, sizeof(esp_bd_addr_t));
477             memcpy(&param.audio_cfg.mcc, p_data, sizeof(esp_a2d_mcc_t));
478             btc_a2d_cb_to_app(ESP_A2D_AUDIO_CFG_EVT, &param);
479         }
480     } break;
481 
482     case BTC_AV_CONNECT_REQ_EVT:
483         // Check for device, if same device which moved to opening then ignore callback
484         if (memcmp ((bt_bdaddr_t *)p_data, &(btc_av_cb.peer_bda),
485                     sizeof(btc_av_cb.peer_bda)) == 0) {
486             BTC_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req\n", __func__);
487             btc_queue_advance();
488             break;
489         } else {
490             BTC_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__);
491             btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0);
492             btc_queue_advance();
493             break;
494         }
495 
496     case BTA_AV_PENDING_EVT:
497         // Check for device, if same device which moved to opening then ignore callback
498         if (memcmp (((tBTA_AV *)p_data)->pend.bd_addr, &(btc_av_cb.peer_bda),
499                     sizeof(btc_av_cb.peer_bda)) == 0) {
500             BTC_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Pending Req\n", __func__);
501             break;
502         } else {
503             BTC_TRACE_DEBUG("%s: Moved from idle by outgoing Connection request\n", __func__);
504             BTA_AvDisconnect(((tBTA_AV *)p_data)->pend.bd_addr);
505             break;
506         }
507 
508     CHECK_RC_EVENT(event, p_data);
509 
510     default:
511         BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
512         return FALSE;
513     }
514     return TRUE;
515 }
516 
517 
518 /*****************************************************************************
519 **
520 ** Function        btc_av_state_closing_handler
521 **
522 ** Description     Intermediate state managing events during closing
523 **                 of avdtp channel
524 **
525 ** Returns         TRUE if event was processed, FALSE otherwise
526 **
527 *******************************************************************************/
528 
btc_av_state_closing_handler(btc_sm_event_t event,void * p_data)529 static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
530 {
531     BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
532               dump_av_sm_event_name(event), btc_av_cb.flags);
533 
534     switch (event) {
535     case BTC_SM_ENTER_EVT:
536 #if BTC_AV_SRC_INCLUDED
537         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
538             /* immediately stop transmission of frames */
539             btc_a2dp_source_set_tx_flush(TRUE);
540             /* wait for audioflinger to stop a2dp */
541         }
542 #endif /* BTC_AV_SRC_INCLUDED */
543 #if BTC_AV_SINK_INCLUDED
544         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
545             btc_a2dp_sink_set_rx_flush(TRUE);
546         }
547 #endif /* BTC_AV_SINK_INCLUDED */
548         break;
549 
550     case BTA_AV_STOP_EVT:
551     case BTC_AV_STOP_STREAM_REQ_EVT:
552 #if BTC_AV_SRC_INCLUDED
553         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
554             /* immediately flush any pending tx frames while suspend is pending */
555             btc_a2dp_source_set_tx_flush(TRUE);
556         }
557 #endif /* BTC_AV_SRC_INCLUDED */
558 #if BTC_AV_SINK_INCLUDED
559         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
560             btc_a2dp_sink_set_rx_flush(TRUE);
561         }
562 #endif /* BTC_AV_SINK_INCLUDED */
563         btc_a2dp_on_stopped(NULL);
564         break;
565 
566     case BTC_SM_EXIT_EVT:
567         break;
568 
569     case BTA_AV_CLOSE_EVT: {
570         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
571         /* inform the application that we are disconnecting */
572         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn);
573         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
574         break;
575     }
576 
577     /* Handle the RC_CLOSE event for the cleanup */
578     case BTA_AV_RC_CLOSE_EVT:
579         btc_rc_handler(event, (tBTA_AV *)p_data);
580         break;
581 
582     default:
583         BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
584         return FALSE;
585     }
586     return TRUE;
587 }
588 
589 /*****************************************************************************
590 **
591 ** Function     btc_av_state_opened_handler
592 **
593 ** Description  Handles AV events while AVDTP is in OPEN state
594 **
595 ** Returns      TRUE if event was processed, FALSE otherwise
596 **
597 *******************************************************************************/
btc_av_state_opened_handler(btc_sm_event_t event,void * p_data)598 static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
599 {
600     tBTA_AV *p_av = (tBTA_AV *)p_data;
601 
602     BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
603               dump_av_sm_event_name(event), btc_av_cb.flags);
604 
605     if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btc_av_cb.flags & BTC_AV_FLAG_REMOTE_SUSPEND) &&
606             (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY) ) {
607         BTC_TRACE_DEBUG("%s: Resetting remote suspend flag on RC PLAY\n", __FUNCTION__);
608         btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND;
609     }
610 
611     switch (event) {
612     case BTC_SM_ENTER_EVT:
613         btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_STOP;
614         btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START;
615         break;
616 
617     case BTC_SM_EXIT_EVT:
618         btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START;
619         break;
620 
621     case BTC_AV_START_STREAM_REQ_EVT:
622 #if BTC_AV_SRC_INCLUDED
623         if (btc_av_cb.peer_sep != AVDT_TSEP_SRC) {
624             btc_a2dp_source_setup_codec();
625         }
626 #endif  /* BTC_AV_SRC_INCLUDED */
627         BTA_AvStart();
628         btc_av_cb.flags |= BTC_AV_FLAG_PENDING_START;
629         break;
630 
631     case BTA_AV_START_EVT: {
632         BTC_TRACE_DEBUG("BTA_AV_START_EVT status %d, suspending %d, init %d\n",
633                  p_av->start.status, p_av->start.suspending, p_av->start.initiator);
634 
635         if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE)) {
636             return TRUE;
637         }
638 #if BTC_AV_SRC_INCLUDED
639         /* if remote tries to start a2dp when DUT is a2dp source
640          * then suspend. In case a2dp is sink and call is active
641          * then disconnect the AVDTP channel
642          */
643         if (!(btc_av_cb.flags & BTC_AV_FLAG_PENDING_START)) {
644             if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
645                 BTC_TRACE_DEBUG("%s: trigger suspend as remote initiated!!", __FUNCTION__);
646                 btc_dispatch_sm_event(BTC_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
647             }
648         }
649         /*  In case peer is A2DP SRC we do not want to ack commands on UIPC*/
650         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
651             if (btc_a2dp_on_started(&p_av->start,
652                                     ((btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) != 0))) {
653                 /* only clear pending flag after acknowledgement */
654                 btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START;
655             }
656         }
657 #endif /* BTC_AV_SRC_INCLUDED */
658         /* remain in open state if status failed */
659         if (p_av->start.status != BTA_AV_SUCCESS) {
660             return FALSE;
661         }
662 #if BTC_AV_SINK_INCLUDED
663         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
664             btc_a2dp_sink_set_rx_flush(FALSE); /*  remove flush state, ready for streaming*/
665         }
666 #endif /* BTC_AV_SINK_INCLUDED */
667 #if BTC_AV_SRC_INCLUDED
668         /* change state to started, send acknowledgement if start is pending */
669         if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
670             if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
671                 btc_a2dp_on_started(NULL, TRUE);
672             }
673             /* pending start flag will be cleared when exit current state */
674         }
675 #endif /* BTC_AV_SRC_INCLUDED */
676         /* wait for audio path to open */
677         btc_a2dp_control_datapath_ctrl(BTC_AV_DATAPATH_OPEN_EVT);
678 
679         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_STARTED);
680 
681     } break;
682 
683     case BTC_AV_DISCONNECT_REQ_EVT:
684         BTA_AvClose(btc_av_cb.bta_handle);
685         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC && g_av_with_rc == true) {
686             BTA_AvCloseRc(btc_av_cb.bta_handle);
687         }
688 
689         /* inform the application that we are disconnecting */
690         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
691         break;
692 
693     case BTA_AV_CLOSE_EVT: {
694         /* avdtp link is closed */
695         btc_a2dp_on_stopped(NULL);
696         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
697         /* inform the application that we are disconnected */
698         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
699                                     close->disc_rsn);
700 
701         if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
702             btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
703             /* pending start flag will be cleared when exit current state */
704         }
705 
706         /* change state to idle, send acknowledgement if start is pending */
707         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
708 
709         if (g_a2dp_source_ongoing_deinit) {
710             clean_up(BTA_A2DP_SOURCE_SERVICE_ID);
711         } else if (g_a2dp_sink_ongoing_deinit) {
712             clean_up(BTA_A2DP_SINK_SERVICE_ID);
713         }
714         break;
715     }
716 
717     case BTA_AV_RECONFIG_EVT:
718         if ((btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) &&
719                 (p_av->reconfig.status == BTA_AV_SUCCESS)) {
720             BTC_TRACE_WARNING("reconfig done BTA_AVstart()\n");
721             BTA_AvStart();
722         } else if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
723             btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START;
724             btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
725         }
726         break;
727 
728     case BTC_AV_CONNECT_REQ_EVT:
729         if (memcmp (&((btc_av_connect_req_t *)p_data)->target_bda, &(btc_av_cb.peer_bda),
730                     sizeof(btc_av_cb.peer_bda)) == 0) {
731             BTC_TRACE_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__);
732         } else {
733             BTC_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__);
734             btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED,
735                                         (bt_bdaddr_t *)p_data, ESP_A2D_DISC_RSN_NORMAL);
736         }
737         btc_queue_advance();
738         break;
739 
740     CHECK_RC_EVENT(event, p_data);
741 
742     default:
743         BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
744                  dump_av_sm_event_name(event));
745         return FALSE;
746 
747     }
748     return TRUE;
749 }
750 
751 /*****************************************************************************
752 **
753 ** Function     btc_av_state_started_handler
754 **
755 ** Description  Handles AV events while A2DP stream is started
756 **
757 ** Returns      TRUE if event was processed, FALSE otherwise
758 **
759 *******************************************************************************/
760 
btc_av_state_started_handler(btc_sm_event_t event,void * p_data)761 static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
762 {
763     tBTA_AV *p_av = (tBTA_AV *)p_data;
764 
765     BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
766               dump_av_sm_event_name(event), btc_av_cb.flags);
767 
768     switch (event) {
769     case BTC_SM_ENTER_EVT:
770 
771         /* we are again in started state, clear any remote suspend flags */
772         btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND;
773 
774         btc_report_audio_state(ESP_A2D_AUDIO_STATE_STARTED, &(btc_av_cb.peer_bda));
775 
776         /* increase the a2dp consumer task priority temporarily when start
777         ** audio playing, to avoid overflow the audio packet queue. */
778         // adjust_priority_a2dp(TRUE);
779 
780         break;
781 
782     case BTC_SM_EXIT_EVT:
783         /* restore the a2dp consumer task priority when stop audio playing. */
784         // adjust_priority_a2dp(FALSE);
785 
786         break;
787 
788     case BTC_AV_START_STREAM_REQ_EVT:
789 #if BTC_AV_SRC_INCLUDED
790         /* we were remotely started, just ack back the local request */
791         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
792             btc_a2dp_on_started(NULL, TRUE);
793         }
794 #endif /* BTC_AV_SRC_INCLUDED */
795         break;
796 
797     /* fixme -- use suspend = true always to work around issue with BTA AV */
798     case BTC_AV_STOP_STREAM_REQ_EVT:
799     case BTC_AV_SUSPEND_STREAM_REQ_EVT:
800 
801         /* set pending flag to ensure btc task is not trying to restart
802            stream while suspend is in progress */
803         btc_av_cb.flags |= BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
804 
805         /* if we were remotely suspended but suspend locally, local suspend
806            always overrides */
807         btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND;
808 #if BTC_AV_SRC_INCLUDED
809         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
810             /* immediately stop transmission of frames while suspend is pending */
811             btc_a2dp_source_set_tx_flush(TRUE);
812         }
813 #endif /* BTC_AV_SRC_INCLUDED */
814 #if BTC_AV_SINK_INCLUDED
815         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
816             btc_a2dp_sink_set_rx_flush(TRUE);
817             btc_a2dp_on_stopped(NULL);
818         }
819 #endif /* BTC_AV_SINK_INCLUDED */
820         BTA_AvStop(TRUE);
821         break;
822 
823     case BTC_AV_DISCONNECT_REQ_EVT:
824 
825         /* request avdtp to close */
826         BTA_AvClose(btc_av_cb.bta_handle);
827         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC && g_av_with_rc == true) {
828             BTA_AvCloseRc(btc_av_cb.bta_handle);
829         }
830 
831         /* inform the application that we are disconnecting */
832         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
833 
834         /* wait in closing state until fully closed */
835         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
836         break;
837 
838     case BTA_AV_SUSPEND_EVT:
839 
840         BTC_TRACE_DEBUG("BTA_AV_SUSPEND_EVT status %d, init %d\n",
841                  p_av->suspend.status, p_av->suspend.initiator);
842 
843         /* a2dp suspended, stop media task until resumed */
844         btc_a2dp_on_suspended(&p_av->suspend);
845 
846         /* if not successful, remain in current state */
847         if (p_av->suspend.status != BTA_AV_SUCCESS) {
848             btc_av_cb.flags &= ~BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
849 #if BTC_AV_SRC_INCLUDED
850             if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
851                 /* suspend failed, reset back tx flush state */
852                 btc_a2dp_source_set_tx_flush(FALSE);
853             }
854 #endif /* BTC_AV_SRC_INCLUDED */
855             return FALSE;
856         }
857 
858         if (p_av->suspend.initiator != TRUE) {
859             /* remote suspend, notify HAL and await audioflinger to
860                suspend/stop stream */
861 
862             /* set remote suspend flag to block media task from restarting
863                stream only if we did not already initiate a local suspend */
864             if ((btc_av_cb.flags & BTC_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0) {
865                 btc_av_cb.flags |= BTC_AV_FLAG_REMOTE_SUSPEND;
866             }
867 
868             btc_report_audio_state(ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND, &(btc_av_cb.peer_bda));
869         } else {
870             btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
871         }
872 
873         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
874 
875         /* suspend completed and state changed, clear pending status */
876         btc_av_cb.flags &= ~BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
877         break;
878 
879     case BTA_AV_STOP_EVT:
880 
881         btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
882         btc_a2dp_on_stopped(&p_av->suspend);
883 
884         btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
885 
886         /* if stop was successful, change state to open */
887         if (p_av->suspend.status == BTA_AV_SUCCESS) {
888             btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
889         }
890         break;
891 
892     case BTA_AV_CLOSE_EVT:
893         btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
894 
895         /* avdtp link is closed */
896         btc_a2dp_on_stopped(NULL);
897         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
898         /* inform the application that we are disconnected */
899         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
900                                     close->disc_rsn);
901         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
902 
903         if (g_a2dp_source_ongoing_deinit) {
904             clean_up(BTA_A2DP_SOURCE_SERVICE_ID);
905         } else if (g_a2dp_sink_ongoing_deinit) {
906             clean_up(BTA_A2DP_SINK_SERVICE_ID);
907         }
908         break;
909 
910     CHECK_RC_EVENT(event, p_data);
911 
912     default:
913         BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
914                  dump_av_sm_event_name(event));
915         return FALSE;
916 
917     }
918     return TRUE;
919 }
920 
921 /*****************************************************************************
922 **  Local event handlers
923 ******************************************************************************/
924 
btc_av_event_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)925 void btc_av_event_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
926 {
927     tBTA_AV *av_src = (tBTA_AV *)p_src;
928     tBTA_AV *av_dest = (tBTA_AV *)p_dest;
929 
930     // First copy the structure
931     memcpy(p_dest, p_src, sizeof(tBTA_AV));
932 
933     switch (msg->act) {
934     case BTA_AV_META_MSG_EVT:
935         if (av_src->meta_msg.p_data && av_src->meta_msg.len) {
936             av_dest->meta_msg.p_data = osi_calloc(av_src->meta_msg.len);
937             assert(av_dest->meta_msg.p_data);
938             memcpy(av_dest->meta_msg.p_data, av_src->meta_msg.p_data, av_src->meta_msg.len);
939         }
940 
941         if (av_src->meta_msg.p_msg) {
942             av_dest->meta_msg.p_msg = osi_calloc(sizeof(tAVRC_MSG));
943             assert(av_dest->meta_msg.p_msg);
944             memcpy(av_dest->meta_msg.p_msg, av_src->meta_msg.p_msg, sizeof(tAVRC_MSG));
945 
946             if (av_src->meta_msg.p_msg->vendor.p_vendor_data &&
947                     av_src->meta_msg.p_msg->vendor.vendor_len) {
948                 av_dest->meta_msg.p_msg->vendor.p_vendor_data = osi_calloc(
949                             av_src->meta_msg.p_msg->vendor.vendor_len);
950                 assert(av_dest->meta_msg.p_msg->vendor.p_vendor_data);
951                 memcpy(av_dest->meta_msg.p_msg->vendor.p_vendor_data,
952                        av_src->meta_msg.p_msg->vendor.p_vendor_data,
953                        av_src->meta_msg.p_msg->vendor.vendor_len);
954             }
955         }
956         break;
957 
958     default:
959         break;
960     }
961 }
962 
btc_av_event_free_data(btc_sm_event_t event,void * p_data)963 static void btc_av_event_free_data(btc_sm_event_t event, void *p_data)
964 {
965     switch (event) {
966     case BTA_AV_META_MSG_EVT: {
967         tBTA_AV *av = (tBTA_AV *)p_data;
968         if (av->meta_msg.p_data) {
969             osi_free(av->meta_msg.p_data);
970         }
971 
972         if (av->meta_msg.p_msg) {
973             if (av->meta_msg.p_msg->vendor.p_vendor_data) {
974                 osi_free(av->meta_msg.p_msg->vendor.p_vendor_data);
975             }
976             osi_free(av->meta_msg.p_msg);
977         }
978     }
979     break;
980 
981     default:
982         break;
983     }
984 }
985 
986 /*******************************************************************************
987 **
988 ** Function         btc_av_init
989 **
990 ** Description      Initializes btc AV if not already done
991 **
992 ** Returns          bt_status_t
993 **
994 *******************************************************************************/
btc_av_init(int service_id)995 static bt_status_t btc_av_init(int service_id)
996 {
997 
998 #if A2D_DYNAMIC_MEMORY == TRUE
999     if (btc_av_cb_ptr != NULL) {
1000         return BT_STATUS_FAIL;
1001     }
1002 
1003     if ((btc_av_cb_ptr = (btc_av_cb_t *)osi_malloc(sizeof(btc_av_cb_t))) == NULL) {
1004         APPL_TRACE_ERROR("%s malloc failed!", __func__);
1005         return BT_STATUS_NOMEM;
1006     }
1007     memset((void *)btc_av_cb_ptr, 0, sizeof(btc_av_cb_t));
1008 #endif
1009 
1010     if (btc_av_cb.sm_handle == NULL) {
1011         btc_av_cb.service_id = service_id;
1012         bool stat = false;
1013         if (service_id == BTA_A2DP_SOURCE_SERVICE_ID) {
1014 #if BTC_AV_SRC_INCLUDED
1015             stat = btc_a2dp_source_startup();
1016 #endif
1017         } else if (service_id == BTA_A2DP_SINK_SERVICE_ID) {
1018 #if BTC_AV_SINK_INCLUDED
1019             stat = btc_a2dp_sink_startup();
1020 #endif
1021         }
1022 
1023         if (!stat) {
1024 #if A2D_DYNAMIC_MEMORY == TRUE
1025             osi_free(btc_av_cb_ptr);
1026             btc_av_cb_ptr = NULL;
1027 #endif
1028             g_a2dp_on_init = false;
1029             g_a2dp_on_deinit = true;
1030             g_a2dp_source_ongoing_deinit = false;
1031             g_a2dp_sink_ongoing_deinit = false;
1032             goto av_init_fail;
1033         }
1034 
1035         /* Also initialize the AV state machine */
1036         btc_av_cb.sm_handle =
1037             btc_sm_init((const btc_sm_handler_t *)btc_av_state_handlers, BTC_AV_STATE_IDLE);
1038 
1039         if (service_id == BTA_A2DP_SINK_SERVICE_ID) {
1040             btc_dm_enable_service(BTA_A2DP_SINK_SERVICE_ID);
1041         } else {
1042             btc_dm_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
1043         }
1044 
1045         btc_a2dp_on_init();
1046         g_a2dp_on_init = true;
1047         g_a2dp_on_deinit = false;
1048         g_a2dp_source_ongoing_deinit = false;
1049         g_a2dp_sink_ongoing_deinit = false;
1050 
1051         esp_a2d_cb_param_t param;
1052         memset(&param, 0, sizeof(esp_a2d_cb_param_t));
1053         param.a2d_prof_stat.init_state = ESP_A2D_INIT_SUCCESS;
1054         btc_a2d_cb_to_app(ESP_A2D_PROF_STATE_EVT, &param);
1055         return BT_STATUS_SUCCESS;
1056     }
1057 
1058 av_init_fail:
1059     return BT_STATUS_FAIL;
1060 }
1061 
1062 /*******************************************************************************
1063 **
1064 ** Function         connect
1065 **
1066 ** Description      Establishes the AV signalling channel with the remote headset
1067 **
1068 ** Returns          bt_status_t
1069 **
1070 *******************************************************************************/
1071 
connect_int(bt_bdaddr_t * bd_addr,uint16_t uuid)1072 static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
1073 {
1074     btc_av_connect_req_t connect_req;
1075     memcpy(&connect_req.target_bda, bd_addr, sizeof(bt_bdaddr_t));
1076     connect_req.uuid = uuid;
1077     BTC_TRACE_DEBUG("%s\n", __FUNCTION__);
1078 
1079     btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_CONNECT_REQ_EVT, (char *)&connect_req);
1080 
1081     return BT_STATUS_SUCCESS;
1082 }
1083 
1084 /*******************************************************************************
1085 **
1086 ** Function         clean_up
1087 **
1088 ** Description      Shuts down the AV interface and does the cleanup
1089 **
1090 ** Returns          None
1091 **
1092 *******************************************************************************/
clean_up(int service_id)1093 static void clean_up(int service_id)
1094 {
1095     BTC_TRACE_DEBUG("%s\n", __FUNCTION__);
1096 
1097     if (service_id == BTA_A2DP_SOURCE_SERVICE_ID) {
1098 #if BTC_AV_SRC_INCLUDED
1099         btc_a2dp_source_shutdown();
1100         if (btc_av_cb.tle_av_open_on_rc) {
1101             osi_alarm_free(btc_av_cb.tle_av_open_on_rc);
1102             btc_av_cb.tle_av_open_on_rc = NULL;
1103         }
1104 #endif /* BTC_AV_SRC_INCLUDED */
1105         btc_dm_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
1106     }
1107 
1108     if (service_id == BTA_A2DP_SINK_SERVICE_ID) {
1109 #if BTC_AV_SINK_INCLUDED
1110         btc_a2dp_sink_shutdown();
1111 #endif /* BTC_AV_SINK_INCLUDED */
1112         btc_dm_disable_service(BTA_A2DP_SINK_SERVICE_ID);
1113     }
1114 
1115     /* Also shut down the AV state machine */
1116     btc_sm_shutdown(btc_av_cb.sm_handle);
1117     btc_av_cb.sm_handle = NULL;
1118 
1119 #if A2D_DYNAMIC_MEMORY == TRUE
1120     osi_free(btc_av_cb_ptr);
1121     btc_av_cb_ptr = NULL;
1122 #endif
1123     g_a2dp_on_init = false;
1124     g_a2dp_on_deinit = true;
1125     g_a2dp_source_ongoing_deinit = false;
1126     g_a2dp_sink_ongoing_deinit = false;
1127 
1128     esp_a2d_cb_param_t param;
1129     memset(&param, 0, sizeof(esp_a2d_cb_param_t));
1130     param.a2d_prof_stat.init_state = ESP_A2D_DEINIT_SUCCESS;
1131     btc_a2d_cb_to_app(ESP_A2D_PROF_STATE_EVT, &param);
1132 }
1133 
1134 /*******************************************************************************
1135 **
1136 ** Function         btc_av_get_sm_handle
1137 **
1138 ** Description      Fetches current av SM handle
1139 **
1140 ** Returns          None
1141 **
1142 *******************************************************************************/
1143 
btc_av_get_sm_handle(void)1144 btc_sm_handle_t btc_av_get_sm_handle(void)
1145 {
1146     return btc_av_cb.sm_handle;
1147 }
1148 
1149 /*******************************************************************************
1150 **
1151 ** Function         btc_av_stream_ready
1152 **
1153 ** Description      Checks whether AV is ready for starting a stream
1154 **
1155 ** Returns          None
1156 **
1157 *******************************************************************************/
1158 
btc_av_stream_ready(void)1159 BOOLEAN btc_av_stream_ready(void)
1160 {
1161     btc_sm_state_t state = btc_sm_get_state(btc_av_cb.sm_handle);
1162 
1163     BTC_TRACE_DEBUG("btc_av_stream_ready : sm hdl %d, state %d, flags %x\n",
1164               (int)btc_av_cb.sm_handle, state, btc_av_cb.flags);
1165 
1166     /* check if we are remotely suspended or stop is pending */
1167     if (btc_av_cb.flags & (BTC_AV_FLAG_REMOTE_SUSPEND | BTC_AV_FLAG_PENDING_STOP)) {
1168         return FALSE;
1169     }
1170 
1171     return (state == BTC_AV_STATE_OPENED);
1172 }
1173 
1174 /*******************************************************************************
1175 **
1176 ** Function         btc_av_stream_started_ready
1177 **
1178 ** Description      Checks whether AV ready for media start in streaming state
1179 **
1180 ** Returns          None
1181 **
1182 *******************************************************************************/
1183 
btc_av_stream_started_ready(void)1184 BOOLEAN btc_av_stream_started_ready(void)
1185 {
1186     btc_sm_state_t state = btc_sm_get_state(btc_av_cb.sm_handle);
1187 
1188     BTC_TRACE_DEBUG("btc_av_stream_started : sm hdl %d, state %d, flags %x\n",
1189               (int)btc_av_cb.sm_handle, state, btc_av_cb.flags);
1190 
1191     /* disallow media task to start if we have pending actions */
1192     if (btc_av_cb.flags & (BTC_AV_FLAG_LOCAL_SUSPEND_PENDING | BTC_AV_FLAG_REMOTE_SUSPEND
1193                            | BTC_AV_FLAG_PENDING_STOP)) {
1194         return FALSE;
1195     }
1196 
1197     return (state == BTC_AV_STATE_STARTED);
1198 }
1199 
1200 /*******************************************************************************
1201 **
1202 ** Function         btc_dispatch_sm_event
1203 **
1204 ** Description      Send event to AV statemachine
1205 **
1206 ** Returns          None
1207 **
1208 *******************************************************************************/
1209 
1210 /* used to pass events to AV statemachine from other tasks */
btc_dispatch_sm_event(btc_av_sm_event_t event,void * p_data,int len)1211 void btc_dispatch_sm_event(btc_av_sm_event_t event, void *p_data, int len)
1212 {
1213     btc_msg_t msg;
1214     msg.sig = BTC_SIG_API_CALL;
1215     msg.pid = BTC_PID_A2DP;
1216     msg.act = event;
1217     btc_transfer_context(&msg, p_data, len, NULL);
1218 }
1219 
bte_av_callback(tBTA_AV_EVT event,tBTA_AV * p_data)1220 static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data)
1221 {
1222     bt_status_t stat;
1223     btc_msg_t msg;
1224 
1225     msg.sig = BTC_SIG_API_CB;
1226     msg.pid = BTC_PID_A2DP;
1227     msg.act = (uint8_t) event;
1228     stat = btc_transfer_context(&msg, p_data, sizeof(tBTA_AV), btc_av_event_deep_copy);
1229 
1230     if (stat) {
1231         BTC_TRACE_ERROR("%s transfer failed\n", __func__);
1232     }
1233 }
1234 
1235 #if BTC_AV_SINK_INCLUDED
bte_av_media_callback(tBTA_AV_EVT event,tBTA_AV_MEDIA * p_data)1236 static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
1237 {
1238     btc_sm_state_t state;
1239     UINT8 que_len;
1240     tA2D_STATUS a2d_status;
1241     tA2D_SBC_CIE sbc_cie;
1242 
1243     if (event == BTA_AV_MEDIA_DATA_EVT) { /* Switch to BTC_MEDIA context */
1244         state = btc_sm_get_state(btc_av_cb.sm_handle);
1245         if ( (state == BTC_AV_STATE_STARTED) || /* send SBC packets only in Started State */
1246                 (state == BTC_AV_STATE_OPENED) ) {
1247             que_len = btc_a2dp_sink_enque_buf((BT_HDR *)p_data);
1248             BTC_TRACE_DEBUG(" Packets in Que %d\n", que_len);
1249         } else {
1250             return;
1251         }
1252     }
1253 
1254     if (event == BTA_AV_MEDIA_SINK_CFG_EVT) {
1255         /* send a command to BT Media Task */
1256         btc_a2dp_sink_reset_decoder((UINT8 *)p_data);
1257 
1258         /* currently only supportes SBC */
1259         a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE);
1260         if (a2d_status == A2D_SUCCESS) {
1261             btc_msg_t msg;
1262             btc_av_args_t arg;
1263 
1264             msg.sig = BTC_SIG_API_CB;
1265             msg.pid = BTC_PID_A2DP;
1266             msg.act = BTC_AV_SINK_CONFIG_REQ_EVT;
1267 
1268             memset(&arg, 0, sizeof(btc_av_args_t));
1269             arg.mcc.type = ESP_A2D_MCT_SBC;
1270             memcpy(arg.mcc.cie.sbc, (uint8_t *)p_data + 3, ESP_A2D_CIE_LEN_SBC);
1271             btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL);
1272         } else {
1273             BTC_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
1274         }
1275     }
1276     UNUSED(que_len);
1277 }
1278 #else
bte_av_media_callback(tBTA_AV_EVT event,tBTA_AV_MEDIA * p_data)1279 static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
1280 {
1281     UNUSED(event);
1282     UNUSED(p_data);
1283     BTC_TRACE_WARNING("%s : event %u\n", __func__, event);
1284 }
1285 #endif
1286 
1287 /*******************************************************************************
1288 **
1289 ** Function         btc_av_execute_service
1290 **
1291 ** Description      Initializes/Shuts down the service
1292 **
1293 ** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1294 **
1295 *******************************************************************************/
btc_av_execute_service(BOOLEAN b_enable,UINT8 tsep)1296 bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
1297 {
1298     if (b_enable) {
1299         /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
1300          * handle this request in order to allow incoming connections to succeed.
1301          * We need to put this back once support for this is added */
1302 
1303         /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
1304          * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
1305          * be initiated by the app/audioflinger layers */
1306         if (g_av_with_rc) {
1307             BTC_TRACE_WARNING("A2DP Enable with AVRC")
1308             BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD |
1309                         BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
1310                         BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL,
1311                         bte_av_callback);
1312             BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, &bta_avrc_cos, tsep);
1313         } else {
1314             BTC_TRACE_WARNING("A2DP Enable without AVRC")
1315             BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD, bte_av_callback);
1316             BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, NULL, tsep);
1317         }
1318     } else {
1319         BTA_AvDeregister(btc_av_cb.bta_handle);
1320         BTA_AvDisable();
1321     }
1322     return BT_STATUS_SUCCESS;
1323 }
1324 
1325 /*******************************************************************************
1326 **
1327 ** Function         btc_av_source_execute_service
1328 **
1329 ** Description      Initializes/Shuts down the A2DP source service
1330 **
1331 ** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1332 **
1333 *******************************************************************************/
btc_av_source_execute_service(BOOLEAN b_enable)1334 bt_status_t btc_av_source_execute_service(BOOLEAN b_enable)
1335 {
1336     return btc_av_execute_service(b_enable, AVDT_TSEP_SRC);
1337 }
1338 
1339 /*******************************************************************************
1340 **
1341 ** Function         btc_av_sink_execute_service
1342 **
1343 ** Description      Initializes/Shuts down the service
1344 **
1345 ** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1346 **
1347 *******************************************************************************/
btc_av_sink_execute_service(BOOLEAN b_enable)1348 bt_status_t btc_av_sink_execute_service(BOOLEAN b_enable)
1349 {
1350     bt_status_t ret = btc_av_execute_service(b_enable, AVDT_TSEP_SNK);
1351     if (ret != BT_STATUS_SUCCESS) {
1352         return ret;
1353     }
1354 #if (BTA_AV_SINK_INCLUDED == TRUE)
1355     BTA_AvEnable_Sink(b_enable);
1356 #endif
1357     return BT_STATUS_SUCCESS;
1358 }
1359 
1360 /*******************************************************************************
1361 **
1362 ** Function         btc_av_is_connected
1363 **
1364 ** Description      Checks if av has a connected sink
1365 **
1366 ** Returns          BOOLEAN
1367 **
1368 *******************************************************************************/
btc_av_is_connected(void)1369 BOOLEAN btc_av_is_connected(void)
1370 {
1371     btc_sm_state_t state = btc_sm_get_state(btc_av_cb.sm_handle);
1372     return ((state == BTC_AV_STATE_OPENED) || (state ==  BTC_AV_STATE_STARTED));
1373 }
1374 
1375 /*******************************************************************************
1376  *
1377  * Function         btc_av_get_service_id
1378  *
1379  * Description      Get the current AV service ID.
1380  *
1381  * Returns          The stream endpoint type: either BTA_A2DP_SOURCE_SERVICE_ID or
1382  *                  BTA_A2DP_SINK_SERVICE_ID.
1383  *
1384  ******************************************************************************/
btc_av_get_service_id(void)1385 uint8_t btc_av_get_service_id(void)
1386 {
1387     return btc_av_cb.service_id;
1388 }
1389 
1390 /*******************************************************************************
1391  *
1392  * Function         btc_av_get_peer_sep
1393  *
1394  * Description      Get the stream endpoint type.
1395  *
1396  * Returns          The stream endpoint type: either AVDT_TSEP_SRC or
1397  *                  AVDT_TSEP_SNK.
1398  *
1399  ******************************************************************************/
1400 
btc_av_get_peer_sep(void)1401 uint8_t btc_av_get_peer_sep(void)
1402 {
1403     return btc_av_cb.peer_sep;
1404 }
1405 /*******************************************************************************
1406 **
1407 ** Function         btc_av_is_peer_edr
1408 **
1409 ** Description      Check if the connected a2dp device supports
1410 **                  EDR or not. Only when connected this function
1411 **                  will accurately provide a true capability of
1412 **                  remote peer. If not connected it will always be false.
1413 **
1414 ** Returns          TRUE if remote device is capable of EDR
1415 **
1416 *******************************************************************************/
btc_av_is_peer_edr(void)1417 BOOLEAN btc_av_is_peer_edr(void)
1418 {
1419     BTC_ASSERTC(btc_av_is_connected(), "No active a2dp connection\n", 0);
1420 
1421     if (btc_av_cb.edr) {
1422         return TRUE;
1423     } else {
1424         return FALSE;
1425     }
1426 }
1427 
1428 /******************************************************************************
1429 **
1430 ** Function        btc_av_clear_remote_suspend_flag
1431 **
1432 ** Description     Clears btc_av_cb.flags if BTC_AV_FLAG_REMOTE_SUSPEND is set
1433 **
1434 ** Returns          void
1435 ******************************************************************************/
btc_av_clear_remote_suspend_flag(void)1436 void btc_av_clear_remote_suspend_flag(void)
1437 {
1438     BTC_TRACE_DEBUG("%s: flag :%x\n", __func__, btc_av_cb.flags);
1439     btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND;
1440 }
1441 
btc_a2dp_call_handler(btc_msg_t * msg)1442 void btc_a2dp_call_handler(btc_msg_t *msg)
1443 {
1444     btc_av_args_t *arg = (btc_av_args_t *)(msg->arg);
1445     switch (msg->act) {
1446 #if BTC_AV_SINK_INCLUDED
1447     case BTC_AV_SINK_CONFIG_REQ_EVT: {
1448         btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (void *)(msg->arg));
1449         break;
1450     }
1451     case BTC_AV_SINK_API_INIT_EVT: {
1452         btc_a2d_sink_init();
1453         // todo: callback to application
1454         break;
1455     }
1456     case BTC_AV_SINK_API_DEINIT_EVT: {
1457         btc_a2d_sink_deinit();
1458         // todo: callback to application
1459         break;
1460     }
1461     case BTC_AV_SINK_API_CONNECT_EVT: {
1462         btc_a2d_sink_connect(&arg->connect);
1463         // todo: callback to application
1464         break;
1465     }
1466     case BTC_AV_SINK_API_DISCONNECT_EVT: {
1467         CHECK_BTAV_INIT();
1468         btc_av_disconn_req_t disconn_req;
1469         memcpy(&disconn_req.target_bda, &arg->disconn, sizeof(bt_bdaddr_t));
1470         btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
1471         break;
1472     }
1473     case BTC_AV_SINK_API_REG_DATA_CB_EVT: {
1474         btc_a2dp_sink_reg_data_cb(arg->data_cb);
1475         break;
1476     }
1477 #endif /* BTC_AV_SINK_INCLUDED */
1478 #if BTC_AV_SRC_INCLUDED
1479     case BTC_AV_SRC_API_INIT_EVT: {
1480         btc_a2d_src_init();
1481         break;
1482     }
1483     case BTC_AV_SRC_API_DEINIT_EVT: {
1484         btc_a2d_src_deinit();
1485         break;
1486     }
1487     case BTC_AV_SRC_API_CONNECT_EVT: {
1488         btc_a2d_src_connect(&arg->src_connect);
1489         break;
1490     }
1491     case BTC_AV_SRC_API_DISCONNECT_EVT: {
1492         CHECK_BTAV_INIT();
1493         btc_av_disconn_req_t disconn_req;
1494         memcpy(&disconn_req.target_bda, &arg->src_disconn, sizeof(bt_bdaddr_t));
1495         btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
1496         break;
1497     }
1498     case BTC_AV_SRC_API_REG_DATA_CB_EVT: {
1499         btc_a2dp_src_reg_data_cb(arg->src_data_cb);
1500         break;
1501     }
1502 #endif /* BTC_AV_SRC_INCLUDED */
1503     case BTC_AV_API_MEDIA_CTRL_EVT: {
1504         btc_a2dp_control_media_ctrl(arg->ctrl);
1505         break;
1506     }
1507     case BTC_AV_CONNECT_REQ_EVT:
1508         btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (char *)msg->arg);
1509         break;
1510     // case BTC_AV_DISCONNECT_REQ_EVT:
1511     case BTC_AV_START_STREAM_REQ_EVT:
1512     case BTC_AV_STOP_STREAM_REQ_EVT:
1513     case BTC_AV_SUSPEND_STREAM_REQ_EVT: {
1514         btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, NULL);
1515         break;
1516     }
1517     default:
1518         BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
1519     }
1520 }
1521 
btc_a2dp_cb_handler(btc_msg_t * msg)1522 void btc_a2dp_cb_handler(btc_msg_t *msg)
1523 {
1524     btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (void *)(msg->arg));
1525     btc_av_event_free_data(msg->act, msg->arg);
1526 }
1527 
1528 #if BTC_AV_SINK_INCLUDED
1529 
1530 /*******************************************************************************
1531 **
1532 ** Function         init_sink
1533 **
1534 ** Description      Initializes the AV interface for sink mode
1535 **
1536 ** Returns          bt_status_t
1537 **
1538 *******************************************************************************/
btc_a2d_sink_init(void)1539 static bt_status_t btc_a2d_sink_init(void)
1540 {
1541     BTC_TRACE_DEBUG("%s()\n", __func__);
1542 
1543     return btc_av_init(BTA_A2DP_SINK_SERVICE_ID);
1544 }
1545 
btc_a2d_sink_connect(bt_bdaddr_t * remote_bda)1546 static bt_status_t btc_a2d_sink_connect(bt_bdaddr_t *remote_bda)
1547 {
1548     BTC_TRACE_DEBUG("%s\n", __FUNCTION__);
1549     CHECK_BTAV_INIT();
1550 
1551     return btc_queue_connect(UUID_SERVCLASS_AUDIO_SINK, remote_bda, connect_int);
1552 }
1553 
btc_a2d_sink_deinit(void)1554 static void btc_a2d_sink_deinit(void)
1555 {
1556     g_a2dp_sink_ongoing_deinit = true;
1557     if (btc_av_is_connected()) {
1558         BTA_AvClose(btc_av_cb.bta_handle);
1559         if (btc_av_cb.peer_sep == AVDT_TSEP_SRC && g_av_with_rc == true) {
1560             BTA_AvCloseRc(btc_av_cb.bta_handle);
1561         }
1562     } else {
1563         clean_up(BTA_A2DP_SINK_SERVICE_ID);
1564     }
1565 }
1566 
1567 #endif /* BTC_AV_SINK_INCLUDED */
1568 
1569 #if BTC_AV_SRC_INCLUDED
1570 
1571 /*******************************************************************************
1572 **
1573 ** Function         btc_a2d_src_init
1574 **
1575 ** Description      Initializes the AV interface for source mode
1576 **
1577 ** Returns          bt_status_t
1578 **
1579 *******************************************************************************/
btc_a2d_src_init(void)1580 static bt_status_t btc_a2d_src_init(void)
1581 {
1582     BTC_TRACE_DEBUG("%s()\n", __func__);
1583 
1584     return btc_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
1585 }
1586 
btc_a2d_src_deinit(void)1587 static void btc_a2d_src_deinit(void)
1588 {
1589     g_a2dp_source_ongoing_deinit = true;
1590     if (btc_av_is_connected()) {
1591         BTA_AvClose(btc_av_cb.bta_handle);
1592         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK && g_av_with_rc == true) {
1593             BTA_AvCloseRc(btc_av_cb.bta_handle);
1594         }
1595     } else {
1596         clean_up(BTA_A2DP_SOURCE_SERVICE_ID);
1597     }
1598 }
1599 
btc_a2d_src_connect(bt_bdaddr_t * remote_bda)1600 static bt_status_t btc_a2d_src_connect(bt_bdaddr_t *remote_bda)
1601 {
1602     BTC_TRACE_DEBUG("%s\n", __FUNCTION__);
1603     CHECK_BTAV_INIT();
1604 
1605     return btc_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, remote_bda, connect_int);
1606 }
1607 
1608 #endif /* BTC_AV_SRC_INCLUDED */
1609 
1610 #endif /* #if BTC_AV_INCLUDED */
1611