mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-04 15:39:59 +00:00
avdtp: cleanup connect, on incoming connection set context to the active one
This commit is contained in:
parent
1436d179b7
commit
36da874766
@ -53,8 +53,9 @@
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_util.h"
|
||||
|
||||
avdtp_context_t * avdtp_source_context;
|
||||
avdtp_context_t * avdtp_sink_context;
|
||||
avdtp_context_t * avdtp_source_context = NULL;
|
||||
avdtp_context_t * avdtp_sink_context = NULL;
|
||||
static avdtp_context_t * sdp_query_context = NULL;
|
||||
|
||||
static int record_id = -1;
|
||||
static uint8_t attribute_value[45];
|
||||
@ -71,12 +72,12 @@ static const unsigned int attribute_value_buffer_size = sizeof(attribute_value);
|
||||
// uint8_t role_supported;
|
||||
// } avdtp_sdp_query_context_t;
|
||||
|
||||
static avdtp_context_t * sdp_query_context;
|
||||
static uint16_t avdtp_cid_counter = 0;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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){
|
||||
@ -85,14 +86,30 @@ static uint16_t avdtp_get_next_initiator_transaction_label(avdtp_context_t * con
|
||||
return context->initiator_transaction_id_counter;
|
||||
}
|
||||
|
||||
static uint16_t avdtp_get_next_cid(avdtp_context_t * context){
|
||||
do {
|
||||
if (avdtp_cid_counter == 0xffff) {
|
||||
avdtp_cid_counter = 1;
|
||||
} else {
|
||||
avdtp_cid_counter++;
|
||||
}
|
||||
} while (avdtp_get_connection_for_avdtp_cid(avdtp_cid_counter, context) != NULL) ;
|
||||
static avdtp_connection_t * avdtp_create_connection(bd_addr_t remote_addr, uint16_t cid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = btstack_memory_avdtp_connection_get();
|
||||
if (!connection){
|
||||
log_error("Not enough memory to create connection");
|
||||
return NULL;
|
||||
}
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
|
||||
connection->initiator_transaction_label = avdtp_get_next_initiator_transaction_label(context);
|
||||
connection->configuration_state = AVDTP_CONFIGURATION_STATE_IDLE;
|
||||
connection->avdtp_cid = cid;
|
||||
(void)memcpy(connection->remote_addr, remote_addr, 6);
|
||||
|
||||
context->avdtp_cid = cid;
|
||||
|
||||
btstack_linked_list_add(&context->connections, (btstack_linked_item_t *) connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
static uint16_t avdtp_get_next_cid(void){
|
||||
if (avdtp_cid_counter == 0xffff) {
|
||||
avdtp_cid_counter = 1;
|
||||
} else {
|
||||
avdtp_cid_counter++;
|
||||
}
|
||||
return avdtp_cid_counter;
|
||||
}
|
||||
|
||||
@ -127,12 +144,11 @@ static uint8_t avdtp_start_sdp_query(btstack_packet_handler_t packet_handler, av
|
||||
sdp_query_context->avdtp_cid = cid;
|
||||
memcpy(sdp_query_context->remote_addr, remote_addr, 6);
|
||||
|
||||
return sdp_client_query_uuid16(packet_handler, (uint8_t *) remote_addr, BLUETOOTH_PROTOCOL_AVCTP);
|
||||
return sdp_client_query_uuid16(packet_handler, (uint8_t *) remote_addr, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
}
|
||||
|
||||
uint8_t avdtp_connect(bd_addr_t remote, avdtp_context_t * avdtp_context, uint16_t * avdtp_cid){
|
||||
btstack_assert(avdtp_context != NULL);
|
||||
|
||||
// TODO: implement delayed SDP query
|
||||
if (sdp_client_ready() == 0){
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
@ -143,19 +159,17 @@ uint8_t avdtp_connect(bd_addr_t remote, avdtp_context_t * avdtp_context, uint16_
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
|
||||
uint16_t cid = avdtp_get_next_cid(sdp_query_context);
|
||||
|
||||
connection = avdtp_create_connection(remote, sdp_query_context);
|
||||
if (!connection) return BTSTACK_MEMORY_ALLOC_FAILED;
|
||||
|
||||
uint16_t cid = avdtp_get_next_cid();
|
||||
if (avdtp_cid != NULL) {
|
||||
*avdtp_cid = cid;
|
||||
}
|
||||
|
||||
connection = avdtp_create_connection(remote, cid, avdtp_context);
|
||||
if (!connection) return BTSTACK_MEMORY_ALLOC_FAILED;
|
||||
|
||||
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE;
|
||||
connection->avdtp_cid = cid;
|
||||
|
||||
return avdtp_start_sdp_query(&avdtp_handle_sdp_client_query_result, avdtp_context, remote, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
return avdtp_start_sdp_query(&avdtp_handle_sdp_client_query_result, avdtp_context, remote, cid);
|
||||
}
|
||||
|
||||
void avdtp_register_media_transport_category(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
@ -290,20 +304,6 @@ void avdtp_handle_can_send_now(avdtp_connection_t * connection, uint16_t l2cap_c
|
||||
}
|
||||
/* END: tracking can send now requests pro l2cap cid */
|
||||
|
||||
avdtp_connection_t * avdtp_create_connection(bd_addr_t remote_addr, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = btstack_memory_avdtp_connection_get();
|
||||
if (!connection){
|
||||
log_error("Not enough memory to create connection");
|
||||
return NULL;
|
||||
}
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
|
||||
connection->initiator_transaction_label = avdtp_get_next_initiator_transaction_label(context);
|
||||
connection->configuration_state = AVDTP_CONFIGURATION_STATE_IDLE;
|
||||
context->avdtp_cid = connection->avdtp_cid;
|
||||
(void)memcpy(connection->remote_addr, remote_addr, 6);
|
||||
btstack_linked_list_add(&context->connections, (btstack_linked_item_t *) connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = btstack_memory_avdtp_stream_endpoint_get();
|
||||
@ -454,7 +454,6 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
|
||||
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);
|
||||
@ -485,17 +484,33 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
|
||||
}
|
||||
}
|
||||
|
||||
static avdtp_connection_t * avdtp_handle_incoming_connection(avdtp_connection_t * connection, bd_addr_t event_addr, uint16_t local_cid, avdtp_context_t * context){
|
||||
if (connection == NULL){
|
||||
uint16_t cid = avdtp_get_next_cid();
|
||||
connection = avdtp_create_connection(event_addr, cid, context);
|
||||
}
|
||||
|
||||
if (connection) {
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
|
||||
connection->l2cap_signaling_cid = local_cid;
|
||||
btstack_run_loop_remove_timer(&connection->reconnect_timer);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avdtp_context_t * context){
|
||||
bd_addr_t event_addr;
|
||||
uint16_t psm;
|
||||
uint16_t local_cid;
|
||||
uint8_t status;
|
||||
bool accept_signaling_connection;
|
||||
|
||||
bool accept_streaming_connection;
|
||||
bool outoing_signaling_active;
|
||||
bool decline_connection;
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = NULL;
|
||||
avdtp_connection_t * connection = NULL;
|
||||
|
||||
btstack_linked_list_t * avdtp_connections = &context->connections;
|
||||
btstack_linked_list_t * stream_endpoints = &context->stream_endpoints;
|
||||
handle_media_data = context->handle_media_data;
|
||||
@ -530,10 +545,8 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
}
|
||||
|
||||
if (channel == stream_endpoint->l2cap_reporting_cid){
|
||||
// TODO
|
||||
log_info("L2CAP_DATA_PACKET for reporting: NOT IMPLEMENTED");
|
||||
} else if (channel == stream_endpoint->l2cap_recovery_cid){
|
||||
// TODO
|
||||
log_info("L2CAP_DATA_PACKET for recovery: NOT IMPLEMENTED");
|
||||
} else {
|
||||
log_error("avdtp packet handler L2CAP_DATA_PACKET: local cid 0x%02x not found", channel);
|
||||
@ -542,73 +555,70 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
|
||||
case L2CAP_EVENT_INCOMING_CONNECTION:
|
||||
l2cap_event_incoming_connection_get_address(packet, event_addr);
|
||||
local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
|
||||
|
||||
// on incoming connection context is unknown
|
||||
// assume only one context is active, and store connection there
|
||||
if (avdtp_sink_context != NULL){
|
||||
context = avdtp_sink_context;
|
||||
} else if (avdtp_source_context != NULL){
|
||||
context = avdtp_source_context;
|
||||
}
|
||||
if (context == NULL) return;
|
||||
connection = avdtp_get_connection_for_bd_addr(event_addr, context);
|
||||
if (connection == NULL){
|
||||
// create connection struct for regular inconming connection request
|
||||
connection = avdtp_create_connection(event_addr, context);
|
||||
if (connection == NULL){
|
||||
log_error("Could not create connection, reject");
|
||||
l2cap_decline_connection(local_cid);
|
||||
break;
|
||||
|
||||
outoing_signaling_active = false;
|
||||
accept_streaming_connection = false;
|
||||
|
||||
if (connection != NULL){
|
||||
switch (connection->state){
|
||||
case AVDTP_SIGNALING_CONNECTION_IDLE:
|
||||
case AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE:
|
||||
break;
|
||||
|
||||
case AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED:
|
||||
case AVDTP_SIGNALING_CONNECTION_W2_L2CAP_RECONNECT:
|
||||
case AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED:
|
||||
outoing_signaling_active = true;
|
||||
connection->incoming_declined = true;
|
||||
break;
|
||||
case AVDTP_SIGNALING_CONNECTION_OPENED:
|
||||
outoing_signaling_active = true;
|
||||
accept_streaming_connection = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
|
||||
}
|
||||
|
||||
// connection exists, check states
|
||||
log_info("Connection state %d", connection->state);
|
||||
accept_signaling_connection = false;
|
||||
switch (connection->state){
|
||||
case AVDTP_SIGNALING_CONNECTION_IDLE:
|
||||
// regular incoming connection
|
||||
accept_signaling_connection = 1;
|
||||
break;
|
||||
case AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE:
|
||||
// incoming connection during sdp query, just accept it
|
||||
accept_signaling_connection = 1;
|
||||
break;
|
||||
case AVDTP_SIGNALING_CONNECTION_OPENED:
|
||||
// handled below
|
||||
break;
|
||||
case AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED:
|
||||
case AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED:
|
||||
case AVDTP_SIGNALING_CONNECTION_W2_L2CAP_RECONNECT:
|
||||
log_info("Reject incoming connection during disconnect");
|
||||
l2cap_decline_connection(local_cid);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (accept_signaling_connection){
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
|
||||
log_info("L2CAP_EVENT_INCOMING_CONNECTION, connection %p, state connection %d, avdtp cid 0x%02x", connection, connection->state, connection->avdtp_cid);
|
||||
log_info("incoming: %s, outoing_signaling_active %d, accept_streaming_connection %d",
|
||||
bd_addr_to_str(event_addr), outoing_signaling_active, accept_streaming_connection);
|
||||
|
||||
decline_connection = outoing_signaling_active && !accept_streaming_connection;
|
||||
if (outoing_signaling_active == false){
|
||||
connection = avdtp_handle_incoming_connection(connection, event_addr, local_cid, context);
|
||||
if (connection == NULL){
|
||||
decline_connection = true;
|
||||
}
|
||||
} else if (accept_streaming_connection){
|
||||
if ((connection == NULL) || (connection->configuration_state != AVDTP_CONFIGURATION_STATE_REMOTE_CONFIGURED)) {
|
||||
decline_connection = true;
|
||||
} else {
|
||||
// now, we're only dealing with media connections that are created by remote side - we're acceptor here
|
||||
stream_endpoint = avdtp_get_stream_endpoint_with_seid(connection->acceptor_local_seid, context);
|
||||
if ((stream_endpoint == NULL) || (stream_endpoint->l2cap_media_cid != 0) ) {
|
||||
decline_connection = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (decline_connection){
|
||||
l2cap_decline_connection(local_cid);
|
||||
} else {
|
||||
l2cap_accept_connection(local_cid);
|
||||
break;
|
||||
}
|
||||
|
||||
// now, we're only dealing with media connections that are created by remote side - we're acceptor here
|
||||
stream_endpoint = avdtp_get_stream_endpoint_with_seid(connection->acceptor_local_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
log_info("L2CAP_EVENT_INCOMING_CONNECTION no streamendpoint found for local seid %x", connection->acceptor_local_seid);
|
||||
l2cap_decline_connection(local_cid);
|
||||
break;
|
||||
}
|
||||
|
||||
log_info("Checking l2cap_media_cid %d, state of stream endpoint %d", stream_endpoint->l2cap_media_cid, stream_endpoint->state);
|
||||
if (stream_endpoint->l2cap_media_cid != 0){
|
||||
l2cap_decline_connection(local_cid);
|
||||
break;
|
||||
}
|
||||
if (connection->configuration_state != AVDTP_CONFIGURATION_STATE_REMOTE_CONFIGURED){
|
||||
l2cap_decline_connection(local_cid);
|
||||
break;
|
||||
}
|
||||
l2cap_accept_connection(local_cid);
|
||||
}
|
||||
break;
|
||||
|
||||
case L2CAP_EVENT_CHANNEL_OPENED:
|
||||
@ -622,16 +632,16 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *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 (context == NULL) return;
|
||||
connection = avdtp_get_connection_for_bd_addr(event_addr, context);
|
||||
|
||||
log_info("L2CAP_EVENT_CHANNEL_OPENED: status %d, cid 0x%02x , signaling connection %p ", status, local_cid, connection);
|
||||
connection = avdtp_get_connection_for_bd_addr(event_addr, context);
|
||||
if (!connection){
|
||||
log_info("L2CAP_EVENT_CHANNEL_OPENED 2: status %d, signaling connection %p ", status, connection);
|
||||
|
||||
if (connection == NULL){
|
||||
log_info("L2CAP_EVENT_CHANNEL_OPENED: no connection found for %s", bd_addr_to_str(event_addr));
|
||||
break;
|
||||
}
|
||||
|
||||
if (connection->l2cap_signaling_cid == 0) {
|
||||
}
|
||||
|
||||
if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED) {
|
||||
if (status){
|
||||
log_info("L2CAP connection to %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
|
||||
@ -684,10 +694,12 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
|
||||
case L2CAP_EVENT_CHANNEL_CLOSED:
|
||||
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
|
||||
connection = avdtp_get_connection_for_l2cap_signaling_cid(local_cid, context);
|
||||
// connection = avdtp_get_connection_for_l2cap_signaling_cid(local_cid, context);
|
||||
stream_endpoint = avdtp_get_stream_endpoint_for_l2cap_cid(local_cid, context);
|
||||
log_info("Received L2CAP_EVENT_CHANNEL_CLOSED, cid 0x%2x, connection %p, stream_endpoint %p", local_cid, connection, stream_endpoint);
|
||||
|
||||
connection = avdtp_get_connection_for_l2cap_signaling_cid(local_cid, context);
|
||||
|
||||
if (stream_endpoint){
|
||||
if (stream_endpoint->l2cap_media_cid == local_cid){
|
||||
connection = stream_endpoint->connection;
|
||||
|
@ -566,7 +566,6 @@ void avdtp_register_multiplexing_category(avdtp_stream_endpoint_t * stream_endpo
|
||||
void avdtp_handle_can_send_now(avdtp_connection_t * connection, uint16_t l2cap_cid, avdtp_context_t * context);
|
||||
|
||||
void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avdtp_context_t * context);
|
||||
avdtp_connection_t * avdtp_create_connection(bd_addr_t remote_addr, avdtp_context_t * context);
|
||||
avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context);
|
||||
|
||||
uint8_t avdtp_connect(bd_addr_t remote, avdtp_context_t * context, uint16_t * avdtp_cid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user