From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This enables any code using shared to log information using the logging channel which can then be decoded by the likes of btmon. --- Makefile.am | 1 + src/shared/log.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++ src/shared/log.h | 31 ++++++++ 3 files changed, 223 insertions(+) create mode 100644 src/shared/log.c create mode 100644 src/shared/log.h diff --git a/Makefile.am b/Makefile.am index 0ccf393c6..3f613a617 100644 --- a/Makefile.am +++ b/Makefile.am @@ -119,6 +119,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \ src/shared/gatt-server.h src/shared/gatt-server.c \ src/shared/gatt-db.h src/shared/gatt-db.c \ src/shared/gap.h src/shared/gap.c \ + src/shared/log.h src/shared/log.c \ src/shared/tty.h if READLINE diff --git a/src/shared/log.c b/src/shared/log.c new file mode 100644 index 000000000..d42bae713 --- /dev/null +++ b/src/shared/log.c @@ -0,0 +1,191 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <inttypes.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <signal.h> +#include <sys/socket.h> + +#include "lib/bluetooth.h" +#include "lib/hci.h" + +#include "src/shared/util.h" +#include "src/shared/log.h" + +struct log_hdr { + uint16_t opcode; + uint16_t index; + uint16_t len; + uint8_t priority; + uint8_t ident_len; +} __attribute__((packed)); + +struct log_l2cap_hdr { + uint16_t cid; + uint16_t psm; +} __attribute__((packed)); + +static int log_fd = -1; + +int bt_log_sendmsg(uint16_t index, const char *label, int level, + struct iovec *io, size_t io_len) +{ + struct log_hdr hdr; + struct msghdr msg; + struct iovec iov[5]; + size_t i; + int err; + + if (io_len > 3) + return -EMSGSIZE; + + log_fd = bt_log_open(); + if (log_fd < 0) + return log_fd; + + hdr.opcode = cpu_to_le16(0x0000); + hdr.index = cpu_to_le16(index); + hdr.ident_len = strlen(label) + 1; + hdr.len = cpu_to_le16(2 + hdr.ident_len); + hdr.priority = level; + + iov[0].iov_base = &hdr; + iov[0].iov_len = sizeof(hdr); + + iov[1].iov_base = (void *) label; + iov[1].iov_len = hdr.ident_len; + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + + for (i = 0; i < io_len; i++) { + iov[i + 2] = io[i]; + hdr.len += io[i].iov_len; + msg.msg_iovlen++; + } + + err = sendmsg(log_fd, &msg, 0); + if (err < 0) { + err = -errno; + close(log_fd); + log_fd = -1; + } + + return err; +} + +int bt_log_open(void) +{ + struct sockaddr_hci addr; + int fd; + static int err; + + if (err < 0) + return err; + + if (log_fd >= 0) + return log_fd; + + fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (fd < 0) { + err = -errno; + return -errno; + } + + memset(&addr, 0, sizeof(addr)); + addr.hci_family = AF_BLUETOOTH; + addr.hci_dev = HCI_DEV_NONE; + addr.hci_channel = HCI_CHANNEL_LOGGING; + + err = bind(fd, (struct sockaddr *) &addr, sizeof(addr)); + if (err < 0) { + err = -errno; + close(fd); + return err; + } + + log_fd = fd; + + return fd; +} + +int bt_log_vprintf(uint16_t index, const char *label, int level, + const char *format, va_list ap) +{ + struct iovec iov; + char *str; + int len; + + len = vasprintf(&str, format, ap); + if (len < 0) + return errno; + + len = strlen(str); + + /* Replace new line since btmon already adds it */ + if (len > 1 && str[len - 1] == '\n') { + str[len - 1] = '\0'; + len--; + } + + iov.iov_base = str; + iov.iov_len = len + 1; + + len = bt_log_sendmsg(index, label, level, &iov, 1); + + free(str); + + return len; +} + +int bt_log_printf(uint16_t index, const char *label, int level, + const char *format, ...) +{ + va_list ap; + int err; + + va_start(ap, format); + err = bt_log_vprintf(index, label, level, format, ap); + va_end(ap); + + return err; +} + +void bt_log_close(void) +{ + if (log_fd < 0) + return; + + close(log_fd); + log_fd = -1; +} diff --git a/src/shared/log.h b/src/shared/log.h new file mode 100644 index 000000000..c72ab735b --- /dev/null +++ b/src/shared/log.h @@ -0,0 +1,31 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +int bt_log_open(void); +int bt_log_sendmsg(uint16_t index, const char *label, int level, + struct iovec *io, size_t io_len); +int bt_log_vprintf(uint16_t index, const char *label, int level, + const char *format, va_list ap); +int bt_log_printf(uint16_t index, const char *label, int level, + const char *format, ...); +void bt_log_close(void); -- 2.17.2