mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-28 16:11:24 +00:00
avdtp: differentiate SDP queries towards sink and source
This commit is contained in:
parent
bd6f65db86
commit
149deddbd9
@ -240,7 +240,6 @@ static void a2dp_signaling_emit_reconfigured(btstack_packet_handler_t callback,
|
||||
|
||||
static void a2dp_source_set_config_timer_handler(btstack_timer_source_t * ts){
|
||||
UNUSED(ts);
|
||||
log_info("a2dp_source_set_config_timer_handler, app state %u", app_state);
|
||||
if (app_state != A2DP_CONNECTED) return;
|
||||
app_state = A2DP_W2_DISCOVER_SEPS;
|
||||
avdtp_source_discover_stream_endpoints(sc.avdtp_cid);
|
||||
@ -278,12 +277,12 @@ 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);
|
||||
log_info("A2DP singnaling connection failed status %d", status);
|
||||
app_state = A2DP_IDLE;
|
||||
a2dp_signaling_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, status);
|
||||
break;
|
||||
}
|
||||
log_info("A2DP_SUBEVENT_SIGNALING_CONNECTION established avdtp_cid 0x%02x ---", a2dp_source_context.avdtp_cid);
|
||||
log_info("A2DP singnaling connection established avdtp_cid 0x%02x", a2dp_source_context.avdtp_cid);
|
||||
|
||||
sc.avdtp_cid = cid;
|
||||
sc.active_remote_sep = NULL;
|
||||
@ -292,11 +291,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
memset(remote_seps, 0, sizeof(avdtp_sep_t) * AVDTP_MAX_SEP_NUM);
|
||||
|
||||
// if we initiated the connection, start config right away, else wait a bit to give remote a chance to do it first
|
||||
log_info("A2DP_SUBEVENT_SIGNALING_CONNECTION app_state %u", app_state);
|
||||
if (app_state == A2DP_W4_CONNECTED){
|
||||
log_info("A2DP singnaling connection: discover seps");
|
||||
app_state = A2DP_W2_DISCOVER_SEPS;
|
||||
avdtp_source_discover_stream_endpoints(sc.avdtp_cid);
|
||||
} else {
|
||||
log_info("A2DP singnaling connection: wait a bit, then discover seps");
|
||||
app_state = A2DP_CONNECTED;
|
||||
a2dp_source_set_config_timer_start();
|
||||
}
|
||||
|
@ -245,6 +245,8 @@ static uint8_t avdtp_start_sdp_query(btstack_packet_handler_t packet_handler, av
|
||||
sdp_query_context->avdtp_l2cap_psm = 0;
|
||||
sdp_query_context->avdtp_version = 0;
|
||||
sdp_query_context->avdtp_cid = cid;
|
||||
sdp_query_context->sink_supported = false;
|
||||
sdp_query_context->source_supported = false;
|
||||
memcpy(sdp_query_context->remote_addr, remote_addr, 6);
|
||||
|
||||
return sdp_client_query_uuid16(packet_handler, (uint8_t *) remote_addr, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
@ -269,11 +271,18 @@ uint8_t avdtp_connect(bd_addr_t remote, avdtp_context_t * avdtp_context, uint16_
|
||||
|
||||
connection = avdtp_create_connection(remote, cid);
|
||||
if (!connection) return BTSTACK_MEMORY_ALLOC_FAILED;
|
||||
|
||||
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE;
|
||||
|
||||
connection->avdtp_cid = cid;
|
||||
avdtp_context->avdtp_cid = cid;
|
||||
|
||||
switch (avdtp_context->role){
|
||||
case AVDTP_ROLE_SOURCE:
|
||||
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SINK_COMPLETE;
|
||||
break;
|
||||
case AVDTP_ROLE_SINK:
|
||||
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SOURCE_COMPLETE;
|
||||
break;
|
||||
default:
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
return avdtp_start_sdp_query(&avdtp_handle_sdp_client_query_result, avdtp_context, remote, cid);
|
||||
}
|
||||
|
||||
@ -456,6 +465,7 @@ static void avdtp_handle_sdp_client_query_attribute_value(uint8_t *packet){
|
||||
if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)) {
|
||||
|
||||
switch(sdp_event_query_attribute_byte_get_attribute_id(packet)) {
|
||||
|
||||
case BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST:
|
||||
if (de_get_element_type(attribute_value) != DE_DES) break;
|
||||
for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) {
|
||||
@ -464,20 +474,12 @@ static void avdtp_handle_sdp_client_query_attribute_value(uint8_t *packet){
|
||||
uint32_t uuid = de_get_uuid32(element);
|
||||
switch (uuid){
|
||||
case BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE:
|
||||
if (sdp_query_context->query_role == AVDTP_SOURCE) {
|
||||
sdp_query_context->role_supported = 1;
|
||||
break;
|
||||
}
|
||||
// log_info("SDP Attribute 0x%04x: AVDTP SOURCE protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid);
|
||||
// avdtp_remote_uuid = uuid;
|
||||
sdp_query_context->source_supported = true;
|
||||
log_info("source_supported");
|
||||
break;
|
||||
case BLUETOOTH_SERVICE_CLASS_AUDIO_SINK:
|
||||
if (sdp_query_context->query_role == AVDTP_SINK) {
|
||||
sdp_query_context->role_supported = 1;
|
||||
break;
|
||||
}
|
||||
// log_info("SDP Attribute 0x%04x: AVDTP SINK protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid);
|
||||
// avdtp_remote_uuid = uuid;
|
||||
sdp_query_context->sink_supported = true;
|
||||
log_info("sink_supported");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -485,7 +487,7 @@ static void avdtp_handle_sdp_client_query_attribute_value(uint8_t *packet){
|
||||
}
|
||||
break;
|
||||
|
||||
case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST: {
|
||||
case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST:
|
||||
// log_info("SDP Attribute: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet));
|
||||
for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) {
|
||||
uint8_t *des_element;
|
||||
@ -502,10 +504,11 @@ static void avdtp_handle_sdp_client_query_attribute_value(uint8_t *packet){
|
||||
|
||||
uuid = de_get_uuid32(element);
|
||||
des_iterator_next(&prot_it);
|
||||
// we assume that the even if there are both roles supported, remote device uses the same psm and avdtp version for both
|
||||
switch (uuid){
|
||||
case BLUETOOTH_PROTOCOL_L2CAP:
|
||||
if (!des_iterator_has_more(&prot_it)) continue;
|
||||
de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avdtp_l2cap_psm);
|
||||
de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avdtp_l2cap_psm);
|
||||
break;
|
||||
case BLUETOOTH_PROTOCOL_AVDTP:
|
||||
if (!des_iterator_has_more(&prot_it)) continue;
|
||||
@ -515,8 +518,8 @@ static void avdtp_handle_sdp_client_query_attribute_value(uint8_t *packet){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -547,45 +550,64 @@ static void avdtp_handle_sdp_query_succeeded(avdtp_connection_t * connection){
|
||||
}
|
||||
|
||||
static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(sdp_query_context->avdtp_cid);
|
||||
if (!connection) {
|
||||
log_error("SDP query, connection with 0x%02x cid not found", sdp_query_context->avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE) return;
|
||||
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
|
||||
uint8_t status;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
|
||||
avdtp_handle_sdp_client_query_attribute_value(packet);
|
||||
bool query_succeded = false;
|
||||
|
||||
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(packet);
|
||||
return;
|
||||
case SDP_EVENT_QUERY_COMPLETE:
|
||||
status = sdp_event_query_complete_get_status(packet);
|
||||
if (status != ERROR_CODE_SUCCESS) break;
|
||||
if (!sdp_query_context->sink_supported) break;
|
||||
if (sdp_query_context->avdtp_l2cap_psm == 0) break;
|
||||
query_succeded = true;
|
||||
break;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDP_EVENT_QUERY_COMPLETE:
|
||||
if (connection->state != AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE){
|
||||
// bail out, we must have had an incoming connection in the meantime;
|
||||
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(packet);
|
||||
return;
|
||||
case SDP_EVENT_QUERY_COMPLETE:
|
||||
status = sdp_event_query_complete_get_status(packet);
|
||||
if (status != ERROR_CODE_SUCCESS) break;
|
||||
if (!sdp_query_context->source_supported) break;
|
||||
if (sdp_query_context->avdtp_l2cap_psm == 0) break;
|
||||
query_succeded = true;
|
||||
break;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
}
|
||||
status = sdp_event_query_complete_get_status(packet);
|
||||
if (status != ERROR_CODE_SUCCESS){
|
||||
avdtp_handle_sdp_query_failed(connection, status);
|
||||
break;
|
||||
}
|
||||
if (!sdp_query_context->role_supported){
|
||||
avdtp_handle_sdp_query_failed(connection, status);
|
||||
break;
|
||||
}
|
||||
if (!sdp_query_context->avdtp_l2cap_psm) {
|
||||
avdtp_handle_sdp_query_failed(connection, status);
|
||||
break;
|
||||
}
|
||||
avdtp_handle_sdp_query_succeeded(connection);
|
||||
break;
|
||||
default:
|
||||
// bail out, we must have had an incoming connection in the meantime;
|
||||
return;
|
||||
}
|
||||
|
||||
l2cap_create_channel(sdp_query_context->packet_handler, connection->remote_addr, connection->avdtp_l2cap_psm, l2cap_max_mtu(), NULL);
|
||||
break;
|
||||
if (query_succeded){
|
||||
avdtp_handle_sdp_query_succeeded(connection);
|
||||
l2cap_create_channel(sdp_query_context->packet_handler, connection->remote_addr, connection->avdtp_l2cap_psm, l2cap_max_mtu(), NULL);
|
||||
} else {
|
||||
avdtp_handle_sdp_query_failed(connection, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,13 +133,13 @@ typedef enum {
|
||||
AVDTP_RESPONSE_REJECT_MSG
|
||||
} avdtp_message_type_t;
|
||||
|
||||
typedef enum{
|
||||
typedef enum {
|
||||
AVDTP_AUDIO = 0,
|
||||
AVDTP_VIDEO,
|
||||
AVDTP_MULTIMEDIA
|
||||
} avdtp_media_type_t;
|
||||
|
||||
typedef enum{
|
||||
typedef enum {
|
||||
AVDTP_CODEC_SBC = 0x00,
|
||||
AVDTP_CODEC_MPEG_1_2_AUDIO = 0x01,
|
||||
AVDTP_CODEC_MPEG_2_4_AAC = 0x02,
|
||||
@ -147,24 +147,21 @@ typedef enum{
|
||||
AVDTP_CODEC_NON_A2DP = 0xFF
|
||||
} avdtp_media_codec_type_t;
|
||||
|
||||
typedef enum{
|
||||
typedef enum {
|
||||
AVDTP_CONTENT_PROTECTION_DTCP = 0x0001,
|
||||
AVDTP_CONTENT_PROTECTION_SCMS_T = 0x0002
|
||||
} avdtp_content_protection_type_t;
|
||||
|
||||
typedef enum{
|
||||
typedef enum {
|
||||
AVDTP_SOURCE = 0,
|
||||
AVDTP_SINK
|
||||
} avdtp_sep_type_t;
|
||||
|
||||
typedef enum{
|
||||
typedef enum {
|
||||
AVDTP_ROLE_SOURCE = 0,
|
||||
AVDTP_ROLE_SINK,
|
||||
AVDTP_ROLE_SINK_AND_SOURCE,
|
||||
AVDTP_ROLE_UNKNOWN
|
||||
AVDTP_ROLE_SINK
|
||||
} avdtp_role_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
AVDTP_SERVICE_CATEGORY_INVALID_0 = 0x00,
|
||||
AVDTP_MEDIA_TRANSPORT = 0X01,
|
||||
@ -351,7 +348,8 @@ typedef struct {
|
||||
|
||||
typedef enum {
|
||||
AVDTP_SIGNALING_CONNECTION_IDLE,
|
||||
AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE,
|
||||
AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SINK_COMPLETE,
|
||||
AVDTP_SIGNALING_W4_SDP_QUERY_FOR_REMOTE_SOURCE_COMPLETE,
|
||||
AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED,
|
||||
AVDTP_SIGNALING_CONNECTION_W2_L2CAP_RETRY,
|
||||
AVDTP_SIGNALING_CONNECTION_OPENED,
|
||||
@ -551,7 +549,8 @@ typedef struct {
|
||||
void (*handle_media_data)(uint8_t local_seid, uint8_t *packet, uint16_t size);
|
||||
btstack_packet_handler_t packet_handler;
|
||||
|
||||
avdtp_sep_type_t query_role;
|
||||
//avdtp_sep_type_t query_role;
|
||||
|
||||
avdtp_role_t role;
|
||||
|
||||
// SDP query
|
||||
@ -559,7 +558,8 @@ typedef struct {
|
||||
uint16_t avdtp_cid;
|
||||
uint16_t avdtp_l2cap_psm;
|
||||
uint16_t avdtp_version;
|
||||
uint8_t role_supported;
|
||||
bool sink_supported;
|
||||
bool source_supported;
|
||||
} avdtp_context_t;
|
||||
|
||||
extern avdtp_context_t * avdtp_source_context;
|
||||
|
@ -278,27 +278,27 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
|
||||
static bool avdtp_initiator_stream_config_subsm_run_signaling(avdtp_connection_t * connection){
|
||||
switch (connection->initiator_connection_state){
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS:
|
||||
log_info("INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS");
|
||||
log_info("INT: W2_DISCOVER_SEPS");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd(connection->l2cap_signaling_cid, AVDTP_SI_DISCOVER, connection->initiator_transaction_label);
|
||||
return true;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES:
|
||||
log_info("INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES");
|
||||
log_info("INT: W2_GET_CAPABILITIES");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CAPABILITIES, connection->initiator_transaction_label, connection->initiator_remote_seid);
|
||||
return true;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES:
|
||||
log_info("INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES");
|
||||
log_info("INT: W2_GET_ALL_CAPABILITIES");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_ALL_CAPABILITIES, connection->initiator_transaction_label, connection->initiator_remote_seid);
|
||||
return true;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION:
|
||||
log_info("INT: AVDTP_INITIATOR_W4_GET_CONFIGURATION");
|
||||
log_info("INT: W4_GET_CONFIGURATION");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CONFIGURATION, connection->initiator_transaction_label, connection->initiator_remote_seid);
|
||||
return true;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SEND_DELAY_REPORT:
|
||||
log_info("INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_DELAY_REPORT");
|
||||
log_info("INT: W4_DELAY_REPORT");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd_delay_report(connection->l2cap_signaling_cid, connection->initiator_transaction_label,
|
||||
connection->initiator_remote_seid, connection->delay_ms);
|
||||
@ -317,7 +317,7 @@ static void avdtp_initiator_stream_config_subsm_run_endpoint(avdtp_connection_t
|
||||
log_info("initiator SM stop sending SET_CONFIGURATION cmd:");
|
||||
break;
|
||||
}
|
||||
log_info("INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, local seid %d, remote seid 0x%02x", connection->initiator_local_seid, connection->initiator_remote_seid);
|
||||
log_info("INT: W2_(RE)CONFIGURATION bitmap, local seid %d, remote seid 0x%02x", connection->initiator_local_seid, connection->initiator_remote_seid);
|
||||
// log_info_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len);
|
||||
connection->initiator_signaling_packet.acp_seid = connection->initiator_remote_seid;
|
||||
connection->initiator_signaling_packet.int_seid = connection->initiator_local_seid;
|
||||
|
@ -115,7 +115,6 @@ void avdtp_sink_init(avdtp_context_t * avdtp_context){
|
||||
avdtp_sink_context = avdtp_context;
|
||||
avdtp_sink_context->stream_endpoints = NULL;
|
||||
avdtp_sink_context->stream_endpoints_id_counter = 0;
|
||||
avdtp_sink_context->query_role = AVDTP_SOURCE;
|
||||
avdtp_sink_context->packet_handler = packet_handler;
|
||||
avdtp_sink_context->role = AVDTP_ROLE_SINK;
|
||||
|
||||
|
@ -172,7 +172,6 @@ void avdtp_source_init(avdtp_context_t * avdtp_context){
|
||||
avdtp_source_context = avdtp_context;
|
||||
avdtp_source_context->stream_endpoints = NULL;
|
||||
avdtp_source_context->stream_endpoints_id_counter = 0;
|
||||
avdtp_source_context->query_role = AVDTP_SINK;
|
||||
avdtp_source_context->packet_handler = packet_handler;
|
||||
avdtp_source_context->role = AVDTP_ROLE_SOURCE;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user