Home | History | Annotate | Download | only in src
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2015 Google Inc.
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #include <assert.h>
     20 #include <resolv.h>
     21 #include <zlib.h>
     22 
     23 #include "btif/include/btif_debug.h"
     24 #include "btif/include/btif_debug_btsnoop.h"
     25 #include "hci/include/btsnoop_mem.h"
     26 #include "include/bt_target.h"
     27 #include "osi/include/ringbuffer.h"
     28 
     29 #define REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type) (type >> 8)
     30 
     31 // Total btsnoop memory log buffer size
     32 #ifndef BTSNOOP_MEM_BUFFER_SIZE
     33 static const size_t BTSNOOP_MEM_BUFFER_SIZE = (256 * 1024);
     34 #endif
     35 
     36 // Block size for copying buffers (for compression/encoding etc.)
     37 static const size_t BLOCK_SIZE = 16384;
     38 
     39 // Maximum line length in bugreport (should be multiple of 4 for base64 output)
     40 static const uint8_t MAX_LINE_LENGTH = 128;
     41 
     42 static ringbuffer_t *buffer = NULL;
     43 static uint64_t last_timestamp_ms = 0;
     44 
     45 static size_t btsnoop_calculate_packet_length(uint16_t type, const uint8_t *data, size_t length);
     46 
     47 static void btsnoop_cb(const uint16_t type, const uint8_t *data, const size_t length) {
     48   btsnooz_header_t header;
     49 
     50   size_t included_length = btsnoop_calculate_packet_length(type, data, length);
     51   if (included_length == 0)
     52     return;
     53 
     54   // Make room in the ring buffer
     55 
     56   while (ringbuffer_available(buffer) < (included_length + sizeof(btsnooz_header_t))) {
     57     ringbuffer_pop(buffer, (uint8_t *)&header, sizeof(btsnooz_header_t));
     58     ringbuffer_delete(buffer, header.length - 1);
     59   }
     60 
     61   // Insert data
     62 
     63   const uint64_t now = btif_debug_ts();
     64 
     65   header.type = REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type);
     66   header.length = included_length + 1;  // +1 for type byte
     67   header.packet_length = length + 1;  // +1 for type byte.
     68   header.delta_time_ms = last_timestamp_ms ? now - last_timestamp_ms : 0;
     69   last_timestamp_ms = now;
     70 
     71   ringbuffer_insert(buffer, (uint8_t *)&header, sizeof(btsnooz_header_t));
     72   ringbuffer_insert(buffer, data, included_length);
     73 }
     74 
     75 static size_t btsnoop_calculate_packet_length(uint16_t type, const uint8_t *data, size_t length) {
     76   static const size_t HCI_ACL_HEADER_SIZE = 4;
     77   static const size_t L2CAP_HEADER_SIZE = 4;
     78   static const size_t L2CAP_CID_OFFSET = (HCI_ACL_HEADER_SIZE + 2);
     79   static const uint16_t L2CAP_SIGNALING_CID = 0x0001;
     80 
     81   // Maximum amount of ACL data to log.
     82   // Enough for an RFCOMM frame up to the frame check;
     83   // not enough for a HID report or audio data.
     84   static const size_t MAX_HCI_ACL_LEN = 14;
     85 
     86   // Calculate packet length to be included
     87 
     88   switch (type) {
     89     case BT_EVT_TO_LM_HCI_CMD:
     90       return length;
     91 
     92     case BT_EVT_TO_BTU_HCI_EVT:
     93       return length;
     94 
     95     case BT_EVT_TO_LM_HCI_ACL:
     96     case BT_EVT_TO_BTU_HCI_ACL:
     97     {
     98       size_t len_hci_acl = HCI_ACL_HEADER_SIZE + L2CAP_HEADER_SIZE;
     99       // Check if we have enough data for an L2CAP header
    100       if (length > len_hci_acl) {
    101         uint16_t l2cap_cid = data[L2CAP_CID_OFFSET] | (data[L2CAP_CID_OFFSET + 1] << 8);
    102         if (l2cap_cid == L2CAP_SIGNALING_CID) {
    103           // For the signaling CID, take the full packet.
    104           // That way, the PSM setup is captured, allowing decoding of PSMs down the road.
    105           return length;
    106         } else {
    107           // Otherwise, return as much as we reasonably can
    108           len_hci_acl = MAX_HCI_ACL_LEN;
    109         }
    110       }
    111       return len_hci_acl < length ? len_hci_acl : length;
    112     }
    113 
    114     case BT_EVT_TO_LM_HCI_SCO:
    115     case BT_EVT_TO_BTU_HCI_SCO:
    116       // We're not logging SCO packets at this time since they are not currently used.
    117       // FALLTHROUGH
    118     default:
    119       return 0;
    120   }
    121 }
    122 
    123 static bool btsnoop_compress(ringbuffer_t *rb_dst, ringbuffer_t *rb_src) {
    124   assert(rb_dst != NULL);
    125   assert(rb_src != NULL);
    126 
    127   z_stream zs = {.zalloc = Z_NULL, .zfree = Z_NULL, .opaque = Z_NULL};
    128   if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK)
    129     return false;
    130 
    131   bool rc = true;
    132   uint8_t block_src[BLOCK_SIZE];
    133   uint8_t block_dst[BLOCK_SIZE];
    134 
    135   const size_t num_blocks = (ringbuffer_size(rb_src) + BLOCK_SIZE - 1) / BLOCK_SIZE;
    136   for (size_t i = 0; i < num_blocks; ++i) {
    137     zs.avail_in = ringbuffer_peek(rb_src, i * BLOCK_SIZE, block_src, BLOCK_SIZE);
    138     zs.next_in = block_src;
    139 
    140     do {
    141       zs.avail_out = BLOCK_SIZE;
    142       zs.next_out = block_dst;
    143 
    144       int err = deflate(&zs, (i == num_blocks - 1) ? Z_FINISH : Z_NO_FLUSH);
    145       if (err == Z_STREAM_ERROR) {
    146         rc = false;
    147         break;
    148       }
    149 
    150       const size_t length = BLOCK_SIZE - zs.avail_out;
    151       ringbuffer_insert(rb_dst, block_dst, length);
    152     } while (zs.avail_out == 0);
    153   }
    154 
    155   deflateEnd(&zs);
    156   return rc;
    157 }
    158 
    159 void btif_debug_btsnoop_init(void) {
    160   if (buffer == NULL)
    161     buffer = ringbuffer_init(BTSNOOP_MEM_BUFFER_SIZE);
    162   btsnoop_mem_set_callback(btsnoop_cb);
    163 }
    164 
    165 void btif_debug_btsnoop_dump(int fd) {
    166   dprintf(fd, "--- BEGIN:BTSNOOP_LOG_SUMMARY (%zu bytes in) ---\n", ringbuffer_size(buffer));
    167 
    168   ringbuffer_t *ringbuffer = ringbuffer_init(BTSNOOP_MEM_BUFFER_SIZE);
    169   if (ringbuffer == NULL) {
    170     dprintf(fd, "%s Unable to allocate memory for compression", __func__);
    171     return;
    172   }
    173 
    174   // Prepend preamble
    175 
    176   btsnooz_preamble_t preamble;
    177   preamble.version = BTSNOOZ_CURRENT_VERSION;
    178   preamble.last_timestamp_ms = last_timestamp_ms;
    179   ringbuffer_insert(ringbuffer, (uint8_t *)&preamble, sizeof(btsnooz_preamble_t));
    180 
    181   // Compress data
    182 
    183   bool rc = btsnoop_compress(ringbuffer, buffer);
    184   if (rc == false) {
    185     dprintf(fd, "%s Log compression failed", __func__);
    186     goto error;
    187   }
    188 
    189   // Base64 encode & output
    190 
    191   uint8_t b64_in[3] = {0};
    192   char b64_out[5] = {0};
    193 
    194   size_t line_length = 0;
    195   while (ringbuffer_size(ringbuffer) > 0) {
    196     size_t read = ringbuffer_pop(ringbuffer, b64_in, 3);
    197     if (line_length >= MAX_LINE_LENGTH) {
    198       dprintf(fd, "\n");
    199       line_length = 0;
    200     }
    201     line_length += b64_ntop(b64_in, read, b64_out, 5);
    202     dprintf(fd, "%s", b64_out);
    203   }
    204 
    205   dprintf(fd, "\n--- END:BTSNOOP_LOG_SUMMARY ---\n");
    206 
    207 error:
    208   ringbuffer_free(ringbuffer);
    209 }
    210