CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: orangepi-xunlong/orangepi-build
Path: blob/next/external/cache/sources/hcitools/monitor/btsnoop.c
Views: 3959
1
/*
2
*
3
* BlueZ - Bluetooth protocol stack for Linux
4
*
5
* Copyright (C) 2011-2012 Intel Corporation
6
* Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
7
*
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program 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
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
*
23
*/
24
25
#ifdef HAVE_CONFIG_H
26
#include <config.h>
27
#endif
28
29
#include <stdio.h>
30
#include <errno.h>
31
#include <fcntl.h>
32
#include <unistd.h>
33
#include <stdint.h>
34
#include <string.h>
35
#include <sys/stat.h>
36
#include <arpa/inet.h>
37
38
#include <bluetooth/bluetooth.h>
39
#include <bluetooth/hci.h>
40
41
#include "btsnoop.h"
42
43
struct btsnoop_hdr {
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))
49
50
struct btsnoop_pkt {
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))
59
60
static const uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e,
61
0x6f, 0x6f, 0x70, 0x00 };
62
63
static const uint32_t btsnoop_version = 1;
64
static uint32_t btsnoop_type = 0;
65
66
static int btsnoop_fd = -1;
67
static uint16_t btsnoop_index = 0xffff;
68
69
void btsnoop_create(const char *path, uint32_t type)
70
{
71
struct btsnoop_hdr hdr;
72
ssize_t written;
73
74
if (btsnoop_fd >= 0)
75
return;
76
77
btsnoop_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
78
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
79
if (btsnoop_fd < 0)
80
return;
81
82
btsnoop_type = type;
83
84
memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
85
hdr.version = htonl(btsnoop_version);
86
hdr.type = htonl(btsnoop_type);
87
88
written = write(btsnoop_fd, &hdr, BTSNOOP_HDR_SIZE);
89
if (written < 0) {
90
close(btsnoop_fd);
91
btsnoop_fd = -1;
92
return;
93
}
94
}
95
96
void btsnoop_write(struct timeval *tv, uint32_t flags,
97
const void *data, uint16_t size)
98
{
99
struct btsnoop_pkt pkt;
100
uint64_t ts;
101
ssize_t written;
102
103
ts = (tv->tv_sec - 946684800ll) * 1000000ll + tv->tv_usec;
104
105
pkt.size = htonl(size);
106
pkt.len = htonl(size);
107
pkt.flags = htonl(flags);
108
pkt.drops = htonl(0);
109
pkt.ts = hton64(ts + 0x00E03AB44A676000ll);
110
111
written = write(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
112
if (written < 0)
113
return;
114
115
if (data && size > 0) {
116
written = write(btsnoop_fd, data, size);
117
if (written < 0)
118
return;
119
}
120
}
121
122
static uint32_t get_flags_from_opcode(uint16_t opcode)
123
{
124
switch (opcode) {
125
case BTSNOOP_OPCODE_NEW_INDEX:
126
case BTSNOOP_OPCODE_DEL_INDEX:
127
break;
128
case BTSNOOP_OPCODE_COMMAND_PKT:
129
return 0x02;
130
case BTSNOOP_OPCODE_EVENT_PKT:
131
return 0x03;
132
case BTSNOOP_OPCODE_ACL_TX_PKT:
133
return 0x00;
134
case BTSNOOP_OPCODE_ACL_RX_PKT:
135
return 0x01;
136
case BTSNOOP_OPCODE_SCO_TX_PKT:
137
case BTSNOOP_OPCODE_SCO_RX_PKT:
138
break;
139
}
140
141
return 0xff;
142
}
143
144
void btsnoop_write_hci(struct timeval *tv, uint16_t index, uint16_t opcode,
145
const void *data, uint16_t size)
146
{
147
uint32_t flags;
148
149
if (!tv)
150
return;
151
152
if (btsnoop_fd < 0)
153
return;
154
155
switch (btsnoop_type) {
156
case BTSNOOP_TYPE_HCI:
157
if (btsnoop_index == 0xffff)
158
btsnoop_index = index;
159
160
if (index != btsnoop_index)
161
return;
162
163
flags = get_flags_from_opcode(opcode);
164
if (flags == 0xff)
165
return;
166
break;
167
168
case BTSNOOP_TYPE_EXTENDED_HCI:
169
flags = (index << 16) | opcode;
170
break;
171
172
default:
173
return;
174
}
175
176
btsnoop_write(tv, flags, data, size);
177
}
178
179
void btsnoop_write_phy(struct timeval *tv, uint16_t frequency,
180
const void *data, uint16_t size)
181
{
182
uint32_t flags;
183
184
if (!tv)
185
return;
186
187
if (btsnoop_fd < 0)
188
return;
189
190
switch (btsnoop_type) {
191
case BTSNOOP_TYPE_EXTENDED_PHY:
192
flags = (1 << 16) | frequency;
193
break;
194
195
default:
196
return;
197
}
198
199
btsnoop_write(tv, flags, data, size);
200
}
201
202
int btsnoop_open(const char *path, uint32_t *type)
203
{
204
struct btsnoop_hdr hdr;
205
ssize_t len;
206
207
if (btsnoop_fd >= 0) {
208
fprintf(stderr, "Too many open files\n");
209
return -1;
210
}
211
212
btsnoop_fd = open(path, O_RDONLY | O_CLOEXEC);
213
if (btsnoop_fd < 0) {
214
perror("Failed to open file");
215
return -1;
216
}
217
218
len = read(btsnoop_fd, &hdr, BTSNOOP_HDR_SIZE);
219
if (len < 0 || len != BTSNOOP_HDR_SIZE) {
220
perror("Failed to read header");
221
close(btsnoop_fd);
222
btsnoop_fd = -1;
223
return -1;
224
}
225
226
if (memcmp(hdr.id, btsnoop_id, sizeof(btsnoop_id))) {
227
fprintf(stderr, "Invalid btsnoop header\n");
228
close(btsnoop_fd);
229
btsnoop_fd = -1;
230
return -1;
231
}
232
233
if (ntohl(hdr.version) != btsnoop_version) {
234
fprintf(stderr, "Invalid btsnoop version\n");
235
close(btsnoop_fd);
236
btsnoop_fd = -1;
237
return -1;
238
}
239
240
btsnoop_type = ntohl(hdr.type);
241
242
if (type)
243
*type = btsnoop_type;
244
245
return 0;
246
}
247
248
static uint16_t get_opcode_from_flags(uint8_t type, uint32_t flags)
249
{
250
switch (type) {
251
case HCI_COMMAND_PKT:
252
return BTSNOOP_OPCODE_COMMAND_PKT;
253
case HCI_ACLDATA_PKT:
254
if (flags & 0x01)
255
return BTSNOOP_OPCODE_ACL_RX_PKT;
256
else
257
return BTSNOOP_OPCODE_ACL_TX_PKT;
258
case HCI_SCODATA_PKT:
259
if (flags & 0x01)
260
return BTSNOOP_OPCODE_SCO_RX_PKT;
261
else
262
return BTSNOOP_OPCODE_SCO_TX_PKT;
263
case HCI_EVENT_PKT:
264
return BTSNOOP_OPCODE_EVENT_PKT;
265
case 0xff:
266
if (flags & 0x02) {
267
if (flags & 0x01)
268
return BTSNOOP_OPCODE_EVENT_PKT;
269
else
270
return BTSNOOP_OPCODE_COMMAND_PKT;
271
} else {
272
if (flags & 0x01)
273
return BTSNOOP_OPCODE_ACL_RX_PKT;
274
else
275
return BTSNOOP_OPCODE_ACL_TX_PKT;
276
}
277
break;
278
}
279
280
return 0xff;
281
}
282
283
int btsnoop_read_hci(struct timeval *tv, uint16_t *index, uint16_t *opcode,
284
void *data, uint16_t *size)
285
{
286
struct btsnoop_pkt pkt;
287
uint32_t toread, flags;
288
uint64_t ts;
289
uint8_t pkt_type;
290
ssize_t len;
291
292
if (btsnoop_fd < 0)
293
return -1;
294
295
len = read(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
296
if (len == 0)
297
return -1;
298
299
if (len < 0 || len != BTSNOOP_PKT_SIZE) {
300
perror("Failed to read packet");
301
close(btsnoop_fd);
302
btsnoop_fd = -1;
303
return -1;
304
}
305
306
toread = ntohl(pkt.size);
307
flags = ntohl(pkt.flags);
308
309
ts = ntoh64(pkt.ts) - 0x00E03AB44A676000ll;
310
tv->tv_sec = (ts / 1000000ll) + 946684800ll;
311
tv->tv_usec = ts % 1000000ll;
312
313
switch (btsnoop_type) {
314
case BTSNOOP_TYPE_HCI:
315
*index = 0;
316
*opcode = get_opcode_from_flags(0xff, flags);
317
break;
318
319
case BTSNOOP_TYPE_UART:
320
len = read(btsnoop_fd, &pkt_type, 1);
321
if (len < 0) {
322
perror("Failed to read packet type");
323
close(btsnoop_fd);
324
btsnoop_fd = -1;
325
return -1;
326
}
327
toread--;
328
329
*index = 0;
330
*opcode = get_opcode_from_flags(pkt_type, flags);
331
break;
332
333
case BTSNOOP_TYPE_EXTENDED_HCI:
334
*index = flags >> 16;
335
*opcode = flags & 0xffff;
336
break;
337
338
default:
339
fprintf(stderr, "Unknown packet type\n");
340
close(btsnoop_fd);
341
btsnoop_fd = -1;
342
return -1;
343
}
344
345
len = read(btsnoop_fd, data, toread);
346
if (len < 0) {
347
perror("Failed to read data");
348
close(btsnoop_fd);
349
btsnoop_fd = -1;
350
return -1;
351
}
352
353
*size = toread;
354
355
return 0;
356
}
357
358
int btsnoop_read_phy(struct timeval *tv, uint16_t *frequency,
359
void *data, uint16_t *size)
360
{
361
struct btsnoop_pkt pkt;
362
uint32_t toread, flags;
363
uint64_t ts;
364
ssize_t len;
365
366
if (btsnoop_fd < 0)
367
return -1;
368
369
len = read(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
370
if (len == 0)
371
return -1;
372
373
if (len < 0 || len != BTSNOOP_PKT_SIZE) {
374
perror("Failed to read packet");
375
close(btsnoop_fd);
376
btsnoop_fd = -1;
377
return -1;
378
}
379
380
toread = ntohl(pkt.size);
381
flags = ntohl(pkt.flags);
382
383
ts = ntoh64(pkt.ts) - 0x00E03AB44A676000ll;
384
tv->tv_sec = (ts / 1000000ll) + 946684800ll;
385
tv->tv_usec = ts % 1000000ll;
386
387
switch (btsnoop_type) {
388
case BTSNOOP_TYPE_EXTENDED_PHY:
389
if ((flags >> 16) != 1)
390
break;
391
*frequency = flags & 0xffff;
392
break;
393
394
default:
395
fprintf(stderr, "Unknown packet type\n");
396
close(btsnoop_fd);
397
btsnoop_fd = -1;
398
return -1;
399
}
400
401
len = read(btsnoop_fd, data, toread);
402
if (len < 0) {
403
perror("Failed to read data");
404
close(btsnoop_fd);
405
btsnoop_fd = -1;
406
return -1;
407
}
408
409
*size = toread;
410
411
return 0;
412
}
413
414
void btsnoop_close(void)
415
{
416
if (btsnoop_fd < 0)
417
return;
418
419
close(btsnoop_fd);
420
btsnoop_fd = -1;
421
422
btsnoop_index = 0xffff;
423
}
424
425