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 ---