Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / src / log.c
index 7137258..6cae418 100644 (file)
--- a/src/log.c
+++ b/src/log.c
 #endif
 
 #include <stdio.h>
-#include <stdarg.h>
+#include <errno.h>
 #include <syslog.h>
+#include <stdarg.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"
 
-void info(const char *format, ...)
+#define LOG_IDENT "bluetoothd"
+#define LOG_IDENT_LEN sizeof(LOG_IDENT)
+
+struct log_hdr {
+       uint16_t opcode;
+       uint16_t index;
+       uint16_t len;
+       uint8_t  priority;
+       uint8_t  ident_len;
+} __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(uint16_t index, int priority,
+                                       const char *format, va_list ap)
+{
+       struct log_hdr hdr;
+       struct msghdr msg;
+       struct iovec iov[3];
+       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(index);
+       hdr.len = cpu_to_le16(2 + LOG_IDENT_LEN + len);
+       hdr.priority = priority;
+       hdr.ident_len = LOG_IDENT_LEN;
+
+       iov[0].iov_base = &hdr;
+       iov[0].iov_len = sizeof(hdr);
+
+       iov[1].iov_base = LOG_IDENT;
+       iov[1].iov_len = LOG_IDENT_LEN;
+
+       iov[2].iov_base = str;
+       iov[2].iov_len = len;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = iov;
+       msg.msg_iovlen = 3;
+
+       if (sendmsg(logging_fd, &msg, 0) < 0) {
+               if (errno != ENODEV) {
+                       close(logging_fd);
+                       logging_fd = -1;
+               }
+       }
+
+       free(str);
+}
+
+void error(const char *format, ...)
 {
        va_list ap;
 
        va_start(ap, format);
+       vsyslog(LOG_ERR, format, ap);
+       va_end(ap);
 
-       vsyslog(LOG_INFO, format, ap);
+       if (logging_fd < 0)
+               return;
 
+       va_start(ap, format);
+       logging_log(HCI_DEV_NONE, LOG_ERR, format, ap);
        va_end(ap);
 }
 
@@ -49,31 +153,110 @@ 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(HCI_DEV_NONE, LOG_WARNING, format, ap);
        va_end(ap);
 }
 
-void error(const char *format, ...)
+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(HCI_DEV_NONE, LOG_INFO, format, ap);
+       va_end(ap);
+}
+
+void btd_log(uint16_t index, int priority, const char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       vsyslog(priority, format, ap);
+       va_end(ap);
+
+       if (logging_fd < 0)
+               return;
+
+       va_start(ap, format);
+       logging_log(index, priority, format, ap);
+       va_end(ap);
+}
+
+void btd_error(uint16_t index, 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(index, LOG_ERR, format, ap);
        va_end(ap);
 }
 
-void btd_debug(const char *format, ...)
+void btd_warn(uint16_t index, 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(index, LOG_WARNING, format, ap);
+       va_end(ap);
+}
+
+void btd_info(uint16_t index, 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(index, LOG_INFO, format, ap);
+       va_end(ap);
+}
+
+void btd_debug(uint16_t index, 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(index, LOG_DEBUG, format, ap);
        va_end(ap);
 }
 
@@ -124,18 +307,13 @@ void __hci_attach_log_init(void)
 {
        int option = LOG_NDELAY | LOG_PID;
 
-       /* Fix : RESOURCE_LEAK */
-       char *str = g_strdup("*");
-
-       enabled = g_strsplit_set(str, ":, ", 0);
+       enabled = g_strsplit_set(g_strdup("*"), ":, ", 0);
 
        __btd_enable_debug(__start___debug, __stop___debug);
 
        openlog("hciattach", option, LOG_DAEMON);
 
        syslog(LOG_INFO, "hciattach daemon for debugging");
-
-       g_free(str);
 }
 #endif
 
@@ -149,17 +327,21 @@ void __btd_log_init(const char *debug, int detach)
 
        __btd_enable_debug(__start___debug, __stop___debug);
 
+       logging_open();
+
        if (!detach)
                option |= LOG_PERROR;
 
-       openlog("bluetoothd", option, LOG_DAEMON);
+       openlog(LOG_IDENT, option, LOG_DAEMON);
 
-       syslog(LOG_INFO, "Bluetooth daemon %s", VERSION);
+       info("Bluetooth daemon %s", VERSION);
 }
 
 void __btd_log_cleanup(void)
 {
        closelog();
 
+       logging_close();
+
        g_strfreev(enabled);
 }