From d8b859a262ef210d04bceba7f9228a540da8bd3b Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Fri, 1 Dec 2017 15:23:03 +0100 Subject: [PATCH] avdtp: on reject set configuration change role from initiator to acceptor, and set timer to repeat set configuration until successful --- src/classic/avdtp.c | 27 ++++++++++++++++++++++++++- src/classic/avdtp.h | 6 +++++- src/classic/avdtp_acceptor.c | 2 +- src/classic/avdtp_initiator.c | 15 ++++++++++++--- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index b093fb8df..a0baab56f 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -49,6 +49,8 @@ #include "classic/avdtp_acceptor.h" #include "classic/avdtp_initiator.h" +#define CONFIGURATION_TIMEOUT_MS 300 + static int record_id = -1; static uint8_t attribute_value[1000]; static const unsigned int attribute_value_buffer_size = sizeof(attribute_value); @@ -70,6 +72,29 @@ static uint16_t avdtp_cid_counter = 0x55; static void (*handle_media_data)(uint8_t local_seid, uint8_t *packet, uint16_t size); static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +void avdtp_configuration_timeout_handler(btstack_timer_source_t * timer){ + avdtp_connection_t * connection = (avdtp_connection_t *) btstack_run_loop_get_timer_context(timer); + if (!connection){ + log_error("Context of avdtp_configuration_timeout_handler is NULL"); + return; + } + connection->is_initiator = 1; + connection->is_configuration_initiated_locally = 1; + avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); +} + +void avdtp_configuration_timer_start(avdtp_connection_t * connection){ + btstack_run_loop_remove_timer(&connection->configuration_timer); + btstack_run_loop_set_timer_handler(&connection->configuration_timer, avdtp_configuration_timeout_handler); + btstack_run_loop_set_timer_context(&connection->configuration_timer, connection); + btstack_run_loop_set_timer(&connection->configuration_timer, CONFIGURATION_TIMEOUT_MS); + btstack_run_loop_add_timer(&connection->configuration_timer); +} + +void avdtp_configuration_timer_stop(avdtp_connection_t * connection){ + btstack_run_loop_remove_timer(&connection->configuration_timer); +} + static uint16_t avdtp_get_next_initiator_transaction_label(avdtp_context_t * context){ context->initiator_transaction_id_counter++; if (context->initiator_transaction_id_counter == 0){ @@ -907,7 +932,7 @@ void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t rem log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d", local_seid); return; } - connection->is_configuration_initiated_localy = 1; + connection->is_configuration_initiated_locally = 1; connection->is_initiator = 1; connection->initiator_transaction_label++; diff --git a/src/classic/avdtp.h b/src/classic/avdtp.h index 50d0b0467..b38c1958a 100644 --- a/src/classic/avdtp.h +++ b/src/classic/avdtp.h @@ -414,7 +414,8 @@ typedef struct { // store current role uint8_t is_initiator; - uint8_t is_configuration_initiated_localy; + uint8_t is_configuration_initiated_locally; + btstack_timer_source_t configuration_timer; } avdtp_connection_t; typedef enum { @@ -563,6 +564,9 @@ uint8_t avdtp_choose_sbc_max_bitpool_value(avdtp_stream_endpoint_t * stream_endp uint8_t avdtp_choose_sbc_min_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_min_bitpool_value); uint8_t avdtp_stream_endpoint_seid(avdtp_stream_endpoint_t * stream_endpoint); +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); #if defined __cplusplus } diff --git a/src/classic/avdtp_acceptor.c b/src/classic/avdtp_acceptor.c index 006eeee9b..09757ae8d 100644 --- a/src/classic/avdtp_acceptor.c +++ b/src/classic/avdtp_acceptor.c @@ -194,7 +194,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES; break; case AVDTP_SI_SET_CONFIGURATION:{ - if (connection->is_configuration_initiated_localy){ + if (connection->is_configuration_initiated_locally){ log_info("ACP: Set configuration already initiated localy, reject cmd "); // fire configuration parsing errors connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; diff --git a/src/classic/avdtp_initiator.c b/src/classic/avdtp_initiator.c index 9b7b38b35..1f2c0c6e7 100644 --- a/src/classic/avdtp_initiator.c +++ b/src/classic/avdtp_initiator.c @@ -37,7 +37,6 @@ #define __BTSTACK_FILE__ "avdtp_initiator.c" - #include #include #include @@ -48,7 +47,6 @@ #include "classic/avdtp_util.h" #include "classic/avdtp_initiator.h" - static int avdtp_initiator_send_signaling_cmd(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t transaction_label){ uint8_t command[2]; command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_CMD_MSG); @@ -168,6 +166,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ break; case AVDTP_SI_SET_CONFIGURATION:{ + avdtp_configuration_timer_stop(connection); if (!stream_endpoint){ log_error("AVDTP_SI_SET_CONFIGURATION: stream endpoint is null"); break; @@ -260,6 +259,15 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ connection->initiator_transaction_label++; break; case AVDTP_RESPONSE_REJECT_MSG: + switch (connection->signaling_packet.signal_identifier){ + case AVDTP_SI_SET_CONFIGURATION: + connection->is_initiator = 0; + log_info("Received reject for set configuration, role changed from initiator to acceptor."); + avdtp_configuration_timer_start(connection); + break; + default: + break; + } log_info(" AVDTP_RESPONSE_REJECT_MSG signal %d", connection->signaling_packet.signal_identifier); avdtp_signaling_emit_reject(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->signaling_packet.signal_identifier); return; @@ -375,9 +383,10 @@ int sent = 1; case AVDTP_INITIATOR_W2_SET_CONFIGURATION: case AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID:{ if (!connection->is_initiator){ - connection->is_configuration_initiated_localy = 0; + connection->is_configuration_initiated_locally = 0; break; } + connection->is_configuration_initiated_locally = 1; log_info("INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d", connection->local_seid, connection->remote_seid); // log_info_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len);