1 // SPDX-License-Identifier: LGPL-2.1-or-later
4 * BlueZ - Bluetooth protocol stack for Linux
6 * Copyright (C) 2011-2014 Intel Corporation
7 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
23 #include "src/shared/mainloop.h"
24 #include "src/shared/tty.h"
34 static void signal_callback(int signum, void *user_data)
44 static void usage(void)
46 printf("btmon - Bluetooth monitor\n"
48 printf("\tbtmon [options]\n");
50 "\t-r, --read <file> Read traces in btsnoop format\n"
51 "\t-w, --write <file> Save traces in btsnoop format\n"
52 "\t-a, --analyze <file> Analyze traces in btsnoop format\n"
53 "\t If gnuplot is installed on the\n"
54 "\t system it will also attempt to plot\n"
55 "\t packet latency graph.\n"
56 "\t-s, --server <socket> Start monitor server socket\n"
57 "\t-p, --priority <level> Show only priority or lower\n"
58 "\t-i, --index <num> Show only specified controller\n"
59 "\t-d, --tty <tty> Read data from TTY\n"
60 "\t-B, --tty-speed <rate> Set TTY speed (default 115200)\n"
61 "\t-V, --vendor <compid> Set default company identifier\n"
62 "\t-M, --mgmt Open channel for mgmt events\n"
63 "\t-t, --time Show time instead of time offset\n"
64 "\t-T, --date Show time and date information\n"
65 "\t-S, --sco Dump SCO traffic\n"
66 "\t-A, --a2dp Dump A2DP stream traffic\n"
67 "\t-I, --iso Dump ISO traffic\n"
68 "\t-E, --ellisys [ip] Send Ellisys HCI Injection\n"
69 "\t-P, --no-pager Disable pager usage\n"
70 "\t-J --jlink <device>,[<serialno>],[<interface>],[<speed>]\n"
71 "\t Read data from RTT\n"
72 "\t-R --rtt [<address>],[<area>],[<name>]\n"
73 "\t RTT control block parameters\n"
74 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
75 "\t-C, --count <num> Save traces by <num> rotation\n"
76 "\t-W, --size <num> Save traces at most <num> size\n"
78 "\t-C, --columns [width] Output width if not a terminal\n"
80 "\t-c, --color [mode] Output color: auto/always/never\n"
81 "\t-h, --help Show help options\n");
84 static const struct option main_options[] = {
85 { "read", required_argument, NULL, 'r' },
86 { "write", required_argument, NULL, 'w' },
87 { "analyze", required_argument, NULL, 'a' },
88 { "server", required_argument, NULL, 's' },
89 { "priority", required_argument, NULL, 'p' },
90 { "index", required_argument, NULL, 'i' },
91 { "tty", required_argument, NULL, 'd' },
92 { "tty-speed", required_argument, NULL, 'B' },
93 { "vendor", required_argument, NULL, 'V' },
94 { "mgmt", no_argument, NULL, 'M' },
95 { "no-time", no_argument, NULL, 'N' },
96 { "time", no_argument, NULL, 't' },
97 { "date", no_argument, NULL, 'T' },
98 { "sco", no_argument, NULL, 'S' },
99 { "a2dp", no_argument, NULL, 'A' },
100 { "iso", no_argument, NULL, 'I' },
101 { "ellisys", required_argument, NULL, 'E' },
102 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
103 { "count", required_argument, NULL, 'C' },
104 { "size", required_argument, NULL, 'W' },
106 { "no-pager", no_argument, NULL, 'P' },
107 { "jlink", required_argument, NULL, 'J' },
108 { "rtt", required_argument, NULL, 'R' },
109 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
110 { "columns", required_argument, NULL, 'C' },
112 { "color", required_argument, NULL, 'c' },
113 { "todo", no_argument, NULL, '#' },
114 { "version", no_argument, NULL, 'v' },
115 { "help", no_argument, NULL, 'h' },
119 int main(int argc, char *argv[])
121 unsigned long filter_mask = 0;
122 bool use_pager = true;
123 const char *reader_path = NULL;
124 const char *writer_path = NULL;
125 const char *analyze_path = NULL;
126 const char *ellisys_server = NULL;
127 const char *tty = NULL;
128 unsigned int tty_speed = B115200;
129 unsigned short ellisys_port = 0;
130 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
131 int16_t rotate_count = -1;
132 ssize_t file_size = -1;
141 filter_mask |= PACKET_FILTER_SHOW_TIME_OFFSET;
145 struct sockaddr_un addr;
147 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
148 opt = getopt_long(argc, argv, "d:r:w:a:s:p:i:tTSE:C:W:vh",
151 opt = getopt_long(argc, argv,
152 "r:w:a:s:p:i:d:B:V:MNtTSAIE:PJ:R:C:c:vh",
160 reader_path = optarg;
163 writer_path = optarg;
166 analyze_path = optarg;
169 if (strlen(optarg) > sizeof(addr.sun_path) - 1) {
170 fprintf(stderr, "Socket name too long\n");
173 control_server(optarg);
176 packet_set_priority(optarg);
179 if (strlen(optarg) > 3 && !strncmp(optarg, "hci", 3))
183 if (!isdigit(*str)) {
187 packet_select_index(atoi(str));
193 tty_speed = tty_get_speed(atoi(optarg));
195 fprintf(stderr, "Unknown speed: %s\n", optarg);
201 packet_set_fallback_manufacturer(atoi(str));
204 filter_mask |= PACKET_FILTER_SHOW_MGMT_SOCKET;
207 filter_mask &= ~PACKET_FILTER_SHOW_TIME_OFFSET;
210 filter_mask &= ~PACKET_FILTER_SHOW_TIME_OFFSET;
211 filter_mask |= PACKET_FILTER_SHOW_TIME;
214 filter_mask &= ~PACKET_FILTER_SHOW_TIME_OFFSET;
215 filter_mask |= PACKET_FILTER_SHOW_TIME;
216 filter_mask |= PACKET_FILTER_SHOW_DATE;
219 filter_mask |= PACKET_FILTER_SHOW_SCO_DATA;
222 filter_mask |= PACKET_FILTER_SHOW_A2DP_STREAM;
225 filter_mask |= PACKET_FILTER_SHOW_ISO_DATA;
228 ellisys_server = optarg;
229 ellisys_port = 24352;
234 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
236 rotate_count = atoi(optarg);
239 file_size = atoll(optarg);
248 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
250 set_default_pager_num_columns(atoi(optarg));
254 if (strcmp("always", optarg) == 0)
255 set_monitor_color(COLOR_ALWAYS);
256 else if (strcmp("never", optarg) == 0)
257 set_monitor_color(COLOR_NEVER);
258 else if (strcmp("auto", optarg) == 0)
259 set_monitor_color(COLOR_AUTO);
261 fprintf(stderr, "Color option must be one of "
262 "auto/always/never\n");
271 printf("%s\n", VERSION);
281 if (argc - optind > 0) {
282 fprintf(stderr, "Invalid command line parameters\n");
286 if (reader_path && analyze_path) {
287 fprintf(stderr, "Display and analyze can't be combined\n");
291 printf("Bluetooth monitor ver %s\n", VERSION);
295 packet_set_filter(filter_mask);
298 analyze_trace(analyze_path);
304 ellisys_enable(ellisys_server, ellisys_port);
306 control_reader(reader_path, use_pager);
310 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
311 if (writer_path && !control_writer(writer_path,
312 rotate_count, file_size)) {
313 printf("Failed to open '%s'\n", writer_path);
317 if (writer_path && !control_writer(writer_path)) {
318 printf("Failed to open '%s'\n", writer_path);
324 ellisys_enable(ellisys_server, ellisys_port);
326 if (!tty && !jlink && control_tracing() < 0)
329 if (tty && control_tty(tty, tty_speed) < 0)
332 if (jlink && control_rtt(jlink, rtt) < 0)
335 exit_status = mainloop_run_with_signal(signal_callback, NULL);