l2cap: use connection handle for channel lookup

This commit is contained in:
Matthias Ringwald 2020-11-23 10:37:19 +01:00
parent e04eae2275
commit 7d5c2f20da
2 changed files with 22 additions and 11 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Fixed
- L2CAP: use connection handle for channel lookups
### Added
### Changed

View File

@ -1125,6 +1125,14 @@ static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){
return (l2cap_channel_t*) l2cap_channel_item_by_cid(local_cid);
}
static l2cap_channel_t * l2cap_get_channel_for_local_cid_and_handle(uint16_t local_cid, hci_con_handle_t con_handle){
if (local_cid < 0x40u) return NULL;
l2cap_channel_t * l2cap_channel = (l2cap_channel_t*) l2cap_channel_item_by_cid(local_cid);
if (l2cap_channel == NULL) return NULL;
if (l2cap_channel->con_handle != con_handle) return NULL;
return l2cap_channel;
}
void l2cap_request_can_send_now_event(uint16_t local_cid){
l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) return;
@ -3279,7 +3287,7 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
// find channel
local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0);
channel = l2cap_get_channel_for_local_cid(local_cid);
channel = l2cap_get_channel_for_local_cid_and_handle(local_cid, handle);
if (!channel) {
log_error("l2cap: no channel for cid 0x%02x", local_cid);
break;
@ -3303,7 +3311,7 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
// find channel
local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0);
channel = l2cap_get_channel_for_local_cid(local_cid);
channel = l2cap_get_channel_for_local_cid_and_handle(local_cid, handle);
if (!channel) {
log_error("l2cap: no channel for cid 0x%02x", local_cid);
break;
@ -3534,10 +3542,12 @@ static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet,
l2cap_channel_t * l2cap_channel;
l2cap_fixed_channel_t * l2cap_fixed_channel;
uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet);
uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet);
uint8_t broadcast_flag = READ_ACL_FLAGS(packet) >> 2;
switch (channel_id) {
case L2CAP_CID_SIGNALING: {
if (broadcast_flag != 0) break;
uint32_t command_offset = 8;
while ((command_offset + L2CAP_SIGNALING_COMMAND_DATA_OFFSET) < size) {
// assert signaling command is fully inside packet
@ -3555,16 +3565,18 @@ static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet,
break;
}
case L2CAP_CID_CONNECTIONLESS_CHANNEL:
if (broadcast_flag == 0) break;
l2cap_fixed_channel = l2cap_fixed_channel_for_channel_id(L2CAP_CID_CONNECTIONLESS_CHANNEL);
if (!l2cap_fixed_channel) break;
if (!l2cap_fixed_channel->packet_handler) break;
(*l2cap_fixed_channel->packet_handler)(UCD_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER);
break;
default:
default:
if (broadcast_flag != 0) break;
// Find channel for this channel_id and connection handle
l2cap_channel = l2cap_get_channel_for_local_cid(channel_id);
if (l2cap_channel) {
l2cap_channel = l2cap_get_channel_for_local_cid_and_handle(channel_id, handle);
if (l2cap_channel != NULL){
l2cap_acl_classic_handler_for_channel(l2cap_channel, packet, size);
}
break;
@ -3615,11 +3627,11 @@ static void l2cap_acl_le_handler(hci_con_handle_t handle, uint8_t *packet, uint1
default:
#ifdef ENABLE_LE_DATA_CHANNELS
l2cap_channel = l2cap_get_channel_for_local_cid(channel_id);
if (l2cap_channel) {
l2cap_channel = l2cap_get_channel_for_local_cid_and_handle(channel_id, handle);
if (l2cap_channel != NULL) {
// credit counting
if (l2cap_channel->credits_incoming == 0u){
log_error("LE Data Channel packet received but no incoming credits");
log_info("LE Data Channel packet received but no incoming credits");
l2cap_channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST;
break;
}
@ -3653,8 +3665,6 @@ static void l2cap_acl_le_handler(hci_con_handle_t handle, uint8_t *packet, uint1
l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, l2cap_channel->receive_sdu_buffer, l2cap_channel->receive_sdu_len);
l2cap_channel->receive_sdu_len = 0;
}
} else {
log_error("LE Data Channel packet received but no channel found for cid 0x%02x", channel_id);
}
#endif
break;