Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f56a65ce authored by Kim Schulz's avatar Kim Schulz Committed by Zhihai Xu
Browse files

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
parent be7d4b28
Loading
Loading
Loading
Loading
+66 −135
Original line number Diff line number Diff line
@@ -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,51 +258,63 @@ static int btsnoop_log_close(void)
}

/*******************************************************************************
 ** Function          btsnoop_write
 **
 ** Function         btsnoop_hci_cmd
 ** Description       Function used to write the actual data to the log
 **
 ** Description      Function to add a command in the BTSNOOP file
 **
 ** Returns          None
 ** Returns           none
*******************************************************************************/
void btsnoop_hci_cmd(uint8_t *p)
{
    SNOOPDBG("btsnoop_hci_cmd: fd = %d", hci_btsnoop_fd);

    if (hci_btsnoop_fd != -1)
void btsnoop_write(uint8_t *p, uint32_t flags, const uint8_t *ptype, uint32_t len)
{
    uint32_t value, value_hi;
    struct timeval tv;

        /* since these display functions are called from different contexts */
        utils_lock();
    struct iovec io[3];
    uint32_t header[6];

    /* 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);
    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 */
        value = 0;
        write(hci_btsnoop_fd, &value, 4);
    header[3] = 0;
    /* 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);
    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;

        /* since these display functions are called from different contexts */
        utils_unlock();
    (void) writev(hci_btsnoop_fd, io, 3);
}

/*******************************************************************************
 **
 ** Function         btsnoop_hci_cmd
 **
 ** Description      Function to add a command in the BTSNOOP file
 **
 ** Returns          None
*******************************************************************************/
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);
    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,42 +361,16 @@ void btsnoop_sco_data(uint8_t *p, uint8_t is_rcvd)
*******************************************************************************/
void btsnoop_acl_data(uint8_t *p, uint8_t is_rcvd)
{
    SNOOPDBG("btsnoop_acl_data: fd = %d", hci_btsnoop_fd);
    if (hci_btsnoop_fd != -1)
    {
        uint32_t value, value_hi;
        struct timeval tv;
    const uint8_t acl = HCIT_TYPE_ACL_DATA;
    int plen;

        /* since these display functions are called from different contexts */
        utils_lock();
    SNOOPDBG("btsnoop_acl_data: fd = %d", hci_btsnoop_fd);

        /* 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);
    plen = (((int) p[3]) << 8) + ((int) p[2]) +4;

        /* since these display functions are called from different contexts */
        utils_unlock();
    }
    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;