fix creation of l2cap channel if hci connection already exists

This commit is contained in:
matthias.ringwald@gmail.com 2014-01-23 14:32:23 +00:00
parent 62bda3fbc5
commit 2df5dadc33

View File

@ -600,6 +600,30 @@ uint16_t l2cap_max_mtu(void){
return hci_max_acl_data_packet_length() - L2CAP_HEADER_SIZE;
}
static void l2cap_handle_connection_complete(uint16_t handle, l2cap_channel_t * channel){
if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
// success, start l2cap handshake
channel->handle = handle;
channel->local_cid = l2cap_next_local_cid();
// check remote SSP feature first
channel->state = L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES;
}
}
static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * channel){
if (channel->state != L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES) return;
// we have been waiting for remote supported features, if both support SSP,
if (hci_ssp_supported_on_both_sides(channel->handle) && !l2cap_security_level_0_allowed_for_PSM(channel->psm)){
// request security level 2
gap_request_security_level(channel->handle, LEVEL_2);
channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE;
return;
}
// fine, go ahead
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
}
// open outgoing L2CAP channel
void l2cap_create_channel_internal(void * connection, btstack_packet_handler_t packet_handler,
bd_addr_t address, uint16_t psm, uint16_t mtu){
@ -640,6 +664,16 @@ void l2cap_create_channel_internal(void * connection, btstack_packet_handler_t p
// add to connections list
linked_list_add(&l2cap_channels, (linked_item_t *) chan);
// check if hci connection is already usable
hci_connection_t * conn = hci_connection_for_bd_addr((bd_addr_t*)address);
if (conn){
l2cap_handle_connection_complete(conn->con_handle, chan);
// check ir remote supported fearures are already received
if (conn->bonding_flags & BONDING_RECEIVED_REMOTE_FEATURES) {
l2cap_handle_remote_supported_features_received(chan);
}
}
l2cap_run();
}
@ -677,13 +711,7 @@ static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_
for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
l2cap_channel_t * channel = (l2cap_channel_t *) it;
if ( ! BD_ADDR_CMP( channel->address, address) ){
if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
// success, start l2cap handshake
channel->handle = handle;
channel->local_cid = l2cap_next_local_cid();
// check remote SSP feature first
channel->state = L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES;
}
l2cap_handle_connection_complete(handle, channel);
}
}
// process
@ -786,16 +814,7 @@ void l2cap_event_handler( uint8_t *packet, uint16_t size ){
for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
channel = (l2cap_channel_t *) it;
if (channel->handle != handle) continue;
if (channel->state != L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES) continue;
// we have been waiting for remote supported features, if both support SSP,
if (hci_ssp_supported_on_both_sides(channel->handle) && !l2cap_security_level_0_allowed_for_PSM(channel->psm)){
// request security level 2
gap_request_security_level(channel->handle, LEVEL_2);
channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE;
break;
}
// fine, go ahead
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
l2cap_handle_remote_supported_features_received(channel);
break;
}