Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/hcitools/monitor/hcidump.c
Views: 3959
/*1*2* BlueZ - Bluetooth protocol stack for Linux3*4* Copyright (C) 2011-2012 Intel Corporation5* Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>6*7*8* This program is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License as published by10* the Free Software Foundation; either version 2 of the License, or11* (at your option) any later version.12*13* This program is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*18* You should have received a copy of the GNU General Public License19* along with this program; if not, write to the Free Software20* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA21*22*/2324#ifdef HAVE_CONFIG_H25#include <config.h>26#endif2728#include <stdio.h>29#include <errno.h>30#include <unistd.h>31#include <stdlib.h>32#include <string.h>33#include <fcntl.h>34#include <sys/types.h>35#include <sys/ioctl.h>36#include <sys/socket.h>3738#include <bluetooth/bluetooth.h>39#include <bluetooth/hci.h>40#include <bluetooth/hci_lib.h>4142#include "mainloop.h"43#include "packet.h"44#include "hcidump.h"4546struct hcidump_data {47uint16_t index;48int fd;49};5051static void free_data(void *user_data)52{53struct hcidump_data *data = user_data;5455close(data->fd);5657free(data);58}5960static int open_hci_dev(uint16_t index)61{62struct sockaddr_hci addr;63struct hci_filter flt;64int fd, opt = 1;6566fd = socket(AF_BLUETOOTH, SOCK_RAW | O_CLOEXEC, BTPROTO_HCI);67if (fd < 0) {68perror("Failed to open channel");69return -1;70}7172/* Setup filter */73hci_filter_clear(&flt);74hci_filter_all_ptypes(&flt);75hci_filter_all_events(&flt);7677if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {78perror("Failed to set HCI filter");79close(fd);80return -1;81}8283if (setsockopt(fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {84perror("Failed to enable HCI data direction info");85close(fd);86return -1;87}8889if (setsockopt(fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {90perror("Failed to enable HCI time stamps");91close(fd);92return -1;93}9495memset(&addr, 0, sizeof(addr));96addr.hci_family = AF_BLUETOOTH;97addr.hci_dev = index;98addr.hci_channel = HCI_CHANNEL_RAW;99100if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {101perror("Failed to bind channel");102close(fd);103return -1;104}105106return fd;107}108109static void device_callback(int fd, uint32_t events, void *user_data)110{111struct hcidump_data *data = user_data;112unsigned char buf[HCI_MAX_FRAME_SIZE * 2];113unsigned char control[64];114struct msghdr msg;115struct iovec iov;116117if (events & (EPOLLERR | EPOLLHUP)) {118mainloop_remove_fd(fd);119return;120}121122iov.iov_base = buf;123iov.iov_len = sizeof(buf);124125memset(&msg, 0, sizeof(msg));126msg.msg_iov = &iov;127msg.msg_iovlen = 1;128msg.msg_control = control;129msg.msg_controllen = sizeof(control);130131while (1) {132struct cmsghdr *cmsg;133struct timeval *tv = NULL;134struct timeval ctv;135int dir = -1;136ssize_t len;137138len = recvmsg(fd, &msg, MSG_DONTWAIT);139if (len < 0)140break;141142for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;143cmsg = CMSG_NXTHDR(&msg, cmsg)) {144if (cmsg->cmsg_level != SOL_HCI)145continue;146147switch (cmsg->cmsg_type) {148case HCI_DATA_DIR:149memcpy(&dir, CMSG_DATA(cmsg), sizeof(dir));150break;151case HCI_CMSG_TSTAMP:152memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));153tv = &ctv;154break;155}156}157158if (dir < 0 || len < 1)159continue;160161switch (buf[0]) {162case HCI_COMMAND_PKT:163packet_hci_command(tv, data->index, buf + 1, len - 1);164break;165case HCI_EVENT_PKT:166packet_hci_event(tv, data->index, buf + 1, len - 1);167break;168case HCI_ACLDATA_PKT:169packet_hci_acldata(tv, data->index, !!dir,170buf + 1, len - 1);171break;172case HCI_SCODATA_PKT:173packet_hci_scodata(tv, data->index, !!dir,174buf + 1, len - 1);175break;176}177}178}179180static void open_device(uint16_t index)181{182struct hcidump_data *data;183184data = malloc(sizeof(*data));185if (!data)186return;187188memset(data, 0, sizeof(*data));189data->index = index;190191data->fd = open_hci_dev(index);192if (data->fd < 0) {193free(data);194return;195}196197mainloop_add_fd(data->fd, EPOLLIN, device_callback, data, free_data);198}199200static void device_info(int fd, uint16_t index, uint8_t *type, uint8_t *bus,201bdaddr_t *bdaddr, char *name)202{203struct hci_dev_info di;204205memset(&di, 0, sizeof(di));206di.dev_id = index;207208if (ioctl(fd, HCIGETDEVINFO, (void *) &di) < 0) {209perror("Failed to get device information");210return;211}212213*type = di.type >> 4;214*bus = di.type & 0x0f;215216bacpy(bdaddr, &di.bdaddr);217memcpy(name, di.name, 8);218}219220static void device_list(int fd, int max_dev)221{222struct hci_dev_list_req *dl;223struct hci_dev_req *dr;224int i;225226dl = malloc(max_dev * sizeof(*dr) + sizeof(*dl));227if (!dl) {228perror("Failed to allocate device list memory");229return;230}231232memset(dl, 0, max_dev * sizeof(*dr) + sizeof(*dl));233dl->dev_num = max_dev;234235dr = dl->dev_req;236237if (ioctl(fd, HCIGETDEVLIST, (void *) dl) < 0) {238perror("Failed to get device list");239goto done;240}241242for (i = 0; i < dl->dev_num; i++, dr++) {243struct timeval tmp_tv, *tv = NULL;244uint8_t type = 0xff, bus = 0xff;245char str[18], name[8] = "";246bdaddr_t bdaddr;247248bacpy(&bdaddr, BDADDR_ANY);249250if (!gettimeofday(&tmp_tv, NULL))251tv = &tmp_tv;252253device_info(fd, dr->dev_id, &type, &bus, &bdaddr, name);254ba2str(&bdaddr, str);255packet_new_index(tv, dr->dev_id, str, type, bus, name);256open_device(dr->dev_id);257}258259done:260free(dl);261}262263static int open_stack_internal(void)264{265struct sockaddr_hci addr;266struct hci_filter flt;267int fd, opt = 1;268269fd = socket(AF_BLUETOOTH, SOCK_RAW | O_CLOEXEC, BTPROTO_HCI);270if (fd < 0) {271perror("Failed to open channel");272return -1;273}274275/* Setup filter */276hci_filter_clear(&flt);277hci_filter_set_ptype(HCI_EVENT_PKT, &flt);278hci_filter_set_event(EVT_STACK_INTERNAL, &flt);279280if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {281perror("Failed to set HCI filter");282close(fd);283return -1;284}285286if (setsockopt(fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {287perror("Failed to enable HCI time stamps");288close(fd);289return -1;290}291292memset(&addr, 0, sizeof(addr));293addr.hci_family = AF_BLUETOOTH;294addr.hci_dev = HCI_DEV_NONE;295addr.hci_channel = HCI_CHANNEL_RAW;296297if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {298perror("Failed to bind channel");299close(fd);300return -1;301}302303device_list(fd, HCI_MAX_DEV);304305return fd;306}307308static void stack_internal_callback(int fd, uint32_t events, void *user_data)309{310unsigned char buf[HCI_MAX_FRAME_SIZE];311unsigned char control[32];312struct msghdr msg;313struct iovec iov;314struct cmsghdr *cmsg;315ssize_t len;316hci_event_hdr *eh;317evt_stack_internal *si;318evt_si_device *sd;319struct timeval *tv = NULL;320struct timeval ctv;321uint8_t type = 0xff, bus = 0xff;322char str[18], name[8] = "";323bdaddr_t bdaddr;324325bacpy(&bdaddr, BDADDR_ANY);326327if (events & (EPOLLERR | EPOLLHUP)) {328mainloop_remove_fd(fd);329return;330}331332iov.iov_base = buf;333iov.iov_len = sizeof(buf);334335memset(&msg, 0, sizeof(msg));336msg.msg_iov = &iov;337msg.msg_iovlen = 1;338msg.msg_control = control;339msg.msg_controllen = sizeof(control);340341len = recvmsg(fd, &msg, MSG_DONTWAIT);342if (len < 0)343return;344345for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;346cmsg = CMSG_NXTHDR(&msg, cmsg)) {347if (cmsg->cmsg_level != SOL_HCI)348continue;349350switch (cmsg->cmsg_type) {351case HCI_CMSG_TSTAMP:352memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));353tv = &ctv;354break;355}356}357358if (len < 1 + HCI_EVENT_HDR_SIZE + EVT_STACK_INTERNAL_SIZE +359EVT_SI_DEVICE_SIZE)360return;361362if (buf[0] != HCI_EVENT_PKT)363return;364365eh = (hci_event_hdr *) (buf + 1);366if (eh->evt != EVT_STACK_INTERNAL)367return;368369si = (evt_stack_internal *) (buf + 1 + HCI_EVENT_HDR_SIZE);370if (si->type != EVT_SI_DEVICE)371return;372373sd = (evt_si_device *) &si->data;374375switch (sd->event) {376case HCI_DEV_REG:377device_info(fd, sd->dev_id, &type, &bus, &bdaddr, name);378ba2str(&bdaddr, str);379packet_new_index(tv, sd->dev_id, str, type, bus, name);380open_device(sd->dev_id);381break;382case HCI_DEV_UNREG:383ba2str(&bdaddr, str);384packet_del_index(tv, sd->dev_id, str);385break;386}387}388389int hcidump_tracing(void)390{391struct hcidump_data *data;392393data = malloc(sizeof(*data));394if (!data)395return -1;396397memset(data, 0, sizeof(*data));398data->index = HCI_DEV_NONE;399400data->fd = open_stack_internal();401if (data->fd < 0) {402free(data);403return -1;404}405406mainloop_add_fd(data->fd, EPOLLIN, stack_internal_callback,407data, free_data);408409return 0;410}411412413