Diff between 3b8f3b74066eaa6cde54d71d38c8c3050fdbc084 and 002e0d0ab1e46a830fa5f06da8122db4e0487e21

Changed Files

File Additions Deletions Status
src/log.c +115 -4 modified

Full Patch

diff --git a/src/log.c b/src/log.c
index ca783f3..aa1c822 100644
--- a/src/log.c
+++ b/src/log.c
@@ -28,19 +28,111 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <syslog.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
 
 #include <glib.h>
 
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+
+#include "src/shared/util.h"
 #include "log.h"
 
+struct log_hdr {
+	uint16_t opcode;
+	uint16_t index;
+	uint16_t len;
+	uint8_t  priority;
+} __attribute__((packed));
+
+static int logging_fd = -1;
+
+static void logging_open(void)
+{
+	struct sockaddr_hci addr;
+	int fd;
+
+	if (logging_fd >= 0)
+		return;
+
+	fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+	if (fd < 0)
+		return;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.hci_family = AF_BLUETOOTH;
+	addr.hci_dev = HCI_DEV_NONE;
+	addr.hci_channel = HCI_CHANNEL_LOGGING;
+
+	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		close(fd);
+		return;
+	}
+
+	logging_fd = fd;
+}
+
+static void logging_close(void)
+{
+	if (logging_fd >= 0) {
+		close(logging_fd);
+		logging_fd = -1;
+	}
+}
+
+static void logging_log(int priority, const char *format, va_list ap)
+{
+	struct log_hdr hdr;
+	struct msghdr msg;
+	struct iovec iov[2];
+	uint16_t len;
+	char *str;
+
+	if (vasprintf(&str, format, ap) < 0)
+		return;
+
+	len = strlen(str) + 1;
+
+	hdr.opcode = cpu_to_le16(0x0000);
+	hdr.index = cpu_to_le16(0xffff);
+	hdr.len = cpu_to_le16(len + 1);
+	hdr.priority = priority;
+
+	iov[0].iov_base = &hdr;
+	iov[0].iov_len = sizeof(hdr);
+
+	iov[1].iov_base = str;
+	iov[1].iov_len = len;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 2;
+
+	if (sendmsg(logging_fd, &msg, 0) < 0) {
+		close(logging_fd);
+		logging_fd = -1;
+	}
+
+	free(str);
+}
+
 void info(const char *format, ...)
 {
 	va_list ap;
 
 	va_start(ap, format);
-
 	vsyslog(LOG_INFO, format, ap);
+	va_end(ap);
 
+	if (logging_fd < 0)
+		return;
+
+	va_start(ap, format);
+	logging_log(LOG_INFO, format, ap);
 	va_end(ap);
 }
 
@@ -49,9 +141,14 @@ void warn(const char *format, ...)
 	va_list ap;
 
 	va_start(ap, format);
-
 	vsyslog(LOG_WARNING, format, ap);
+	va_end(ap);
+
+	if (logging_fd < 0)
+		return;
 
+	va_start(ap, format);
+	logging_log(LOG_WARNING, format, ap);
 	va_end(ap);
 }
 
@@ -60,9 +157,14 @@ void error(const char *format, ...)
 	va_list ap;
 
 	va_start(ap, format);
-
 	vsyslog(LOG_ERR, format, ap);
+	va_end(ap);
 
+	if (logging_fd < 0)
+		return;
+
+	va_start(ap, format);
+	logging_log(LOG_ERR, format, ap);
 	va_end(ap);
 }
 
@@ -71,9 +173,14 @@ void btd_debug(const char *format, ...)
 	va_list ap;
 
 	va_start(ap, format);
-
 	vsyslog(LOG_DEBUG, format, ap);
+	va_end(ap);
+
+	if (logging_fd < 0)
+		return;
 
+	va_start(ap, format);
+	logging_log(LOG_DEBUG, format, ap);
 	va_end(ap);
 }
 
@@ -128,6 +235,8 @@ void __btd_log_init(const char *debug, int detach)
 
 	__btd_enable_debug(__start___debug, __stop___debug);
 
+	logging_open();
+
 	if (!detach)
 		option |= LOG_PERROR;
 
@@ -140,5 +249,7 @@ void __btd_log_cleanup(void)
 {
 	closelog();
 
+	logging_close();
+
 	g_strfreev(enabled);
 }