diff options
author | Andre Eisenbach <eisenbach@google.com> | 2015-09-10 21:41:39 -0700 |
---|---|---|
committer | Andre Eisenbach <eisenbach@google.com> | 2015-10-21 20:51:51 +0000 |
commit | bdd19e0873854567bb6bd9bc8905a87a3a4744c4 (patch) | |
tree | d612c5073b9c49129b6a3bae4741b4950b0b9e3f | |
parent | 58593a02736ff9ac9bdccd0e3186602f17452cdf (diff) | |
download | bt-bdd19e0873854567bb6bd9bc8905a87a3a4744c4.tar.gz |
Workaround for H4 HCI stream corruption during LE scans
Sometimes, during result-heavy LE scans, the UART byte stream can become
corrupted, leading to assertions caused by mis-interpreting the bytes
following the corruption.
This workaround looks for tell-tale signs of a BLE event and attempts to
skip the correct amount of bytes in the stream to re-synchronize onto a
packet boundary.
Bug: 23934838
Change-Id: Ifadaecf8077cb1defc7134c59c97302fca660f81
-rw-r--r-- | hci/src/hci_hal_h4.c | 43 | ||||
-rw-r--r-- | hci/test/hci_hal_h4_test.cpp | 7 |
2 files changed, 50 insertions, 0 deletions
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c index e9364c473..49e9463d2 100644 --- a/hci/src/hci_hal_h4.c +++ b/hci/src/hci_hal_h4.c @@ -32,6 +32,7 @@ #include "vendor.h" #define HCI_HAL_SERIAL_BUFFER_SIZE 1026 +#define HCI_BLE_EVENT 0x3e // Increased HCI thread priority to keep up with the audio sub-system // when streaming time sensitive data (A2DP). @@ -48,6 +49,8 @@ static int uart_fd; static eager_reader_t *uart_stream; static serial_data_type_t current_data_type; static bool stream_has_interpretation; +static bool stream_corruption_detected; +static uint8_t stream_corruption_bytes_to_ignore; static void event_uart_has_bytes(eager_reader_t *reader, void *context); @@ -87,6 +90,8 @@ static bool hal_open() { } stream_has_interpretation = false; + stream_corruption_detected = false; + stream_corruption_bytes_to_ignore = 0; eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL); // Raise thread priorities to keep up with audio @@ -178,6 +183,40 @@ done:; // Internal functions +// WORKAROUND: +// As exhibited by b/23934838, during result-heavy LE scans, the UART byte +// stream can get corrupted, leading to assertions caused by mis-interpreting +// the bytes following the corruption. +// This workaround looks for tell-tale signs of a BLE event and attempts to +// skip the correct amount of bytes in the stream to re-synchronize onto +// a packet boundary. +// Function returns true if |byte_read| has been processed by the workaround. +static bool stream_corrupted_during_le_scan_workaround(const uint8_t byte_read) +{ + if (!stream_corruption_detected && byte_read == HCI_BLE_EVENT) { + LOG_ERROR(LOG_TAG, "%s HCI stream corrupted (message type 0x3E)!", __func__); + stream_corruption_detected = true; + return true; + } + + if (stream_corruption_detected) { + if (stream_corruption_bytes_to_ignore == 0) { + stream_corruption_bytes_to_ignore = byte_read; + LOG_ERROR(LOG_TAG, "%s About to skip %d bytes...", __func__, stream_corruption_bytes_to_ignore); + } else { + --stream_corruption_bytes_to_ignore; + } + + if (stream_corruption_bytes_to_ignore == 0) { + LOG_ERROR(LOG_TAG, "%s Back to our regularly scheduled program...", __func__); + stream_corruption_detected = false; + } + return true; + } + + return false; +} + // See what data is waiting, and notify the upper layer static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) { if (stream_has_interpretation) { @@ -188,6 +227,10 @@ static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *conte LOG_ERROR(LOG_TAG, "%s could not read HCI message type", __func__); return; } + + if (stream_corrupted_during_le_scan_workaround(type_byte)) + return; + if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) { LOG_ERROR(LOG_TAG, "%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT); return; diff --git a/hci/test/hci_hal_h4_test.cpp b/hci/test/hci_hal_h4_test.cpp index 870b2587d..56705e754 100644 --- a/hci/test/hci_hal_h4_test.cpp +++ b/hci/test/hci_hal_h4_test.cpp @@ -43,6 +43,9 @@ DECLARE_TEST_MODES( type_byte_only ); +// Use as packet type to test stream_corrupted_during_le_scan_workaround() +static const uint8_t HCI_BLE_EVENT = 0x3e; + static char sample_data1[100] = "A point is that which has no part."; static char sample_data2[100] = "A line is breadthless length."; static char sample_data3[100] = "The ends of a line are points."; @@ -50,6 +53,9 @@ static char acl_data[100] = "A straight line is a line which lies evenly wit static char sco_data[100] = "A surface is that which has length and breadth only."; static char event_data[100] = "The edges of a surface are lines."; +// Test data for stream_corrupted_during_le_scan_workaround() +static char corrupted_data[] = { 0x5 /* length of remaining data */, 'H', 'e', 'l', 'l', 'o' }; + static const hci_hal_t *hal; static int dummy_serial_fd; static int reentry_i = 0; @@ -221,6 +227,7 @@ TEST_F(HciHalH4Test, test_read_synchronous) { reset_for(read_synchronous); write_packet(sockfd[1], DATA_TYPE_ACL, acl_data); + write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data); write_packet(sockfd[1], DATA_TYPE_SCO, sco_data); write_packet(sockfd[1], DATA_TYPE_EVENT, event_data); |