From f1d68e95f34921361dced60b1b53e3fef8401f03 Mon Sep 17 00:00:00 2001 From: Kim Schulz Date: Mon, 23 Sep 2013 12:48:47 +0200 Subject: [PATCH] fix for btsnoop log blogging HCI socket 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 | 201 ++++++++++++++++++------------------------------------ 1 file changed, 66 insertions(+), 135 deletions(-) diff --git a/hci/src/btsnoop.c b/hci/src/btsnoop.c index 4807df839..5b0f26d39 100755 --- a/hci/src/btsnoop.c +++ b/hci/src/btsnoop.c @@ -66,6 +66,11 @@ #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; -- 2.11.0