l2cap.c (8f4dd6c139388844e52e2802e9061184f613fa9f) | l2cap.c (b90eac910b0b2b6602bcf13f378371bb03d224a7) |
---|---|
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 --- 187 unchanged lines hidden (view full) --- 196 return (seq_nr + 1) & 0x3f; 197} 198 199static int l2cap_ertm_can_store_packet_now(l2cap_channel_t * channel){ 200 // get num free tx buffers 201 int num_free_tx_buffers = channel->num_tx_buffers - channel->num_stored_tx_frames; 202 // calculate num tx buffers for remote MTU 203 int num_tx_buffers_for_max_remote_mtu; | 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 --- 187 unchanged lines hidden (view full) --- 196 return (seq_nr + 1) & 0x3f; 197} 198 199static int l2cap_ertm_can_store_packet_now(l2cap_channel_t * channel){ 200 // get num free tx buffers 201 int num_free_tx_buffers = channel->num_tx_buffers - channel->num_stored_tx_frames; 202 // calculate num tx buffers for remote MTU 203 int num_tx_buffers_for_max_remote_mtu; |
204 if (channel->remote_mtu <= channel->remote_mps){ | 204 uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps); 205 if (channel->remote_mtu <= effective_mps){ |
205 // MTU fits into single packet 206 num_tx_buffers_for_max_remote_mtu = 1; 207 } else { 208 // include SDU Length | 206 // MTU fits into single packet 207 num_tx_buffers_for_max_remote_mtu = 1; 208 } else { 209 // include SDU Length |
209 num_tx_buffers_for_max_remote_mtu = (channel->remote_mtu + 2 + (channel->remote_mps - 1)) / channel->remote_mps; | 210 num_tx_buffers_for_max_remote_mtu = (channel->remote_mtu + 2 + (effective_mps - 1)) / effective_mps; |
210 } 211 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); 212 return num_tx_buffers_for_max_remote_mtu <= num_free_tx_buffers; 213} 214 215static void l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel_t * l2cap_channel){ 216 log_info("Retransmit unacknowleged frames"); 217 l2cap_channel->unacked_frames = 0;; --- 99 unchanged lines hidden (view full) --- 317} 318 319static void l2cap_ertm_store_fragment(l2cap_channel_t * channel, l2cap_segmentation_and_reassembly_t sar, uint16_t sdu_length, uint8_t * data, uint16_t len){ 320 // get next index for storing packets 321 int index = channel->tx_write_index; 322 323 l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index]; 324 tx_state->tx_seq = channel->next_tx_seq; | 211 } 212 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); 213 return num_tx_buffers_for_max_remote_mtu <= num_free_tx_buffers; 214} 215 216static void l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel_t * l2cap_channel){ 217 log_info("Retransmit unacknowleged frames"); 218 l2cap_channel->unacked_frames = 0;; --- 99 unchanged lines hidden (view full) --- 318} 319 320static void l2cap_ertm_store_fragment(l2cap_channel_t * channel, l2cap_segmentation_and_reassembly_t sar, uint16_t sdu_length, uint8_t * data, uint16_t len){ 321 // get next index for storing packets 322 int index = channel->tx_write_index; 323 324 l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index]; 325 tx_state->tx_seq = channel->next_tx_seq; |
325 tx_state->len = len; | |
326 tx_state->sar = sar; 327 tx_state->retry_count = 0; 328 329 uint8_t * tx_packet = &channel->tx_packets_data[index * channel->local_mps]; | 326 tx_state->sar = sar; 327 tx_state->retry_count = 0; 328 329 uint8_t * tx_packet = &channel->tx_packets_data[index * channel->local_mps]; |
330 log_debug("index %u, mtu %u, packet tx %p", index, channel->local_mtu, tx_packet); | 330 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); |
331 int pos = 0; 332 if (sar == L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU){ 333 little_endian_store_16(tx_packet, 0, sdu_length); 334 pos += 2; 335 } 336 memcpy(&tx_packet[pos], data, len); | 331 int pos = 0; 332 if (sar == L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU){ 333 little_endian_store_16(tx_packet, 0, sdu_length); 334 pos += 2; 335 } 336 memcpy(&tx_packet[pos], data, len); |
337 tx_state->len = pos + len; |
|
337 338 // update 339 channel->num_stored_tx_frames++; 340 channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq); 341 l2cap_ertm_next_tx_write_index(channel); 342 343 log_info("l2cap_ertm_store_fragment: tx_read_index %u, tx_write_index %u, num stored %u", channel->tx_read_index, channel->tx_write_index, channel->num_stored_tx_frames); 344 --- 6 unchanged lines hidden (view full) --- 351 } 352 353 if (!l2cap_ertm_can_store_packet_now(channel)){ 354 log_error("l2cap_ertm_send cid 0x%02x, fragment store full", channel->local_cid); 355 return BTSTACK_ACL_BUFFERS_FULL; 356 } 357 358 // check if it needs to get fragmented | 338 339 // update 340 channel->num_stored_tx_frames++; 341 channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq); 342 l2cap_ertm_next_tx_write_index(channel); 343 344 log_info("l2cap_ertm_store_fragment: tx_read_index %u, tx_write_index %u, num stored %u", channel->tx_read_index, channel->tx_write_index, channel->num_stored_tx_frames); 345 --- 6 unchanged lines hidden (view full) --- 352 } 353 354 if (!l2cap_ertm_can_store_packet_now(channel)){ 355 log_error("l2cap_ertm_send cid 0x%02x, fragment store full", channel->local_cid); 356 return BTSTACK_ACL_BUFFERS_FULL; 357 } 358 359 // check if it needs to get fragmented |
359 if (len > channel->remote_mps){ | 360 uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps); 361 if (len > effective_mps){ |
360 // fragmentation needed. 361 l2cap_segmentation_and_reassembly_t sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU; 362 int chunk_len; 363 while (len){ 364 switch (sar){ 365 case L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU: | 362 // fragmentation needed. 363 l2cap_segmentation_and_reassembly_t sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU; 364 int chunk_len; 365 while (len){ 366 switch (sar){ 367 case L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU: |
366 chunk_len = channel->remote_mps - 2; // sdu_length | 368 chunk_len = effective_mps - 2; // sdu_length |
367 l2cap_ertm_store_fragment(channel, sar, len, data, chunk_len); 368 len -= chunk_len; 369 sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU; 370 break; 371 case L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU: | 369 l2cap_ertm_store_fragment(channel, sar, len, data, chunk_len); 370 len -= chunk_len; 371 sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU; 372 break; 373 case L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU: |
372 chunk_len = channel->remote_mps; | 374 chunk_len = effective_mps; |
373 if (chunk_len >= len){ 374 sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_END_OF_L2CAP_SDU; 375 chunk_len = len; 376 } 377 l2cap_ertm_store_fragment(channel, sar, len, data, chunk_len); 378 len -= chunk_len; 379 break; 380 default: --- 50 unchanged lines hidden (view full) --- 431 // and indicates the value that will be used by the sender of the Configuration Response -> use our value 432 little_endian_store_16( config_options, pos, channel->local_retransmission_timeout_ms); 433 pos += 2; 434 // A value for the Monitor time-out shall be sent in a positive Configuration Response 435 // and indicates the value that will be used by the sender of the Configuration Response -> use our value 436 little_endian_store_16( config_options, pos, channel->local_monitor_timeout_ms); 437 pos += 2; 438 // less or equal to remote mps | 375 if (chunk_len >= len){ 376 sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_END_OF_L2CAP_SDU; 377 chunk_len = len; 378 } 379 l2cap_ertm_store_fragment(channel, sar, len, data, chunk_len); 380 len -= chunk_len; 381 break; 382 default: --- 50 unchanged lines hidden (view full) --- 433 // and indicates the value that will be used by the sender of the Configuration Response -> use our value 434 little_endian_store_16( config_options, pos, channel->local_retransmission_timeout_ms); 435 pos += 2; 436 // A value for the Monitor time-out shall be sent in a positive Configuration Response 437 // and indicates the value that will be used by the sender of the Configuration Response -> use our value 438 little_endian_store_16( config_options, pos, channel->local_monitor_timeout_ms); 439 pos += 2; 440 // less or equal to remote mps |
439 little_endian_store_16( config_options, pos, btstack_min(channel->local_mps, channel->remote_mps)); | 441 uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps); 442 little_endian_store_16( config_options, pos, effective_mps); |
440 pos += 2; 441 // 442 config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT; // MTU 443 config_options[pos++] = 2; // length 444 little_endian_store_16(config_options, pos, channel->remote_mtu); 445 pos += 2; 446#if 0 447 // --- 3442 unchanged lines hidden --- | 443 pos += 2; 444 // 445 config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT; // MTU 446 config_options[pos++] = 2; // length 447 little_endian_store_16(config_options, pos, channel->remote_mtu); 448 pos += 2; 449#if 0 450 // --- 3442 unchanged lines hidden --- |