3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 #ifdef __TIZEN_PATCH__
36 #include <arpa/inet.h>
39 #include "src/shared/btsnoop.h"
42 uint8_t id[8]; /* Identification Pattern */
43 uint32_t version; /* Version Number = 1 */
44 uint32_t type; /* Datalink Type */
45 } __attribute__ ((packed));
46 #define BTSNOOP_HDR_SIZE (sizeof(struct btsnoop_hdr))
49 uint32_t size; /* Original Length */
50 uint32_t len; /* Included Length */
51 uint32_t flags; /* Packet Flags */
52 uint32_t drops; /* Cumulative Drops */
53 uint64_t ts; /* Timestamp microseconds */
54 uint8_t data[0]; /* Packet Data */
55 } __attribute__ ((packed));
56 #define BTSNOOP_PKT_SIZE (sizeof(struct btsnoop_pkt))
58 static const uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e,
59 0x6f, 0x6f, 0x70, 0x00 };
61 static const uint32_t btsnoop_version = 1;
67 } __attribute__ ((packed));
68 #define PKLG_PKT_SIZE (sizeof(struct pklg_pkt))
79 #ifdef __TIZEN_PATCH__
86 struct btsnoop *btsnoop_open(const char *path, unsigned long flags)
88 struct btsnoop *btsnoop;
89 struct btsnoop_hdr hdr;
92 btsnoop = calloc(1, sizeof(*btsnoop));
96 btsnoop->fd = open(path, O_RDONLY | O_CLOEXEC);
97 if (btsnoop->fd < 0) {
102 btsnoop->flags = flags;
104 len = read(btsnoop->fd, &hdr, BTSNOOP_HDR_SIZE);
105 if (len < 0 || len != BTSNOOP_HDR_SIZE)
108 if (!memcmp(hdr.id, btsnoop_id, sizeof(btsnoop_id))) {
109 /* Check for BTSnoop version 1 format */
110 if (be32toh(hdr.version) != btsnoop_version)
113 btsnoop->format = be32toh(hdr.type);
114 btsnoop->index = 0xffff;
116 if (!(btsnoop->flags & BTSNOOP_FLAG_PKLG_SUPPORT))
119 /* Check for Apple Packet Logger format */
120 if (hdr.id[0] != 0x00 ||
121 (hdr.id[1] != 0x00 && hdr.id[1] != 0x01))
124 btsnoop->format = BTSNOOP_FORMAT_MONITOR;
125 btsnoop->index = 0xffff;
126 btsnoop->pklg_format = true;
127 btsnoop->pklg_v2 = (hdr.id[1] == 0x01);
129 /* Apple Packet Logger format has no header */
130 lseek(btsnoop->fd, 0, SEEK_SET);
133 return btsnoop_ref(btsnoop);
142 #ifdef __TIZEN_PATCH__
143 struct btsnoop *btsnoop_create(const char *path, uint32_t format,
144 int16_t rotate_count, ssize_t file_size)
146 struct btsnoop *btsnoop_create(const char *path, uint32_t format)
149 struct btsnoop *btsnoop;
150 struct btsnoop_hdr hdr;
153 btsnoop = calloc(1, sizeof(*btsnoop));
157 btsnoop->fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
158 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
159 if (btsnoop->fd < 0) {
164 btsnoop->format = format;
165 btsnoop->index = 0xffff;
167 memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
168 hdr.version = htobe32(btsnoop_version);
169 hdr.type = htobe32(btsnoop->format);
171 written = write(btsnoop->fd, &hdr, BTSNOOP_HDR_SIZE);
178 #ifdef __TIZEN_PATCH__
179 if (rotate_count > 0 && file_size > 0) {
180 btsnoop->path = strdup(path);
181 btsnoop->rotate_count = rotate_count;
182 btsnoop->file_size = file_size;
186 return btsnoop_ref(btsnoop);
189 #ifdef __TIZEN_PATCH__
190 static int btsnoop_create_2(struct btsnoop *btsnoop)
192 struct btsnoop_hdr hdr;
195 if (btsnoop->fd >= 0)
198 btsnoop->fd = open(btsnoop->path,
199 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
200 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
201 if (btsnoop->fd < 0) {
202 btsnoop_unref(btsnoop);
206 memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
207 hdr.version = htobe32(btsnoop_version);
208 hdr.type = htobe32(btsnoop->format);
210 written = write(btsnoop->fd, &hdr, BTSNOOP_HDR_SIZE);
212 btsnoop_unref(btsnoop);
219 static void btsnoop_rotate_files(struct btsnoop *btsnoop)
221 char *filename = NULL;
222 char *new_filename = NULL;
224 int postfix_width = 0;
227 if (btsnoop->rotate_count <= 1)
230 for (i = btsnoop->rotate_count / 10; i; i /= 10)
233 for (i = btsnoop->rotate_count - 2; i >= 0; i--) {
235 filename = strdup(btsnoop->path);
236 err = (filename == NULL) ? -1 : 0;
238 err = asprintf(&filename, "%s.%0*d",
239 btsnoop->path, postfix_width, i);
242 if (err < 0 || access(filename, F_OK) < 0)
245 err = asprintf(&new_filename, "%s.%0*d",
246 btsnoop->path, postfix_width, i + 1);
250 err = rename(filename, new_filename);
271 struct btsnoop *btsnoop_ref(struct btsnoop *btsnoop)
276 __sync_fetch_and_add(&btsnoop->ref_count, 1);
281 void btsnoop_unref(struct btsnoop *btsnoop)
286 if (__sync_sub_and_fetch(&btsnoop->ref_count, 1))
289 #ifdef __TIZEN_PATCH__
294 if (btsnoop->fd >= 0)
300 uint32_t btsnoop_get_format(struct btsnoop *btsnoop)
303 return BTSNOOP_FORMAT_INVALID;
305 return btsnoop->format;
308 bool btsnoop_write(struct btsnoop *btsnoop, struct timeval *tv,
309 uint32_t flags, const void *data, uint16_t size)
311 struct btsnoop_pkt pkt;
318 ts = (tv->tv_sec - 946684800ll) * 1000000ll + tv->tv_usec;
320 pkt.size = htobe32(size);
321 pkt.len = htobe32(size);
322 pkt.flags = htobe32(flags);
323 pkt.drops = htobe32(0);
324 pkt.ts = htobe64(ts + 0x00E03AB44A676000ll);
326 #ifdef __TIZEN_PATCH__
327 if ((btsnoop->rotate_count > 0 && btsnoop->file_size > 0) &&
328 lseek(btsnoop->fd, 0x00, SEEK_CUR) +
329 BTSNOOP_PKT_SIZE + size > btsnoop->file_size) {
330 btsnoop_rotate_files(btsnoop);
331 if (btsnoop_create_2(btsnoop) < 0)
336 written = write(btsnoop->fd, &pkt, BTSNOOP_PKT_SIZE);
340 if (data && size > 0) {
341 written = write(btsnoop->fd, data, size);
349 static uint32_t get_flags_from_opcode(uint16_t opcode)
352 case BTSNOOP_OPCODE_NEW_INDEX:
353 case BTSNOOP_OPCODE_DEL_INDEX:
355 case BTSNOOP_OPCODE_COMMAND_PKT:
357 case BTSNOOP_OPCODE_EVENT_PKT:
359 case BTSNOOP_OPCODE_ACL_TX_PKT:
361 case BTSNOOP_OPCODE_ACL_RX_PKT:
363 case BTSNOOP_OPCODE_SCO_TX_PKT:
364 case BTSNOOP_OPCODE_SCO_RX_PKT:
366 case BTSNOOP_OPCODE_OPEN_INDEX:
367 case BTSNOOP_OPCODE_CLOSE_INDEX:
374 bool btsnoop_write_hci(struct btsnoop *btsnoop, struct timeval *tv,
375 uint16_t index, uint16_t opcode,
376 const void *data, uint16_t size)
383 switch (btsnoop->format) {
384 case BTSNOOP_FORMAT_HCI:
385 if (btsnoop->index == 0xffff)
386 btsnoop->index = index;
388 if (index != btsnoop->index)
391 flags = get_flags_from_opcode(opcode);
396 case BTSNOOP_FORMAT_MONITOR:
397 flags = (index << 16) | opcode;
404 return btsnoop_write(btsnoop, tv, flags, data, size);
407 bool btsnoop_write_phy(struct btsnoop *btsnoop, struct timeval *tv,
408 uint16_t frequency, const void *data, uint16_t size)
415 switch (btsnoop->format) {
416 case BTSNOOP_FORMAT_SIMULATOR:
417 flags = (1 << 16) | frequency;
424 return btsnoop_write(btsnoop, tv, flags, data, size);
427 static bool pklg_read_hci(struct btsnoop *btsnoop, struct timeval *tv,
428 uint16_t *index, uint16_t *opcode,
429 void *data, uint16_t *size)
436 len = read(btsnoop->fd, &pkt, PKLG_PKT_SIZE);
440 if (len < 0 || len != PKLG_PKT_SIZE) {
441 btsnoop->aborted = true;
445 if (btsnoop->pklg_v2) {
446 toread = le32toh(pkt.len) - (PKLG_PKT_SIZE - 4);
448 ts = le64toh(pkt.ts);
449 tv->tv_sec = ts & 0xffffffff;
450 tv->tv_usec = ts >> 32;
452 toread = be32toh(pkt.len) - (PKLG_PKT_SIZE - 4);
454 ts = be64toh(pkt.ts);
455 tv->tv_sec = ts >> 32;
456 tv->tv_usec = ts & 0xffffffff;
462 *opcode = BTSNOOP_OPCODE_COMMAND_PKT;
466 *opcode = BTSNOOP_OPCODE_EVENT_PKT;
470 *opcode = BTSNOOP_OPCODE_ACL_TX_PKT;
474 *opcode = BTSNOOP_OPCODE_ACL_RX_PKT;
478 *opcode = BTSNOOP_OPCODE_VENDOR_DIAG;
482 *opcode = BTSNOOP_OPCODE_SYSTEM_NOTE;
490 len = read(btsnoop->fd, data, toread);
492 btsnoop->aborted = true;
501 static uint16_t get_opcode_from_flags(uint8_t type, uint32_t flags)
505 return BTSNOOP_OPCODE_COMMAND_PKT;
508 return BTSNOOP_OPCODE_ACL_RX_PKT;
510 return BTSNOOP_OPCODE_ACL_TX_PKT;
513 return BTSNOOP_OPCODE_SCO_RX_PKT;
515 return BTSNOOP_OPCODE_SCO_TX_PKT;
517 return BTSNOOP_OPCODE_EVENT_PKT;
521 return BTSNOOP_OPCODE_EVENT_PKT;
523 return BTSNOOP_OPCODE_COMMAND_PKT;
526 return BTSNOOP_OPCODE_ACL_RX_PKT;
528 return BTSNOOP_OPCODE_ACL_TX_PKT;
536 bool btsnoop_read_hci(struct btsnoop *btsnoop, struct timeval *tv,
537 uint16_t *index, uint16_t *opcode,
538 void *data, uint16_t *size)
540 struct btsnoop_pkt pkt;
541 uint32_t toread, flags;
546 if (!btsnoop || btsnoop->aborted)
549 if (btsnoop->pklg_format)
550 return pklg_read_hci(btsnoop, tv, index, opcode, data, size);
552 len = read(btsnoop->fd, &pkt, BTSNOOP_PKT_SIZE);
556 if (len < 0 || len != BTSNOOP_PKT_SIZE) {
557 btsnoop->aborted = true;
561 toread = be32toh(pkt.size);
562 if (toread > BTSNOOP_MAX_PACKET_SIZE) {
563 btsnoop->aborted = true;
567 flags = be32toh(pkt.flags);
569 ts = be64toh(pkt.ts) - 0x00E03AB44A676000ll;
570 tv->tv_sec = (ts / 1000000ll) + 946684800ll;
571 tv->tv_usec = ts % 1000000ll;
573 switch (btsnoop->format) {
574 case BTSNOOP_FORMAT_HCI:
576 *opcode = get_opcode_from_flags(0xff, flags);
579 case BTSNOOP_FORMAT_UART:
580 len = read(btsnoop->fd, &pkt_type, 1);
582 btsnoop->aborted = true;
588 *opcode = get_opcode_from_flags(pkt_type, flags);
591 case BTSNOOP_FORMAT_MONITOR:
592 *index = flags >> 16;
593 *opcode = flags & 0xffff;
597 btsnoop->aborted = true;
601 len = read(btsnoop->fd, data, toread);
603 btsnoop->aborted = true;
612 bool btsnoop_read_phy(struct btsnoop *btsnoop, struct timeval *tv,
613 uint16_t *frequency, void *data, uint16_t *size)