mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-23 11:43:24 +00:00
l2cap-ertm: store tx packets in channel->tx_packets_data before sending
This commit is contained in:
parent
d84e866fb8
commit
f0fb4cd727
61
src/l2cap.c
61
src/l2cap.c
@ -560,17 +560,58 @@ static inline uint16_t l2cap_encanced_control_field_for_supevisor_frame(l2cap_su
|
|||||||
static int l2cap_next_ertm_seq_nr(int seq_nr){
|
static int l2cap_next_ertm_seq_nr(int seq_nr){
|
||||||
return (seq_nr + 1) & 0x3f;
|
return (seq_nr + 1) & 0x3f;
|
||||||
}
|
}
|
||||||
|
static void l2cap_ertm_next_tx_write_index(l2cap_channel_t * channel){
|
||||||
|
channel->tx_write_index++;
|
||||||
|
if (channel->tx_write_index < channel->num_tx_buffers) return;
|
||||||
|
channel->tx_write_index = 0;
|
||||||
|
}
|
||||||
|
static int l2cap_ertm_send_information_frame(l2cap_channel_t * channel, int index){
|
||||||
|
l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index];
|
||||||
|
hci_reserve_packet_buffer();
|
||||||
|
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||||
|
uint16_t control = l2cap_encanced_control_field_for_information_frame(tx_state->tx_seq, 0, 0, L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU);
|
||||||
|
log_info("I-Frame: control 0x%04x", control);
|
||||||
|
little_endian_store_16(acl_buffer, 8, control);
|
||||||
|
memcpy(&acl_buffer[8+2], &channel->tx_packets_data[index * channel->local_mtu], tx_state->len);
|
||||||
|
// send
|
||||||
|
return l2cap_send_prepared(channel->local_cid, 2 + tx_state->len);
|
||||||
|
}
|
||||||
|
static int l2cap_ertm_send(l2cap_channel_t * channel, uint8_t * data, uint16_t len){
|
||||||
|
if (len > channel->remote_mtu){
|
||||||
|
log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", channel->local_cid);
|
||||||
|
return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU;
|
||||||
|
}
|
||||||
|
// TODO: check tx_transmit
|
||||||
|
// store int tx packet buffer
|
||||||
|
int index = channel->tx_write_index;
|
||||||
|
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;
|
||||||
|
memcpy(&channel->tx_packets_data[index * channel->local_mtu], data, len);
|
||||||
|
// update
|
||||||
|
channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq);
|
||||||
|
l2cap_ertm_next_tx_write_index(channel);
|
||||||
|
// test sendiging it right away
|
||||||
|
l2cap_ertm_send_information_frame(channel, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// assumption - only on Classic connections
|
// assumption - only on Classic connections
|
||||||
int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){
|
int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){
|
||||||
|
|
||||||
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
|
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
log_error("l2cap_send no channel for cid 0x%02x", local_cid);
|
log_error("l2cap_send no channel for cid 0x%02x", local_cid);
|
||||||
return -1; // TODO: define error
|
return -1; // TODO: define error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
|
||||||
|
// send in ERTM
|
||||||
|
if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){
|
||||||
|
return l2cap_ertm_send(channel, data, len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (len > channel->remote_mtu){
|
if (len > channel->remote_mtu){
|
||||||
log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid);
|
log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid);
|
||||||
return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU;
|
return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU;
|
||||||
@ -583,22 +624,8 @@ int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){
|
|||||||
|
|
||||||
hci_reserve_packet_buffer();
|
hci_reserve_packet_buffer();
|
||||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||||
|
memcpy(&acl_buffer[8], data, len);
|
||||||
int control_size = 0;
|
return l2cap_send_prepared(local_cid, len);
|
||||||
#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
|
|
||||||
// hack to send i-frames
|
|
||||||
if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){
|
|
||||||
uint16_t control = l2cap_encanced_control_field_for_information_frame(channel->next_tx_seq, 0, 0, L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU);
|
|
||||||
log_info("I-Frame: control 0x%04x", control);
|
|
||||||
little_endian_store_16(acl_buffer, 8, control);
|
|
||||||
channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq);
|
|
||||||
control_size = 2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memcpy(&acl_buffer[8+control_size], data, len);
|
|
||||||
|
|
||||||
return l2cap_send_prepared(local_cid, len+control_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int l2cap_send_echo_request(hci_con_handle_t con_handle, uint8_t *data, uint16_t len){
|
int l2cap_send_echo_request(hci_con_handle_t con_handle, uint8_t *data, uint16_t len){
|
||||||
|
11
src/l2cap.h
11
src/l2cap.h
@ -123,6 +123,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t tx_seq;
|
uint8_t tx_seq;
|
||||||
|
uint16_t len;
|
||||||
} l2cap_ertm_tx_packet_state_t;
|
} l2cap_ertm_tx_packet_state_t;
|
||||||
|
|
||||||
|
|
||||||
@ -210,12 +211,18 @@ typedef struct {
|
|||||||
// if ertm is not mandatory, allow fallback to L2CAP Basic Mode - flag
|
// if ertm is not mandatory, allow fallback to L2CAP Basic Mode - flag
|
||||||
uint8_t ertm_mandatory;
|
uint8_t ertm_mandatory;
|
||||||
|
|
||||||
// receiver: send RR frame - flag
|
// sender: buffer index to store tx packet
|
||||||
uint8_t send_supervisor_frame_receiver_ready;
|
uint8_t tx_write_index;
|
||||||
|
|
||||||
|
// sender: buffer index of packet to send next
|
||||||
|
uint8_t tx_read_index;
|
||||||
|
|
||||||
// sender: next seq nr used for sending
|
// sender: next seq nr used for sending
|
||||||
uint8_t next_tx_seq;
|
uint8_t next_tx_seq;
|
||||||
|
|
||||||
|
// receiver: send RR frame - flag
|
||||||
|
uint8_t send_supervisor_frame_receiver_ready;
|
||||||
|
|
||||||
// receiver: value of tx_seq in next expected i-frame
|
// receiver: value of tx_seq in next expected i-frame
|
||||||
uint8_t expected_tx_seq;
|
uint8_t expected_tx_seq;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user