meta-digi/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.33/ccimx6ul/0007-bluetooth-Check-TTY-bu...

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