From bb80652885b216a770e07c298e1e380bdf5fe08a Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 19 Jan 2020 00:39:55 +0100 Subject: [PATCH] hci_transport_h4: avoid uart read for empty payload --- src/hci_transport_h4.c | 75 +++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/src/hci_transport_h4.c b/src/hci_transport_h4.c index e9f9d5877..4d6d1def8 100644 --- a/src/hci_transport_h4.c +++ b/src/hci_transport_h4.c @@ -187,9 +187,42 @@ static void hci_transport_h4_trigger_next_read(void){ btstack_uart->receive_block(&hci_packet[read_pos], bytes_to_read); } -static void hci_transport_h4_block_read(void){ +static void hci_transport_h4_packet_complete(void){ +#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND + if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE + && memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){ +#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND + if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){ + // detect TI CC256x controller based on manufacturer + log_info("Detected CC256x controller"); + baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED; + } else { + // work around not needed + log_info("Bluetooth controller not by TI"); + baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; + } +#endif +#ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND + if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){ + // detect Cypress controller based on manufacturer + log_info("Detected Cypress controller"); + baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED; + } else { + // work around not needed + log_info("Bluetooth controller not by Cypress"); + baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; + } +#endif + } +#endif + uint16_t packet_len = read_pos-1; - uint16_t packet_len; + // reset state machine before delivering packet to stack as it might close the transport + hci_transport_h4_reset_statemachine(); + packet_handler(hci_packet[0], &hci_packet[1], packet_len); +} + +static void hci_transport_h4_block_read(void){ read_pos += bytes_to_read; @@ -258,38 +291,7 @@ static void hci_transport_h4_block_read(void){ break; case H4_W4_PAYLOAD: -#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND - if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE - && memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){ -#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND - if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){ - // detect TI CC256x controller based on manufacturer - log_info("Detected CC256x controller"); - baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED; - } else { - // work around not needed - log_info("Bluetooth controller not by TI"); - baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; - } -#endif -#ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND - if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){ - // detect Cypress controller based on manufacturer - log_info("Detected Cypress controller"); - baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED; - } else { - // work around not needed - log_info("Bluetooth controller not by Cypress"); - baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; - } -#endif - } -#endif - packet_len = read_pos-1; - - // reset state machine before delivering packet to stack as it might close the transport - hci_transport_h4_reset_statemachine(); - packet_handler(hci_packet[0], &hci_packet[1], packet_len); + hci_transport_h4_packet_complete(); break; case H4_OFF: @@ -306,6 +308,11 @@ static void hci_transport_h4_block_read(void){ } #endif + // forward packet if payload size == 0 + if (h4_state == H4_W4_PAYLOAD && bytes_to_read == 0) { + hci_transport_h4_packet_complete(); + } + if (h4_state != H4_OFF) { hci_transport_h4_trigger_next_read(); }