From 7050d2ca520e2b58a676c8a081aab3872c899807 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Fri, 7 Jul 2017 14:09:31 +0200 Subject: [PATCH] a2dp sink: start extracting code from demo to a2dp layer --- example/a2dp_sink_demo.c | 24 +++--- example/avdtp_sink_demo.c | 4 +- example/avdtp_source_demo.c | 5 +- src/btstack_defines.h | 68 +++++++++------- src/btstack_event.h | 112 +++++++++++++------------- src/classic/a2dp_sink.c | 155 +++++++++++++++++++++++++++++++++++- src/classic/a2dp_sink.h | 51 +++++++++++- src/classic/a2dp_source.c | 60 +++++--------- src/classic/a2dp_source.h | 2 +- src/classic/avdtp.c | 7 +- src/classic/avdtp.h | 23 ++++++ src/classic/avdtp_sink.c | 67 ++++++++-------- src/classic/avdtp_sink.h | 2 +- 13 files changed, 398 insertions(+), 182 deletions(-) diff --git a/example/a2dp_sink_demo.c b/example/a2dp_sink_demo.c index 8159b8816..a3a37e137 100644 --- a/example/a2dp_sink_demo.c +++ b/example/a2dp_sink_demo.c @@ -169,8 +169,9 @@ typedef struct { #ifdef HAVE_BTSTACK_STDIN // mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3}; // pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5}; -// mac 2013: -static const char * device_addr_string = "00:1B:DC:08:0A:A5"; +// mac 2013: static const char * device_addr_string = "00:1B:DC:08:0A:A5"; +// iPhone 5S: +static const char * device_addr_string = "54:E4:3A:26:A2:39"; #endif // bt dongle: -u 02-02 static bd_addr_t remote = {0x00, 0x02, 0x72, 0xDC, 0x31, 0xC1}; @@ -183,6 +184,8 @@ static adtvp_media_codec_information_sbc_t sbc_capability; static avdtp_media_codec_configuration_sbc_t sbc_configuration; static avdtp_stream_endpoint_t * local_stream_endpoint; +static uint8_t local_seid = 0; + #ifdef HAVE_BTSTACK_STDIN static uint16_t remote_configuration_bitmap; static avdtp_capabilities_t remote_configuration; @@ -1049,20 +1052,11 @@ int btstack_main(int argc, const char * argv[]){ l2cap_init(); // Initialize AVDTP Sink - avdtp_sink_init(); - avdtp_sink_register_packet_handler(&packet_handler); + a2dp_sink_init(); + a2dp_sink_register_packet_handler(&packet_handler); + a2dp_sink_register_media_handler(&handle_l2cap_media_data_packet); -//#ifndef SMG_BI - local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, AVDTP_AUDIO); - local_stream_endpoint->sep.seid = 1; - avdtp_sink_register_media_transport_category(local_stream_endpoint->sep.seid); - avdtp_sink_register_media_codec_category(local_stream_endpoint->sep.seid, AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities)); -//#endif - // uint8_t cp_type_lsb, uint8_t cp_type_msb, const uint8_t * cp_type_value, uint8_t cp_type_value_len - // avdtp_sink_register_content_protection_category(seid, 2, 2, NULL, 0); - - avdtp_sink_register_media_handler(&handle_l2cap_media_data_packet); - printf("reistered media handler\n"); + local_seid = a2dp_sink_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration)); // Initialize AVRCP COntroller avrcp_controller_init(); diff --git a/example/avdtp_sink_demo.c b/example/avdtp_sink_demo.c index fa8a15467..f0cc116bf 100644 --- a/example/avdtp_sink_demo.c +++ b/example/avdtp_sink_demo.c @@ -176,6 +176,8 @@ static uint16_t avdtp_cid = 0; static uint8_t sdp_avdtp_sink_service_buffer[150]; static avdtp_sep_t sep; +static avdtp_context_t adtvp_sink_context; + static adtvp_media_codec_information_sbc_t sbc_capability; static avdtp_media_codec_configuration_sbc_t sbc_configuration; static avdtp_stream_endpoint_t * local_stream_endpoint; @@ -788,7 +790,7 @@ int btstack_main(int argc, const char * argv[]){ l2cap_init(); // Initialize AVDTP Sink - avdtp_sink_init(); + avdtp_sink_init(&adtvp_sink_context); avdtp_sink_register_packet_handler(&packet_handler); //#ifndef SMG_BI diff --git a/example/avdtp_source_demo.c b/example/avdtp_source_demo.c index 925b16738..c566dac2e 100644 --- a/example/avdtp_source_demo.c +++ b/example/avdtp_source_demo.c @@ -168,7 +168,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); break; - case A2DP_SUBEVENT_STREAM_START_ACCEPTED: + case A2DP_SUBEVENT_STREAM_STARTED: if (local_seid != media_tracker.local_seid) break; if (!a2dp_source_stream_endpoint_ready(media_tracker.local_seid)) break; a2dp_fill_audio_buffer_timer_start(&media_tracker); @@ -386,11 +386,10 @@ int btstack_main(int argc, const char * argv[]){ hci_add_event_handler(&hci_event_callback_registration); l2cap_init(); - // Initialize AVDTP Sink + // Initialize AVDTP Source a2dp_source_init(); a2dp_source_register_packet_handler(&packet_handler); - //#ifndef SMG_BI local_seid = a2dp_source_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration)); // Initialize SDP diff --git a/src/btstack_defines.h b/src/btstack_defines.h index 90bd95eb5..3cb1f5acc 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -1262,7 +1262,7 @@ typedef uint8_t sm_key_t[16]; /** AVDTP Subevent */ /** - * @format 1H111 + * @format 12111 * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1272,7 +1272,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_ACCEPT 0x01 /** - * @format 1H11 + * @format 1211 * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1281,7 +1281,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_REJECT 0x02 /** - * @format 1H11 + * @format 1211 * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1290,7 +1290,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT 0x03 /** - * @format 1HB1 + * @format 12B1 * @param subevent_code * @param avdtp_cid * @param bd_addr @@ -1299,14 +1299,14 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED 0x04 /** - * @format 1H + * @format 12 * @param subevent_code * @param avdtp_cid */ #define AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED 0x05 /** - * @format 1H1111 + * @format 121111 * @param subevent_code * @param avdtp_cid * @param seid 0x01 – 0x3E @@ -1317,7 +1317,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_SEP_FOUND 0x06 /** - * @format 1H1111111111 + * @format 121111111111 * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1334,7 +1334,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY 0x07 /** - * @format 1H1112LV + * @format 121112LV * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1347,7 +1347,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY 0x08 /** - * @format 1H111121111111 + * @format 12111121111111 * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1366,7 +1366,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION 0x09 /** - * @format 1H11112LV + * @format 1211112LV * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1380,7 +1380,7 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION 0x0A /** - * @format 1H111 + * @format 12111 * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1390,14 +1390,14 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED 0x0B /** - * @format 1H + * @format 12 * @param subevent_code * @param avdtp_cid */ #define AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED 0x0C /** - * @format 1H12 + * @format 1212 * @param subevent_code * @param avdtp_cid * @param int_seid @@ -1407,48 +1407,60 @@ typedef uint8_t sm_key_t[16]; /** A2DP Subevent */ +/* Stream goes through following states: + * - OPEN - indicated with A2DP_SUBEVENT_STREAM_ESTABLISHED event + * - START - indicated with A2DP_SUBEVENT_STREAM_STARTED event + * - SUSPEND - indicated with A2DP_SUBEVENT_STREAM_SUSPENDED event + * - ABORT/STOP - indicated with A2DP_SUBEVENT_STREAM_RELEASED event + + OPEN state will be followed by ABORT/STOP. Stream is ready but media transfer is not started. + START can come only after the stream is OPENED, and indicates that media transfer is started. + SUSPEND is optional, it pauses the stream. + */ /** - * @format 1H111 + * @format 121 Sent only by A2DP source. * @param subevent_code + * @param avdtp_cid + * @param local_seid + */ +#define A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x01 + +/** + * @format 12111 Stream is opened byt not started. + * @param subevent_code * @param a2dp_cid * @param local_seid * @param remote_seid * @param status */ -#define A2DP_SUBEVENT_STREAM_ESTABLISHED 0x01 +#define A2DP_SUBEVENT_STREAM_ESTABLISHED 0x02 /** - * @format 1H1 + * @format 121 Indicates that media transfer is started. * @param subevent_code * @param a2dp_cid * @param local_seid */ -#define A2DP_SUBEVENT_STREAM_START_ACCEPTED 0x02 +#define A2DP_SUBEVENT_STREAM_STARTED 0x03 /** - * @format 1H1 + * @format 121 Stream is paused. * @param subevent_code * @param a2dp_cid * @param local_seid */ -#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x03 +#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x04 /** - * @format 1H1 + * @format 121 Stream is released. * @param subevent_code * @param avdtp_cid * @param local_seid */ -#define A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x04 +#define A2DP_SUBEVENT_STREAM_RELEASED 0x05 + -/** - * @format 1H1 - * @param subevent_code - * @param avdtp_cid - * @param local_seid - */ -#define A2DP_SUBEVENT_STREAM_RELEASED 0x05 /** AVRCP Subevent */ diff --git a/src/btstack_event.h b/src/btstack_event.h index 0232c61de..27db3467a 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -3983,9 +3983,9 @@ static inline hci_con_handle_t ancs_subevent_client_disconnected_get_handle(cons * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_ACCEPT * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_accept_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_accept_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4020,9 +4020,9 @@ static inline uint8_t avdtp_subevent_signaling_accept_get_status(const uint8_t * * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_REJECT * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_reject_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_reject_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4048,9 +4048,9 @@ static inline uint8_t avdtp_subevent_signaling_reject_get_signal_identifier(cons * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_general_reject_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_general_reject_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4076,9 +4076,9 @@ static inline uint8_t avdtp_subevent_signaling_general_reject_get_signal_identif * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_connection_established_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_connection_established_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4104,9 +4104,9 @@ static inline uint8_t avdtp_subevent_signaling_connection_established_get_status * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_connection_released_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_connection_released_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } @@ -4114,9 +4114,9 @@ static inline hci_con_handle_t avdtp_subevent_signaling_connection_released_get_ * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_sep_found_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_sep_found_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4160,9 +4160,9 @@ static inline uint8_t avdtp_subevent_signaling_sep_found_get_sep_type(const uint * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_capability_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_capability_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4260,9 +4260,9 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_ma * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_capability_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_media_codec_other_capability_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4324,9 +4324,9 @@ static inline const uint8_t * avdtp_subevent_signaling_media_codec_other_capabil * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4442,9 +4442,9 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_configuration_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_signaling_media_codec_other_configuration_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4515,9 +4515,9 @@ static inline const uint8_t * avdtp_subevent_signaling_media_codec_other_configu * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_streaming_connection_established_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_streaming_connection_established_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4552,9 +4552,9 @@ static inline uint8_t avdtp_subevent_streaming_connection_established_get_status * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_streaming_connection_released_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_streaming_connection_released_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } @@ -4562,9 +4562,9 @@ static inline hci_con_handle_t avdtp_subevent_streaming_connection_released_get_ * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t avdtp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4586,13 +4586,32 @@ static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_se return little_endian_read_16(event, 6); } +/** + * @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ +static inline uint16_t a2dp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){ + return little_endian_read_16(event, 3); +} +/** + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ +static inline uint8_t a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(const uint8_t * event){ + return event[5]; +} + /** * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_ESTABLISHED * @param event packet * @return a2dp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t a2dp_subevent_stream_established_get_a2dp_cid(const uint8_t * event){ +static inline uint16_t a2dp_subevent_stream_established_get_a2dp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4624,21 +4643,21 @@ static inline uint8_t a2dp_subevent_stream_established_get_status(const uint8_t } /** - * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_START_ACCEPTED + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_STARTED * @param event packet * @return a2dp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t a2dp_subevent_stream_start_accepted_get_a2dp_cid(const uint8_t * event){ +static inline uint16_t a2dp_subevent_stream_started_get_a2dp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** - * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_START_ACCEPTED + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_STARTED * @param event packet * @return local_seid * @note: btstack_type 1 */ -static inline uint8_t a2dp_subevent_stream_start_accepted_get_local_seid(const uint8_t * event){ +static inline uint8_t a2dp_subevent_stream_started_get_local_seid(const uint8_t * event){ return event[5]; } @@ -4646,9 +4665,9 @@ static inline uint8_t a2dp_subevent_stream_start_accepted_get_local_seid(const u * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_SUSPENDED * @param event packet * @return a2dp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t a2dp_subevent_stream_suspended_get_a2dp_cid(const uint8_t * event){ +static inline uint16_t a2dp_subevent_stream_suspended_get_a2dp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** @@ -4661,32 +4680,13 @@ static inline uint8_t a2dp_subevent_stream_suspended_get_local_seid(const uint8_ return event[5]; } -/** - * @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW - * @param event packet - * @return avdtp_cid - * @note: btstack_type H - */ -static inline hci_con_handle_t a2dp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){ - return little_endian_read_16(event, 3); -} -/** - * @brief Get field local_seid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW - * @param event packet - * @return local_seid - * @note: btstack_type 1 - */ -static inline uint8_t a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(const uint8_t * event){ - return event[5]; -} - /** * @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAM_RELEASED * @param event packet * @return avdtp_cid - * @note: btstack_type H + * @note: btstack_type 2 */ -static inline hci_con_handle_t a2dp_subevent_stream_released_get_avdtp_cid(const uint8_t * event){ +static inline uint16_t a2dp_subevent_stream_released_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } /** diff --git a/src/classic/a2dp_sink.c b/src/classic/a2dp_sink.c index 341a0d2b3..a742af8c3 100644 --- a/src/classic/a2dp_sink.c +++ b/src/classic/a2dp_sink.c @@ -51,7 +51,14 @@ static const char * default_a2dp_sink_service_name = "BTstack A2DP Sink Service"; static const char * default_a2dp_sink_service_provider_name = "BTstack A2DP Sink Service Provider"; -// static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +static avdtp_context_t a2dp_sink_context; + +static a2dp_state_t app_state = A2DP_IDLE; +static avdtp_stream_endpoint_context_t sc; +static uint16_t avdtp_cid = 0; +// static int next_remote_sep_index_to_query = 0; + +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){ uint8_t* attribute; @@ -131,3 +138,149 @@ void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_han de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); } + +void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback){ + avdtp_sink_register_packet_handler(callback); + return; + if (callback == NULL){ + log_error("a2dp_sink_register_packet_handler called with NULL callback"); + return; + } + avdtp_sink_register_packet_handler(&packet_handler); + a2dp_sink_context.a2dp_callback = callback; +} + +void a2dp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size)){ + if (callback == NULL){ + log_error("a2dp_sink_register_media_handler called with NULL callback"); + return; + } + avdtp_sink_register_media_handler(callback); +} + +void a2dp_sink_init(void){ + avdtp_sink_init(&a2dp_sink_context); + l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0); +} + +uint8_t a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, + uint8_t * codec_capabilities, uint16_t codec_capabilities_len, + uint8_t * media_codec_info, uint16_t media_codec_info_len){ + avdtp_stream_endpoint_t * local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, media_type); + avdtp_sink_register_media_transport_category(avdtp_stream_endpoint_seid(local_stream_endpoint)); + avdtp_sink_register_media_codec_category(avdtp_stream_endpoint_seid(local_stream_endpoint), media_type, media_codec_type, + codec_capabilities, codec_capabilities_len); + local_stream_endpoint->remote_configuration.media_codec.media_codec_information = media_codec_info; + local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_info_len; + + return local_stream_endpoint->sep.seid; +} + +void a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid){ + sc.local_stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_sink_context); + if (!sc.local_stream_endpoint){ + log_error(" no local_stream_endpoint for seid %d", local_seid); + return; + } + avdtp_sink_connect(bd_addr); +} + +void a2dp_sink_disconnect(uint16_t a2dp_cid){ + avdtp_disconnect(a2dp_cid, &a2dp_sink_context); +} + + +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ + + UNUSED(channel); + UNUSED(size); + + bd_addr_t event_addr; + switch (packet_type) { + + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case HCI_EVENT_PIN_CODE_REQUEST: + // inform about pin code request + printf("Pin code request - using '0000'\n"); + hci_event_pin_code_request_get_bd_addr(packet, event_addr); + hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); + break; + case HCI_EVENT_DISCONNECTION_COMPLETE: + // connection closed -> quit test app + app_state = A2DP_IDLE; + printf("\n --- avdtp_test: HCI_EVENT_DISCONNECTION_COMPLETE ---\n"); + break; + case HCI_EVENT_AVDTP_META: + switch (packet[2]){ + case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: + app_state = A2DP_CONNECTED; + avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet); + printf("\n --- avdtp_test: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, cid 0x%02x ---\n", avdtp_cid); + break; + case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND: + if (app_state < A2DP_CONNECTED) return; + // sep.seid = avdtp_subevent_signaling_sep_found_get_seid(packet); + // sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet); + // sep.media_type = avdtp_subevent_signaling_sep_found_get_media_type(packet); + // sep.type = avdtp_subevent_signaling_sep_found_get_sep_type(packet); + // printf("Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)\n", sep.seid, sep.in_use, sep.media_type, sep.type); + break; + case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY: + if (app_state < A2DP_CONNECTED) return; + // sbc_capability.sampling_frequency_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet); + // sbc_capability.channel_mode_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet); + // sbc_capability.block_length_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet); + // sbc_capability.subbands_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet); + // sbc_capability.allocation_method_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet); + // sbc_capability.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet); + // sbc_capability.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet); + // dump_sbc_capability(sbc_capability); + break; + case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ + if (app_state < A2DP_CONNECTED) return; + // sbc_configuration.reconfigure = avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); + // sbc_configuration.num_channels = avdtp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); + // sbc_configuration.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); + // sbc_configuration.channel_mode = avdtp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); + // sbc_configuration.block_length = avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); + // sbc_configuration.subbands = avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); + // sbc_configuration.allocation_method = avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); + // sbc_configuration.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); + // sbc_configuration.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); + // sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; + // dump_sbc_configuration(sbc_configuration); + // // // TODO: use actual config + // btstack_sbc_encoder_init(&local_stream_endpoint->sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53); + + // if (sbc_configuration.reconfigure){ + // media_processing_close(); + // media_processing_init(sbc_configuration); + // } else { + // media_processing_init(sbc_configuration); + // } + break; + } + case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: + app_state = A2DP_STREAMING_OPENED; + break; + case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY: + printf(" received non SBC codec. not implemented\n"); + break; + case AVDTP_SUBEVENT_SIGNALING_ACCEPT: + break; + default: + printf(" not implemented\n"); + break; + } + break; + default: + break; + } + break; + default: + // other packet type + break; + } +} + diff --git a/src/classic/a2dp_sink.h b/src/classic/a2dp_sink.h index cf58c946f..8c660473c 100644 --- a/src/classic/a2dp_sink.h +++ b/src/classic/a2dp_sink.h @@ -58,14 +58,63 @@ extern "C" { * @brief A2DP Sink service record. * @param service * @param service_record_handle - * @param supported_features 16-bit bitmap, see AVDTP_SINK_SF_* values in avdtp.h + * @param supported_features 16-bit bitmap, see a2dp_SINK_SF_* values in avdtp.h * @param service_name * @param service_provider_name */ void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name); +/** + * @brief Set up A2DP Sink device. + */ +void a2dp_sink_init(void); + +uint8_t a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, + uint8_t * codec_capabilities, uint16_t codec_capabilities_len, + uint8_t * codec_configuration, uint16_t codec_configuration_len); + +/** + * @brief Register callback for the A2DP Sink client. + * @param callback + */ +void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback); + + +/** + * @brief Register media handler for the A2DP Sink client. + * @param callback + */ +void a2dp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size)); + +/** + * @brief Open stream + * @param avdtp_cid + * @param local_seid + */ +void a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid); + +/** + * @brief Start stream + * @param local_seid + */ +void a2dp_sink_start_stream(uint8_t local_seid); + +/** + * @brief Suspend stream + * @param local_seid + */ +void a2dp_sink_pause(uint8_t local_seid); + +/** + * @brief Abort stream + * @param local_seid + */ +void a2dp_sink_stop_stream(uint8_t local_seid); + +void a2dp_sink_disconnect(uint16_t a2dp_cid); /* API_END */ + #if defined __cplusplus } #endif diff --git a/src/classic/a2dp_source.c b/src/classic/a2dp_source.c index 5ea77edef..1597f56a3 100644 --- a/src/classic/a2dp_source.c +++ b/src/classic/a2dp_source.c @@ -49,35 +49,12 @@ #include "avdtp_source.h" #include "a2dp_source.h" +#define AVDTP_MEDIA_PAYLOAD_HEADER_SIZE 12 + static const char * default_a2dp_source_service_name = "BTstack A2DP Source Service"; static const char * default_a2dp_source_service_provider_name = "BTstack A2DP Source Service Provider"; static avdtp_context_t a2dp_source_context; -#define AVDTP_MEDIA_PAYLOAD_HEADER_SIZE 12 - -typedef struct { -// to app - uint32_t fill_audio_ring_buffer_timeout_ms; - uint32_t time_audio_data_sent; // ms - uint32_t acc_num_missed_samples; - uint32_t samples_ready; - btstack_timer_source_t fill_audio_ring_buffer_timer; - btstack_ring_buffer_t sbc_ring_buffer; - btstack_sbc_encoder_state_t sbc_encoder_state; - - int reconfigure; - int num_channels; - int sampling_frequency; - int channel_mode; - int block_length; - int subbands; - int allocation_method; - int min_bitpool_value; - int max_bitpool_value; - avdtp_stream_endpoint_t * local_stream_endpoint; - avdtp_sep_t * active_remote_sep; -} avdtp_stream_endpoint_context_t; - static a2dp_state_t app_state = A2DP_IDLE; static avdtp_stream_endpoint_context_t sc; static uint16_t avdtp_cid = 0; @@ -340,26 +317,13 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe int pos = 0; event[pos++] = HCI_EVENT_A2DP_META; event[pos++] = sizeof(event) - 2; - event[pos++] = A2DP_SUBEVENT_STREAM_START_ACCEPTED; + event[pos++] = A2DP_SUBEVENT_STREAM_STARTED; little_endian_store_16(event, pos, avdtp_cid); pos += 2; event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint); (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); break; } - case AVDTP_SI_CLOSE:{ - uint8_t event[6]; - int pos = 0; - event[pos++] = HCI_EVENT_A2DP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = A2DP_SUBEVENT_STREAM_RELEASED; - little_endian_store_16(event, pos, avdtp_cid); - pos += 2; - log_info("send A2DP_SUBEVENT_STREAM_RELEASED to app"); - event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint); - (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); - break; - } case AVDTP_SI_SUSPEND:{ uint8_t event[6]; int pos = 0; @@ -372,6 +336,20 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); break; } + case AVDTP_SI_ABORT: + case AVDTP_SI_CLOSE:{ + uint8_t event[6]; + int pos = 0; + event[pos++] = HCI_EVENT_A2DP_META; + event[pos++] = sizeof(event) - 2; + event[pos++] = A2DP_SUBEVENT_STREAM_RELEASED; + little_endian_store_16(event, pos, avdtp_cid); + pos += 2; + log_info("send A2DP_SUBEVENT_STREAM_RELEASED to app"); + event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint); + (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); + break; + } default: break; } @@ -443,8 +421,8 @@ void a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid){ avdtp_source_connect(bd_addr); } -void a2dp_source_disconnect(uint16_t con_handle){ - avdtp_disconnect(con_handle, &a2dp_source_context); +void a2dp_source_disconnect(uint16_t local_seid){ + avdtp_disconnect(local_seid, &a2dp_source_context); } void a2dp_source_start_stream(uint8_t int_seid){ diff --git a/src/classic/a2dp_source.h b/src/classic/a2dp_source.h index 247f581e7..56a66d7df 100644 --- a/src/classic/a2dp_source.h +++ b/src/classic/a2dp_source.h @@ -101,7 +101,7 @@ void a2dp_source_pause_stream(uint8_t int_seid); void a2dp_source_release_stream(uint8_t int_seid); /** - * @brief Disconnect from device with connection handle. + * @brief Disconnect from device with cid. * @param avdtp_cid */ void a2dp_source_disconnect(uint16_t avdtp_cid); diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index 7ceb2340e..22ecc8e55 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -339,7 +339,7 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c case BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE: if (sdp_query_context.query_role != AVDTP_SOURCE) { sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE; - avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, 0); + avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, SDP_SERVICE_NOT_FOUND); break; } // log_info("SDP Attribute 0x%04x: AVDTP SOURCE protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid); @@ -348,7 +348,7 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c case BLUETOOTH_SERVICE_CLASS_AUDIO_SINK: if (sdp_query_context.query_role != AVDTP_SINK) { sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE; - avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, 0); + avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, SDP_SERVICE_NOT_FOUND); break; } // log_info("SDP Attribute 0x%04x: AVDTP SINK protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid); @@ -498,7 +498,9 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet case L2CAP_EVENT_CHANNEL_OPENED: // inform about new l2cap connection l2cap_event_channel_opened_get_address(packet, event_addr); + local_cid = l2cap_event_channel_opened_get_local_cid(packet); if (l2cap_event_channel_opened_get_status(packet)){ + avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, event_addr, l2cap_event_channel_opened_get_status(packet)); log_error("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), l2cap_event_channel_opened_get_status(packet)); break; @@ -510,7 +512,6 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet } con_handle = l2cap_event_channel_opened_get_handle(packet); - local_cid = l2cap_event_channel_opened_get_local_cid(packet); log_info("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x", bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet)); diff --git a/src/classic/avdtp.h b/src/classic/avdtp.h index b4d0a7df5..b3118f0b4 100644 --- a/src/classic/avdtp.h +++ b/src/classic/avdtp.h @@ -470,6 +470,29 @@ typedef struct avdtp_stream_endpoint { uint16_t sequence_number; } avdtp_stream_endpoint_t; +typedef struct { +// to app + uint32_t fill_audio_ring_buffer_timeout_ms; + uint32_t time_audio_data_sent; // ms + uint32_t acc_num_missed_samples; + uint32_t samples_ready; + btstack_timer_source_t fill_audio_ring_buffer_timer; + btstack_ring_buffer_t sbc_ring_buffer; + btstack_sbc_encoder_state_t sbc_encoder_state; + + int reconfigure; + int num_channels; + int sampling_frequency; + int channel_mode; + int block_length; + int subbands; + int allocation_method; + int min_bitpool_value; + int max_bitpool_value; + avdtp_stream_endpoint_t * local_stream_endpoint; + avdtp_sep_t * active_remote_sep; +} avdtp_stream_endpoint_context_t; + typedef struct { btstack_linked_list_t connections; btstack_linked_list_t stream_endpoints; diff --git a/src/classic/avdtp_sink.c b/src/classic/avdtp_sink.c index 45400244b..088eaa3d6 100644 --- a/src/classic/avdtp_sink.c +++ b/src/classic/avdtp_sink.c @@ -49,47 +49,47 @@ #include "avdtp_initiator.h" #include "avdtp_acceptor.h" -static avdtp_context_t avdtp_sink_context; +static avdtp_context_t * avdtp_sink_context; static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); void avdtp_sink_register_media_transport_category(uint8_t seid){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_media_transport_category(stream_endpoint); } void avdtp_sink_register_reporting_category(uint8_t seid){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_reporting_category(stream_endpoint); } void avdtp_sink_register_delay_reporting_category(uint8_t seid){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_delay_reporting_category(stream_endpoint); } void avdtp_sink_register_recovery_category(uint8_t seid, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_recovery_category(stream_endpoint, maximum_recovery_window_size, maximum_number_media_packets); } void avdtp_sink_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_content_protection_category(stream_endpoint, cp_type, cp_type_value, cp_type_value_len); } void avdtp_sink_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_header_compression_category(stream_endpoint, back_ch, media, recovery); } void avdtp_sink_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_media_codec_category(stream_endpoint, media_type, media_codec_type, media_codec_info, media_codec_info_len); } void avdtp_sink_register_multiplexing_category(uint8_t seid, uint8_t fragmentation){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context); + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_sink_context); avdtp_register_multiplexing_category(stream_endpoint, fragmentation); } @@ -103,21 +103,26 @@ void avdtp_sink_register_multiplexing_category(uint8_t seid, uint8_t fragmentati // TODO remove static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ - avdtp_packet_handler(packet_type, channel, packet, size, &avdtp_sink_context); + avdtp_packet_handler(packet_type, channel, packet, size, avdtp_sink_context); } // TODO: find out which security level is needed, and replace LEVEL_0 in avdtp_sink_init -void avdtp_sink_init(void){ - avdtp_sink_context.stream_endpoints = NULL; - avdtp_sink_context.connections = NULL; - avdtp_sink_context.stream_endpoints_id_counter = 0; - avdtp_sink_context.packet_handler = packet_handler; +void avdtp_sink_init(avdtp_context_t * avdtp_context){ + if (!avdtp_context){ + log_error("avdtp_source_context is NULL"); + return; + } + avdtp_sink_context = avdtp_context; + avdtp_sink_context->stream_endpoints = NULL; + avdtp_sink_context->connections = NULL; + avdtp_sink_context->stream_endpoints_id_counter = 0; + avdtp_sink_context->packet_handler = packet_handler; l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0); } avdtp_stream_endpoint_t * avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type){ - return avdtp_create_stream_endpoint(sep_type, media_type, &avdtp_sink_context); + return avdtp_create_stream_endpoint(sep_type, media_type, avdtp_sink_context); } void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size)){ @@ -125,7 +130,7 @@ void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t log_error("avdtp_sink_register_media_handler called with NULL callback"); return; } - avdtp_sink_context.handle_media_data = callback; + avdtp_sink_context->handle_media_data = callback; } void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback){ @@ -133,58 +138,58 @@ void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback){ log_error("avdtp_sink_register_packet_handler called with NULL callback"); return; } - avdtp_sink_context.avdtp_callback = callback; + avdtp_sink_context->avdtp_callback = callback; } void avdtp_sink_connect(bd_addr_t remote){ - avdtp_connect(remote, AVDTP_SOURCE, &avdtp_sink_context); + avdtp_connect(remote, AVDTP_SOURCE, avdtp_sink_context); } void avdtp_sink_disconnect(uint16_t avdtp_cid){ - avdtp_disconnect(avdtp_cid, &avdtp_sink_context); + avdtp_disconnect(avdtp_cid, avdtp_sink_context); } void avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid){ - avdtp_open_stream(avdtp_cid, int_seid, acp_seid, &avdtp_sink_context); + avdtp_open_stream(avdtp_cid, int_seid, acp_seid, avdtp_sink_context); } void avdtp_sink_start_stream(uint8_t int_seid){ - avdtp_start_stream(int_seid, &avdtp_sink_context); + avdtp_start_stream(int_seid, avdtp_sink_context); } void avdtp_sink_stop_stream(uint8_t int_seid){ - avdtp_stop_stream(int_seid, &avdtp_sink_context); + avdtp_stop_stream(int_seid, avdtp_sink_context); } void avdtp_sink_abort_stream(uint8_t int_seid){ - avdtp_abort_stream(int_seid, &avdtp_sink_context); + avdtp_abort_stream(int_seid, avdtp_sink_context); } void avdtp_sink_suspend(uint8_t int_seid){ - avdtp_suspend_stream(int_seid, &avdtp_sink_context); + avdtp_suspend_stream(int_seid, avdtp_sink_context); } void avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid){ - avdtp_discover_stream_endpoints(avdtp_cid, &avdtp_sink_context); + avdtp_discover_stream_endpoints(avdtp_cid, avdtp_sink_context); } void avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid){ - avdtp_get_capabilities(avdtp_cid, acp_seid, &avdtp_sink_context); + avdtp_get_capabilities(avdtp_cid, acp_seid, avdtp_sink_context); } void avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid){ - avdtp_get_all_capabilities(avdtp_cid, acp_seid, &avdtp_sink_context); + avdtp_get_all_capabilities(avdtp_cid, acp_seid, avdtp_sink_context); } void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid){ - avdtp_get_configuration(avdtp_cid, acp_seid, &avdtp_sink_context); + avdtp_get_configuration(avdtp_cid, acp_seid, avdtp_sink_context); } void avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_set_configuration(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, &avdtp_sink_context); + avdtp_set_configuration(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_sink_context); } void avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_reconfigure(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, &avdtp_sink_context); + avdtp_reconfigure(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_sink_context); } diff --git a/src/classic/avdtp_sink.h b/src/classic/avdtp_sink.h index 4a5bc6304..91d1522e4 100644 --- a/src/classic/avdtp_sink.h +++ b/src/classic/avdtp_sink.h @@ -59,7 +59,7 @@ extern "C" { /** * @brief Set up AVDTP Sink device. */ -void avdtp_sink_init(void); +void avdtp_sink_init(avdtp_context_t * avdtp_context); // returns avdtp_stream_endpoint_t * avdtp_stream_endpoint_t * avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type);