OSDN Git Service

fix for btsnoop log blogging HCI socket
authorKim Schulz <k.schulz@samsung.com>
Mon, 23 Sep 2013 10:48:47 +0000 (12:48 +0200)
committerZhihai Xu <zhihaixu@google.com>
Mon, 16 Dec 2013 22:27:34 +0000 (14:27 -0800)
Fix for bug 10887611 - btsnoop logging can block HCI socket for longer times.
- Removed the use of the same mutex as the receive queue.
- optimized the code (combined identical code pieces)
- added new function for writing to the log
- switched from using multiple write() calls to using a single writev() (to get atomicity).
patch-set 2:
- fixed review comments (overruns + warnings)
patch-set 3:
- fixed problem with non-matching flags for H4

Bug: 10887611
Change-Id: I16cc23a850093448309ec34c73d536b8571441e9

hci/src/btsnoop.c

index 4807df8..5b0f26d 100755 (executable)
 #define SNOOPDBG(param, ...) {}
 #endif
 
+#define HCIT_TYPE_COMMAND   1
+#define HCIT_TYPE_ACL_DATA  2
+#define HCIT_TYPE_SCO_DATA  3
+#define HCIT_TYPE_EVENT     4
+
 /* file descriptor of the BT snoop file (by default, -1 means disabled) */
 int hci_btsnoop_fd = -1;
 
