mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-19 15:40:52 +00:00
l2cap: limit fragments by remote_mps, send first fragment fully
This commit is contained in:
parent
7261e5d87f
commit
b90eac910b
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
- RFCOMM: limit RFCOMM MTU by local L2CAP MTU for outgoing connections (revelvant only for ERTM)
|
||||
- POSIX, WICED, Windows, FreeRTOS: handle time_ms overrun after 49 days
|
||||
- L2CAP ERTM: stop timers on disconnect
|
||||
- L2CAP ERTM: fix sending of segmented SDUs
|
||||
|
||||
### Added
|
||||
- btstack_run_loop_base: portable implementation of timer and data source managment as base for platform specific implementations
|
||||
|
19
src/l2cap.c
19
src/l2cap.c
@ -201,12 +201,13 @@ static int l2cap_ertm_can_store_packet_now(l2cap_channel_t * channel){
|
||||
int num_free_tx_buffers = channel->num_tx_buffers - channel->num_stored_tx_frames;
|
||||
// calculate num tx buffers for remote MTU
|
||||
int num_tx_buffers_for_max_remote_mtu;
|
||||
if (channel->remote_mtu <= channel->remote_mps){
|
||||
uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps);
|
||||
if (channel->remote_mtu <= effective_mps){
|
||||
// MTU fits into single packet
|
||||
num_tx_buffers_for_max_remote_mtu = 1;
|
||||
} else {
|
||||
// include SDU Length
|
||||
num_tx_buffers_for_max_remote_mtu = (channel->remote_mtu + 2 + (channel->remote_mps - 1)) / channel->remote_mps;
|
||||
num_tx_buffers_for_max_remote_mtu = (channel->remote_mtu + 2 + (effective_mps - 1)) / effective_mps;
|
||||
}
|
||||
log_debug("num_free_tx_buffers %u, num_tx_buffers_for_max_remote_mtu %u", num_free_tx_buffers, num_tx_buffers_for_max_remote_mtu);
|
||||
return num_tx_buffers_for_max_remote_mtu <= num_free_tx_buffers;
|
||||
@ -322,18 +323,18 @@ static void l2cap_ertm_store_fragment(l2cap_channel_t * channel, l2cap_segmentat
|
||||
|
||||
l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index];
|
||||
tx_state->tx_seq = channel->next_tx_seq;
|
||||
tx_state->len = len;
|
||||
tx_state->sar = sar;
|
||||
tx_state->retry_count = 0;
|
||||
|
||||
uint8_t * tx_packet = &channel->tx_packets_data[index * channel->local_mps];
|
||||
log_debug("index %u, mtu %u, packet tx %p", index, channel->local_mtu, tx_packet);
|
||||
log_debug("index %u, local mps %u, remote mps %u, packet tx %p, len %u", index, channel->local_mps, channel->remote_mps, tx_packet, len);
|
||||
int pos = 0;
|
||||
if (sar == L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU){
|
||||
little_endian_store_16(tx_packet, 0, sdu_length);
|
||||
pos += 2;
|
||||
}
|
||||
memcpy(&tx_packet[pos], data, len);
|
||||
tx_state->len = pos + len;
|
||||
|
||||
// update
|
||||
channel->num_stored_tx_frames++;
|
||||
@ -356,20 +357,21 @@ static int l2cap_ertm_send(l2cap_channel_t * channel, uint8_t * data, uint16_t l
|
||||
}
|
||||
|
||||
// check if it needs to get fragmented
|
||||
if (len > channel->remote_mps){
|
||||
uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps);
|
||||
if (len > effective_mps){
|
||||
// fragmentation needed.
|
||||
l2cap_segmentation_and_reassembly_t sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU;
|
||||
int chunk_len;
|
||||
while (len){
|
||||
switch (sar){
|
||||
case L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU:
|
||||
chunk_len = channel->remote_mps - 2; // sdu_length
|
||||
chunk_len = effective_mps - 2; // sdu_length
|
||||
l2cap_ertm_store_fragment(channel, sar, len, data, chunk_len);
|
||||
len -= chunk_len;
|
||||
sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU;
|
||||
break;
|
||||
case L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU:
|
||||
chunk_len = channel->remote_mps;
|
||||
chunk_len = effective_mps;
|
||||
if (chunk_len >= len){
|
||||
sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_END_OF_L2CAP_SDU;
|
||||
chunk_len = len;
|
||||
@ -436,7 +438,8 @@ static uint16_t l2cap_setup_options_ertm_response(l2cap_channel_t * channel, uin
|
||||
little_endian_store_16( config_options, pos, channel->local_monitor_timeout_ms);
|
||||
pos += 2;
|
||||
// less or equal to remote mps
|
||||
little_endian_store_16( config_options, pos, btstack_min(channel->local_mps, channel->remote_mps));
|
||||
uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps);
|
||||
little_endian_store_16( config_options, pos, effective_mps);
|
||||
pos += 2;
|
||||
//
|
||||
config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT; // MTU
|
||||
|
Loading…
x
Reference in New Issue
Block a user