#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);
}
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);
}
{
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
__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);
}