diff --git a/src/log.c b/src/log.c
index ca783f3..aa1c822 100644
--- a/src/log.c
+++ b/src/log.c
#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);
}
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);
}
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);
}
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);
}
__btd_enable_debug(__start___debug, __stop___debug);
+ logging_open();
+
if (!detach)
option |= LOG_PERROR;
{
closelog();
+ logging_close();
+
g_strfreev(enabled);
}