190 lines
6.3 KiB
Diff
190 lines
6.3 KiB
Diff
From: Anantha Krishnan <ananthk@codeaurora.org>
|
|
Date: Tue, 30 Sep 2014 12:13:00 +0530
|
|
Subject: [PATCH] bluetooth: Check TTY buffer for data availability before
|
|
reading
|
|
|
|
When operating at higher baud rates check the TTY buffer for
|
|
availability of data before proceeding to read. Call select() with
|
|
a 3 sec timeout value to check for the availablitiy of data.
|
|
select() will return once data is available in the TTY buffers
|
|
and will allow read() to fetch the data. If data is not available
|
|
in the TTY buffer until the timeout valueexpires, do not proceed
|
|
to read the data from the TTY buffers as there is none.
|
|
|
|
Occasionally corrupt data is received on UART lines while we wait
|
|
for vendor specific event from Controller. Expected vendor specific
|
|
events are received after the corrupt data. But we do not retry
|
|
and exit and this causes firmware download failures. So, retry once
|
|
if we did not get HCI event.
|
|
|
|
Change-Id: I3b672a7762403690f8b934ca216492f16285e8da
|
|
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
|
|
---
|
|
tools/hciattach.c | 20 ++++++++++++-
|
|
tools/hciattach_rome.c | 77 +++++++++++++++++++++++++++++++++++++++-----------
|
|
tools/hciattach_rome.h | 3 ++
|
|
3 files changed, 83 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/tools/hciattach.c b/tools/hciattach.c
|
|
index 3041e28ff82a..13f073325c43 100644
|
|
--- a/tools/hciattach.c
|
|
+++ b/tools/hciattach.c
|
|
@@ -163,16 +163,34 @@ int read_hci_event(int fd, unsigned char* buf, int size)
|
|
{
|
|
int remain, r;
|
|
int count = 0;
|
|
+ fd_set infids;
|
|
+ struct timeval timeout;
|
|
|
|
if (size <= 0)
|
|
return -1;
|
|
|
|
+ FD_ZERO (&infids);
|
|
+ FD_SET (fd, &infids);
|
|
+ timeout.tv_sec = 3;
|
|
+ timeout.tv_usec = 0;
|
|
+
|
|
+ /* Check whether data is available in TTY buffer before calling read() */
|
|
+ if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1) {
|
|
+ fprintf(stderr, "%s: Timing out on select for 3 secs.\n", __FUNCTION__);
|
|
+ return -1;
|
|
+ }
|
|
+ else
|
|
+ fprintf(stderr, "%s: Data(HCI-CMD-COMP-EVENT) available in TTY Serial buffer\n", __FUNCTION__);
|
|
+
|
|
/* The first byte identifies the packet type. For HCI event packets, it
|
|
* should be 0x04, so we read until we get to the 0x04. */
|
|
while (1) {
|
|
r = read(fd, buf, 1);
|
|
- if (r <= 0)
|
|
+ if (r <= 0) {
|
|
+ fprintf(stderr, "%s: read() failed with return value: %d\n",
|
|
+ __FUNCTION__, r);
|
|
return -1;
|
|
+ }
|
|
if (buf[0] == 0x04)
|
|
break;
|
|
}
|
|
diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
|
|
index d0e2935b9997..d2687b1ef01a 100644
|
|
--- a/tools/hciattach_rome.c
|
|
+++ b/tools/hciattach_rome.c
|
|
@@ -326,42 +326,87 @@ failed:
|
|
}
|
|
|
|
|
|
+int wait_for_data(int fd, int maxTimeOut)
|
|
+{
|
|
+ fd_set infids;
|
|
+ struct timeval timeout;
|
|
+
|
|
+ if (maxTimeOut <= 0) {
|
|
+ fprintf(stderr, "%s: Invalid timeout value specified", __func__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ FD_ZERO (&infids);
|
|
+ FD_SET (fd, &infids);
|
|
+ timeout.tv_sec = maxTimeOut;
|
|
+ timeout.tv_usec = 0;
|
|
+
|
|
+ /* Check whether data is available in TTY buffer before calling read() */
|
|
+ if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1) {
|
|
+ fprintf(stderr, "%s: Timing out on select for %d secs.\n", __FUNCTION__, maxTimeOut);
|
|
+ return -1;
|
|
+ }
|
|
+ else
|
|
+ fprintf(stderr, "%s: HCI-VS-EVENT available in TTY Serial buffer\n",
|
|
+ __FUNCTION__);
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
/*
|
|
* Read an VS HCI event from the given file descriptor.
|
|
*/
|
|
int read_vs_hci_event(int fd, unsigned char* buf, int size)
|
|
{
|
|
- int remain, r;
|
|
+ int remain, r, retry = 0;
|
|
int count = 0;
|
|
- fd_set infids;
|
|
- struct timeval timeout;
|
|
|
|
if (size <= 0) {
|
|
fprintf(stderr, "Invalid size arguement!\n");
|
|
return -1;
|
|
}
|
|
|
|
- fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC\n", __FUNCTION__);
|
|
-
|
|
- FD_ZERO (&infids);
|
|
- FD_SET (fd, &infids);
|
|
- timeout.tv_sec = 3;
|
|
- timeout.tv_usec = 0; /* half second is a long time at 115.2 Kbps */
|
|
+ fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC\n",
|
|
+ __FUNCTION__);
|
|
|
|
- if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1)
|
|
- fprintf(stderr, "%s: Timing out on select for 3 secs.\n", __FUNCTION__);
|
|
- else
|
|
- fprintf(stderr, "%s: Data available in TTY Serial buffer\n", __FUNCTION__);
|
|
+ /* Check whether data is available in TTY buffer before calling read() */
|
|
+ if (wait_for_data(fd, SELECT_TIMEOUT) < 1)
|
|
+ return -1;
|
|
|
|
/* The first byte identifies the packet type. For HCI event packets, it
|
|
* should be 0x04, so we read until we get to the 0x04. */
|
|
/* It will keep reading until find 0x04 byte */
|
|
while (1) {
|
|
+ /* Read UART Buffer for HCI-DATA */
|
|
r = read(fd, buf, 1);
|
|
- if (r <= 0)
|
|
- return -1;
|
|
- if (buf[0] == 0x04)
|
|
+ if (r <= 0) {
|
|
+ fprintf(stderr, "%s: read() failed. error: %d\n",
|
|
+ __FUNCTION__, r);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /* Check if received data is HCI-DATA or not.
|
|
+ * If not HCI-DATA, then retry reading the UART Buffer once.
|
|
+ * Sometimes there could be corruption on the UART lines and to
|
|
+ * avoid that retry once reading the UART Buffer for HCI-DATA.
|
|
+ */
|
|
+ if (buf[0] == 0x04) { /* Recvd. HCI DATA */
|
|
+ retry = 0;
|
|
break;
|
|
+ }
|
|
+ else if (retry < MAX_RETRY_CNT){ /* Retry mechanism */
|
|
+ retry++;
|
|
+ fprintf(stderr, "%s: Not an HCI-VS-Event! buf[0]: %d",
|
|
+ __FUNCTION__, buf[0]);
|
|
+ if (wait_for_data(fd, SELECT_TIMEOUT) < 1)
|
|
+ return -1;
|
|
+ else /* Data available in UART Buffer: Continue to read */
|
|
+ continue;
|
|
+ }
|
|
+ else { /* RETRY failed : Exiting with failure */
|
|
+ fprintf(stderr, "%s: RETRY failed!", __FUNCTION__);
|
|
+ return -1;
|
|
+ }
|
|
}
|
|
count++;
|
|
|
|
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
|
|
index a4abe9f73080..3efb71995c45 100644
|
|
--- a/tools/hciattach_rome.h
|
|
+++ b/tools/hciattach_rome.h
|
|
@@ -179,6 +179,9 @@ typedef struct
|
|
#define TAG_NUM_2 2
|
|
#define TAG_BDADDR_OFFSET 7
|
|
|
|
+#define MAX_RETRY_CNT 1
|
|
+#define SELECT_TIMEOUT 3
|
|
+
|
|
/* NVM Tags specifically used for ROME 1.0 */
|
|
#define ROME_1_0_100022_1 0x101000221
|
|
#define ROME_1_0_100019 0x101000190
|