l2cap.c (18ef5dfc3c950410b449df7c7ebb6238d64bd058) | l2cap.c (7d5c2f20da25e56e90bc87f1f8b57caba59706da) |
---|---|
1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 1111 unchanged lines hidden (view full) --- 1120 1121// used for Classic Channels + LE Data Channels. local_cid >= 0x40 1122#ifdef L2CAP_USES_CHANNELS 1123static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){ 1124 if (local_cid < 0x40u) return NULL; 1125 return (l2cap_channel_t*) l2cap_channel_item_by_cid(local_cid); 1126} 1127 | 1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 1111 unchanged lines hidden (view full) --- 1120 1121// used for Classic Channels + LE Data Channels. local_cid >= 0x40 1122#ifdef L2CAP_USES_CHANNELS 1123static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){ 1124 if (local_cid < 0x40u) return NULL; 1125 return (l2cap_channel_t*) l2cap_channel_item_by_cid(local_cid); 1126} 1127 |
1128static l2cap_channel_t * l2cap_get_channel_for_local_cid_and_handle(uint16_t local_cid, hci_con_handle_t con_handle){ 1129 if (local_cid < 0x40u) return NULL; 1130 l2cap_channel_t * l2cap_channel = (l2cap_channel_t*) l2cap_channel_item_by_cid(local_cid); 1131 if (l2cap_channel == NULL) return NULL; 1132 if (l2cap_channel->con_handle != con_handle) return NULL; 1133 return l2cap_channel; 1134} 1135 |
|
1128void l2cap_request_can_send_now_event(uint16_t local_cid){ 1129 l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 1130 if (!channel) return; 1131 channel->waiting_for_can_send_now = 1; 1132#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1133 if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 1134 l2cap_ertm_notify_channel_can_send(channel); 1135 return; --- 2138 unchanged lines hidden (view full) --- 3274 break; 3275 3276 case LE_FLOW_CONTROL_CREDIT: 3277 // check size 3278 if (len < 4u) return 0u; 3279 3280 // find channel 3281 local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); | 1136void l2cap_request_can_send_now_event(uint16_t local_cid){ 1137 l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 1138 if (!channel) return; 1139 channel->waiting_for_can_send_now = 1; 1140#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1141 if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 1142 l2cap_ertm_notify_channel_can_send(channel); 1143 return; --- 2138 unchanged lines hidden (view full) --- 3282 break; 3283 3284 case LE_FLOW_CONTROL_CREDIT: 3285 // check size 3286 if (len < 4u) return 0u; 3287 3288 // find channel 3289 local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); |
3282 channel = l2cap_get_channel_for_local_cid(local_cid); | 3290 channel = l2cap_get_channel_for_local_cid_and_handle(local_cid, handle); |
3283 if (!channel) { 3284 log_error("l2cap: no channel for cid 0x%02x", local_cid); 3285 break; 3286 } 3287 new_credits = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 3288 credits_before = channel->credits_outgoing; 3289 channel->credits_outgoing += new_credits; 3290 // check for credit overrun --- 7 unchanged lines hidden (view full) --- 3298 3299 case DISCONNECTION_REQUEST: 3300 3301 // check size 3302 if (len < 4u) return 0u; 3303 3304 // find channel 3305 local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); | 3291 if (!channel) { 3292 log_error("l2cap: no channel for cid 0x%02x", local_cid); 3293 break; 3294 } 3295 new_credits = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 3296 credits_before = channel->credits_outgoing; 3297 channel->credits_outgoing += new_credits; 3298 // check for credit overrun --- 7 unchanged lines hidden (view full) --- 3306 3307 case DISCONNECTION_REQUEST: 3308 3309 // check size 3310 if (len < 4u) return 0u; 3311 3312 // find channel 3313 local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); |
3306 channel = l2cap_get_channel_for_local_cid(local_cid); | 3314 channel = l2cap_get_channel_for_local_cid_and_handle(local_cid, handle); |
3307 if (!channel) { 3308 log_error("l2cap: no channel for cid 0x%02x", local_cid); 3309 break; 3310 } 3311 channel->remote_sig_id = sig_id; 3312 channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE; 3313 break; 3314 --- 214 unchanged lines hidden (view full) --- 3529} 3530#endif 3531 3532static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet, uint16_t size){ 3533#ifdef ENABLE_CLASSIC 3534 l2cap_channel_t * l2cap_channel; 3535 l2cap_fixed_channel_t * l2cap_fixed_channel; 3536 | 3315 if (!channel) { 3316 log_error("l2cap: no channel for cid 0x%02x", local_cid); 3317 break; 3318 } 3319 channel->remote_sig_id = sig_id; 3320 channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE; 3321 break; 3322 --- 214 unchanged lines hidden (view full) --- 3537} 3538#endif 3539 3540static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet, uint16_t size){ 3541#ifdef ENABLE_CLASSIC 3542 l2cap_channel_t * l2cap_channel; 3543 l2cap_fixed_channel_t * l2cap_fixed_channel; 3544 |
3537 uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet); | 3545 uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet); 3546 uint8_t broadcast_flag = READ_ACL_FLAGS(packet) >> 2; |
3538 switch (channel_id) { 3539 3540 case L2CAP_CID_SIGNALING: { | 3547 switch (channel_id) { 3548 3549 case L2CAP_CID_SIGNALING: { |
3550 if (broadcast_flag != 0) break; |
|
3541 uint32_t command_offset = 8; 3542 while ((command_offset + L2CAP_SIGNALING_COMMAND_DATA_OFFSET) < size) { 3543 // assert signaling command is fully inside packet 3544 uint16_t data_len = little_endian_read_16(packet, command_offset + L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 3545 uint32_t next_command_offset = command_offset + L2CAP_SIGNALING_COMMAND_DATA_OFFSET + data_len; 3546 if (next_command_offset > size){ 3547 log_error("l2cap signaling command len invalid -> drop"); 3548 break; 3549 } 3550 // handle signaling command 3551 l2cap_signaling_handler_dispatch(handle, &packet[command_offset]); 3552 // go to next command 3553 command_offset = next_command_offset; 3554 } 3555 break; 3556 } 3557 case L2CAP_CID_CONNECTIONLESS_CHANNEL: | 3551 uint32_t command_offset = 8; 3552 while ((command_offset + L2CAP_SIGNALING_COMMAND_DATA_OFFSET) < size) { 3553 // assert signaling command is fully inside packet 3554 uint16_t data_len = little_endian_read_16(packet, command_offset + L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 3555 uint32_t next_command_offset = command_offset + L2CAP_SIGNALING_COMMAND_DATA_OFFSET + data_len; 3556 if (next_command_offset > size){ 3557 log_error("l2cap signaling command len invalid -> drop"); 3558 break; 3559 } 3560 // handle signaling command 3561 l2cap_signaling_handler_dispatch(handle, &packet[command_offset]); 3562 // go to next command 3563 command_offset = next_command_offset; 3564 } 3565 break; 3566 } 3567 case L2CAP_CID_CONNECTIONLESS_CHANNEL: |
3568 if (broadcast_flag == 0) break; |
|
3558 l2cap_fixed_channel = l2cap_fixed_channel_for_channel_id(L2CAP_CID_CONNECTIONLESS_CHANNEL); 3559 if (!l2cap_fixed_channel) break; 3560 if (!l2cap_fixed_channel->packet_handler) break; 3561 (*l2cap_fixed_channel->packet_handler)(UCD_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 3562 break; 3563 | 3569 l2cap_fixed_channel = l2cap_fixed_channel_for_channel_id(L2CAP_CID_CONNECTIONLESS_CHANNEL); 3570 if (!l2cap_fixed_channel) break; 3571 if (!l2cap_fixed_channel->packet_handler) break; 3572 (*l2cap_fixed_channel->packet_handler)(UCD_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 3573 break; 3574 |
3564 default: | 3575 default: 3576 if (broadcast_flag != 0) break; |
3565 // Find channel for this channel_id and connection handle | 3577 // Find channel for this channel_id and connection handle |
3566 l2cap_channel = l2cap_get_channel_for_local_cid(channel_id); 3567 if (l2cap_channel) { | 3578 l2cap_channel = l2cap_get_channel_for_local_cid_and_handle(channel_id, handle); 3579 if (l2cap_channel != NULL){ |
3568 l2cap_acl_classic_handler_for_channel(l2cap_channel, packet, size); 3569 } 3570 break; 3571 } 3572#else 3573 UNUSED(handle); // ok: no code 3574 UNUSED(packet); // ok: no code 3575 UNUSED(size); // ok: no code --- 34 unchanged lines hidden (view full) --- 3610 if (!l2cap_fixed_channel) break; 3611 if (!l2cap_fixed_channel->packet_handler) break; 3612 (*l2cap_fixed_channel->packet_handler)(SM_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 3613 break; 3614 3615 default: 3616 3617#ifdef ENABLE_LE_DATA_CHANNELS | 3580 l2cap_acl_classic_handler_for_channel(l2cap_channel, packet, size); 3581 } 3582 break; 3583 } 3584#else 3585 UNUSED(handle); // ok: no code 3586 UNUSED(packet); // ok: no code 3587 UNUSED(size); // ok: no code --- 34 unchanged lines hidden (view full) --- 3622 if (!l2cap_fixed_channel) break; 3623 if (!l2cap_fixed_channel->packet_handler) break; 3624 (*l2cap_fixed_channel->packet_handler)(SM_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 3625 break; 3626 3627 default: 3628 3629#ifdef ENABLE_LE_DATA_CHANNELS |
3618 l2cap_channel = l2cap_get_channel_for_local_cid(channel_id); 3619 if (l2cap_channel) { | 3630 l2cap_channel = l2cap_get_channel_for_local_cid_and_handle(channel_id, handle); 3631 if (l2cap_channel != NULL) { |
3620 // credit counting 3621 if (l2cap_channel->credits_incoming == 0u){ | 3632 // credit counting 3633 if (l2cap_channel->credits_incoming == 0u){ |
3622 log_error("LE Data Channel packet received but no incoming credits"); | 3634 log_info("LE Data Channel packet received but no incoming credits"); |
3623 l2cap_channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 3624 break; 3625 } 3626 l2cap_channel->credits_incoming--; 3627 3628 // automatic credits 3629 if ((l2cap_channel->credits_incoming < L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_WATERMARK) && l2cap_channel->automatic_credits){ 3630 l2cap_channel->new_credits_incoming = L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_INCREMENT; --- 17 unchanged lines hidden (view full) --- 3648 fragment_size); 3649 l2cap_channel->receive_sdu_pos += size - COMPLETE_L2CAP_HEADER; 3650 // done? 3651 log_debug("le packet pos %u, len %u", l2cap_channel->receive_sdu_pos, l2cap_channel->receive_sdu_len); 3652 if (l2cap_channel->receive_sdu_pos >= l2cap_channel->receive_sdu_len){ 3653 l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, l2cap_channel->receive_sdu_buffer, l2cap_channel->receive_sdu_len); 3654 l2cap_channel->receive_sdu_len = 0; 3655 } | 3635 l2cap_channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 3636 break; 3637 } 3638 l2cap_channel->credits_incoming--; 3639 3640 // automatic credits 3641 if ((l2cap_channel->credits_incoming < L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_WATERMARK) && l2cap_channel->automatic_credits){ 3642 l2cap_channel->new_credits_incoming = L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_INCREMENT; --- 17 unchanged lines hidden (view full) --- 3660 fragment_size); 3661 l2cap_channel->receive_sdu_pos += size - COMPLETE_L2CAP_HEADER; 3662 // done? 3663 log_debug("le packet pos %u, len %u", l2cap_channel->receive_sdu_pos, l2cap_channel->receive_sdu_len); 3664 if (l2cap_channel->receive_sdu_pos >= l2cap_channel->receive_sdu_len){ 3665 l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, l2cap_channel->receive_sdu_buffer, l2cap_channel->receive_sdu_len); 3666 l2cap_channel->receive_sdu_len = 0; 3667 } |
3656 } else { 3657 log_error("LE Data Channel packet received but no channel found for cid 0x%02x", channel_id); | |
3658 } 3659#endif 3660 break; 3661 } 3662#else 3663 UNUSED(handle); // ok: no code 3664 UNUSED(packet); // ok: no code 3665 UNUSED(size); // ok: no code --- 529 unchanged lines hidden --- | 3668 } 3669#endif 3670 break; 3671 } 3672#else 3673 UNUSED(handle); // ok: no code 3674 UNUSED(packet); // ok: no code 3675 UNUSED(size); // ok: no code --- 529 unchanged lines hidden --- |