From 49307b6323d817317a24880846c7a7fc77c53d07 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Tue, 17 Apr 2018 15:27:08 +0200 Subject: [PATCH] avdtp: remove list of remote seps, emit instead seps to the app, with event done to mark the end --- src/classic/a2dp_source.c | 34 ++++++++----- src/classic/avdtp.c | 83 +++++++++++++++----------------- src/classic/avdtp.h | 14 +++--- src/classic/avdtp_acceptor.c | 35 +++++--------- src/classic/avdtp_initiator.c | 41 ++++++---------- src/classic/avdtp_source.c | 7 --- src/classic/avdtp_source.h | 2 - src/classic/avdtp_util.c | 78 +++++++++++++++--------------- src/classic/avdtp_util.h | 9 ++-- test/pts/avrcp_controller_test.c | 14 +++--- 10 files changed, 145 insertions(+), 172 deletions(-) diff --git a/src/classic/a2dp_source.c b/src/classic/a2dp_source.c index 3ebcba9f7..db7515db4 100644 --- a/src/classic/a2dp_source.c +++ b/src/classic/a2dp_source.c @@ -49,6 +49,7 @@ #include "classic/avdtp_source.h" #include "classic/a2dp_source.h" +#define AVDTP_MAX_SEP_NUM 10 #define AVDTP_MEDIA_PAYLOAD_HEADER_SIZE 12 static const char * default_a2dp_source_service_name = "BTstack A2DP Source Service"; @@ -57,6 +58,8 @@ static avdtp_context_t a2dp_source_context; static a2dp_state_t app_state = A2DP_IDLE; static avdtp_stream_endpoint_context_t sc; +static avdtp_sep_t remote_seps[AVDTP_MAX_SEP_NUM]; +static int remote_seps_index = 0; static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); @@ -227,12 +230,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe sc.active_remote_sep = NULL; sc.active_remote_sep_index = 0; app_state = A2DP_W2_DISCOVER_SEPS; + remote_seps_index = 0; + memset(remote_seps, 0, sizeof(avdtp_sep_t) * AVDTP_MAX_SEP_NUM); a2dp_signaling_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, status); avdtp_source_discover_stream_endpoints(cid); break; } - case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND: - break; case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:{ log_info("A2DP received SBC capability."); @@ -327,6 +330,21 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, address, local_seid, remote_seid, 0); break; + case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:{ + avdtp_sep_t sep; + sep.seid = avdtp_subevent_signaling_sep_found_get_remote_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); + log_info("Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)", sep.seid, sep.in_use, sep.media_type, sep.type); + remote_seps[remote_seps_index++] = sep; + break; + } + case AVDTP_SUBEVENT_SIGNALING_SEP_DICOVERY_DONE: + app_state = A2DP_W2_GET_CAPABILITIES; + sc.active_remote_sep_index = 0; + break; + case AVDTP_SUBEVENT_SIGNALING_ACCEPT: // TODO check cid signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); @@ -334,17 +352,11 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe log_info("A2DP Accepted %d, state %d", signal_identifier, app_state); switch (app_state){ - case A2DP_W2_DISCOVER_SEPS: case A2DP_W2_GET_CAPABILITIES: - case A2DP_W2_GET_ALL_CAPABILITIES: - app_state = A2DP_W2_GET_ALL_CAPABILITIES; - sc.active_remote_sep = avdtp_source_remote_sep(cid, sc.active_remote_sep_index++); - if (!sc.active_remote_sep) { - app_state = A2DP_IDLE; - a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, AVDTP_SEID_DOES_NOT_EXIST); - break; + if (sc.active_remote_sep_index < remote_seps_index){ + sc.active_remote_sep = &remote_seps[sc.active_remote_sep_index++]; + avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid); } - avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid); break; case A2DP_W2_SET_CONFIGURATION:{ if (!sc.local_stream_endpoint) return; diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index 19932e86d..e1a528223 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -654,7 +654,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet local_cid = l2cap_event_channel_closed_get_local_cid(packet); connection = avdtp_connection_for_l2cap_signaling_cid(local_cid, context); stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(local_cid, context); - log_info("Neceived L2CAP_EVENT_CHANNEL_CLOSED, cid 0x%2x, connection %p, stream_endpoint %p", local_cid, connection, stream_endpoint); + log_info("Received L2CAP_EVENT_CHANNEL_CLOSED, cid 0x%2x, connection %p, stream_endpoint %p", local_cid, connection, stream_endpoint); if (stream_endpoint){ if (stream_endpoint->l2cap_media_cid == local_cid){ @@ -662,11 +662,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet if (connection) { avdtp_streaming_emit_connection_released(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint)); } - stream_endpoint->l2cap_media_cid = 0; - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE; - stream_endpoint->remote_sep_index = 0; + avdtp_reset_stream_endpoint(stream_endpoint); if (connection && connection->disconnect){ avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid); } @@ -686,19 +682,17 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet } if (connection){ - btstack_run_loop_remove_timer(&connection->configuration_timer); - avdtp_signaling_emit_connection_released(context->avdtp_callback, connection->avdtp_cid); - - btstack_linked_list_remove(avdtp_connections, (btstack_linked_item_t*) connection); btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, stream_endpoints); while (btstack_linked_list_iterator_has_next(&it)){ avdtp_stream_endpoint_t * _stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - if (_stream_endpoint->connection == connection){ - avdtp_initialize_stream_endpoint(_stream_endpoint); + avdtp_reset_stream_endpoint(_stream_endpoint); } } + btstack_run_loop_remove_timer(&connection->configuration_timer); + avdtp_signaling_emit_connection_released(context->avdtp_callback, connection->avdtp_cid); + btstack_linked_list_remove(avdtp_connections, (btstack_linked_item_t*) connection); btstack_memory_avdtp_connection_free(connection); break; } @@ -749,10 +743,6 @@ uint8_t avdtp_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote log_error("avdtp_media_connect: no connection for signaling cid 0x%02x found", avdtp_cid); return AVDTP_CONNECTION_DOES_NOT_EXIST; } - if (avdtp_find_remote_sep(connection, remote_seid) == 0xFF){ - log_error("avdtp_media_connect: no remote sep for seid %d found", remote_seid); - return AVDTP_SEID_DOES_NOT_EXIST; - } if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { log_error("avdtp_media_connect: wrong connection state %d", connection->state); @@ -764,10 +754,14 @@ uint8_t avdtp_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote log_error("avdtp_media_connect: no stream_endpoint with seid %d found", local_seid); return AVDTP_SEID_DOES_NOT_EXIST; } + + if (stream_endpoint->remote_sep.seid != remote_seid){ + log_error("avdtp_media_connect: no remote sep with seid %d registered with the stream endpoint", remote_seid); + return AVDTP_SEID_DOES_NOT_EXIST; + } if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE; - if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return AVDTP_SEID_DOES_NOT_EXIST; - + connection->initiator_transaction_label++; connection->remote_seid = remote_seid; connection->local_seid = local_seid; @@ -795,8 +789,9 @@ uint8_t avdtp_start_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST; } - if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX || stream_endpoint->start_stream){ - return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE; + if (!is_avdtp_remote_seid_registered(stream_endpoint)){ + log_error("avdtp_media_connect: no remote sep registered with the stream endpoint"); + return AVDTP_SEID_DOES_NOT_EXIST; } stream_endpoint->start_stream = 1; @@ -822,8 +817,11 @@ uint8_t avdtp_stop_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_ log_error("avdtp_stop_stream: no media connection for stream_endpoint with seid %d found", local_seid); return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST; } - if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return ERROR_CODE_SUCCESS; + if (!is_avdtp_remote_seid_registered(stream_endpoint) || stream_endpoint->stop_stream){ + return ERROR_CODE_SUCCESS; + } + stream_endpoint->stop_stream = 1; connection->local_seid = local_seid; avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); @@ -847,7 +845,10 @@ uint8_t avdtp_abort_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context log_error("avdtp_abort_stream: no media connection for stream_endpoint with seid %d found", local_seid); return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST; } - if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->abort_stream) return ERROR_CODE_SUCCESS; + + if (!is_avdtp_remote_seid_registered(stream_endpoint) || stream_endpoint->abort_stream){ + return ERROR_CODE_SUCCESS; + } stream_endpoint->abort_stream = 1; connection->local_seid = local_seid; @@ -871,8 +872,11 @@ uint8_t avdtp_suspend_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_conte log_error("avdtp_suspend_stream: no media connection for stream_endpoint with seid %d found", local_seid); return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST; } - if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->suspend_stream) return ERROR_CODE_SUCCESS; + if (!is_avdtp_remote_seid_registered(stream_endpoint) || stream_endpoint->suspend_stream){ + return ERROR_CODE_SUCCESS; + } + stream_endpoint->suspend_stream = 1; connection->local_seid = local_seid; avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); @@ -956,6 +960,7 @@ uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t } if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED || connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) { + log_error("connection in wrong state, %d, initiator state %d", connection->state, connection->initiator_connection_state); return AVDTP_CONNECTION_IN_WRONG_STATE; } @@ -965,7 +970,7 @@ uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t return AVDTP_STREAM_ENDPOINT_DOES_NOT_EXIST; } if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_CONFIGURED){ - log_error("Ntream endpoint seid %d in wrong state", local_seid); + log_error("Stream endpoint seid %d in wrong state %d", local_seid, stream_endpoint->state); return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE; } connection->active_stream_endpoint = (void*) stream_endpoint; @@ -1006,10 +1011,11 @@ uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote return AVDTP_STREAM_ENDPOINT_DOES_NOT_EXIST; } - if (stream_endpoint->remote_sep_index == 0xFF){ + if (!is_avdtp_remote_seid_registered(stream_endpoint)){ log_error("avdtp_reconfigure: no associated remote sep"); return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE; } + connection->initiator_transaction_label++; connection->remote_seid = remote_seid; connection->local_seid = local_seid; @@ -1019,26 +1025,6 @@ uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); } -uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context){ - avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); - if (!connection){ - log_error("avdtp_suspend: no connection for AVDTP cid 0x%02x found", avdtp_cid); - return 0; - } - return connection->remote_seps_num; -} - -avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context){ - avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); - if (!connection){ - log_error("avdtp_suspend: no connection for AVDTP cid 0x%02x found", avdtp_cid); - return NULL; - } - if (index == AVDTP_INVALID_SEP_INDEX) return NULL; - if (index >= connection->remote_seps_num || index >= AVDTP_MAX_NUM_SEPS) return NULL; - return &connection->remote_seps[index]; -} - void avdtp_initialize_sbc_configuration_storage(avdtp_stream_endpoint_t * stream_endpoint, uint8_t * config_storage, uint16_t storage_size, uint8_t * packet, uint16_t packet_size){ UNUSED(packet_size); if (storage_size < 4) { @@ -1161,3 +1147,10 @@ uint8_t avdtp_choose_sbc_min_bitpool_value(avdtp_stream_endpoint_t * stream_endp uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information; return btstack_max(media_codec[2], remote_min_bitpool_value); } + +uint8_t is_avdtp_remote_seid_registered(avdtp_stream_endpoint_t * stream_endpoint){ + if (!stream_endpoint) return 0; + if (stream_endpoint->remote_sep.seid == 0) return 0; + if (stream_endpoint->remote_sep.seid > 0x3E) return 0; + return 1; +} \ No newline at end of file diff --git a/src/classic/avdtp.h b/src/classic/avdtp.h index b242a5779..e734f24c2 100644 --- a/src/classic/avdtp.h +++ b/src/classic/avdtp.h @@ -97,6 +97,9 @@ extern "C" { // ACP to INT, Procedure Error Codes #define BAD_STATE 0x31 + +#define AVDTP_INVALID_SEP_SEID 0xFF + // Signal Identifier fields typedef enum { AVDTP_SI_NONE = 0x00, @@ -412,8 +415,8 @@ typedef struct { uint8_t error_code; // store configurations with remote seps - avdtp_sep_t remote_seps[AVDTP_MAX_NUM_SEPS]; - uint8_t remote_seps_num; + // avdtp_sep_t remote_seps[AVDTP_MAX_NUM_SEPS]; + // uint8_t remote_seps_num; // store current role uint8_t is_initiator; @@ -445,6 +448,7 @@ typedef struct avdtp_stream_endpoint { // original capabilities avdtp_sep_t sep; + avdtp_sep_t remote_sep; hci_con_handle_t media_con_handle; uint16_t l2cap_media_cid; uint16_t l2cap_reporting_cid; @@ -457,7 +461,7 @@ typedef struct avdtp_stream_endpoint { // active connection avdtp_connection_t * connection; // currently active remote seid - uint8_t remote_sep_index; + // uint8_t remote_sep_index; avdtp_capabilities_t remote_capabilities; uint16_t remote_capabilities_bitmap; @@ -477,7 +481,6 @@ typedef struct avdtp_stream_endpoint { uint8_t send_stream; uint8_t abort_stream; uint8_t suspend_stream; - uint16_t sequence_number; } avdtp_stream_endpoint_t; @@ -553,8 +556,6 @@ uint8_t avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdt uint8_t avdtp_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context); uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context); uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context); -uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context); -avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context); void avdtp_initialize_sbc_configuration_storage(avdtp_stream_endpoint_t * stream_endpoint, uint8_t * config_storage, uint16_t storage_size, uint8_t * packet, uint16_t packet_size); uint8_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap); @@ -571,6 +572,7 @@ void avdtp_configuration_timeout_handler(btstack_timer_source_t * timer); void avdtp_configuration_timer_start(avdtp_connection_t * connection); void avdtp_configuration_timer_stop(avdtp_connection_t * connection); +uint8_t is_avdtp_remote_seid_registered(avdtp_stream_endpoint_t * stream_endpoint); #if defined __cplusplus } #endif diff --git a/src/classic/avdtp_acceptor.c b/src/classic/avdtp_acceptor.c index 0392fc40c..a6d16bfa7 100644 --- a/src/classic/avdtp_acceptor.c +++ b/src/classic/avdtp_acceptor.c @@ -207,7 +207,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t log_info("acceptor SM received SET_CONFIGURATION cmd: change role to acceptor, is_initiator %d", connection->is_initiator); } - log_info("ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION "); + log_info("ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION connection %p", connection); stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURATION_SUBSTATEMACHINE; stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION; connection->reject_service_category = 0; @@ -225,17 +225,11 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t } // find or add sep - stream_endpoint->remote_sep_index = avdtp_find_remote_sep(stream_endpoint->connection, sep.seid); - log_info("ACP .. seid %d, index %d", sep.seid, stream_endpoint->remote_sep_index); + log_info("ACP .. seid %d, remote sep seid %d", sep.seid, stream_endpoint->remote_sep.seid); - if (stream_endpoint->remote_sep_index != AVDTP_INVALID_SEP_INDEX){ - if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].in_use){ - if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED){ - stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep; - log_info("ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); - break; - } - // reject if already configured + if (is_avdtp_remote_seid_registered(stream_endpoint)){ + if (stream_endpoint->remote_sep.in_use){ + log_info("reject as it is already in use"); connection->error_code = SEP_IN_USE; // find first registered category and fire the error connection->reject_service_category = 0; @@ -249,16 +243,14 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; } else { - stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep; - log_info("ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); + stream_endpoint->remote_sep = sep; + log_info("ACP: update seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint); } } else { // add new log_info("ACP: seid %d not found in %p", sep.seid, stream_endpoint); - stream_endpoint->remote_sep_index = connection->remote_seps_num; - connection->remote_seps_num++; - connection->remote_seps[stream_endpoint->remote_sep_index] = sep; - log_info("ACP: add seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); + stream_endpoint->remote_sep = sep; + log_info("ACP: add seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint); } avdtp_emit_configuration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), &sep.configuration, sep.configured_service_categories); @@ -281,16 +273,15 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t } // find sep or raise error - stream_endpoint->remote_sep_index = avdtp_find_remote_sep(stream_endpoint->connection, sep.seid); - if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX){ + if (!is_avdtp_remote_seid_registered(stream_endpoint)){ log_info("ACP: REJECT AVDTP_SI_RECONFIGURE, BAD_ACP_SEID"); stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; connection->error_code = BAD_ACP_SEID; connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; break; } - stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep; - log_info("ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); + stream_endpoint->remote_sep = sep; + log_info("ACP: update seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint); avdtp_emit_configuration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), &sep.configuration, sep.configured_service_categories); avdtp_signaling_emit_accept(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->signaling_packet.signal_identifier); @@ -534,7 +525,7 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd break; case AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION:{ - avdtp_sep_t sep = stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index]; + avdtp_sep_t sep = stream_endpoint->remote_sep; avdtp_prepare_capabilities(&connection->signaling_packet, trid, sep.configured_service_categories, sep.configuration, AVDTP_SI_GET_CONFIGURATION); l2cap_reserve_packet_buffer(); out_buffer = l2cap_get_outgoing_buffer(); diff --git a/src/classic/avdtp_initiator.c b/src/classic/avdtp_initiator.c index 0a3271b5f..c38cc6d79 100644 --- a/src/classic/avdtp_initiator.c +++ b/src/classic/avdtp_initiator.c @@ -66,7 +66,6 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ // int status = 0; avdtp_stream_endpoint_t * stream_endpoint = NULL; - uint8_t remote_sep_index; avdtp_sep_t sep; if (connection->initiator_connection_state == AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER) { connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE; @@ -97,7 +96,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ break; } - int i; + int i; for (i = offset; i < size; i += 2){ sep.seid = packet[i] >> 2; offset++; @@ -109,12 +108,9 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ sep.in_use = (packet[i] >> 1) & 0x01; sep.media_type = (avdtp_media_type_t)(packet[i+1] >> 4); sep.type = (avdtp_sep_type_t)((packet[i+1] >> 3) & 0x01); - - if (avdtp_find_remote_sep(connection, sep.seid) == 0xFF){ - connection->remote_seps[connection->remote_seps_num++] = sep; - } avdtp_signaling_emit_sep(context->avdtp_callback, connection->avdtp_cid, sep); } + avdtp_signaling_emit_sep_done(context->avdtp_callback, connection->avdtp_cid); break; } @@ -147,12 +143,10 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+4, connection->signaling_packet.size-4); // TODO check if configuration is supported - remote_sep_index = avdtp_find_remote_sep(connection, sep.seid); - if (remote_sep_index != 0xFF){ - stream_endpoint->remote_sep_index = remote_sep_index; - connection->remote_seps[stream_endpoint->remote_sep_index] = sep; + if (!is_avdtp_remote_seid_registered(stream_endpoint)){ + stream_endpoint->remote_sep = sep; stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED; - log_info("INT: update seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); + log_info("INT: update seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint); } break; @@ -165,20 +159,13 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ sep.configured_service_categories = stream_endpoint->remote_configuration_bitmap; sep.configuration = stream_endpoint->remote_configuration; sep.in_use = 1; - // TODO check if configuration is supported - // find or add sep - remote_sep_index = avdtp_find_remote_sep(connection, sep.seid); - if (remote_sep_index != 0xFF){ - stream_endpoint->remote_sep_index = remote_sep_index; - } else { - stream_endpoint->remote_sep_index = connection->remote_seps_num; - connection->remote_seps_num++; - } - connection->remote_seps[stream_endpoint->remote_sep_index] = sep; - log_info("INT: configured remote seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED; - + stream_endpoint->remote_sep = sep; + stream_endpoint->connection = connection; + + log_info("INT: configured remote seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint); + switch (stream_endpoint->media_codec_type){ case AVDTP_CODEC_SBC: avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->remote_seid, @@ -186,7 +173,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ break; default: // TODO: we don\t have codec info to emit config - // avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->remote_seid, sep.configuration.media_codec); + avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->remote_seid, sep.configuration.media_codec); break; } @@ -317,7 +304,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av stream_endpoint->start_stream = 0; if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_OPENED){ connection->local_seid = stream_endpoint->sep.seid; - connection->remote_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid; + connection->remote_seid = stream_endpoint->remote_sep.seid; avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label++, connection->remote_seid); return; } @@ -328,7 +315,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av stream_endpoint->stop_stream = 0; if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED){ connection->local_seid = stream_endpoint->sep.seid; - connection->remote_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid; + connection->remote_seid = stream_endpoint->remote_sep.seid; avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label++, connection->remote_seid); return; } @@ -342,7 +329,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av case AVDTP_STREAM_ENDPOINT_OPENED: case AVDTP_STREAM_ENDPOINT_STREAMING: connection->local_seid = stream_endpoint->sep.seid; - connection->remote_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid; + connection->remote_seid = stream_endpoint->remote_sep.seid; stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING; avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label++, connection->remote_seid); return; diff --git a/src/classic/avdtp_source.c b/src/classic/avdtp_source.c index e9511f551..3993b3874 100644 --- a/src/classic/avdtp_source.c +++ b/src/classic/avdtp_source.c @@ -175,10 +175,3 @@ void avdtp_source_init(avdtp_context_t * avdtp_context){ l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0); } -uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid){ - return avdtp_remote_seps_num(avdtp_cid, avdtp_source_context); -} - -avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index){ - return avdtp_remote_sep(avdtp_cid, index, avdtp_source_context); -} diff --git a/src/classic/avdtp_source.h b/src/classic/avdtp_source.h index 6897a5541..b3010b1ff 100644 --- a/src/classic/avdtp_source.h +++ b/src/classic/avdtp_source.h @@ -152,8 +152,6 @@ uint8_t avdtp_source_suspend(uint16_t avdtp_cid, uint8_t local_seid); avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type); -uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid); -avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index); /* API_END */ #if defined __cplusplus diff --git a/src/classic/avdtp_util.c b/src/classic/avdtp_util.c index d968f0291..bea340ec4 100644 --- a/src/classic/avdtp_util.c +++ b/src/classic/avdtp_util.c @@ -70,15 +70,33 @@ const char * avdtp_si2str(uint16_t index){ return avdtp_si_name[index]; } -void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){ +void avdtp_reset_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){ + stream_endpoint->media_con_handle = 0; + stream_endpoint->l2cap_media_cid = 0; + stream_endpoint->l2cap_reporting_cid = 0; + stream_endpoint->l2cap_recovery_cid = 0; + stream_endpoint->connection = NULL; stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE; stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE; - stream_endpoint->remote_sep_index = AVDTP_INVALID_SEP_INDEX; - stream_endpoint->media_disconnect = 0; + stream_endpoint->sep.in_use = 0; - stream_endpoint->remote_sep_index = 0; + memset(&stream_endpoint->remote_sep, 0, sizeof(avdtp_sep_t)); + memset(&stream_endpoint->remote_capabilities, 0, sizeof(avdtp_capabilities_t)); + memset(&stream_endpoint->remote_configuration, 0, sizeof(avdtp_capabilities_t)); + + stream_endpoint->remote_capabilities_bitmap = 0; + stream_endpoint->remote_configuration_bitmap = 0; + + stream_endpoint->media_disconnect = 0; + stream_endpoint->media_connect = 0; + stream_endpoint->start_stream = 0; + stream_endpoint->stop_stream = 0; + stream_endpoint->send_stream = 0; + stream_endpoint->abort_stream = 0; + stream_endpoint->suspend_stream = 0; + stream_endpoint->sequence_number = 0; } avdtp_stream_endpoint_t * avdtp_stream_endpoint_for_seid(uint16_t seid, avdtp_context_t * context){ @@ -175,12 +193,8 @@ avdtp_stream_endpoint_t * avdtp_stream_endpoint_associated_with_acp_seid(uint16_ btstack_linked_list_iterator_init(&it, &context->stream_endpoints); while (btstack_linked_list_iterator_has_next(&it)){ avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - - if (stream_endpoint->remote_sep_index != AVDTP_INVALID_SEP_INDEX){ - if (!stream_endpoint->connection) continue; - if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){ - return stream_endpoint; - } + if (stream_endpoint->remote_sep.seid == acp_seid){ + return stream_endpoint; } } return NULL; @@ -619,6 +633,19 @@ void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_ (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } +void avdtp_signaling_emit_sep_done(btstack_packet_handler_t callback, uint16_t avdtp_cid){ + if (!callback) return; + uint8_t event[5]; + int pos = 0; + event[pos++] = HCI_EVENT_AVDTP_META; + event[pos++] = sizeof(event) - 2; + event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_DICOVERY_DONE; + little_endian_store_16(event, pos, avdtp_cid); + pos += 2; + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); +} + + void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, avdtp_signal_identifier_t identifier){ if (!callback) return; uint8_t event[7]; @@ -1024,32 +1051,6 @@ uint8_t avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_ return ERROR_CODE_SUCCESS; } -uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t seid){ - if (!stream_endpoint->connection) return AVDTP_INVALID_SEP_INDEX; - if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid == seid){ - return stream_endpoint->remote_sep_index; - } - int i; - for (i=0; i < stream_endpoint->connection->remote_seps_num; i++){ - if (stream_endpoint->connection->remote_seps[i].seid == seid){ - return i; - } - } - return AVDTP_INVALID_SEP_INDEX; -} - -uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_seid){ - if (!connection) return AVDTP_INVALID_SEP_INDEX; - int i; - for (i = 0; i < connection->remote_seps_num; i++){ - if (connection->remote_seps[i].seid == remote_seid){ - return i; - } - } - return AVDTP_INVALID_SEP_INDEX; -} - - uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint){ if (!stream_endpoint) return 0; return stream_endpoint->sep.seid; @@ -1057,9 +1058,8 @@ uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint){ } uint8_t avdtp_remote_seid(avdtp_stream_endpoint_t * stream_endpoint){ - if (!stream_endpoint) return 0; - if (!stream_endpoint->connection) return 0; - return stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid; + if (!stream_endpoint) return AVDTP_INVALID_SEP_SEID; + return stream_endpoint->remote_sep.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){ diff --git a/src/classic/avdtp_util.h b/src/classic/avdtp_util.h index 7e88262ff..5c462c869 100644 --- a/src/classic/avdtp_util.h +++ b/src/classic/avdtp_util.h @@ -52,8 +52,6 @@ extern "C" { #endif -#define AVDTP_INVALID_SEP_INDEX 0xff - avdtp_connection_t * avdtp_connection_for_bd_addr(bd_addr_t addr, avdtp_context_t * context); avdtp_connection_t * avdtp_connection_for_avdtp_cid(uint16_t l2cap_cid, avdtp_context_t * context); avdtp_connection_t * avdtp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context); @@ -85,6 +83,8 @@ void avdtp_signaling_emit_connection_released(btstack_packet_handler_t callback, void avdtp_streaming_emit_connection_released(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid); void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_cid, avdtp_sep_t sep); +void avdtp_signaling_emit_sep_done(btstack_packet_handler_t callback, uint16_t avdtp_cid); + void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t seid, avdtp_signal_identifier_t identifier); void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier); void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier); @@ -102,10 +102,7 @@ uint8_t avdtp_request_can_send_now_acceptor(avdtp_connection_t * connection, uin uint8_t avdtp_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid); uint8_t avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid); -uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t acp_seid); - -void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint); -uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_seid); +void avdtp_reset_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint); // uint16_t avdtp_cid(avdtp_stream_endpoint_t * stream_endpoint); uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint); diff --git a/test/pts/avrcp_controller_test.c b/test/pts/avrcp_controller_test.c index 61261c795..9539a01c9 100644 --- a/test/pts/avrcp_controller_test.c +++ b/test/pts/avrcp_controller_test.c @@ -43,6 +43,7 @@ #include #include "btstack.h" +#include "btstack_stdin_pts.h" #define AVRCP_BROWSING_ENABLED 1 #define AVRCP_BROWSING_MAX_PLAYERS 10 @@ -106,6 +107,7 @@ typedef struct { uint8_t num_attributes; } avrcp_browsable_media_element_item_t; +void btstack_stdin_pts_setup(void (*stdin_handler)(char * c, int size)); static uint8_t parent_folder_set = 0; static uint8_t parent_folder_uid[8]; @@ -248,9 +250,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe memcpy(media_element_items[index].uid, packet+pos, 8); printf("Received media element item UID (index %d): ", index); - uint32_t media_uid_high = big_endian_read_32(packet, pos); + // uint32_t media_uid_high = big_endian_read_32(packet, pos); pos += 4; - uint32_t media_uid_low = big_endian_read_32(packet, pos+4); + // uint32_t media_uid_low = big_endian_read_32(packet, pos+4); pos += 4; avrcp_browsing_media_type_t media_type = packet[pos++]; @@ -292,9 +294,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe uint32_t attr_id = avrcp_media_item_iterator_get_attr_id(&media_item_context); uint16_t attr_charset = avrcp_media_item_iterator_get_attr_charset(&media_item_context); uint16_t attr_value_length = avrcp_media_item_iterator_get_attr_value_len(&media_item_context); - uint8_t * attr_value = avrcp_media_item_iterator_get_attr_value(&media_item_context); - attr_value[attr_value_length] = 0; - + const uint8_t * attr_value = avrcp_media_item_iterator_get_attr_value(&media_item_context); printf(" - attr ID 0x%08" PRIx32 ", charset 0x%02x, actual len %d, name %s\n", attr_id, attr_charset, attr_value_length, attr_value); } } @@ -321,7 +321,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe printf("AVDTP connection released: avdtp_cid 0x%02x.\n", avdtp_cid); break; default: - printf("AVDTP event not parsed.\n"); + // printf("AVDTP event not parsed.\n"); break; } break; @@ -985,7 +985,7 @@ static void stdin_process(char * cmd, int size){ status = avrcp_controller_play_item_for_scope(avrcp_cid, media_element_items[0].uid, media_element_item_index, AVRCP_BROWSING_NOW_PLAYING); break; - case '53': + case '5': printf("Add to now playing: first media item from virtual file system\n"); if (media_element_item_index < 0){ printf("AVRCP Browsing: no media items found\n");