diff --git a/CHANGELOG.md b/CHANGELOG.md index f110bdde5..6c97a102a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - SM: fix CTKD key distribution over BR/EDR - SM: fix CTKD after BR/EDR Role Change - A2DP: emit stream established if peer set-up configuration +- AVDTP: fix SDP Client registration bug that could block other SDP queries - HIOS Client: emit disconnected event on HCI disconnect and free connection struct - Scan Parameter Service Client: emit disconnected event on HCI disconnect and free connection struct - PBAP Client: fix PBAP_SUBEVENT_OPERATION_COMPLETED with OBEX_DISCONNECTED for pbap_disconnect diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index 75f6f5fbe..f1acb85a3 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -734,78 +734,60 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c log_error("SDP query, connection with 0x%02x cid not found", avdtp_sdp_query_context_avdtp_cid); return; } - + uint8_t status = ERROR_CODE_SUCCESS; - switch (connection->state){ - case AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SINK_COMPLETE: - switch (hci_event_packet_get_type(packet)){ - case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: - avdtp_handle_sdp_client_query_attribute_value(connection, packet); - return; - case SDP_EVENT_QUERY_COMPLETE: - status = sdp_event_query_complete_get_status(packet); - if (status != ERROR_CODE_SUCCESS) break; - if (!connection->sink_supported || (connection->avdtp_l2cap_psm == 0)) { - status = SDP_SERVICE_NOT_FOUND; - break; - } - break; - default: - btstack_assert(false); - return; - } + switch (hci_event_packet_get_type(packet)){ + case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: + avdtp_handle_sdp_client_query_attribute_value(connection, packet); + return; + case SDP_EVENT_QUERY_COMPLETE: + status = sdp_event_query_complete_get_status(packet); break; - case AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SOURCE_COMPLETE: - switch (hci_event_packet_get_type(packet)){ - case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: - avdtp_handle_sdp_client_query_attribute_value(connection, packet); - return; - case SDP_EVENT_QUERY_COMPLETE: - status = sdp_event_query_complete_get_status(packet); - if (status != ERROR_CODE_SUCCESS) break; - if (!connection->source_supported || (connection->avdtp_l2cap_psm == 0)) { - status = SDP_SERVICE_NOT_FOUND; - break; - } - break; - default: - btstack_assert(false); - return; - } - break; - - case AVDTP_SIGNALING_CONNECTION_OPENED: - switch (hci_event_packet_get_type(packet)){ - case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: - avdtp_handle_sdp_client_query_attribute_value(connection, packet); - return; - case SDP_EVENT_QUERY_COMPLETE: - // without suitable SDP Record, avdtp version v0.0 is assumed - status = sdp_event_query_complete_get_status(packet); - break; - default: - btstack_assert(false); - return; - } - break; - default: - // bail out, we must have had an incoming connection in the meantime; just trigger next sdp query on complete - if (hci_event_packet_get_type(packet) == SDP_EVENT_QUERY_COMPLETE){ - (void) sdp_client_register_query_callback(&avdtp_handle_sdp_client_query_request); - } + btstack_assert(false); return; } - if (status == ERROR_CODE_SUCCESS){ - avdtp_handle_sdp_query_succeeded(connection); - } else { - avdtp_handle_sdp_query_failed(connection, status); + // query completed with status, validate received information + bool handle_query_complete = true; + switch (connection->state){ + case AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SINK_COMPLETE: + if (status == ERROR_CODE_SUCCESS) { + if (!connection->sink_supported || (connection->avdtp_l2cap_psm == 0)) { + status = SDP_SERVICE_NOT_FOUND; + } + } + break; + case AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SOURCE_COMPLETE: + if (status == ERROR_CODE_SUCCESS) { + if (!connection->source_supported || (connection->avdtp_l2cap_psm == 0)) { + status = SDP_SERVICE_NOT_FOUND; + } + } + break; + case AVDTP_SIGNALING_CONNECTION_OPENED: + // without suitable SDP Record, avdtp version v0.0 is assumed + break; + default: + // we must have had an incoming connection in the meantime -> bail out + // just trigger next sdp query on complete + handle_query_complete = false; + break; + } + + if (handle_query_complete){ + if (status == ERROR_CODE_SUCCESS){ + avdtp_handle_sdp_query_succeeded(connection); + } else { + avdtp_handle_sdp_query_failed(connection, status); + } } // register the SDP Query request to check if there is another connection waiting for the query - // ignore ERROR_CODE_COMMAND_DISALLOWED because in that case, we already have requested an SDP callback - (void) sdp_client_register_query_callback(&avdtp_handle_sdp_client_query_request); + if (avdtp_get_next_connection_ready_for_sdp_query() != NULL){ + // ignore ERROR_CODE_COMMAND_DISALLOWED because in that case, we already have requested an SDP callback + (void) sdp_client_register_query_callback(&avdtp_handle_sdp_client_query_request); + } } static avdtp_connection_t * avdtp_handle_incoming_connection(avdtp_connection_t * connection, bd_addr_t event_addr, hci_con_handle_t con_handle, uint16_t local_cid){