3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2011-2014 Intel Corporation
6 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include <arpa/inet.h>
38 #include "lib/bluetooth.h"
44 uint8_t id[8]; /* Identification Pattern */
45 uint32_t version; /* Version Number = 1 */
46 uint32_t type; /* Datalink Type */
47 } __attribute__ ((packed));
48 #define BTSNOOP_HDR_SIZE (sizeof(struct btsnoop_hdr))
51 uint32_t size; /* Original Length */
52 uint32_t len; /* Included Length */
53 uint32_t flags; /* Packet Flags */
54 uint32_t drops; /* Cumulative Drops */
55 uint64_t ts; /* Timestamp microseconds */
56 uint8_t data[0]; /* Packet Data */
57 } __attribute__ ((packed));
58 #define BTSNOOP_PKT_SIZE (sizeof(struct btsnoop_pkt))
60 static const uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e,
61 0x6f, 0x6f, 0x70, 0x00 };
63 static const uint32_t btsnoop_version = 1;
64 static uint32_t btsnoop_type = 0;
66 static int btsnoop_fd = -1;
67 static uint16_t btsnoop_index = 0xffff;
69 #ifdef __TIZEN_PATCH__
70 static char *btsnoop_path = NULL;
71 static int16_t btsnoop_rotate = -1;
72 static ssize_t btsnoop_size = -1;
74 void btsnoop_create(const char *path, uint32_t type,
75 int16_t rotate_count, ssize_t file_size)
77 void btsnoop_create(const char *path, uint32_t type)
80 struct btsnoop_hdr hdr;
86 btsnoop_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
87 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
93 memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
94 hdr.version = htobe32(btsnoop_version);
95 hdr.type = htobe32(btsnoop_type);
97 written = write(btsnoop_fd, &hdr, BTSNOOP_HDR_SIZE);
104 #ifdef __TIZEN_PATCH__
105 if (rotate_count > 0 && file_size > 0) {
106 btsnoop_path = strdup(path);
107 btsnoop_rotate = rotate_count;
108 btsnoop_size = file_size;
113 #ifdef __TIZEN_PATCH__
114 static void btsnoop_create_2(void)
116 struct btsnoop_hdr hdr;
122 btsnoop_fd = open(btsnoop_path,
123 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
124 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
128 memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
129 hdr.version = htobe32(btsnoop_version);
130 hdr.type = htobe32(btsnoop_type);
132 written = write(btsnoop_fd, &hdr, BTSNOOP_HDR_SIZE);
145 btsnoop_index = 0xffff;
150 static void btsnoop_rotate_files(void)
152 char *filename = NULL;
153 char *new_filename = NULL;
155 int postfix_width = 0;
158 if (btsnoop_rotate <= 1)
161 for (i = btsnoop_rotate / 10; i; i /= 10)
164 for (i = btsnoop_rotate - 2; i >= 0; i--) {
166 filename = strdup(btsnoop_path);
167 err = (filename == NULL) ? -1 : 0;
169 err = asprintf(&filename, "%s.%0*d",
170 btsnoop_path, postfix_width, i);
173 if (err < 0 || access(filename, F_OK) < 0)
176 err = asprintf(&new_filename, "%s.%0*d",
177 btsnoop_path, postfix_width, i + 1);
181 err = rename(filename, new_filename)
200 void btsnoop_write(struct timeval *tv, uint32_t flags,
201 const void *data, uint16_t size)
203 struct btsnoop_pkt pkt;
207 ts = (tv->tv_sec - 946684800ll) * 1000000ll + tv->tv_usec;
209 pkt.size = htobe32(size);
210 pkt.len = htobe32(size);
211 pkt.flags = htobe32(flags);
212 pkt.drops = htobe32(0);
213 pkt.ts = htobe64(ts + 0x00E03AB44A676000ll);
215 #ifdef __TIZEN_PATCH__
216 if ((btsnoop_rotate > 0 && btsnoop_size > 0) &&
217 lseek(btsnoop_fd, 0x00, SEEK_CUR) +
218 BTSNOOP_PKT_SIZE + size > btsnoop_size) {
219 btsnoop_rotate_files();
226 written = write(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
230 if (data && size > 0) {
231 written = write(btsnoop_fd, data, size);
237 static uint32_t get_flags_from_opcode(uint16_t opcode)
240 case BTSNOOP_OPCODE_NEW_INDEX:
241 case BTSNOOP_OPCODE_DEL_INDEX:
243 case BTSNOOP_OPCODE_COMMAND_PKT:
245 case BTSNOOP_OPCODE_EVENT_PKT:
247 case BTSNOOP_OPCODE_ACL_TX_PKT:
249 case BTSNOOP_OPCODE_ACL_RX_PKT:
251 case BTSNOOP_OPCODE_SCO_TX_PKT:
252 case BTSNOOP_OPCODE_SCO_RX_PKT:
259 void btsnoop_write_hci(struct timeval *tv, uint16_t index, uint16_t opcode,
260 const void *data, uint16_t size)
270 switch (btsnoop_type) {
271 case BTSNOOP_TYPE_HCI:
272 if (btsnoop_index == 0xffff)
273 btsnoop_index = index;
275 if (index != btsnoop_index)
278 flags = get_flags_from_opcode(opcode);
283 case BTSNOOP_TYPE_MONITOR:
284 flags = (index << 16) | opcode;
291 btsnoop_write(tv, flags, data, size);
294 void btsnoop_write_phy(struct timeval *tv, uint16_t frequency,
295 const void *data, uint16_t size)
305 switch (btsnoop_type) {
306 case BTSNOOP_TYPE_SIMULATOR:
307 flags = (1 << 16) | frequency;
314 btsnoop_write(tv, flags, data, size);
317 int btsnoop_open(const char *path, uint32_t *type)
319 struct btsnoop_hdr hdr;
322 if (btsnoop_fd >= 0) {
323 fprintf(stderr, "Too many open files\n");
327 btsnoop_fd = open(path, O_RDONLY | O_CLOEXEC);
328 if (btsnoop_fd < 0) {
329 perror("Failed to open file");
333 len = read(btsnoop_fd, &hdr, BTSNOOP_HDR_SIZE);
334 if (len < 0 || len != BTSNOOP_HDR_SIZE) {
335 perror("Failed to read header");
341 if (memcmp(hdr.id, btsnoop_id, sizeof(btsnoop_id))) {
342 fprintf(stderr, "Invalid btsnoop header\n");
348 if (be32toh(hdr.version) != btsnoop_version) {
349 fprintf(stderr, "Invalid btsnoop version\n");
355 btsnoop_type = be32toh(hdr.type);
358 *type = btsnoop_type;
363 static uint16_t get_opcode_from_flags(uint8_t type, uint32_t flags)
366 case HCI_COMMAND_PKT:
367 return BTSNOOP_OPCODE_COMMAND_PKT;
368 case HCI_ACLDATA_PKT:
370 return BTSNOOP_OPCODE_ACL_RX_PKT;
372 return BTSNOOP_OPCODE_ACL_TX_PKT;
373 case HCI_SCODATA_PKT:
375 return BTSNOOP_OPCODE_SCO_RX_PKT;
377 return BTSNOOP_OPCODE_SCO_TX_PKT;
379 return BTSNOOP_OPCODE_EVENT_PKT;
383 return BTSNOOP_OPCODE_EVENT_PKT;
385 return BTSNOOP_OPCODE_COMMAND_PKT;
388 return BTSNOOP_OPCODE_ACL_RX_PKT;
390 return BTSNOOP_OPCODE_ACL_TX_PKT;
398 int btsnoop_read_hci(struct timeval *tv, uint16_t *index, uint16_t *opcode,
399 void *data, uint16_t *size)
401 struct btsnoop_pkt pkt;
402 uint32_t toread, flags;
410 len = read(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
414 if (len < 0 || len != BTSNOOP_PKT_SIZE) {
415 perror("Failed to read packet");
421 toread = be32toh(pkt.size);
422 if (toread > BTSNOOP_MAX_PACKET_SIZE) {
423 perror("Packet len suspicially big: %u", toread);
429 flags = be32toh(pkt.flags);
431 ts = be64toh(pkt.ts) - 0x00E03AB44A676000ll;
432 tv->tv_sec = (ts / 1000000ll) + 946684800ll;
433 tv->tv_usec = ts % 1000000ll;
435 switch (btsnoop_type) {
436 case BTSNOOP_TYPE_HCI:
438 *opcode = get_opcode_from_flags(0xff, flags);
441 case BTSNOOP_TYPE_UART:
442 len = read(btsnoop_fd, &pkt_type, 1);
444 perror("Failed to read packet type");
452 *opcode = get_opcode_from_flags(pkt_type, flags);
455 case BTSNOOP_TYPE_MONITOR:
456 *index = flags >> 16;
457 *opcode = flags & 0xffff;
461 fprintf(stderr, "Unknown packet type\n");
467 len = read(btsnoop_fd, data, toread);
469 perror("Failed to read data");
480 int btsnoop_read_phy(struct timeval *tv, uint16_t *frequency,
481 void *data, uint16_t *size)
483 struct btsnoop_pkt pkt;
484 uint32_t toread, flags;
491 len = read(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
495 if (len < 0 || len != BTSNOOP_PKT_SIZE) {
496 perror("Failed to read packet");
502 toread = be32toh(pkt.size);
503 flags = be32toh(pkt.flags);
505 ts = be64toh(pkt.ts) - 0x00E03AB44A676000ll;
506 tv->tv_sec = (ts / 1000000ll) + 946684800ll;
507 tv->tv_usec = ts % 1000000ll;
509 switch (btsnoop_type) {
510 case BTSNOOP_TYPE_SIMULATOR:
511 if ((flags >> 16) != 1)
513 *frequency = flags & 0xffff;
517 fprintf(stderr, "Unknown packet type\n");
523 len = read(btsnoop_fd, data, toread);
525 perror("Failed to read data");
536 void btsnoop_close(void)
541 #ifdef __TIZEN_PATCH__
553 btsnoop_index = 0xffff;