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