mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-24 21:39:55 +00:00
h5: fix corruption of outgoing fragmented ACL packets.
This commit is contained in:
parent
f7d194e559
commit
c65ae2a0ed
@ -94,9 +94,8 @@ extern "C" {
|
|||||||
|
|
||||||
// additional pre- and post-packet buffer for packets to Bluetooth module
|
// additional pre- and post-packet buffer for packets to Bluetooth module
|
||||||
// - pre-buffer used for HCI Transport H4 variants
|
// - pre-buffer used for HCI Transport H4 variants
|
||||||
// - post-buffer used for HCI Transport H5
|
|
||||||
#define HCI_OUTGOING_PRE_BUFFER_SIZE 1
|
#define HCI_OUTGOING_PRE_BUFFER_SIZE 1
|
||||||
#define HCI_OUTGOING_POST_BUFFER_SIZE 2
|
#define HCI_OUTGOING_POST_BUFFER_SIZE 0
|
||||||
|
|
||||||
// BNEP may uncompress the IP Header by 16 bytes
|
// BNEP may uncompress the IP Header by 16 bytes
|
||||||
#ifndef HCI_INCOMING_PRE_BUFFER_SIZE
|
#ifndef HCI_INCOMING_PRE_BUFFER_SIZE
|
||||||
|
@ -111,8 +111,10 @@ static const uint8_t link_control_sleep[] = { 0x07, 0x78};
|
|||||||
// incoming pre-bufffer + 4 bytes H5 header + max(acl header + acl payload, event header + event data) + 2 bytes opt CRC
|
// incoming pre-bufffer + 4 bytes H5 header + max(acl header + acl payload, event header + event data) + 2 bytes opt CRC
|
||||||
static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 6 + HCI_PACKET_BUFFER_SIZE];
|
static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 6 + HCI_PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
// outgoing slip encoded buffer. +1 to assert that last SOF fits in buffer
|
// outgoing slip encoded buffer. +4 to assert that DIC fits in buffer. +1 to assert that last SOF fits in buffer.
|
||||||
static uint8_t slip_outgoing_buffer[LINK_SLIP_TX_CHUNK_LEN+1];
|
static uint8_t slip_outgoing_buffer[LINK_SLIP_TX_CHUNK_LEN+4+1];
|
||||||
|
static uint16_t slip_outgoing_dic;
|
||||||
|
static uint16_t slip_outgoing_dic_present;
|
||||||
static int slip_write_active;
|
static int slip_write_active;
|
||||||
|
|
||||||
// H5 Link State
|
// H5 Link State
|
||||||
@ -219,7 +221,18 @@ static void hci_transport_slip_encode_chunk_and_send(int pos){
|
|||||||
while (btstack_slip_encoder_has_data() & (pos < LINK_SLIP_TX_CHUNK_LEN)) {
|
while (btstack_slip_encoder_has_data() & (pos < LINK_SLIP_TX_CHUNK_LEN)) {
|
||||||
slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
|
slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!btstack_slip_encoder_has_data()){
|
if (!btstack_slip_encoder_has_data()){
|
||||||
|
// Payload encoded, append DIC if present.
|
||||||
|
// note: slip_outgoing_buffer is guaranteed to be big enough to add DIC + SOF after LINK_SLIP_TX_CHUNK_LEN
|
||||||
|
if (slip_outgoing_dic_present){
|
||||||
|
uint8_t dic_buffer[2];
|
||||||
|
big_endian_store_16(dic_buffer, 0, slip_outgoing_dic);
|
||||||
|
btstack_slip_encoder_start(dic_buffer, 2);
|
||||||
|
while (btstack_slip_encoder_has_data()){
|
||||||
|
slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
|
||||||
|
}
|
||||||
|
}
|
||||||
// Start of Frame
|
// Start of Frame
|
||||||
slip_outgoing_buffer[pos++] = BTSTACK_SLIP_SOF;
|
slip_outgoing_buffer[pos++] = BTSTACK_SLIP_SOF;
|
||||||
}
|
}
|
||||||
@ -232,12 +245,16 @@ static inline void hci_transport_slip_send_next_chunk(void){
|
|||||||
hci_transport_slip_encode_chunk_and_send(0);
|
hci_transport_slip_encode_chunk_and_send(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// format: 0xc0 HEADER PACKET 0xc0
|
// format: 0xc0 HEADER PACKET [DIC] 0xc0
|
||||||
// @param uint8_t header[4]
|
// @param uint8_t header[4]
|
||||||
static void hci_transport_slip_send_frame(const uint8_t * header, const uint8_t * packet, uint16_t packet_size){
|
static void hci_transport_slip_send_frame(const uint8_t * header, const uint8_t * packet, uint16_t packet_size, uint16_t data_integrity_check){
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
|
// store data integrity check info
|
||||||
|
slip_outgoing_dic = data_integrity_check;
|
||||||
|
slip_outgoing_dic_present = header[0] & 0x40;
|
||||||
|
|
||||||
// Start of Frame
|
// Start of Frame
|
||||||
slip_outgoing_buffer[pos++] = BTSTACK_SLIP_SOF;
|
slip_outgoing_buffer[pos++] = BTSTACK_SLIP_SOF;
|
||||||
|
|
||||||
@ -279,18 +296,13 @@ static void hci_transport_link_calc_header(uint8_t * header,
|
|||||||
static void hci_transport_link_send_control(const uint8_t * message, int message_len){
|
static void hci_transport_link_send_control(const uint8_t * message, int message_len){
|
||||||
uint8_t header[4];
|
uint8_t header[4];
|
||||||
hci_transport_link_calc_header(header, 0, 0, link_peer_supports_data_integrity_check, 0, LINK_CONTROL_PACKET_TYPE, message_len);
|
hci_transport_link_calc_header(header, 0, 0, link_peer_supports_data_integrity_check, 0, LINK_CONTROL_PACKET_TYPE, message_len);
|
||||||
uint8_t message_with_dic[LINK_CONTROL_MAX_LEN + 2];
|
uint16_t data_integrity_check = 0;
|
||||||
if (link_peer_supports_data_integrity_check){
|
if (link_peer_supports_data_integrity_check){
|
||||||
// append data integrity check value / need to copy control message
|
data_integrity_check = crc16_calc_for_slip_frame(header, message, message_len);
|
||||||
memcpy(message_with_dic, message, message_len);
|
|
||||||
uint16_t dic = crc16_calc_for_slip_frame(header, message, message_len);
|
|
||||||
big_endian_store_16(message_with_dic, message_len, dic);
|
|
||||||
message_len += 2;
|
|
||||||
message = message_with_dic;
|
|
||||||
}
|
}
|
||||||
log_info("hci_transport_link_send_control: size %u, append dic %u", message_len, link_peer_supports_data_integrity_check);
|
log_info("hci_transport_link_send_control: size %u, append dic %u", message_len, link_peer_supports_data_integrity_check);
|
||||||
log_info_hexdump(message, message_len);
|
log_info_hexdump(message, message_len);
|
||||||
hci_transport_slip_send_frame(header, message, message_len);
|
hci_transport_slip_send_frame(header, message, message_len, data_integrity_check);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_transport_link_send_sync(void){
|
static void hci_transport_link_send_sync(void){
|
||||||
@ -333,27 +345,25 @@ static void hci_transport_link_send_queued_packet(void){
|
|||||||
uint8_t header[4];
|
uint8_t header[4];
|
||||||
hci_transport_link_calc_header(header, link_seq_nr, link_ack_nr, link_peer_supports_data_integrity_check, 1, hci_packet_type, hci_packet_size);
|
hci_transport_link_calc_header(header, link_seq_nr, link_ack_nr, link_peer_supports_data_integrity_check, 1, hci_packet_type, hci_packet_size);
|
||||||
|
|
||||||
uint16_t dic = 0;
|
uint16_t data_integrity_check = 0;
|
||||||
if (link_peer_supports_data_integrity_check){
|
if (link_peer_supports_data_integrity_check){
|
||||||
// append data integrity check value
|
data_integrity_check = crc16_calc_for_slip_frame(header, hci_packet, hci_packet_size);
|
||||||
dic = crc16_calc_for_slip_frame(header, hci_packet, hci_packet_size);
|
|
||||||
big_endian_store_16(hci_packet, hci_packet_size, dic);
|
|
||||||
hci_packet_size += 2;
|
|
||||||
}
|
}
|
||||||
log_info("hci_transport_link_send_queued_packet: seq %u, ack %u, size %u, append dic %u", link_seq_nr, link_ack_nr, hci_packet_size, link_peer_supports_data_integrity_check);
|
log_info("hci_transport_link_send_queued_packet: seq %u, ack %u, size %u. Append dic %u, dic = 0x%04x", link_seq_nr, link_ack_nr, hci_packet_size, link_peer_supports_data_integrity_check, data_integrity_check);
|
||||||
log_info_hexdump(hci_packet, hci_packet_size);
|
log_info_hexdump(hci_packet, hci_packet_size);
|
||||||
|
|
||||||
hci_transport_slip_send_frame(header, hci_packet, hci_packet_size);
|
hci_transport_slip_send_frame(header, hci_packet, hci_packet_size, data_integrity_check);
|
||||||
|
|
||||||
// reset inactvitiy timer
|
// reset inactvitiy timer
|
||||||
hci_transport_inactivity_timer_set();
|
hci_transport_inactivity_timer_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_transport_link_send_ack_packet(void){
|
static void hci_transport_link_send_ack_packet(void){
|
||||||
|
// Pure ACK package is without DIC as there is no payload either
|
||||||
log_info("link: send ack %u", link_ack_nr);
|
log_info("link: send ack %u", link_ack_nr);
|
||||||
uint8_t header[4];
|
uint8_t header[4];
|
||||||
hci_transport_link_calc_header(header, 0, link_ack_nr, 0, 0, LINK_ACKNOWLEDGEMENT_TYPE, 0);
|
hci_transport_link_calc_header(header, 0, link_ack_nr, 0, 0, LINK_ACKNOWLEDGEMENT_TYPE, 0);
|
||||||
hci_transport_slip_send_frame(header, NULL, 0);
|
hci_transport_slip_send_frame(header, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_transport_link_run(void){
|
static void hci_transport_link_run(void){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user