diff --git a/src/hci.h b/src/hci.h index f4dde9fbb..2d1b8f1f8 100644 --- a/src/hci.h +++ b/src/hci.h @@ -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 diff --git a/src/hci_transport_h5.c b/src/hci_transport_h5.c index c22c2c5bf..8b82058ca 100644 --- a/src/hci_transport_h5.c +++ b/src/hci_transport_h5.c @@ -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){