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