@@ -117,6 +122,7 @@ do {
 #define BTSNOOP_EPOCH_HI 0x00dcddb3U
 #define BTSNOOP_EPOCH_LO 0x0f2f8000U
 
+
 /*******************************************************************************
  **
  ** Function         tv_to_btsnoop_ts
@@ -252,6 +258,46 @@ static int btsnoop_log_close(void)
 }
 
 /*******************************************************************************
+ ** Function          btsnoop_write
+ **
+ ** Description       Function used to write the actual data to the log
+ **
+ ** Returns           none
+*******************************************************************************/
+
+void btsnoop_write(uint8_t *p, uint32_t flags, const uint8_t *ptype, uint32_t len)
+{
+    uint32_t value, value_hi;
+    struct timeval tv;
+    struct iovec io[3];
+    uint32_t header[6];
+
+    /* store the length in both original and included fields */
+    header[0] = l_to_be(len + 1);
+    header[1] = header[0];
+    /* flags: data can be sent or received */
+    header[2] = l_to_be(flags);
+    /* drops: none */
+    header[3] = 0;
+    /* time */
+    gettimeofday(&tv, NULL);
+    tv_to_btsnoop_ts(&header[5], &header[4], &tv);
+    header[4] = l_to_be(header[4]);
+    header[5] = l_to_be(header[5]);
+
+    io[0].iov_base = header;
+    io[0].iov_len = sizeof(header);
+
+    io[1].iov_base = (void*)ptype;
+    io[1].iov_len = 1;
+
+    io[2].iov_base = p;
+    io[2].iov_len = len;
+
+    (void) writev(hci_btsnoop_fd, io, 3);
+}
+
+/*******************************************************************************
  **
  ** Function         btsnoop_hci_cmd
  **
@@ -261,42 +307,14 @@ static int btsnoop_log_close(void)
 *******************************************************************************/
 void btsnoop_hci_cmd(uint8_t *p)
 {
+    const uint8_t cmd = HCIT_TYPE_COMMAND;
+    int plen;
     SNOOPDBG("btsnoop_hci_cmd: fd = %d", hci_btsnoop_fd);
-
-    if (hci_btsnoop_fd != -1)
-    {
-        uint32_t value, value_hi;
-        struct timeval tv;
-
-        /* since these display functions are called from different contexts */
-        utils_lock();
-
-        /* store the length in both original and included fields */
-        value = l_to_be(p[2] + 4);
-        write(hci_btsnoop_fd, &value, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* flags: command sent from the host */
-        value = l_to_be(2);
-        write(hci_btsnoop_fd, &value, 4);
-        /* drops: none */
-        value = 0;
-        write(hci_btsnoop_fd, &value, 4);
-        /* time */
-        gettimeofday(&tv, NULL);
-        tv_to_btsnoop_ts(&value, &value_hi, &tv);
-        value_hi = l_to_be(value_hi);
-        value = l_to_be(value);
-        write(hci_btsnoop_fd, &value_hi, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* data */
-        write(hci_btsnoop_fd, "\x1", 1);
-        write(hci_btsnoop_fd, p, p[2] + 3);
-
-        /* since these display functions are called from different contexts */
-        utils_unlock();
-    }
+    plen = (int) p[2] + 3;
+    btsnoop_write(p, 2, &cmd, plen);
 }
 
+
 /*******************************************************************************
  **
  ** Function         btsnoop_hci_evt
@@ -307,40 +325,12 @@ void btsnoop_hci_cmd(uint8_t *p)
 *******************************************************************************/
 void btsnoop_hci_evt(uint8_t *p)
 {
+    const uint8_t evt = HCIT_TYPE_EVENT;
+    int plen;
     SNOOPDBG("btsnoop_hci_evt: fd = %d", hci_btsnoop_fd);
+    plen = (int) p[1] + 2;
 
-    if (hci_btsnoop_fd != -1)
-    {
-        uint32_t value, value_hi;
-        struct timeval tv;
-
-        /* since these display functions are called from different contexts */
-        utils_lock();
-
-        /* store the length in both original and included fields */
-        value = l_to_be(p[1] + 3);
-        write(hci_btsnoop_fd, &value, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* flags: event received in the host */
-        value = l_to_be(3);
-        write(hci_btsnoop_fd, &value, 4);
-        /* drops: none */
-        value = 0;
-        write(hci_btsnoop_fd, &value, 4);
-        /* time */
-        gettimeofday(&tv, NULL);
-        tv_to_btsnoop_ts(&value, &value_hi, &tv);
-        value_hi = l_to_be(value_hi);
-        value = l_to_be(value);
-        write(hci_btsnoop_fd, &value_hi, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* data */
-        write(hci_btsnoop_fd, "\x4", 1);
-        write(hci_btsnoop_fd, p, p[1] + 2);
-
-        /* since these display functions are called from different contexts */
-        utils_unlock();
-    }
+    btsnoop_write(p, 3, &evt, plen);
 }
 
 /*******************************************************************************
@@ -353,40 +343,12 @@ void btsnoop_hci_evt(uint8_t *p)
 *******************************************************************************/
 void btsnoop_sco_data(uint8_t *p, uint8_t is_rcvd)
 {
+    const uint8_t sco = HCIT_TYPE_SCO_DATA;
+    int plen;
     SNOOPDBG("btsnoop_sco_data: fd = %d", hci_btsnoop_fd);
+    plen = (int) p[2] + 3;
 
-    if (hci_btsnoop_fd != -1)
-    {
-        uint32_t value, value_hi;
-        struct timeval tv;
-
-        /* since these display functions are called from different contexts */
-        utils_lock();
-
-        /* store the length in both original and included fields */
-        value = l_to_be(p[2] + 4);
-        write(hci_btsnoop_fd, &value, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* flags: data can be sent or received */
-        value = l_to_be(is_rcvd?1:0);
-        write(hci_btsnoop_fd, &value, 4);
-        /* drops: none */
-        value = 0;
-        write(hci_btsnoop_fd, &value, 4);
-        /* time */
-        gettimeofday(&tv, NULL);
-        tv_to_btsnoop_ts(&value, &value_hi, &tv);
-        value_hi = l_to_be(value_hi);
-        value = l_to_be(value);
-        write(hci_btsnoop_fd, &value_hi, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* data */
-        write(hci_btsnoop_fd, "\x3", 1);
-        write(hci_btsnoop_fd, p, p[2] + 3);
-
-        /* since these display functions are called from different contexts */
-        utils_unlock();
-    }
+    btsnoop_write(p, is_rcvd, &sco, plen);
 }
 
 /*******************************************************************************
@@ -399,41 +361,15 @@ void btsnoop_sco_data(uint8_t *p, uint8_t is_rcvd)
 *******************************************************************************/
 void btsnoop_acl_data(uint8_t *p, uint8_t is_rcvd)
 {
+    const uint8_t acl = HCIT_TYPE_ACL_DATA;
+    int plen;
+
     SNOOPDBG("btsnoop_acl_data: fd = %d", hci_btsnoop_fd);
-    if (hci_btsnoop_fd != -1)
-    {
-        uint32_t value, value_hi;
-        struct timeval tv;
-
-        /* since these display functions are called from different contexts */
-        utils_lock();
-
-        /* store the length in both original and included fields */
-        value = l_to_be((p[3]<<8) + p[2] + 5);
-        write(hci_btsnoop_fd, &value, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* flags: data can be sent or received */
-        value = l_to_be(is_rcvd?1:0);
-        write(hci_btsnoop_fd, &value, 4);
-        /* drops: none */
-        value = 0;
-        write(hci_btsnoop_fd, &value, 4);
-        /* time */
-        gettimeofday(&tv, NULL);
-        tv_to_btsnoop_ts(&value, &value_hi, &tv);
-        value_hi = l_to_be(value_hi);
-        value = l_to_be(value);
-        write(hci_btsnoop_fd, &value_hi, 4);
-        write(hci_btsnoop_fd, &value, 4);
-        /* data */
-        write(hci_btsnoop_fd, "\x2", 1);
-        write(hci_btsnoop_fd, p, (p[3]<<8) + p[2] + 4);
-
-        /* since these display functions are called from different contexts */
-        utils_unlock();
-    }
-}
 
+    plen = (((int) p[3]) << 8) + ((int) p[2]) +4;
+
+    btsnoop_write(p, is_rcvd, &acl, plen);
+}
 
 /********************************************************************************
  ** API allow external realtime parsing of output using e.g hcidump
@@ -619,11 +555,6 @@ void btsnoop_cleanup (void)
 }
 
 
-#define HCIT_TYPE_COMMAND   1
-#define HCIT_TYPE_ACL_DATA  2
-#define HCIT_TYPE_SCO_DATA  3
-#define HCIT_TYPE_EVENT     4
-
 void btsnoop_capture(HC_BT_HDR *p_buf, uint8_t is_rcvd)
 {
     uint8_t *p = (uint8_t *)(p_buf + 1) + p_buf->offset;