From ef5ad9d62b6847dd5d3550af277e0e643d69383f Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Fri, 11 Aug 2017 11:26:34 +0200 Subject: [PATCH] a2dp: pass remote bd address on stream established event --- example/a2dp_sink_demo.c | 148 ++++++++++++++++++------------------- example/a2dp_source_demo.c | 97 +++++++++++------------- src/btstack_defines.h | 6 +- src/btstack_event.h | 30 ++++++-- src/classic/a2dp_sink.c | 26 ++----- src/classic/a2dp_source.c | 33 +++------ src/classic/avdtp.c | 44 ++++++----- src/classic/avdtp_util.c | 23 +++++- src/classic/avdtp_util.h | 4 +- 9 files changed, 207 insertions(+), 204 deletions(-) diff --git a/example/a2dp_sink_demo.c b/example/a2dp_sink_demo.c index 869565369..82a89865b 100644 --- a/example/a2dp_sink_demo.c +++ b/example/a2dp_sink_demo.c @@ -571,9 +571,9 @@ static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configu static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); UNUSED(size); - bd_addr_t event_addr; uint16_t local_cid; uint8_t status = 0xFF; + bd_addr_t adress; if (packet_type != HCI_EVENT_PACKET) return; if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; @@ -593,8 +593,8 @@ static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channe } avrcp_cid = local_cid; - avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); - printf("Channel successfully opened: %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), avrcp_cid); + avrcp_subevent_connection_established_get_bd_addr(packet, adress); + printf("Channel successfully opened: %s, avrcp_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_cid); // automatically enable notifications avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED); @@ -688,87 +688,79 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe UNUSED(channel); UNUSED(size); uint16_t cid; + bd_addr_t address; - switch (packet_type) { - case HCI_EVENT_PACKET: - switch (hci_event_packet_get_type(packet)) { - case HCI_EVENT_A2DP_META: - switch (packet[2]){ - case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION: - printf(" received non SBC codec. not implemented\n"); - break; - case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ - sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); - sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); - sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); - sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); - sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); - sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); - sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); - sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); - sbc_configuration.max_bitpool_value = a2dp_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); + if (packet_type != HCI_EVENT_PACKET) return; + if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; - if (sbc_configuration.reconfigure){ - media_processing_close(); - } + switch (packet[2]){ + case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION: + printf(" received non SBC codec. not implemented\n"); + break; + case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ + sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); + sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); + sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); + sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); + sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); + sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); + sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); + sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); + sbc_configuration.max_bitpool_value = a2dp_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); - // prepare media processing - media_processing_init(sbc_configuration); - break; - } - case A2DP_SUBEVENT_STREAM_ESTABLISHED: - cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); - if (cid != a2dp_cid) break; - local_seid = a2dp_subevent_stream_established_get_local_seid(packet); - printf(" -- a2dp sink demo: streaming connection is established, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); - app_state = AVDTP_APPLICATION_STREAMING; - break; - - case A2DP_SUBEVENT_STREAM_STARTED: - cid = a2dp_subevent_stream_started_get_a2dp_cid(packet); - if (cid != a2dp_cid) break; - local_seid = a2dp_subevent_stream_started_get_local_seid(packet); - printf(" -- a2dp sink demo: stream started, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); - - // started - // media_processing_init(sbc_configuration); - break; - - case A2DP_SUBEVENT_STREAM_SUSPENDED: - cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet); - if (cid != a2dp_cid) break; - local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet); - printf(" -- a2dp sink demo: stream paused, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); - - // paused/stopped - // media_processing_close(); - break; - - case A2DP_SUBEVENT_STREAM_RELEASED: - cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); - if (cid != a2dp_cid) break; - local_seid = a2dp_subevent_stream_released_get_local_seid(packet); - app_state = AVDTP_APPLICATION_IDLE; - printf(" -- a2dp sink demo: stream released, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); - - // paused/stopped - media_processing_close(); - break; - - default: - printf(" not implemented\n"); - break; - } - break; - default: - break; + if (sbc_configuration.reconfigure){ + media_processing_close(); } + + // prepare media processing + media_processing_init(sbc_configuration); break; + } + case A2DP_SUBEVENT_STREAM_ESTABLISHED: + a2dp_subevent_stream_established_get_bd_addr(packet, address); + cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); + if (cid != a2dp_cid) break; + local_seid = a2dp_subevent_stream_established_get_local_seid(packet); + printf(" -- a2dp sink demo: streaming connection is established, address %s, a2dp cid 0x%02X, local_seid %d\n", bd_addr_to_str(address), a2dp_cid, local_seid); + app_state = AVDTP_APPLICATION_STREAMING; + break; + + case A2DP_SUBEVENT_STREAM_STARTED: + cid = a2dp_subevent_stream_started_get_a2dp_cid(packet); + if (cid != a2dp_cid) break; + local_seid = a2dp_subevent_stream_started_get_local_seid(packet); + printf(" -- a2dp sink demo: stream started, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); + + // started + // media_processing_init(sbc_configuration); + break; + + case A2DP_SUBEVENT_STREAM_SUSPENDED: + cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet); + if (cid != a2dp_cid) break; + local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet); + printf(" -- a2dp sink demo: stream paused, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); + + // paused/stopped + // media_processing_close(); + break; + + case A2DP_SUBEVENT_STREAM_RELEASED: + cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); + if (cid != a2dp_cid) break; + local_seid = a2dp_subevent_stream_released_get_local_seid(packet); + app_state = AVDTP_APPLICATION_IDLE; + printf(" -- a2dp sink demo: stream released, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); + + // paused/stopped + media_processing_close(); + break; + default: - // other packet type - break; + printf(" not implemented\n"); + break; } } diff --git a/example/a2dp_source_demo.c b/example/a2dp_source_demo.c index 761de155b..9e8fc00c6 100644 --- a/example/a2dp_source_demo.c +++ b/example/a2dp_source_demo.c @@ -300,64 +300,55 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe UNUSED(size); uint8_t status; uint8_t local_seid; + bd_addr_t address; - switch (packet_type) { - - case HCI_EVENT_PACKET: - switch (hci_event_packet_get_type(packet)) { - case HCI_EVENT_A2DP_META: - switch (packet[2]){ - case A2DP_SUBEVENT_STREAM_ESTABLISHED: - status = a2dp_subevent_stream_established_get_status(packet); - if (status){ - printf("Stream establishment failed: status 0x%02x.\n", status); - break; - } - local_seid = a2dp_subevent_stream_established_get_local_seid(packet); - if (local_seid != media_tracker.local_seid){ - printf("Stream establishment failed: wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); - break; - } + if (packet_type != HCI_EVENT_PACKET) return; + if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; - media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); - printf("Stream established: a2dp cid 0x%02x, local seid %d, remote seid %d.\n", - media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); - break; - - case A2DP_SUBEVENT_STREAM_STARTED: - play_info.status = AVRCP_PLAY_STATUS_PLAYING; - a2dp_demo_timer_start(&media_tracker); - printf("Stream started.\n"); - break; - - case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: - a2dp_demo_send_media_packet(); - break; - - case A2DP_SUBEVENT_STREAM_SUSPENDED: - play_info.status = AVRCP_PLAY_STATUS_PAUSED; - printf("Stream paused.\n"); - a2dp_demo_timer_pause(&media_tracker); - break; - - case A2DP_SUBEVENT_STREAM_RELEASED: - play_info.status = AVRCP_PLAY_STATUS_STOPPED; - printf("Stream released.\n"); - a2dp_demo_timer_stop(&media_tracker); - break; - default: - printf("AVDTP Source demo: event 0x%02x is not implemented\n", packet[2]); - break; - } - break; - default: - break; + switch (packet[2]){ + case A2DP_SUBEVENT_STREAM_ESTABLISHED: + a2dp_subevent_stream_established_get_bd_addr(packet, address); + status = a2dp_subevent_stream_established_get_status(packet); + if (status){ + printf("Stream establishment failed: status 0x%02x.\n", status); + break; } + local_seid = a2dp_subevent_stream_established_get_local_seid(packet); + if (local_seid != media_tracker.local_seid){ + printf("Stream establishment failed: wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); + break; + } + + media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); + printf("Stream established: address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), + media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); + break; + + case A2DP_SUBEVENT_STREAM_STARTED: + play_info.status = AVRCP_PLAY_STATUS_PLAYING; + a2dp_demo_timer_start(&media_tracker); + printf("Stream started.\n"); + break; + + case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: + a2dp_demo_send_media_packet(); + break; + + case A2DP_SUBEVENT_STREAM_SUSPENDED: + play_info.status = AVRCP_PLAY_STATUS_PAUSED; + printf("Stream paused.\n"); + a2dp_demo_timer_pause(&media_tracker); + break; + + case A2DP_SUBEVENT_STREAM_RELEASED: + play_info.status = AVRCP_PLAY_STATUS_STOPPED; + printf("Stream released.\n"); + a2dp_demo_timer_stop(&media_tracker); break; default: - // other packet type - break; - } + printf("AVDTP Source demo: event 0x%02x is not implemented\n", packet[2]); + break; + } } static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ diff --git a/src/btstack_defines.h b/src/btstack_defines.h index 4248f0a15..adcb91ba7 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -1388,9 +1388,10 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION 0x0A /** - * @format 12111 + * @format 12B111 * @param subevent_code * @param avdtp_cid + * @param bd_addr * @param local_seid * @param remote_seid * @param status 0 == OK @@ -1469,9 +1470,10 @@ typedef uint8_t sm_key_t[16]; #define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION 0x03 /** - * @format 12111 Stream is opened byt not started. + * @format 12B111 Stream is opened byt not started. * @param subevent_code * @param a2dp_cid + * @param bd_addr * @param local_seid * @param remote_seid * @param status diff --git a/src/btstack_event.h b/src/btstack_event.h index a375a7435..cc6bc3694 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -4511,6 +4511,15 @@ static inline const uint8_t * avdtp_subevent_signaling_media_codec_other_configu static inline uint16_t avdtp_subevent_streaming_connection_established_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } +/** + * @brief Get field bd_addr from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void avdtp_subevent_streaming_connection_established_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[5], bd_addr); +} /** * @brief Get field local_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED * @param event packet @@ -4518,7 +4527,7 @@ static inline uint16_t avdtp_subevent_streaming_connection_established_get_avdtp * @note: btstack_type 1 */ static inline uint8_t avdtp_subevent_streaming_connection_established_get_local_seid(const uint8_t * event){ - return event[5]; + return event[11]; } /** * @brief Get field remote_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED @@ -4527,7 +4536,7 @@ static inline uint8_t avdtp_subevent_streaming_connection_established_get_local_ * @note: btstack_type 1 */ static inline uint8_t avdtp_subevent_streaming_connection_established_get_remote_seid(const uint8_t * event){ - return event[6]; + return event[12]; } /** * @brief Get field status from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED @@ -4536,7 +4545,7 @@ static inline uint8_t avdtp_subevent_streaming_connection_established_get_remote * @note: btstack_type 1 */ static inline uint8_t avdtp_subevent_streaming_connection_established_get_status(const uint8_t * event){ - return event[7]; + return event[13]; } /** @@ -4805,6 +4814,15 @@ static inline const uint8_t * a2dp_subevent_signaling_media_codec_other_configur static inline uint16_t a2dp_subevent_stream_established_get_a2dp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } +/** + * @brief Get field bd_addr from event A2DP_SUBEVENT_STREAM_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void a2dp_subevent_stream_established_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[5], bd_addr); +} /** * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED * @param event packet @@ -4812,7 +4830,7 @@ static inline uint16_t a2dp_subevent_stream_established_get_a2dp_cid(const uint8 * @note: btstack_type 1 */ static inline uint8_t a2dp_subevent_stream_established_get_local_seid(const uint8_t * event){ - return event[5]; + return event[11]; } /** * @brief Get field remote_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED @@ -4821,7 +4839,7 @@ static inline uint8_t a2dp_subevent_stream_established_get_local_seid(const uint * @note: btstack_type 1 */ static inline uint8_t a2dp_subevent_stream_established_get_remote_seid(const uint8_t * event){ - return event[6]; + return event[12]; } /** * @brief Get field status from event A2DP_SUBEVENT_STREAM_ESTABLISHED @@ -4830,7 +4848,7 @@ static inline uint8_t a2dp_subevent_stream_established_get_remote_seid(const uin * @note: btstack_type 1 */ static inline uint8_t a2dp_subevent_stream_established_get_status(const uint8_t * event){ - return event[7]; + return event[13]; } /** diff --git a/src/classic/a2dp_sink.c b/src/classic/a2dp_sink.c index 7a4bdb395..eb7f919a9 100644 --- a/src/classic/a2dp_sink.c +++ b/src/classic/a2dp_sink.c @@ -201,21 +201,6 @@ void a2dp_sink_disconnect(uint16_t a2dp_cid){ avdtp_disconnect(a2dp_cid, &a2dp_sink_context); } -static void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t cid, uint8_t local_seid, uint8_t remote_seid, uint8_t status){ - if (!callback) return; - uint8_t event[8]; - int pos = 0; - event[pos++] = HCI_EVENT_A2DP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = A2DP_SUBEVENT_STREAM_ESTABLISHED; - little_endian_store_16(event, pos, cid); - pos += 2; - event[pos++] = local_seid; - event[pos++] = remote_seid; - event[pos++] = status; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - static inline void a2dp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){ if (!callback) return; if (event_size < 18) return; @@ -278,7 +263,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe status = avdtp_subevent_signaling_connection_established_get_status(packet); if (status != 0){ log_info("AVDTP_SUBEVENT_SIGNALING_CONNECTION failed status %d ---", status); - a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, 0, 0, status); + a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, address, 0, 0, status); break; } app_state = A2DP_CONNECTED; @@ -296,27 +281,28 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe break; case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: + avdtp_subevent_streaming_connection_established_get_bd_addr(packet, address); status = avdtp_subevent_streaming_connection_established_get_status(packet); cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet); loc_seid = avdtp_subevent_streaming_connection_established_get_local_seid(packet); rem_seid = avdtp_subevent_streaming_connection_established_get_remote_seid(packet); if (status != 0){ - a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, status); + a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, address, loc_seid, rem_seid, status); break; } if (cid != a2dp_cid()){ - a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); + a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, address, loc_seid, rem_seid, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); break; } if (loc_seid != local_seid()){ - a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); + a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, address, loc_seid, rem_seid, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); break; } app_state = A2DP_STREAMING_OPENED; - a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, 0); + a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, address, loc_seid, rem_seid, 0); break; case AVDTP_SUBEVENT_SIGNALING_ACCEPT: diff --git a/src/classic/a2dp_source.c b/src/classic/a2dp_source.c index 90c3a780c..70781aee8 100644 --- a/src/classic/a2dp_source.c +++ b/src/classic/a2dp_source.c @@ -154,21 +154,6 @@ static inline uint8_t remote_seid(void){ return avdtp_remote_seid(sc.local_stream_endpoint); } -static void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t cid, uint8_t local_seid, uint8_t remote_seid, uint8_t status){ - if (!callback) return; - uint8_t event[8]; - int pos = 0; - event[pos++] = HCI_EVENT_A2DP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = A2DP_SUBEVENT_STREAM_ESTABLISHED; - little_endian_store_16(event, pos, cid); - pos += 2; - event[pos++] = local_seid; - event[pos++] = remote_seid; - event[pos++] = status; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - static void a2dp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t callback, uint16_t cid, uint8_t seid){ if (!callback) return; uint8_t event[8]; @@ -201,12 +186,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe switch (packet[2]){ case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: - avdtp_subevent_signaling_connection_established_get_bd_addr(packet, address); + avdtp_subevent_signaling_connection_established_get_bd_addr(packet, sc.remote_addr); cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet); status = avdtp_subevent_signaling_connection_established_get_status(packet); if (status != 0){ log_info("AVDTP_SUBEVENT_SIGNALING_CONNECTION failed status %d ---", status); - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, 0, 0, status); + a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, status); break; } @@ -272,29 +257,31 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe break; case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: + avdtp_subevent_streaming_connection_established_get_bd_addr(packet, address); + status = avdtp_subevent_streaming_connection_established_get_status(packet); cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet); if (cid != a2dp_cid()){ - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); + a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), address, local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); break; } loc_seid = avdtp_subevent_streaming_connection_established_get_local_seid(packet); if (loc_seid != local_seid()){ - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); + a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), address, local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); break; } rem_seid = avdtp_subevent_streaming_connection_established_get_remote_seid(packet); if (status != 0){ log_info("AVDTP_SUBEVENT_STREAMING_CONNECTION could not be established, status %d ---", status); - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), rem_seid, status); + a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), address, local_seid(), rem_seid, status); break; } app_state = A2DP_STREAMING_OPENED; - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), 0); + a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), address, local_seid(), remote_seid(), 0); log_info("AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- avdtp_cid 0x%02x, local seid %d, remote seid %d", a2dp_cid(), local_seid(), remote_seid()); break; @@ -311,7 +298,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe sc.active_remote_sep = avdtp_source_remote_sep(cid, next_remote_sep_index_to_query++); if (!sc.active_remote_sep) { app_state = A2DP_IDLE; - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, 0, 0, AVDTP_SEID_DOES_NOT_EXIST); + a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, AVDTP_SEID_DOES_NOT_EXIST); break; } log_info("Query get caps for seid %d", sc.active_remote_sep->seid); @@ -326,7 +313,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe } else { log_info("No more remote seps found"); app_state = A2DP_IDLE; - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, 0, 0, AVDTP_SEID_DOES_NOT_EXIST); + a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, AVDTP_SEID_DOES_NOT_EXIST); } break; case A2DP_W2_SET_CONFIGURATION:{ diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index 1639b48cb..25743ace4 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -289,6 +289,8 @@ static void handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t packet_type, uint8_t event, uint8_t *packet, uint16_t size, avdtp_context_t * context){ uint16_t local_cid; uint8_t status; + bd_addr_t address; + switch (packet_type){ case L2CAP_DATA_PACKET:{ int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size); @@ -302,28 +304,32 @@ static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp case HCI_EVENT_PACKET: switch (event){ case L2CAP_EVENT_CHANNEL_OPENED: - if (stream_endpoint->l2cap_media_cid == 0){ - if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED){ - log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED failed - stream endpoint in wrong state %d, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d", stream_endpoint->state, connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint)); - avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE); - break; - } - status = l2cap_event_channel_opened_get_status(packet); - if (status){ - log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED failed with status %d, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d", status, connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint)); - avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), status); - break; - } - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; - stream_endpoint->connection = connection; - stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet); - stream_endpoint->media_con_handle = l2cap_event_channel_opened_get_handle(packet); - - // log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d", connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint)); - avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), 0); + l2cap_event_channel_opened_get_address(packet, address); + if (stream_endpoint->l2cap_media_cid != 0){ + log_error("avdtp: channel already opened"); + avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, address, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), L2CAP_SERVICE_ALREADY_REGISTERED); + return; + } + if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED){ + log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED failed - stream endpoint in wrong state %d, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d", stream_endpoint->state, connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint)); + avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, address, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE); + break; + } + status = l2cap_event_channel_opened_get_status(packet); + if (status){ + log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED failed with status %d, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d", status, connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint)); + avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, address, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), status); break; } + stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; + stream_endpoint->connection = connection; + stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet); + stream_endpoint->media_con_handle = l2cap_event_channel_opened_get_handle(packet); + + // log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d", connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint)); + avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, address, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), 0); break; + case L2CAP_EVENT_CHANNEL_CLOSED: local_cid = l2cap_event_channel_closed_get_local_cid(packet); if (stream_endpoint->l2cap_media_cid == local_cid){ diff --git a/src/classic/avdtp_util.c b/src/classic/avdtp_util.c index 8bec7a8c8..116dff5da 100644 --- a/src/classic/avdtp_util.c +++ b/src/classic/avdtp_util.c @@ -565,15 +565,17 @@ void avdtp_streaming_emit_connection_released(btstack_packet_handler_t callback, (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint8_t status){ +void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, bd_addr_t addr, uint8_t local_seid, uint8_t remote_seid, uint8_t status){ if (!callback) return; - uint8_t event[8]; + uint8_t event[14]; int pos = 0; event[pos++] = HCI_EVENT_AVDTP_META; event[pos++] = sizeof(event) - 2; event[pos++] = AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED; little_endian_store_16(event, pos, avdtp_cid); pos += 2; + reverse_bd_addr(addr,&event[pos]); + pos += 6; event[pos++] = local_seid; event[pos++] = remote_seid; event[pos++] = status; @@ -858,3 +860,20 @@ uint8_t avdtp_remote_seid(avdtp_stream_endpoint_t * stream_endpoint){ if (!stream_endpoint->connection) return 0; return stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid; } + +void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t cid, bd_addr_t addr, uint8_t local_seid, uint8_t remote_seid, uint8_t status){ + if (!callback) return; + uint8_t event[14]; + int pos = 0; + event[pos++] = HCI_EVENT_A2DP_META; + event[pos++] = sizeof(event) - 2; + event[pos++] = A2DP_SUBEVENT_STREAM_ESTABLISHED; + little_endian_store_16(event, pos, cid); + pos += 2; + reverse_bd_addr(addr,&event[pos]); + pos += 6; + event[pos++] = local_seid; + event[pos++] = remote_seid; + event[pos++] = status; + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); +} diff --git a/src/classic/avdtp_util.h b/src/classic/avdtp_util.h index f3ac561d5..01c180e5b 100644 --- a/src/classic/avdtp_util.h +++ b/src/classic/avdtp_util.h @@ -78,7 +78,7 @@ void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uin int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer); void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, bd_addr_t addr, uint8_t status); -void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint8_t status); +void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, bd_addr_t addr, uint8_t int_seid, uint8_t acp_seid, uint8_t status); void avdtp_signaling_emit_connection_released(btstack_packet_handler_t callback, uint16_t avdtp_cid); void avdtp_streaming_emit_connection_released(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid); @@ -110,6 +110,8 @@ uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint); uint8_t avdtp_remote_seid(avdtp_stream_endpoint_t * stream_endpoint); const char * avdtp_si2str(uint16_t index); +void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t cid, bd_addr_t addr, uint8_t local_seid, uint8_t remote_seid, uint8_t status); + #if defined __cplusplus } #endif