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
|
||||
// - 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_POST_BUFFER_SIZE 2
|
||||
#define HCI_OUTGOING_PRE_BUFFER_SIZE 1
|
||||
#define HCI_OUTGOING_POST_BUFFER_SIZE 0
|
||||
|
||||
// BNEP may uncompress the IP Header by 16 bytes
|
||||
#ifndef HCI_INCOMING_PRE_BUFFER_SIZE
|
||||
|
@ -111,9 +111,11 @@ 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
|
||||
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
|
||||
static uint8_t slip_outgoing_buffer[LINK_SLIP_TX_CHUNK_LEN+1];
|
||||
static int slip_write_active;
|
||||
// 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+4+1];
|
||||
static uint16_t slip_outgoing_dic;
|
||||
static uint16_t slip_outgoing_dic_present;
|
||||
static int slip_write_active;
|
||||
|
||||
// H5 Link State
|
||||
static hci_transport_link_state_t 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)) {
|
||||
slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
|
||||
}
|
||||
|
||||
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
|
||||
slip_outgoing_buffer[pos++] = BTSTACK_SLIP_SOF;
|
||||
}
|
||||
@ -232,11 +245,15 @@ static inline void hci_transport_slip_send_next_chunk(void){
|
||||
hci_transport_slip_encode_chunk_and_send(0);
|
||||
}
|
||||
|
||||
// format: 0xc0 HEADER PACKET 0xc0
|
||||
// format: 0xc0 HEADER PACKET [DIC] 0xc0
|
||||
// @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;
|
||||
|
||||
// store data integrity check info
|
||||
slip_outgoing_dic = data_integrity_check;
|
||||
slip_outgoing_dic_present = header[0] & 0x40;
|
||||
|
||||
// Start of Frame
|
||||
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){
|
||||
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);
|
||||
uint8_t message_with_dic[LINK_CONTROL_MAX_LEN + 2];
|
||||
uint16_t data_integrity_check = 0;
|
||||
if (link_peer_supports_data_integrity_check){
|
||||
// append data integrity check value / need to copy control message
|
||||
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;
|
||||
data_integrity_check = crc16_calc_for_slip_frame(header, message, message_len);
|
||||
}
|
||||
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);
|
||||
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){
|
||||
@ -333,27 +345,25 @@ static void hci_transport_link_send_queued_packet(void){
|
||||
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);
|
||||
|
||||
uint16_t dic = 0;
|
||||
uint16_t data_integrity_check = 0;
|
||||
if (link_peer_supports_data_integrity_check){
|
||||
// append data integrity check value
|
||||
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;
|
||||
data_integrity_check = crc16_calc_for_slip_frame(header, hci_packet, hci_packet_size);
|
||||
}
|
||||
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);
|
||||
|
||||
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
|
||||
hci_transport_inactivity_timer_set();
|
||||
}
|
||||
|
||||
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);
|
||||
uint8_t header[4];
|
||||
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){
|
||||
|
Loading…
x
Reference in New Issue
Block a user