1 // SPDX-License-Identifier: LGPL-2.1-or-later
4 * BlueZ - Bluetooth protocol stack for Linux
6 * Copyright (C) 2011-2014 Intel Corporation
7 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
24 #include "lib/bluetooth.h"
26 #include "lib/hci_lib.h"
28 #include "src/shared/mainloop.h"
38 static void free_data(void *user_data)
40 struct hcidump_data *data = user_data;
47 static int open_hci_dev(uint16_t index)
49 struct sockaddr_hci addr;
50 struct hci_filter flt;
53 fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
55 perror("Failed to open channel");
60 hci_filter_clear(&flt);
61 hci_filter_all_ptypes(&flt);
62 hci_filter_all_events(&flt);
64 if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
65 perror("Failed to set HCI filter");
70 if (setsockopt(fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
71 perror("Failed to enable HCI data direction info");
76 if (setsockopt(fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
77 perror("Failed to enable HCI time stamps");
82 memset(&addr, 0, sizeof(addr));
83 addr.hci_family = AF_BLUETOOTH;
85 addr.hci_channel = HCI_CHANNEL_RAW;
87 if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
88 perror("Failed to bind channel");
96 static void device_callback(int fd, uint32_t events, void *user_data)
98 struct hcidump_data *data = user_data;
99 unsigned char buf[HCI_MAX_FRAME_SIZE * 2];
100 unsigned char control[64];
104 if (events & (EPOLLERR | EPOLLHUP)) {
105 mainloop_remove_fd(fd);
110 iov.iov_len = sizeof(buf);
112 memset(&msg, 0, sizeof(msg));
115 msg.msg_control = control;
116 msg.msg_controllen = sizeof(control);
119 struct cmsghdr *cmsg;
120 struct timeval *tv = NULL;
125 len = recvmsg(fd, &msg, MSG_DONTWAIT);
129 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
130 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
131 if (cmsg->cmsg_level != SOL_HCI)
134 switch (cmsg->cmsg_type) {
136 memcpy(&dir, CMSG_DATA(cmsg), sizeof(dir));
138 case HCI_CMSG_TSTAMP:
139 memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));
145 if (dir < 0 || len < 1)
149 case HCI_COMMAND_PKT:
150 packet_hci_command(tv, NULL, data->index,
154 packet_hci_event(tv, NULL, data->index,
157 case HCI_ACLDATA_PKT:
158 packet_hci_acldata(tv, NULL, data->index, !!dir,
161 case HCI_SCODATA_PKT:
162 packet_hci_scodata(tv, NULL, data->index, !!dir,
169 static void open_device(uint16_t index)
171 struct hcidump_data *data;
173 data = malloc(sizeof(*data));
177 memset(data, 0, sizeof(*data));
180 data->fd = open_hci_dev(index);
186 if (mainloop_add_fd(data->fd, EPOLLIN, device_callback,
187 data, free_data) < 0) {
193 static void device_info(int fd, uint16_t index, uint8_t *type, uint8_t *bus,
194 bdaddr_t *bdaddr, char *name)
196 struct hci_dev_info di;
198 memset(&di, 0, sizeof(di));
201 if (ioctl(fd, HCIGETDEVINFO, (void *) &di) < 0) {
202 perror("Failed to get device information");
206 *type = di.type >> 4;
207 *bus = di.type & 0x0f;
209 bacpy(bdaddr, &di.bdaddr);
210 memcpy(name, di.name, 8);
213 static void device_list(int fd, int max_dev)
215 struct hci_dev_list_req *dl;
216 struct hci_dev_req *dr;
219 dl = malloc(max_dev * sizeof(*dr) + sizeof(*dl));
221 perror("Failed to allocate device list memory");
225 memset(dl, 0, max_dev * sizeof(*dr) + sizeof(*dl));
226 dl->dev_num = max_dev;
230 if (ioctl(fd, HCIGETDEVLIST, (void *) dl) < 0) {
231 perror("Failed to get device list");
235 for (i = 0; i < dl->dev_num; i++, dr++) {
236 struct timeval tmp_tv, *tv = NULL;
237 uint8_t type = 0xff, bus = 0xff;
238 char str[18], name[8] = "";
241 bacpy(&bdaddr, BDADDR_ANY);
243 if (!gettimeofday(&tmp_tv, NULL))
246 device_info(fd, dr->dev_id, &type, &bus, &bdaddr, name);
247 ba2str(&bdaddr, str);
248 packet_new_index(tv, dr->dev_id, str, type, bus, name);
249 open_device(dr->dev_id);
256 static int open_stack_internal(void)
258 struct sockaddr_hci addr;
259 struct hci_filter flt;
262 fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
264 perror("Failed to open channel");
269 hci_filter_clear(&flt);
270 hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
271 hci_filter_set_event(EVT_STACK_INTERNAL, &flt);
273 if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
274 perror("Failed to set HCI filter");
279 if (setsockopt(fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
280 perror("Failed to enable HCI time stamps");
285 memset(&addr, 0, sizeof(addr));
286 addr.hci_family = AF_BLUETOOTH;
287 addr.hci_dev = HCI_DEV_NONE;
288 addr.hci_channel = HCI_CHANNEL_RAW;
290 if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
291 perror("Failed to bind channel");
296 device_list(fd, HCI_MAX_DEV);
301 static void stack_internal_callback(int fd, uint32_t events, void *user_data)
303 unsigned char buf[HCI_MAX_FRAME_SIZE];
304 unsigned char control[32];
307 struct cmsghdr *cmsg;
310 evt_stack_internal *si;
312 struct timeval *tv = NULL;
314 uint8_t type = 0xff, bus = 0xff;
315 char str[18], name[8] = "";
318 bacpy(&bdaddr, BDADDR_ANY);
320 if (events & (EPOLLERR | EPOLLHUP)) {
321 mainloop_remove_fd(fd);
326 iov.iov_len = sizeof(buf);
328 memset(&msg, 0, sizeof(msg));
331 msg.msg_control = control;
332 msg.msg_controllen = sizeof(control);
334 len = recvmsg(fd, &msg, MSG_DONTWAIT);
338 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
339 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
340 if (cmsg->cmsg_level != SOL_HCI)
343 switch (cmsg->cmsg_type) {
344 case HCI_CMSG_TSTAMP:
345 memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));
351 if (len < 1 + HCI_EVENT_HDR_SIZE + EVT_STACK_INTERNAL_SIZE +
355 if (buf[0] != HCI_EVENT_PKT)
358 eh = (hci_event_hdr *) (buf + 1);
359 if (eh->evt != EVT_STACK_INTERNAL)
362 si = (evt_stack_internal *) (buf + 1 + HCI_EVENT_HDR_SIZE);
363 if (si->type != EVT_SI_DEVICE)
366 sd = (evt_si_device *) &si->data;
370 device_info(fd, sd->dev_id, &type, &bus, &bdaddr, name);
371 ba2str(&bdaddr, str);
372 packet_new_index(tv, sd->dev_id, str, type, bus, name);
373 open_device(sd->dev_id);
376 ba2str(&bdaddr, str);
377 packet_del_index(tv, sd->dev_id, str);
382 int hcidump_tracing(void)
384 struct hcidump_data *data;
386 data = malloc(sizeof(*data));
390 memset(data, 0, sizeof(*data));
391 data->index = HCI_DEV_NONE;
393 data->fd = open_stack_internal();
399 if (mainloop_add_fd(data->fd, EPOLLIN, stack_internal_callback,
400 data, free_data) < 0) {