From 1e1ae2bcab217921b5f25f0e867f5bdee6d5c401 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Tue, 15 Aug 2017 15:05:21 +0200 Subject: [PATCH] a2dp: handle sdp query failure --- example/a2dp_source_demo.c | 24 ++++++++++----------- src/classic/avdtp.c | 44 ++++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/example/a2dp_source_demo.c b/example/a2dp_source_demo.c index 69ee1100d..840e615bb 100644 --- a/example/a2dp_source_demo.c +++ b/example/a2dp_source_demo.c @@ -310,24 +310,24 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe 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); + printf("A2DP: 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); + printf("A2DP: 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), + printf("A2DP: 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"); + printf("A2DP: Stream started.\n"); break; case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: @@ -336,17 +336,17 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe case A2DP_SUBEVENT_STREAM_SUSPENDED: play_info.status = AVRCP_PLAY_STATUS_PAUSED; - printf("Stream paused.\n"); + printf("A2DP: 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"); + printf("A2DP: Stream released.\n"); a2dp_demo_timer_stop(&media_tracker); break; default: - printf("AVDTP Source demo: event 0x%02x is not implemented\n", packet[2]); + printf("A2DP: event 0x%02x is not implemented\n", packet[2]); break; } } @@ -364,13 +364,13 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); if (avrcp_cid != 0 && avrcp_cid != local_cid) { - printf("AVRCP Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); + printf("AVRCP: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); return; } status = avrcp_subevent_connection_established_get_status(packet); if (status != ERROR_CODE_SUCCESS){ - printf("AVRCP Connection failed: status 0x%02x\n", status); + printf("AVRCP: Connection failed: status 0x%02x\n", status); avrcp_cid = 0; return; } @@ -380,7 +380,7 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u play_info.status = AVRCP_PLAY_STATUS_ERROR; 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), local_cid); + printf("AVRCP: connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); return; } @@ -411,11 +411,11 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u avrcp_target_now_playing_info(avrcp_cid); break; case AVRCP_SUBEVENT_CONNECTION_RELEASED: - printf("Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); + printf("AVRCP: Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); avrcp_cid = 0; return; default: - printf("A2DP Source/AVRCP Target event not parsed %02x\n", packet[2]); + printf("AVRCP: event not parsed %02x\n", packet[2]); break; } } diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index 9679b5fd6..a97e70f6e 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -54,6 +54,7 @@ static uint8_t attribute_value[1000]; static const unsigned int attribute_value_buffer_size = sizeof(attribute_value); typedef struct { + btstack_linked_list_t * avdtp_connections; avdtp_connection_t * connection; btstack_packet_handler_t avdtp_callback; avdtp_sep_type_t query_role; @@ -92,6 +93,7 @@ static uint16_t avdtp_get_next_local_seid(avdtp_context_t * context){ uint8_t avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_t * avdtp_context, uint16_t * avdtp_cid){ sdp_query_context.connection = NULL; + sdp_query_context.avdtp_connections = &avdtp_context->connections; avdtp_connection_t * connection = avdtp_connection_for_bd_addr(remote, avdtp_context); if (!connection){ connection = avdtp_create_connection(remote, avdtp_context); @@ -101,12 +103,13 @@ uint8_t avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_conte } } if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE){ - log_error("avdtp_connect: sink in wrong state,"); + log_error("avdtp_connect: sink in wrong state"); return AVDTP_CONNECTION_IN_WRONG_STATE; } - if (!avdtp_cid) return L2CAP_LOCAL_CID_DOES_NOT_EXIST; - + if (!avdtp_cid) { + return L2CAP_LOCAL_CID_DOES_NOT_EXIST; + } *avdtp_cid = connection->avdtp_cid; connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE; sdp_query_context.connection = connection; @@ -114,7 +117,13 @@ uint8_t avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_conte sdp_query_context.avdtp_callback = avdtp_context->avdtp_callback; sdp_query_context.packet_handler = avdtp_context->packet_handler; - sdp_client_query_uuid16(&avdtp_handle_sdp_client_query_result, remote, BLUETOOTH_PROTOCOL_AVDTP); + uint8_t err = sdp_client_query_uuid16(&avdtp_handle_sdp_client_query_result, remote, BLUETOOTH_PROTOCOL_AVDTP); + if (err != ERROR_CODE_SUCCESS){ + connection->state = AVDTP_SIGNALING_CONNECTION_IDLE; + btstack_linked_list_remove(sdp_query_context.avdtp_connections, (btstack_linked_item_t*) sdp_query_context.connection); + btstack_memory_avdtp_connection_free(sdp_query_context.connection); + return err; + } return ERROR_CODE_SUCCESS; } @@ -382,8 +391,12 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c uint16_t avdtp_l2cap_psm = 0; uint16_t avdtp_version = 0; // uint32_t avdtp_remote_uuid = 0; + uint8_t status; - if (!sdp_query_context.connection) return; + if (!sdp_query_context.connection){ + log_error("avdtp: sdp query, connection is not set."); + return; + } switch (hci_event_packet_get_type(packet)){ case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: @@ -464,6 +477,8 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c } if (!avdtp_l2cap_psm) { sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE; + btstack_linked_list_remove(sdp_query_context.avdtp_connections, (btstack_linked_item_t*) sdp_query_context.connection); + btstack_memory_avdtp_connection_free(sdp_query_context.connection); avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->avdtp_cid, sdp_query_context.connection->remote_addr, L2CAP_SERVICE_DOES_NOT_EXIST); break; } @@ -481,7 +496,15 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c break; case SDP_EVENT_QUERY_COMPLETE: - log_info("General query done with status %d.", sdp_event_query_complete_get_status(packet)); + status = sdp_event_query_complete_get_status(packet); + if (status != 0){ + sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE; + avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->avdtp_cid, sdp_query_context.connection->remote_addr, L2CAP_SERVICE_DOES_NOT_EXIST); + btstack_linked_list_remove(sdp_query_context.avdtp_connections, (btstack_linked_item_t*) sdp_query_context.connection); + btstack_memory_avdtp_connection_free(sdp_query_context.connection); + log_info("AVDTP: SDP query failed with status 0x%02x.", status); + break; + } break; } } @@ -491,6 +514,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet bd_addr_t event_addr; uint16_t psm; uint16_t local_cid; + uint8_t status; avdtp_stream_endpoint_t * stream_endpoint = NULL; avdtp_connection_t * connection = NULL; btstack_linked_list_t * avdtp_connections = &context->connections; @@ -566,13 +590,13 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet break; case L2CAP_EVENT_CHANNEL_OPENED: + status = l2cap_event_channel_opened_get_status(packet); // 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)){ + if (status){ avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->avdtp_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)); + log_error("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status); break; } psm = l2cap_event_channel_opened_get_psm(packet); @@ -612,7 +636,6 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(local_cid, context); if (stream_endpoint){ - printf("stream_endpoint %p, connection %p, se con %p \n", stream_endpoint, connection, stream_endpoint->connection); stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_CLOSED, packet, size, context); break; } @@ -921,7 +944,6 @@ void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_se stream_endpoint->remote_configuration_bitmap = configured_services_bitmap; stream_endpoint->remote_configuration = configuration; stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID; - printf("AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID \n"); avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); }