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