blob: 1fc350a2f8f6b8970e5490ecd510261066ec8d4f [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
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
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070019#define LOG_TAG "btsnoop"
The Android Open Source Project5738f832012-12-12 16:00:35 -080020
21#include <arpa/inet.h>
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070022#include <assert.h>
23#include <ctype.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080024#include <cutils/log.h>
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070025#include <errno.h>
26#include <fcntl.h>
27#include <stdbool.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#include <unistd.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080034
35#include "bt_hci_bdroid.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080036#include "bt_utils.h"
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070037#include "utils.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080038
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070039typedef enum {
40 kCommandPacket = 1,
41 kAclPacket = 2,
42 kScoPacket = 3,
43 kEventPacket = 4
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070044} packet_type_t;
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070045
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070046// Epoch in microseconds since 01/01/0000.
47static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
48
49// File descriptor for btsnoop file.
50static int hci_btsnoop_fd = -1;
51
52void btsnoop_net_open();
53void btsnoop_net_close();
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070054void btsnoop_net_write(const void *data, size_t length);
Kim Schulzf1d68e92013-09-23 12:48:47 +020055
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070056static uint64_t btsnoop_timestamp(void) {
57 struct timeval tv;
58 gettimeofday(&tv, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -080059
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070060 // Timestamp is in microseconds.
61 uint64_t timestamp = tv.tv_sec * 1000 * 1000LL;
62 timestamp += tv.tv_usec;
63 timestamp += BTSNOOP_EPOCH_DELTA;
64 return timestamp;
The Android Open Source Project5738f832012-12-12 16:00:35 -080065}
66
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070067static void btsnoop_write(const void *data, size_t length) {
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070068 if (hci_btsnoop_fd != -1)
Sharvil Nanavati405b5c92016-06-17 14:15:46 -070069 TEMP_FAILURE_RETRY(write(hci_btsnoop_fd, data, length));
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070070
71 btsnoop_net_write(data, length);
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070072}
Kim Schulzf1d68e92013-09-23 12:48:47 +020073
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070074static void btsnoop_write_packet(packet_type_t type, const uint8_t *packet, bool is_received) {
Chris Manton227f6b02014-07-18 13:41:32 -070075 int length_he = 0;
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070076 int length;
77 int flags;
78 int drops = 0;
79 switch (type) {
80 case kCommandPacket:
81 length_he = packet[2] + 4;
82 flags = 2;
83 break;
84 case kAclPacket:
85 length_he = (packet[3] << 8) + packet[2] + 5;
86 flags = is_received;
87 break;
88 case kScoPacket:
89 length_he = packet[2] + 4;
90 flags = is_received;
91 break;
92 case kEventPacket:
93 length_he = packet[1] + 3;
94 flags = 3;
95 break;
96 }
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070097
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070098 uint64_t timestamp = btsnoop_timestamp();
99 uint32_t time_hi = timestamp >> 32;
100 uint32_t time_lo = timestamp & 0xFFFFFFFF;
Kim Schulzf1d68e92013-09-23 12:48:47 +0200101
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700102 length = htonl(length_he);
103 flags = htonl(flags);
104 drops = htonl(drops);
105 time_hi = htonl(time_hi);
106 time_lo = htonl(time_lo);
Kim Schulzf1d68e92013-09-23 12:48:47 +0200107
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700108 // This function is called from different contexts.
109 utils_lock();
Kim Schulzf1d68e92013-09-23 12:48:47 +0200110
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700111 btsnoop_write(&length, 4);
112 btsnoop_write(&length, 4);
113 btsnoop_write(&flags, 4);
114 btsnoop_write(&drops, 4);
115 btsnoop_write(&time_hi, 4);
116 btsnoop_write(&time_lo, 4);
117 btsnoop_write(&type, 1);
118 btsnoop_write(packet, length_he - 1);
Kim Schulzf1d68e92013-09-23 12:48:47 +0200119
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700120 utils_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800121}
122
Andre Eisenbach311e88d2014-09-17 16:40:53 -0700123void btsnoop_open(const char *p_path, const bool save_existing) {
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700124 assert(p_path != NULL);
125 assert(*p_path != '\0');
The Android Open Source Project5738f832012-12-12 16:00:35 -0800126
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700127 btsnoop_net_open();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800128
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700129 if (hci_btsnoop_fd != -1) {
130 ALOGE("%s btsnoop log file is already open.", __func__);
131 return;
132 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800133
Andre Eisenbach311e88d2014-09-17 16:40:53 -0700134 if (save_existing)
135 {
136 char fname_backup[266] = {0};
137 strncat(fname_backup, p_path, 255);
138 strcat(fname_backup, ".last");
139 rename(p_path, fname_backup);
140 }
141
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700142 hci_btsnoop_fd = TEMP_FAILURE_RETRY(open(p_path,
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700143 O_WRONLY | O_CREAT | O_TRUNC,
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700144 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800145
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700146 if (hci_btsnoop_fd == -1) {
147 ALOGE("%s unable to open '%s': %s", __func__, p_path, strerror(errno));
148 return;
149 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800150
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700151 TEMP_FAILURE_RETRY(write(hci_btsnoop_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800152}
153
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700154void btsnoop_close(void) {
155 if (hci_btsnoop_fd != -1)
156 close(hci_btsnoop_fd);
157 hci_btsnoop_fd = -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800158
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700159 btsnoop_net_close();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800160}
161
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700162void btsnoop_capture(const HC_BT_HDR *p_buf, bool is_rcvd) {
163 const uint8_t *p = (const uint8_t *)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800164
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700165 if (hci_btsnoop_fd == -1)
166 return;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800167
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700168 switch (p_buf->event & MSG_EVT_MASK) {
169 case MSG_HC_TO_STACK_HCI_EVT:
170 btsnoop_write_packet(kEventPacket, p, false);
171 break;
172 case MSG_HC_TO_STACK_HCI_ACL:
173 case MSG_STACK_TO_HC_HCI_ACL:
174 btsnoop_write_packet(kAclPacket, p, is_rcvd);
175 break;
176 case MSG_HC_TO_STACK_HCI_SCO:
177 case MSG_STACK_TO_HC_HCI_SCO:
178 btsnoop_write_packet(kScoPacket, p, is_rcvd);
179 break;
180 case MSG_STACK_TO_HC_HCI_CMD:
181 btsnoop_write_packet(kCommandPacket, p, true);
182 break;
183 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800184}