diff --git a/monitor/btmon.rst b/monitor/btmon.rst
index eb5e251..39c185f 100644
--- a/monitor/btmon.rst
+++ b/monitor/btmon.rst
-M, --mgmt Open channel for mgmt events.
+-K, --kernel Open kmsg for kernel messages.
+
-t, --time Show a time instead of time offset.
-T, --date Show a time and date information instead of
diff --git a/monitor/control.c b/monitor/control.c
index cb8e9fe..83347d5 100644
--- a/monitor/control.c
+++ b/monitor/control.c
return 0;
}
+static void kmsg_callback(int fd, uint32_t events, void *user_data)
+{
+ char buf[1024], *msg;
+ ssize_t len;
+ struct timeval tv;
+
+ if (events & (EPOLLERR | EPOLLHUP)) {
+ mainloop_remove_fd(fd);
+ return;
+ }
+
+ memset(buf, 0, sizeof(buf));
+
+ len = read(fd, buf, sizeof(buf));
+ if (len < 0)
+ return;
+
+ /* Check if the kernel message is from Bluetooth */
+ msg = strcasestr(buf, "Bluetooth:");
+ if (!msg)
+ return;
+
+ /* Replace Bluetooth with Kernel to avoid possible confusions */
+ msg += 3;
+ memcpy(msg, "Kernel", 6);
+
+ /* Adjust the actual length since part of the message is skipped and
+ * replace the \n with \0 at the end.
+ */
+ len = len - (msg - buf);
+ msg[len - 1] = '\0';
+
+ gettimeofday(&tv, NULL);
+
+ btsnoop_write_hci(btsnoop_file, &tv, HCI_DEV_NONE,
+ BTSNOOP_OPCODE_SYSTEM_NOTE, 0, msg, len);
+ packet_monitor(&tv, NULL, HCI_DEV_NONE,
+ BTSNOOP_OPCODE_SYSTEM_NOTE, msg, len);
+}
+
+static int open_kmsg(void)
+{
+ int fd;
+
+ fd = open("/dev/kmsg", O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ if (mainloop_add_fd(fd, EPOLLIN, kmsg_callback, NULL, NULL) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return 0;
+}
+
static void client_callback(int fd, uint32_t events, void *user_data)
{
struct control_data *data = user_data;
if (packet_has_filter(PACKET_FILTER_SHOW_MGMT_SOCKET))
open_channel(HCI_CHANNEL_CONTROL);
+ if (packet_has_filter(PACKET_FILTER_SHOW_KMSG))
+ open_kmsg();
+
return 0;
}
diff --git a/monitor/main.c b/monitor/main.c
index fa56fcb..cc947af 100644
--- a/monitor/main.c
+++ b/monitor/main.c
"\t-B, --tty-speed <rate> Set TTY speed (default 115200)\n"
"\t-V, --vendor <compid> Set default company identifier\n"
"\t-M, --mgmt Open channel for mgmt events\n"
+ "\t-K, --kernel Open kmsg for kernel messages\n"
"\t-t, --time Show time instead of time offset\n"
"\t-T, --date Show time and date information\n"
"\t-S, --sco Dump SCO traffic\n"
{ "tty-speed", required_argument, NULL, 'B' },
{ "vendor", required_argument, NULL, 'V' },
{ "mgmt", no_argument, NULL, 'M' },
+ { "kernel", no_argument, NULL, 'K' },
{ "no-time", no_argument, NULL, 'N' },
{ "time", no_argument, NULL, 't' },
{ "date", no_argument, NULL, 'T' },
struct sockaddr_un addr;
opt = getopt_long(argc, argv,
- "r:w:a:s:p:i:d:B:V:MNtTSAIE:PJ:R:C:c:vh",
+ "r:w:a:s:p:i:d:B:V:MKNtTSAIE:PJ:R:C:c:vh",
main_options, NULL);
if (opt < 0)
break;
case 'M':
filter_mask |= PACKET_FILTER_SHOW_MGMT_SOCKET;
break;
+ case 'K':
+ filter_mask |= PACKET_FILTER_SHOW_KMSG;
+ break;
case 'N':
filter_mask &= ~PACKET_FILTER_SHOW_TIME_OFFSET;
break;
diff --git a/monitor/packet.h b/monitor/packet.h
index 964b9a7..154a08e 100644
--- a/monitor/packet.h
+++ b/monitor/packet.h
#define PACKET_FILTER_SHOW_A2DP_STREAM (1 << 6)
#define PACKET_FILTER_SHOW_MGMT_SOCKET (1 << 7)
#define PACKET_FILTER_SHOW_ISO_DATA (1 << 8)
+#define PACKET_FILTER_SHOW_KMSG (1 << 9)
#define TV_MSEC(_tv) (long long)((_tv).tv_sec * 1000 + (_tv).tv_usec / 1000)
struct packet_latency {