mirror of
https://github.com/DrHo1y/orangepi-build.git
synced 2026-11-13 19:43:48 +07:00
First Commit
This commit is contained in:
2149
external/cache/sources/hcitools/monitor/bt.h
vendored
Normal file
2149
external/cache/sources/hcitools/monitor/bt.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
423
external/cache/sources/hcitools/monitor/btsnoop.c
vendored
Normal file
423
external/cache/sources/hcitools/monitor/btsnoop.c
vendored
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
#include "btsnoop.h"
|
||||
|
||||
struct btsnoop_hdr {
|
||||
uint8_t id[8]; /* Identification Pattern */
|
||||
uint32_t version; /* Version Number = 1 */
|
||||
uint32_t type; /* Datalink Type */
|
||||
} __attribute__ ((packed));
|
||||
#define BTSNOOP_HDR_SIZE (sizeof(struct btsnoop_hdr))
|
||||
|
||||
struct btsnoop_pkt {
|
||||
uint32_t size; /* Original Length */
|
||||
uint32_t len; /* Included Length */
|
||||
uint32_t flags; /* Packet Flags */
|
||||
uint32_t drops; /* Cumulative Drops */
|
||||
uint64_t ts; /* Timestamp microseconds */
|
||||
uint8_t data[0]; /* Packet Data */
|
||||
} __attribute__ ((packed));
|
||||
#define BTSNOOP_PKT_SIZE (sizeof(struct btsnoop_pkt))
|
||||
|
||||
static const uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e,
|
||||
0x6f, 0x6f, 0x70, 0x00 };
|
||||
|
||||
static const uint32_t btsnoop_version = 1;
|
||||
static uint32_t btsnoop_type = 0;
|
||||
|
||||
static int btsnoop_fd = -1;
|
||||
static uint16_t btsnoop_index = 0xffff;
|
||||
|
||||
void btsnoop_create(const char *path, uint32_t type)
|
||||
{
|
||||
struct btsnoop_hdr hdr;
|
||||
ssize_t written;
|
||||
|
||||
if (btsnoop_fd >= 0)
|
||||
return;
|
||||
|
||||
btsnoop_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (btsnoop_fd < 0)
|
||||
return;
|
||||
|
||||
btsnoop_type = type;
|
||||
|
||||
memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
|
||||
hdr.version = htonl(btsnoop_version);
|
||||
hdr.type = htonl(btsnoop_type);
|
||||
|
||||
written = write(btsnoop_fd, &hdr, BTSNOOP_HDR_SIZE);
|
||||
if (written < 0) {
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void btsnoop_write(struct timeval *tv, uint32_t flags,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
struct btsnoop_pkt pkt;
|
||||
uint64_t ts;
|
||||
ssize_t written;
|
||||
|
||||
ts = (tv->tv_sec - 946684800ll) * 1000000ll + tv->tv_usec;
|
||||
|
||||
pkt.size = htonl(size);
|
||||
pkt.len = htonl(size);
|
||||
pkt.flags = htonl(flags);
|
||||
pkt.drops = htonl(0);
|
||||
pkt.ts = hton64(ts + 0x00E03AB44A676000ll);
|
||||
|
||||
written = write(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
|
||||
if (written < 0)
|
||||
return;
|
||||
|
||||
if (data && size > 0) {
|
||||
written = write(btsnoop_fd, data, size);
|
||||
if (written < 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_flags_from_opcode(uint16_t opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case BTSNOOP_OPCODE_NEW_INDEX:
|
||||
case BTSNOOP_OPCODE_DEL_INDEX:
|
||||
break;
|
||||
case BTSNOOP_OPCODE_COMMAND_PKT:
|
||||
return 0x02;
|
||||
case BTSNOOP_OPCODE_EVENT_PKT:
|
||||
return 0x03;
|
||||
case BTSNOOP_OPCODE_ACL_TX_PKT:
|
||||
return 0x00;
|
||||
case BTSNOOP_OPCODE_ACL_RX_PKT:
|
||||
return 0x01;
|
||||
case BTSNOOP_OPCODE_SCO_TX_PKT:
|
||||
case BTSNOOP_OPCODE_SCO_RX_PKT:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void btsnoop_write_hci(struct timeval *tv, uint16_t index, uint16_t opcode,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
uint32_t flags;
|
||||
|
||||
if (!tv)
|
||||
return;
|
||||
|
||||
if (btsnoop_fd < 0)
|
||||
return;
|
||||
|
||||
switch (btsnoop_type) {
|
||||
case BTSNOOP_TYPE_HCI:
|
||||
if (btsnoop_index == 0xffff)
|
||||
btsnoop_index = index;
|
||||
|
||||
if (index != btsnoop_index)
|
||||
return;
|
||||
|
||||
flags = get_flags_from_opcode(opcode);
|
||||
if (flags == 0xff)
|
||||
return;
|
||||
break;
|
||||
|
||||
case BTSNOOP_TYPE_EXTENDED_HCI:
|
||||
flags = (index << 16) | opcode;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
btsnoop_write(tv, flags, data, size);
|
||||
}
|
||||
|
||||
void btsnoop_write_phy(struct timeval *tv, uint16_t frequency,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
uint32_t flags;
|
||||
|
||||
if (!tv)
|
||||
return;
|
||||
|
||||
if (btsnoop_fd < 0)
|
||||
return;
|
||||
|
||||
switch (btsnoop_type) {
|
||||
case BTSNOOP_TYPE_EXTENDED_PHY:
|
||||
flags = (1 << 16) | frequency;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
btsnoop_write(tv, flags, data, size);
|
||||
}
|
||||
|
||||
int btsnoop_open(const char *path, uint32_t *type)
|
||||
{
|
||||
struct btsnoop_hdr hdr;
|
||||
ssize_t len;
|
||||
|
||||
if (btsnoop_fd >= 0) {
|
||||
fprintf(stderr, "Too many open files\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
btsnoop_fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (btsnoop_fd < 0) {
|
||||
perror("Failed to open file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = read(btsnoop_fd, &hdr, BTSNOOP_HDR_SIZE);
|
||||
if (len < 0 || len != BTSNOOP_HDR_SIZE) {
|
||||
perror("Failed to read header");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(hdr.id, btsnoop_id, sizeof(btsnoop_id))) {
|
||||
fprintf(stderr, "Invalid btsnoop header\n");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ntohl(hdr.version) != btsnoop_version) {
|
||||
fprintf(stderr, "Invalid btsnoop version\n");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
btsnoop_type = ntohl(hdr.type);
|
||||
|
||||
if (type)
|
||||
*type = btsnoop_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t get_opcode_from_flags(uint8_t type, uint32_t flags)
|
||||
{
|
||||
switch (type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
return BTSNOOP_OPCODE_COMMAND_PKT;
|
||||
case HCI_ACLDATA_PKT:
|
||||
if (flags & 0x01)
|
||||
return BTSNOOP_OPCODE_ACL_RX_PKT;
|
||||
else
|
||||
return BTSNOOP_OPCODE_ACL_TX_PKT;
|
||||
case HCI_SCODATA_PKT:
|
||||
if (flags & 0x01)
|
||||
return BTSNOOP_OPCODE_SCO_RX_PKT;
|
||||
else
|
||||
return BTSNOOP_OPCODE_SCO_TX_PKT;
|
||||
case HCI_EVENT_PKT:
|
||||
return BTSNOOP_OPCODE_EVENT_PKT;
|
||||
case 0xff:
|
||||
if (flags & 0x02) {
|
||||
if (flags & 0x01)
|
||||
return BTSNOOP_OPCODE_EVENT_PKT;
|
||||
else
|
||||
return BTSNOOP_OPCODE_COMMAND_PKT;
|
||||
} else {
|
||||
if (flags & 0x01)
|
||||
return BTSNOOP_OPCODE_ACL_RX_PKT;
|
||||
else
|
||||
return BTSNOOP_OPCODE_ACL_TX_PKT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
int btsnoop_read_hci(struct timeval *tv, uint16_t *index, uint16_t *opcode,
|
||||
void *data, uint16_t *size)
|
||||
{
|
||||
struct btsnoop_pkt pkt;
|
||||
uint32_t toread, flags;
|
||||
uint64_t ts;
|
||||
uint8_t pkt_type;
|
||||
ssize_t len;
|
||||
|
||||
if (btsnoop_fd < 0)
|
||||
return -1;
|
||||
|
||||
len = read(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
if (len < 0 || len != BTSNOOP_PKT_SIZE) {
|
||||
perror("Failed to read packet");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
toread = ntohl(pkt.size);
|
||||
flags = ntohl(pkt.flags);
|
||||
|
||||
ts = ntoh64(pkt.ts) - 0x00E03AB44A676000ll;
|
||||
tv->tv_sec = (ts / 1000000ll) + 946684800ll;
|
||||
tv->tv_usec = ts % 1000000ll;
|
||||
|
||||
switch (btsnoop_type) {
|
||||
case BTSNOOP_TYPE_HCI:
|
||||
*index = 0;
|
||||
*opcode = get_opcode_from_flags(0xff, flags);
|
||||
break;
|
||||
|
||||
case BTSNOOP_TYPE_UART:
|
||||
len = read(btsnoop_fd, &pkt_type, 1);
|
||||
if (len < 0) {
|
||||
perror("Failed to read packet type");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
toread--;
|
||||
|
||||
*index = 0;
|
||||
*opcode = get_opcode_from_flags(pkt_type, flags);
|
||||
break;
|
||||
|
||||
case BTSNOOP_TYPE_EXTENDED_HCI:
|
||||
*index = flags >> 16;
|
||||
*opcode = flags & 0xffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown packet type\n");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = read(btsnoop_fd, data, toread);
|
||||
if (len < 0) {
|
||||
perror("Failed to read data");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*size = toread;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btsnoop_read_phy(struct timeval *tv, uint16_t *frequency,
|
||||
void *data, uint16_t *size)
|
||||
{
|
||||
struct btsnoop_pkt pkt;
|
||||
uint32_t toread, flags;
|
||||
uint64_t ts;
|
||||
ssize_t len;
|
||||
|
||||
if (btsnoop_fd < 0)
|
||||
return -1;
|
||||
|
||||
len = read(btsnoop_fd, &pkt, BTSNOOP_PKT_SIZE);
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
if (len < 0 || len != BTSNOOP_PKT_SIZE) {
|
||||
perror("Failed to read packet");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
toread = ntohl(pkt.size);
|
||||
flags = ntohl(pkt.flags);
|
||||
|
||||
ts = ntoh64(pkt.ts) - 0x00E03AB44A676000ll;
|
||||
tv->tv_sec = (ts / 1000000ll) + 946684800ll;
|
||||
tv->tv_usec = ts % 1000000ll;
|
||||
|
||||
switch (btsnoop_type) {
|
||||
case BTSNOOP_TYPE_EXTENDED_PHY:
|
||||
if ((flags >> 16) != 1)
|
||||
break;
|
||||
*frequency = flags & 0xffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown packet type\n");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = read(btsnoop_fd, data, toread);
|
||||
if (len < 0) {
|
||||
perror("Failed to read data");
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*size = toread;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void btsnoop_close(void)
|
||||
{
|
||||
if (btsnoop_fd < 0)
|
||||
return;
|
||||
|
||||
close(btsnoop_fd);
|
||||
btsnoop_fd = -1;
|
||||
|
||||
btsnoop_index = 0xffff;
|
||||
}
|
||||
57
external/cache/sources/hcitools/monitor/btsnoop.h
vendored
Normal file
57
external/cache/sources/hcitools/monitor/btsnoop.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define BTSNOOP_TYPE_HCI 1001
|
||||
#define BTSNOOP_TYPE_UART 1002
|
||||
#define BTSNOOP_TYPE_BCSP 1003
|
||||
#define BTSNOOP_TYPE_3WIRE 1004
|
||||
|
||||
#define BTSNOOP_TYPE_EXTENDED_HCI 2001
|
||||
#define BTSNOOP_TYPE_EXTENDED_PHY 2002
|
||||
|
||||
#define BTSNOOP_OPCODE_NEW_INDEX 0
|
||||
#define BTSNOOP_OPCODE_DEL_INDEX 1
|
||||
#define BTSNOOP_OPCODE_COMMAND_PKT 2
|
||||
#define BTSNOOP_OPCODE_EVENT_PKT 3
|
||||
#define BTSNOOP_OPCODE_ACL_TX_PKT 4
|
||||
#define BTSNOOP_OPCODE_ACL_RX_PKT 5
|
||||
#define BTSNOOP_OPCODE_SCO_TX_PKT 6
|
||||
#define BTSNOOP_OPCODE_SCO_RX_PKT 7
|
||||
|
||||
void btsnoop_create(const char *path, uint32_t type);
|
||||
void btsnoop_write(struct timeval *tv, uint32_t flags,
|
||||
const void *data, uint16_t size);
|
||||
void btsnoop_write_hci(struct timeval *tv, uint16_t index, uint16_t opcode,
|
||||
const void *data, uint16_t size);
|
||||
void btsnoop_write_phy(struct timeval *tv, uint16_t frequency,
|
||||
const void *data, uint16_t size);
|
||||
int btsnoop_open(const char *path, uint32_t *type);
|
||||
int btsnoop_read_hci(struct timeval *tv, uint16_t *index, uint16_t *opcode,
|
||||
void *data, uint16_t *size);
|
||||
int btsnoop_read_phy(struct timeval *tv, uint16_t *frequency,
|
||||
void *data, uint16_t *size);
|
||||
void btsnoop_close(void);
|
||||
891
external/cache/sources/hcitools/monitor/control.c
vendored
Normal file
891
external/cache/sources/hcitools/monitor/control.c
vendored
Normal file
@@ -0,0 +1,891 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <lib/bluetooth/bluetooth.h>
|
||||
#include <lib/bluetooth/hci.h>
|
||||
#include <lib/mgmt.h>
|
||||
|
||||
#include "mainloop.h"
|
||||
#include "display.h"
|
||||
#include "packet.h"
|
||||
#include "btsnoop.h"
|
||||
#include "hcidump.h"
|
||||
#include "control.h"
|
||||
|
||||
static bool hcidump_fallback = false;
|
||||
|
||||
#define MAX_PACKET_SIZE (1486 + 4)
|
||||
|
||||
struct control_data {
|
||||
uint16_t channel;
|
||||
int fd;
|
||||
unsigned char buf[MAX_PACKET_SIZE];
|
||||
uint16_t offset;
|
||||
};
|
||||
|
||||
static void free_data(void *user_data)
|
||||
{
|
||||
struct control_data *data = user_data;
|
||||
|
||||
close(data->fd);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void mgmt_index_added(uint16_t len, const void *buf)
|
||||
{
|
||||
printf("@ Index Added\n");
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_index_removed(uint16_t len, const void *buf)
|
||||
{
|
||||
printf("@ Index Removed\n");
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_controller_error(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_controller_error *ev = buf;
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Controller Error control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("@ Controller Error: 0x%2.2x\n", ev->error_code);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
#ifndef NELEM
|
||||
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
static const char *settings_str[] = {
|
||||
"powered", "connectable", "fast-connectable", "discoverable",
|
||||
"pairable", "link-security", "ssp", "br/edr", "hs", "le",
|
||||
"advertising",
|
||||
};
|
||||
|
||||
static void mgmt_new_settings(uint16_t len, const void *buf)
|
||||
{
|
||||
uint32_t settings;
|
||||
unsigned int i;
|
||||
|
||||
if (len < 4) {
|
||||
printf("* Malformed New Settings control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
settings = bt_get_le32(buf);
|
||||
|
||||
printf("@ New Settings: 0x%4.4x\n", settings);
|
||||
|
||||
printf("%-12c", ' ');
|
||||
for (i = 0; i < NELEM(settings_str); i++) {
|
||||
if (settings & (1 << i))
|
||||
printf("%s ", settings_str[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
buf += 4;
|
||||
len -= 4;
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_class_of_dev_changed(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_class_of_dev_changed *ev = buf;
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Class of Device Changed control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("@ Class of Device Changed: 0x%2.2x%2.2x%2.2x\n",
|
||||
ev->class_of_dev[2],
|
||||
ev->class_of_dev[1],
|
||||
ev->class_of_dev[0]);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_local_name_changed(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_local_name_changed *ev = buf;
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Local Name Changed control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("@ Local Name Changed: %s (%s)\n", ev->name, ev->short_name);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_new_link_key(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_new_link_key *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed New Link Key control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->key.addr.bdaddr, str);
|
||||
|
||||
printf("@ New Link Key: %s (%d)\n", str, ev->key.addr.type);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_new_long_term_key(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_new_long_term_key *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed New Long Term Key control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->key.addr.bdaddr, str);
|
||||
|
||||
printf("@ New Long Term Key: %s (%d)\n", str, ev->key.addr.type);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_device_connected(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_device_connected *ev = buf;
|
||||
uint32_t flags;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Device Connected control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
flags = btohl(ev->flags);
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Device Connected: %s (%d) flags 0x%4.4x\n",
|
||||
str, ev->addr.type, flags);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_device_disconnected(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_device_disconnected *ev = buf;
|
||||
char str[18];
|
||||
uint8_t reason;
|
||||
uint16_t consumed_len;
|
||||
|
||||
if (len < sizeof(struct mgmt_addr_info)) {
|
||||
printf("* Malformed Device Disconnected control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
reason = MGMT_DEV_DISCONN_UNKNOWN;
|
||||
consumed_len = len;
|
||||
} else {
|
||||
reason = ev->reason;
|
||||
consumed_len = sizeof(*ev);
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Device Disconnected: %s (%d) reason %u\n", str, ev->addr.type,
|
||||
reason);
|
||||
|
||||
buf += consumed_len;
|
||||
len -= consumed_len;
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_connect_failed(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_connect_failed *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Connect Failed control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Connect Failed: %s (%d) status 0x%2.2x\n",
|
||||
str, ev->addr.type, ev->status);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_pin_code_request(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_pin_code_request *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed PIN Code Request control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ PIN Code Request: %s (%d) secure 0x%2.2x\n",
|
||||
str, ev->addr.type, ev->secure);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_user_confirm_request(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_user_confirm_request *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed User Confirmation Request control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ User Confirmation Request: %s (%d) hint %d value %d\n",
|
||||
str, ev->addr.type, ev->confirm_hint, ev->value);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_user_passkey_request(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_user_passkey_request *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed User Passkey Request control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ PIN User Passkey Request: %s (%d)\n", str, ev->addr.type);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_auth_failed(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_auth_failed *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Authentication Failed control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Authentication Failed: %s (%d) status 0x%2.2x\n",
|
||||
str, ev->addr.type, ev->status);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_device_found(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_device_found *ev = buf;
|
||||
uint32_t flags;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Device Found control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
flags = btohl(ev->flags);
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Device Found: %s (%d) rssi %d flags 0x%4.4x\n",
|
||||
str, ev->addr.type, ev->rssi, flags);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_discovering(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_discovering *ev = buf;
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Discovering control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("@ Discovering: 0x%2.2x (%d)\n", ev->discovering, ev->type);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_device_blocked(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_device_blocked *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Device Blocked control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Device Blocked: %s (%d)\n", str, ev->addr.type);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_device_unblocked(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_device_unblocked *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Device Unblocked control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Device Unblocked: %s (%d)\n", str, ev->addr.type);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_device_unpaired(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_device_unpaired *ev = buf;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Device Unpaired control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
printf("@ Device Unpaired: %s (%d)\n", str, ev->addr.type);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
static void mgmt_passkey_notify(uint16_t len, const void *buf)
|
||||
{
|
||||
const struct mgmt_ev_passkey_notify *ev = buf;
|
||||
uint32_t passkey;
|
||||
char str[18];
|
||||
|
||||
if (len < sizeof(*ev)) {
|
||||
printf("* Malformed Passkey Notify control\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&ev->addr.bdaddr, str);
|
||||
|
||||
passkey = btohl(ev->passkey);
|
||||
|
||||
printf("@ Passkey Notify: %s (%d) passkey %06u entered %u\n",
|
||||
str, ev->addr.type, passkey, ev->entered);
|
||||
|
||||
buf += sizeof(*ev);
|
||||
len -= sizeof(*ev);
|
||||
|
||||
packet_hexdump(buf, len);
|
||||
}
|
||||
|
||||
void control_message(uint16_t opcode, const void *data, uint16_t size)
|
||||
{
|
||||
switch (opcode) {
|
||||
case MGMT_EV_INDEX_ADDED:
|
||||
mgmt_index_added(size, data);
|
||||
break;
|
||||
case MGMT_EV_INDEX_REMOVED:
|
||||
mgmt_index_removed(size, data);
|
||||
break;
|
||||
case MGMT_EV_CONTROLLER_ERROR:
|
||||
mgmt_controller_error(size, data);
|
||||
break;
|
||||
case MGMT_EV_NEW_SETTINGS:
|
||||
mgmt_new_settings(size, data);
|
||||
break;
|
||||
case MGMT_EV_CLASS_OF_DEV_CHANGED:
|
||||
mgmt_class_of_dev_changed(size, data);
|
||||
break;
|
||||
case MGMT_EV_LOCAL_NAME_CHANGED:
|
||||
mgmt_local_name_changed(size, data);
|
||||
break;
|
||||
case MGMT_EV_NEW_LINK_KEY:
|
||||
mgmt_new_link_key(size, data);
|
||||
break;
|
||||
case MGMT_EV_NEW_LONG_TERM_KEY:
|
||||
mgmt_new_long_term_key(size, data);
|
||||
break;
|
||||
case MGMT_EV_DEVICE_CONNECTED:
|
||||
mgmt_device_connected(size, data);
|
||||
break;
|
||||
case MGMT_EV_DEVICE_DISCONNECTED:
|
||||
mgmt_device_disconnected(size, data);
|
||||
break;
|
||||
case MGMT_EV_CONNECT_FAILED:
|
||||
mgmt_connect_failed(size, data);
|
||||
break;
|
||||
case MGMT_EV_PIN_CODE_REQUEST:
|
||||
mgmt_pin_code_request(size, data);
|
||||
break;
|
||||
case MGMT_EV_USER_CONFIRM_REQUEST:
|
||||
mgmt_user_confirm_request(size, data);
|
||||
break;
|
||||
case MGMT_EV_USER_PASSKEY_REQUEST:
|
||||
mgmt_user_passkey_request(size, data);
|
||||
break;
|
||||
case MGMT_EV_AUTH_FAILED:
|
||||
mgmt_auth_failed(size, data);
|
||||
break;
|
||||
case MGMT_EV_DEVICE_FOUND:
|
||||
mgmt_device_found(size, data);
|
||||
break;
|
||||
case MGMT_EV_DISCOVERING:
|
||||
mgmt_discovering(size, data);
|
||||
break;
|
||||
case MGMT_EV_DEVICE_BLOCKED:
|
||||
mgmt_device_blocked(size, data);
|
||||
break;
|
||||
case MGMT_EV_DEVICE_UNBLOCKED:
|
||||
mgmt_device_unblocked(size, data);
|
||||
break;
|
||||
case MGMT_EV_DEVICE_UNPAIRED:
|
||||
mgmt_device_unpaired(size, data);
|
||||
break;
|
||||
case MGMT_EV_PASSKEY_NOTIFY:
|
||||
mgmt_passkey_notify(size, data);
|
||||
break;
|
||||
default:
|
||||
printf("* Unknown control (code %d len %d)\n", opcode, size);
|
||||
packet_hexdump(data, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void data_callback(int fd, uint32_t events, void *user_data)
|
||||
{
|
||||
struct control_data *data = user_data;
|
||||
unsigned char control[32];
|
||||
struct mgmt_hdr hdr;
|
||||
struct msghdr msg;
|
||||
struct iovec iov[2];
|
||||
|
||||
if (events & (EPOLLERR | EPOLLHUP)) {
|
||||
mainloop_remove_fd(data->fd);
|
||||
return;
|
||||
}
|
||||
|
||||
iov[0].iov_base = &hdr;
|
||||
iov[0].iov_len = MGMT_HDR_SIZE;
|
||||
iov[1].iov_base = data->buf;
|
||||
iov[1].iov_len = sizeof(data->buf);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof(control);
|
||||
|
||||
while (1) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct timeval *tv = NULL;
|
||||
struct timeval ctv;
|
||||
uint16_t opcode, index, pktlen;
|
||||
ssize_t len;
|
||||
|
||||
len = recvmsg(data->fd, &msg, MSG_DONTWAIT);
|
||||
if (len < 0)
|
||||
break;
|
||||
|
||||
if (len < MGMT_HDR_SIZE)
|
||||
break;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET)
|
||||
continue;
|
||||
|
||||
if (cmsg->cmsg_type == SCM_TIMESTAMP) {
|
||||
memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));
|
||||
tv = &ctv;
|
||||
}
|
||||
}
|
||||
|
||||
opcode = btohs(hdr.opcode);
|
||||
index = btohs(hdr.index);
|
||||
pktlen = btohs(hdr.len);
|
||||
|
||||
switch (data->channel) {
|
||||
case HCI_CHANNEL_CONTROL:
|
||||
packet_control(tv, index, opcode, data->buf, pktlen);
|
||||
break;
|
||||
case HCI_CHANNEL_MONITOR:
|
||||
packet_monitor(tv, index, opcode, data->buf, pktlen);
|
||||
btsnoop_write_hci(tv, index, opcode, data->buf, pktlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int open_socket(uint16_t channel)
|
||||
{
|
||||
struct sockaddr_hci addr;
|
||||
int fd, opt = 1;
|
||||
|
||||
fd = socket(AF_BLUETOOTH, SOCK_RAW | O_CLOEXEC, BTPROTO_HCI);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open channel");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.hci_family = AF_BLUETOOTH;
|
||||
addr.hci_dev = HCI_DEV_NONE;
|
||||
addr.hci_channel = channel;
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
if (errno == EINVAL) {
|
||||
/* Fallback to hcidump support */
|
||||
hcidump_fallback = true;
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
perror("Failed to bind channel");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {
|
||||
perror("Failed to enable timestamps");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int open_channel(uint16_t channel)
|
||||
{
|
||||
struct control_data *data;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->channel = channel;
|
||||
|
||||
data->fd = open_socket(channel);
|
||||
if (data->fd < 0) {
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mainloop_add_fd(data->fd, EPOLLIN, data_callback, data, free_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void client_callback(int fd, uint32_t events, void *user_data)
|
||||
{
|
||||
struct control_data *data = user_data;
|
||||
ssize_t len;
|
||||
|
||||
if (events & (EPOLLERR | EPOLLHUP)) {
|
||||
mainloop_remove_fd(data->fd);
|
||||
return;
|
||||
}
|
||||
|
||||
len = recv(data->fd, data->buf + data->offset,
|
||||
sizeof(data->buf) - data->offset, MSG_DONTWAIT);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
data->offset += len;
|
||||
|
||||
if (data->offset > MGMT_HDR_SIZE) {
|
||||
struct mgmt_hdr *hdr = (struct mgmt_hdr *) data->buf;
|
||||
uint16_t pktlen = btohs(hdr->len);
|
||||
|
||||
if (data->offset > pktlen + MGMT_HDR_SIZE) {
|
||||
uint16_t opcode = btohs(hdr->opcode);
|
||||
uint16_t index = btohs(hdr->index);
|
||||
|
||||
packet_monitor(NULL, index, opcode,
|
||||
data->buf + MGMT_HDR_SIZE, pktlen);
|
||||
|
||||
data->offset -= pktlen + MGMT_HDR_SIZE;
|
||||
|
||||
if (data->offset > 0)
|
||||
memmove(data->buf, data->buf +
|
||||
MGMT_HDR_SIZE + pktlen, data->offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void server_accept_callback(int fd, uint32_t events, void *user_data)
|
||||
{
|
||||
struct control_data *data;
|
||||
struct sockaddr_un addr;
|
||||
socklen_t len;
|
||||
int nfd;
|
||||
|
||||
if (events & (EPOLLERR | EPOLLHUP)) {
|
||||
mainloop_remove_fd(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
len = sizeof(addr);
|
||||
|
||||
nfd = accept(fd, (struct sockaddr *) &addr, &len);
|
||||
if (nfd < 0) {
|
||||
perror("Failed to accept client socket");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("--- New monitor connection ---\n");
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
close(nfd);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->channel = HCI_CHANNEL_MONITOR;
|
||||
data->fd = nfd;
|
||||
|
||||
mainloop_add_fd(data->fd, EPOLLIN, client_callback, data, free_data);
|
||||
}
|
||||
|
||||
static int server_fd = -1;
|
||||
|
||||
void control_server(const char *path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int fd;
|
||||
|
||||
if (server_fd >= 0)
|
||||
return;
|
||||
|
||||
unlink(path);
|
||||
|
||||
fd = socket(PF_UNIX, SOCK_STREAM | O_CLOEXEC, 0);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open server socket");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, path);
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("Failed to bind server socket");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (listen(fd, 5) < 0) {
|
||||
perror("Failed to listen server socket");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainloop_add_fd(fd, EPOLLIN, server_accept_callback,
|
||||
NULL, NULL) < 0) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
server_fd = fd;
|
||||
}
|
||||
|
||||
void control_writer(const char *path)
|
||||
{
|
||||
btsnoop_create(path, BTSNOOP_TYPE_EXTENDED_HCI);
|
||||
}
|
||||
|
||||
void control_reader(const char *path)
|
||||
{
|
||||
unsigned char buf[MAX_PACKET_SIZE];
|
||||
uint16_t pktlen;
|
||||
uint32_t type;
|
||||
struct timeval tv;
|
||||
|
||||
if (btsnoop_open(path, &type) < 0)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case BTSNOOP_TYPE_HCI:
|
||||
case BTSNOOP_TYPE_UART:
|
||||
case BTSNOOP_TYPE_EXTENDED_PHY:
|
||||
packet_del_filter(PACKET_FILTER_SHOW_INDEX);
|
||||
break;
|
||||
|
||||
case BTSNOOP_TYPE_EXTENDED_HCI:
|
||||
packet_add_filter(PACKET_FILTER_SHOW_INDEX);
|
||||
break;
|
||||
}
|
||||
|
||||
open_pager();
|
||||
|
||||
switch (type) {
|
||||
case BTSNOOP_TYPE_HCI:
|
||||
case BTSNOOP_TYPE_UART:
|
||||
case BTSNOOP_TYPE_EXTENDED_HCI:
|
||||
while (1) {
|
||||
uint16_t index, opcode;
|
||||
|
||||
if (btsnoop_read_hci(&tv, &index, &opcode,
|
||||
buf, &pktlen) < 0)
|
||||
break;
|
||||
|
||||
packet_monitor(&tv, index, opcode, buf, pktlen);
|
||||
}
|
||||
break;
|
||||
|
||||
case BTSNOOP_TYPE_EXTENDED_PHY:
|
||||
while (1) {
|
||||
uint16_t frequency;
|
||||
|
||||
if (btsnoop_read_phy(&tv, &frequency,
|
||||
buf, &pktlen) < 0)
|
||||
break;
|
||||
|
||||
packet_simulator(&tv, frequency, buf, pktlen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
close_pager();
|
||||
|
||||
btsnoop_close();
|
||||
}
|
||||
|
||||
int control_tracing(void)
|
||||
{
|
||||
packet_add_filter(PACKET_FILTER_SHOW_INDEX);
|
||||
|
||||
if (server_fd >= 0)
|
||||
return 0;
|
||||
|
||||
if (open_channel(HCI_CHANNEL_MONITOR) < 0) {
|
||||
if (!hcidump_fallback)
|
||||
return -1;
|
||||
if (hcidump_tracing() < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
open_channel(HCI_CHANNEL_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
32
external/cache/sources/hcitools/monitor/control.h
vendored
Normal file
32
external/cache/sources/hcitools/monitor/control.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void control_writer(const char *path);
|
||||
void control_reader(const char *path);
|
||||
void control_server(const char *path);
|
||||
int control_tracing(void);
|
||||
|
||||
void control_message(uint16_t opcode, const void *data, uint16_t size);
|
||||
84
external/cache/sources/hcitools/monitor/crc.c
vendored
Normal file
84
external/cache/sources/hcitools/monitor/crc.c
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* 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 "crc.h"
|
||||
|
||||
uint32_t crc24_bit_reverse(uint32_t value)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 24; i++)
|
||||
result |= ((value >> i) & 1) << (23 - i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t crc24_calculate(uint32_t preset, const uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint32_t state = preset;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
uint8_t n, cur = data[i];
|
||||
|
||||
for (n = 0; n < 8; n++) {
|
||||
int next_bit = (state ^ cur) & 1;
|
||||
|
||||
cur >>= 1;
|
||||
state >>= 1;
|
||||
if (next_bit) {
|
||||
state |= 1 << 23;
|
||||
state ^= 0x5a6000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
uint32_t crc24_reverse(uint32_t crc, const uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint32_t state = crc;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
uint8_t n, cur = data[len - i - 1];
|
||||
|
||||
for (n = 0; n < 8; n++) {
|
||||
int top_bit = state >> 23;
|
||||
|
||||
state = (state << 1) & 0xffffff;
|
||||
state |= top_bit ^ ((cur >> (7 - n)) & 1);
|
||||
if (top_bit)
|
||||
state ^= 0xb4c000;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
30
external/cache/sources/hcitools/monitor/crc.h
vendored
Normal file
30
external/cache/sources/hcitools/monitor/crc.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t crc24_bit_reverse(uint32_t value);
|
||||
|
||||
uint32_t crc24_calculate(uint32_t preset, const uint8_t *data, uint8_t len);
|
||||
uint32_t crc24_reverse(uint32_t crc, const uint8_t *data, uint8_t len);
|
||||
171
external/cache/sources/hcitools/monitor/display.c
vendored
Normal file
171
external/cache/sources/hcitools/monitor/display.c
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "display.h"
|
||||
|
||||
static pid_t pager_pid = 0;
|
||||
|
||||
bool use_color(void)
|
||||
{
|
||||
static int cached_use_color = -1;
|
||||
|
||||
if (__builtin_expect(!!(cached_use_color < 0), 0))
|
||||
cached_use_color = isatty(STDOUT_FILENO) > 0 || pager_pid > 0;
|
||||
|
||||
return cached_use_color;
|
||||
}
|
||||
|
||||
int num_columns(void)
|
||||
{
|
||||
static int cached_num_columns = -1;
|
||||
|
||||
if (__builtin_expect(!!(cached_num_columns < 0), 0)) {
|
||||
struct winsize ws;
|
||||
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0)
|
||||
return -1;
|
||||
|
||||
if (ws.ws_col > 0)
|
||||
cached_num_columns = ws.ws_col;
|
||||
}
|
||||
|
||||
return cached_num_columns;
|
||||
}
|
||||
|
||||
static void close_pipe(int p[])
|
||||
{
|
||||
if (p[0] >= 0)
|
||||
close(p[0]);
|
||||
if (p[1] >= 0)
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
static void wait_for_terminate(pid_t pid)
|
||||
{
|
||||
siginfo_t dummy;
|
||||
|
||||
for (;;) {
|
||||
memset(&dummy, 0, sizeof(dummy));
|
||||
|
||||
if (waitid(P_PID, pid, &dummy, WEXITED) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void open_pager(void)
|
||||
{
|
||||
const char *pager;
|
||||
pid_t parent_pid;
|
||||
int fd[2];
|
||||
|
||||
if (pager_pid > 0)
|
||||
return;
|
||||
|
||||
pager = getenv("PAGER");
|
||||
if (pager) {
|
||||
if (!*pager || strcmp(pager, "cat") == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(isatty(STDOUT_FILENO) > 0))
|
||||
return;
|
||||
|
||||
num_columns();
|
||||
|
||||
if (pipe(fd) < 0) {
|
||||
perror("Failed to create pager pipe");
|
||||
return;
|
||||
}
|
||||
|
||||
parent_pid = getpid();
|
||||
|
||||
pager_pid = fork();
|
||||
if (pager_pid < 0) {
|
||||
perror("Failed to fork pager");
|
||||
close_pipe(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pager_pid == 0) {
|
||||
dup2(fd[0], STDIN_FILENO);
|
||||
close_pipe(fd);
|
||||
|
||||
setenv("LESS", "FRSX", 0);
|
||||
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (getppid() != parent_pid)
|
||||
_exit(EXIT_SUCCESS);
|
||||
|
||||
if (pager) {
|
||||
execlp(pager, pager, NULL);
|
||||
execl("/bin/sh", "sh", "-c", pager, NULL);
|
||||
}
|
||||
|
||||
execlp("pager", "pager", NULL);
|
||||
execlp("less", "less", NULL);
|
||||
execlp("more", "more", NULL);
|
||||
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (dup2(fd[1], STDOUT_FILENO) < 0) {
|
||||
perror("Failed to duplicate pager pipe");
|
||||
return;
|
||||
}
|
||||
|
||||
close_pipe(fd);
|
||||
}
|
||||
|
||||
void close_pager(void)
|
||||
{
|
||||
if (pager_pid <= 0)
|
||||
return;
|
||||
|
||||
fclose(stdout);
|
||||
kill(pager_pid, SIGCONT);
|
||||
wait_for_terminate(pager_pid);
|
||||
pager_pid = 0;
|
||||
}
|
||||
60
external/cache/sources/hcitools/monitor/display.h
vendored
Normal file
60
external/cache/sources/hcitools/monitor/display.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool use_color(void);
|
||||
|
||||
#define COLOR_OFF "\x1B[0m"
|
||||
#define COLOR_BLACK "\x1B[0;30m"
|
||||
#define COLOR_RED "\x1B[0;31m"
|
||||
#define COLOR_GREEN "\x1B[0;32m"
|
||||
#define COLOR_YELLOW "\x1B[0;33m"
|
||||
#define COLOR_BLUE "\x1B[0;34m"
|
||||
#define COLOR_MAGENTA "\x1B[0;35m"
|
||||
#define COLOR_CYAN "\x1B[0;36m"
|
||||
#define COLOR_WHITE "\x1B[0;37m"
|
||||
#define COLOR_WHITE_BG "\x1B[0;47m"
|
||||
#define COLOR_HIGHLIGHT "\x1B[1;39m"
|
||||
|
||||
#define COLOR_ERROR "\x1B[1;31m"
|
||||
|
||||
#define print_indent(indent, color1, prefix, title, color2, fmt, args...) \
|
||||
do { \
|
||||
printf("%*c%s%s%s%s" fmt "%s\n", (indent), ' ', \
|
||||
use_color() ? (color1) : "", prefix, title, \
|
||||
use_color() ? (color2) : "", ## args, \
|
||||
use_color() ? COLOR_OFF : ""); \
|
||||
} while (0)
|
||||
|
||||
#define print_text(color, fmt, args...) \
|
||||
print_indent(8, COLOR_OFF, "", "", color, fmt, ## args)
|
||||
|
||||
#define print_field(fmt, args...) \
|
||||
print_indent(8, COLOR_OFF, "", "", COLOR_OFF, fmt, ## args)
|
||||
|
||||
int num_columns(void);
|
||||
|
||||
void open_pager(void);
|
||||
void close_pager(void);
|
||||
411
external/cache/sources/hcitools/monitor/hcidump.c
vendored
Normal file
411
external/cache/sources/hcitools/monitor/hcidump.c
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_lib.h>
|
||||
|
||||
#include "mainloop.h"
|
||||
#include "packet.h"
|
||||
#include "hcidump.h"
|
||||
|
||||
struct hcidump_data {
|
||||
uint16_t index;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static void free_data(void *user_data)
|
||||
{
|
||||
struct hcidump_data *data = user_data;
|
||||
|
||||
close(data->fd);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
static int open_hci_dev(uint16_t index)
|
||||
{
|
||||
struct sockaddr_hci addr;
|
||||
struct hci_filter flt;
|
||||
int fd, opt = 1;
|
||||
|
||||
fd = socket(AF_BLUETOOTH, SOCK_RAW | O_CLOEXEC, BTPROTO_HCI);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open channel");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup filter */
|
||||
hci_filter_clear(&flt);
|
||||
hci_filter_all_ptypes(&flt);
|
||||
hci_filter_all_events(&flt);
|
||||
|
||||
if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
|
||||
perror("Failed to set HCI filter");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
|
||||
perror("Failed to enable HCI data direction info");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
|
||||
perror("Failed to enable HCI time stamps");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.hci_family = AF_BLUETOOTH;
|
||||
addr.hci_dev = index;
|
||||
addr.hci_channel = HCI_CHANNEL_RAW;
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("Failed to bind channel");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void device_callback(int fd, uint32_t events, void *user_data)
|
||||
{
|
||||
struct hcidump_data *data = user_data;
|
||||
unsigned char buf[HCI_MAX_FRAME_SIZE * 2];
|
||||
unsigned char control[64];
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
|
||||
if (events & (EPOLLERR | EPOLLHUP)) {
|
||||
mainloop_remove_fd(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof(control);
|
||||
|
||||
while (1) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct timeval *tv = NULL;
|
||||
struct timeval ctv;
|
||||
int dir = -1;
|
||||
ssize_t len;
|
||||
|
||||
len = recvmsg(fd, &msg, MSG_DONTWAIT);
|
||||
if (len < 0)
|
||||
break;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_HCI)
|
||||
continue;
|
||||
|
||||
switch (cmsg->cmsg_type) {
|
||||
case HCI_DATA_DIR:
|
||||
memcpy(&dir, CMSG_DATA(cmsg), sizeof(dir));
|
||||
break;
|
||||
case HCI_CMSG_TSTAMP:
|
||||
memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));
|
||||
tv = &ctv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dir < 0 || len < 1)
|
||||
continue;
|
||||
|
||||
switch (buf[0]) {
|
||||
case HCI_COMMAND_PKT:
|
||||
packet_hci_command(tv, data->index, buf + 1, len - 1);
|
||||
break;
|
||||
case HCI_EVENT_PKT:
|
||||
packet_hci_event(tv, data->index, buf + 1, len - 1);
|
||||
break;
|
||||
case HCI_ACLDATA_PKT:
|
||||
packet_hci_acldata(tv, data->index, !!dir,
|
||||
buf + 1, len - 1);
|
||||
break;
|
||||
case HCI_SCODATA_PKT:
|
||||
packet_hci_scodata(tv, data->index, !!dir,
|
||||
buf + 1, len - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void open_device(uint16_t index)
|
||||
{
|
||||
struct hcidump_data *data;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->index = index;
|
||||
|
||||
data->fd = open_hci_dev(index);
|
||||
if (data->fd < 0) {
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
mainloop_add_fd(data->fd, EPOLLIN, device_callback, data, free_data);
|
||||
}
|
||||
|
||||
static void device_info(int fd, uint16_t index, uint8_t *type, uint8_t *bus,
|
||||
bdaddr_t *bdaddr, char *name)
|
||||
{
|
||||
struct hci_dev_info di;
|
||||
|
||||
memset(&di, 0, sizeof(di));
|
||||
di.dev_id = index;
|
||||
|
||||
if (ioctl(fd, HCIGETDEVINFO, (void *) &di) < 0) {
|
||||
perror("Failed to get device information");
|
||||
return;
|
||||
}
|
||||
|
||||
*type = di.type >> 4;
|
||||
*bus = di.type & 0x0f;
|
||||
|
||||
bacpy(bdaddr, &di.bdaddr);
|
||||
memcpy(name, di.name, 8);
|
||||
}
|
||||
|
||||
static void device_list(int fd, int max_dev)
|
||||
{
|
||||
struct hci_dev_list_req *dl;
|
||||
struct hci_dev_req *dr;
|
||||
int i;
|
||||
|
||||
dl = malloc(max_dev * sizeof(*dr) + sizeof(*dl));
|
||||
if (!dl) {
|
||||
perror("Failed to allocate device list memory");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(dl, 0, max_dev * sizeof(*dr) + sizeof(*dl));
|
||||
dl->dev_num = max_dev;
|
||||
|
||||
dr = dl->dev_req;
|
||||
|
||||
if (ioctl(fd, HCIGETDEVLIST, (void *) dl) < 0) {
|
||||
perror("Failed to get device list");
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < dl->dev_num; i++, dr++) {
|
||||
struct timeval tmp_tv, *tv = NULL;
|
||||
uint8_t type = 0xff, bus = 0xff;
|
||||
char str[18], name[8] = "";
|
||||
bdaddr_t bdaddr;
|
||||
|
||||
bacpy(&bdaddr, BDADDR_ANY);
|
||||
|
||||
if (!gettimeofday(&tmp_tv, NULL))
|
||||
tv = &tmp_tv;
|
||||
|
||||
device_info(fd, dr->dev_id, &type, &bus, &bdaddr, name);
|
||||
ba2str(&bdaddr, str);
|
||||
packet_new_index(tv, dr->dev_id, str, type, bus, name);
|
||||
open_device(dr->dev_id);
|
||||
}
|
||||
|
||||
done:
|
||||
free(dl);
|
||||
}
|
||||
|
||||
static int open_stack_internal(void)
|
||||
{
|
||||
struct sockaddr_hci addr;
|
||||
struct hci_filter flt;
|
||||
int fd, opt = 1;
|
||||
|
||||
fd = socket(AF_BLUETOOTH, SOCK_RAW | O_CLOEXEC, BTPROTO_HCI);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open channel");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup filter */
|
||||
hci_filter_clear(&flt);
|
||||
hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
|
||||
hci_filter_set_event(EVT_STACK_INTERNAL, &flt);
|
||||
|
||||
if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
|
||||
perror("Failed to set HCI filter");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
|
||||
perror("Failed to enable HCI time stamps");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.hci_family = AF_BLUETOOTH;
|
||||
addr.hci_dev = HCI_DEV_NONE;
|
||||
addr.hci_channel = HCI_CHANNEL_RAW;
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("Failed to bind channel");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_list(fd, HCI_MAX_DEV);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void stack_internal_callback(int fd, uint32_t events, void *user_data)
|
||||
{
|
||||
unsigned char buf[HCI_MAX_FRAME_SIZE];
|
||||
unsigned char control[32];
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
struct cmsghdr *cmsg;
|
||||
ssize_t len;
|
||||
hci_event_hdr *eh;
|
||||
evt_stack_internal *si;
|
||||
evt_si_device *sd;
|
||||
struct timeval *tv = NULL;
|
||||
struct timeval ctv;
|
||||
uint8_t type = 0xff, bus = 0xff;
|
||||
char str[18], name[8] = "";
|
||||
bdaddr_t bdaddr;
|
||||
|
||||
bacpy(&bdaddr, BDADDR_ANY);
|
||||
|
||||
if (events & (EPOLLERR | EPOLLHUP)) {
|
||||
mainloop_remove_fd(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof(control);
|
||||
|
||||
len = recvmsg(fd, &msg, MSG_DONTWAIT);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_HCI)
|
||||
continue;
|
||||
|
||||
switch (cmsg->cmsg_type) {
|
||||
case HCI_CMSG_TSTAMP:
|
||||
memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));
|
||||
tv = &ctv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len < 1 + HCI_EVENT_HDR_SIZE + EVT_STACK_INTERNAL_SIZE +
|
||||
EVT_SI_DEVICE_SIZE)
|
||||
return;
|
||||
|
||||
if (buf[0] != HCI_EVENT_PKT)
|
||||
return;
|
||||
|
||||
eh = (hci_event_hdr *) (buf + 1);
|
||||
if (eh->evt != EVT_STACK_INTERNAL)
|
||||
return;
|
||||
|
||||
si = (evt_stack_internal *) (buf + 1 + HCI_EVENT_HDR_SIZE);
|
||||
if (si->type != EVT_SI_DEVICE)
|
||||
return;
|
||||
|
||||
sd = (evt_si_device *) &si->data;
|
||||
|
||||
switch (sd->event) {
|
||||
case HCI_DEV_REG:
|
||||
device_info(fd, sd->dev_id, &type, &bus, &bdaddr, name);
|
||||
ba2str(&bdaddr, str);
|
||||
packet_new_index(tv, sd->dev_id, str, type, bus, name);
|
||||
open_device(sd->dev_id);
|
||||
break;
|
||||
case HCI_DEV_UNREG:
|
||||
ba2str(&bdaddr, str);
|
||||
packet_del_index(tv, sd->dev_id, str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int hcidump_tracing(void)
|
||||
{
|
||||
struct hcidump_data *data;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->index = HCI_DEV_NONE;
|
||||
|
||||
data->fd = open_stack_internal();
|
||||
if (data->fd < 0) {
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mainloop_add_fd(data->fd, EPOLLIN, stack_internal_callback,
|
||||
data, free_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
25
external/cache/sources/hcitools/monitor/hcidump.h
vendored
Normal file
25
external/cache/sources/hcitools/monitor/hcidump.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
int hcidump_tracing(void);
|
||||
2690
external/cache/sources/hcitools/monitor/l2cap.c
vendored
Normal file
2690
external/cache/sources/hcitools/monitor/l2cap.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
61
external/cache/sources/hcitools/monitor/l2cap.h
vendored
Normal file
61
external/cache/sources/hcitools/monitor/l2cap.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct l2cap_frame {
|
||||
uint16_t index;
|
||||
bool in;
|
||||
uint16_t handle;
|
||||
uint16_t cid;
|
||||
const void *data;
|
||||
uint16_t size;
|
||||
};
|
||||
|
||||
static inline void l2cap_frame_init(struct l2cap_frame *frame,
|
||||
uint16_t index, bool in, uint16_t handle,
|
||||
uint16_t cid, const void *data, uint16_t size)
|
||||
{
|
||||
frame->index = index;
|
||||
frame->in = in;
|
||||
frame->handle = handle;
|
||||
frame->cid = cid;
|
||||
frame->data = data;
|
||||
frame->size = size;
|
||||
}
|
||||
|
||||
static inline void l2cap_frame_pull(struct l2cap_frame *frame,
|
||||
const struct l2cap_frame *source, uint16_t len)
|
||||
{
|
||||
frame->index = source->index;
|
||||
frame->in = source->in;
|
||||
frame->handle = source->handle;
|
||||
frame->cid = source->cid;
|
||||
frame->data = source->data + len;
|
||||
frame->size = source->size - len;
|
||||
}
|
||||
|
||||
void l2cap_packet(uint16_t index, bool in, uint16_t handle, uint8_t flags,
|
||||
const void *data, uint16_t size);
|
||||
549
external/cache/sources/hcitools/monitor/ll.c
vendored
Normal file
549
external/cache/sources/hcitools/monitor/ll.c
vendored
Normal file
@@ -0,0 +1,549 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <inttypes.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "packet.h"
|
||||
#include "crc.h"
|
||||
#include "bt.h"
|
||||
#include "ll.h"
|
||||
|
||||
#define COLOR_OPCODE COLOR_MAGENTA
|
||||
#define COLOR_OPCODE_UNKNOWN COLOR_WHITE_BG
|
||||
|
||||
#define MAX_CHANNEL 16
|
||||
|
||||
struct channel_data {
|
||||
uint32_t access_addr;
|
||||
uint32_t crc_init;
|
||||
};
|
||||
|
||||
static struct channel_data channel_list[MAX_CHANNEL];
|
||||
|
||||
static void set_crc_init(uint32_t access_addr, uint32_t crc_init)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CHANNEL; i++) {
|
||||
if (channel_list[i].access_addr == 0x00000000 ||
|
||||
channel_list[i].access_addr == access_addr) {
|
||||
channel_list[i].access_addr = access_addr;
|
||||
channel_list[i].crc_init = crc_init;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_crc_init(uint32_t access_addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CHANNEL; i++) {
|
||||
if (channel_list[i].access_addr == access_addr)
|
||||
return channel_list[i].crc_init;
|
||||
}
|
||||
|
||||
return 0x00000000;
|
||||
}
|
||||
|
||||
static void advertising_packet(const void *data, uint8_t size)
|
||||
{
|
||||
const uint8_t *ptr = data;
|
||||
uint8_t pdu_type, length, win_size, hop, sca;
|
||||
bool tx_add, rx_add;
|
||||
uint32_t access_addr, crc_init;
|
||||
uint16_t win_offset, interval, latency, timeout;
|
||||
const char *str;
|
||||
|
||||
if (size < 2) {
|
||||
print_text(COLOR_ERROR, "packet too short");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
pdu_type = ptr[0] & 0x0f;
|
||||
tx_add = !!(ptr[0] & 0x40);
|
||||
rx_add = !!(ptr[0] & 0x80);
|
||||
length = ptr[1] & 0x3f;
|
||||
|
||||
switch (pdu_type) {
|
||||
case 0x00:
|
||||
str = "ADV_IND";
|
||||
break;
|
||||
case 0x01:
|
||||
str = "ADV_DIRECT_IND";
|
||||
break;
|
||||
case 0x02:
|
||||
str = "ADV_NONCONN_IND";
|
||||
break;
|
||||
case 0x03:
|
||||
str = "SCAN_REQ";
|
||||
break;
|
||||
case 0x04:
|
||||
str = "SCAN_RSP";
|
||||
break;
|
||||
case 0x05:
|
||||
str = "CONNECT_REQ";
|
||||
break;
|
||||
case 0x06:
|
||||
str = "ADV_SCAN_IND";
|
||||
break;
|
||||
default:
|
||||
str = "Reserved";
|
||||
break;
|
||||
}
|
||||
|
||||
print_field("Type: %s (0x%2.2x)", str, pdu_type);
|
||||
print_field("TxAdd: %u", tx_add);
|
||||
print_field("RxAdd: %u", rx_add);
|
||||
print_field("Length: %u", length);
|
||||
|
||||
if (length != size - 2) {
|
||||
print_text(COLOR_ERROR, "packet size mismatch");
|
||||
packet_hexdump(data + 2, size - 2);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pdu_type) {
|
||||
case 0x00: /* ADV_IND */
|
||||
case 0x02: /* AVD_NONCONN_IND */
|
||||
case 0x06: /* ADV_SCAN_IND */
|
||||
case 0x04: /* SCAN_RSP */
|
||||
if (length < 6) {
|
||||
print_text(COLOR_ERROR, "payload too short");
|
||||
packet_hexdump(data + 2, length);
|
||||
return;
|
||||
}
|
||||
|
||||
packet_print_addr("Advertiser address", data + 2, tx_add);
|
||||
packet_print_ad(data + 8, length - 6);
|
||||
break;
|
||||
|
||||
case 0x01: /* ADV_DIRECT_IND */
|
||||
if (length < 12) {
|
||||
print_text(COLOR_ERROR, "payload too short");
|
||||
packet_hexdump(data + 2, length);
|
||||
return;
|
||||
}
|
||||
|
||||
packet_print_addr("Advertiser address", data + 2, tx_add);
|
||||
packet_print_addr("Inititator address", data + 8, rx_add);
|
||||
break;
|
||||
|
||||
case 0x03: /* SCAN_REQ */
|
||||
if (length < 12) {
|
||||
print_text(COLOR_ERROR, "payload too short");
|
||||
packet_hexdump(data + 2, length);
|
||||
return;
|
||||
}
|
||||
|
||||
packet_print_addr("Scanner address", data + 2, tx_add);
|
||||
packet_print_addr("Advertiser address", data + 8, rx_add);
|
||||
break;
|
||||
|
||||
case 0x05: /* CONNECT_REQ */
|
||||
if (length < 34) {
|
||||
print_text(COLOR_ERROR, "payload too short");
|
||||
packet_hexdump(data + 2, length);
|
||||
return;
|
||||
}
|
||||
|
||||
packet_print_addr("Inititator address", data + 2, tx_add);
|
||||
packet_print_addr("Advertiser address", data + 8, rx_add);
|
||||
|
||||
access_addr = ptr[14] | ptr[15] << 8 |
|
||||
ptr[16] << 16 | ptr[17] << 24;
|
||||
crc_init = ptr[18] | ptr[19] << 8 | ptr[20] << 16;
|
||||
|
||||
print_field("Access address: 0x%8.8x", access_addr);
|
||||
print_field("CRC init: 0x%6.6x", crc_init);
|
||||
|
||||
set_crc_init(access_addr, crc24_bit_reverse(crc_init));
|
||||
|
||||
win_size = ptr[21];
|
||||
win_offset = ptr[22] | ptr[23] << 8;
|
||||
interval = ptr[24] | ptr[25] << 8;
|
||||
latency = ptr[26] | ptr[27] << 8;
|
||||
timeout = ptr[28] | ptr[29] << 8;
|
||||
|
||||
print_field("Transmit window size: %u", win_size);
|
||||
print_field("Transmit window offset: %u", win_offset);
|
||||
print_field("Connection interval: %u", interval);
|
||||
print_field("Connection slave latency: %u", latency);
|
||||
print_field("Connection supervision timeout: %u", timeout);
|
||||
|
||||
packet_print_channel_map_ll(ptr + 30);
|
||||
|
||||
hop = ptr[35] & 0x1f;
|
||||
sca = (ptr[35] & 0xe0) >> 5;
|
||||
|
||||
switch (sca) {
|
||||
case 0:
|
||||
str = "251 ppm to 500 ppm";
|
||||
break;
|
||||
case 1:
|
||||
str = "151 ppm to 250 ppm";
|
||||
break;
|
||||
case 2:
|
||||
str = "101 ppm to 150ppm";
|
||||
break;
|
||||
case 3:
|
||||
str = "76 ppm to 100 ppm";
|
||||
break;
|
||||
case 4:
|
||||
str = "51 ppm to 75 ppm";
|
||||
break;
|
||||
case 5:
|
||||
str = "31 ppm to 50 ppm";
|
||||
break;
|
||||
case 6:
|
||||
str = "21 ppm to 30 ppm";
|
||||
break;
|
||||
case 7:
|
||||
str = "0 ppm to 20 ppm";
|
||||
break;
|
||||
default:
|
||||
str = "Invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
print_field("Hop increment: %u", hop);
|
||||
print_field("Sleep clock accuracy: %s (%u)", str, sca);
|
||||
break;
|
||||
|
||||
default:
|
||||
packet_hexdump(data + 2, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void data_packet(const void *data, uint8_t size)
|
||||
{
|
||||
const uint8_t *ptr = data;
|
||||
uint8_t llid, length;
|
||||
bool nesn, sn, md;
|
||||
const char *str;
|
||||
|
||||
if (size < 2) {
|
||||
print_text(COLOR_ERROR, "packet too short");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
llid = ptr[0] & 0x03;
|
||||
nesn = !!(ptr[0] & 0x04);
|
||||
sn = !!(ptr[0] & 0x08);
|
||||
md = !!(ptr[0] & 0x10);
|
||||
length = ptr[1] & 0x1f;
|
||||
|
||||
switch (llid) {
|
||||
case 0x01:
|
||||
if (length > 0)
|
||||
str = "Continuation fragement of L2CAP message";
|
||||
else
|
||||
str = "Empty message";
|
||||
break;
|
||||
case 0x02:
|
||||
str = "Start of L2CAP message";
|
||||
break;
|
||||
case 0x03:
|
||||
str = "Control";
|
||||
break;
|
||||
default:
|
||||
str = "Reserved";
|
||||
break;
|
||||
}
|
||||
|
||||
print_field("LLID: %s (0x%2.2x)", str, llid);
|
||||
print_field("Next expected sequence number: %u", nesn);
|
||||
print_field("Sequence number: %u", sn);
|
||||
print_field("More data: %u", md);
|
||||
print_field("Length: %u", length);
|
||||
|
||||
switch (llid) {
|
||||
case 0x03:
|
||||
llcp_packet(data + 2, size - 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
packet_hexdump(data + 2, size - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ll_packet(uint16_t frequency, const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_hdr *hdr = data;
|
||||
uint8_t channel = (frequency - 2402) / 2;
|
||||
uint32_t access_addr;
|
||||
char access_str[12];
|
||||
const char *channel_label, *channel_color;
|
||||
const uint8_t *pdu_data;
|
||||
uint8_t pdu_len;
|
||||
uint32_t pdu_crc, crc, crc_init;
|
||||
|
||||
if (size < sizeof(*hdr)) {
|
||||
print_text(COLOR_ERROR, "packet missing header");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (size < sizeof(*hdr) + 3) {
|
||||
print_text(COLOR_ERROR, "packet missing checksum");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hdr->preamble != 0xaa && hdr->preamble != 0x55) {
|
||||
print_text(COLOR_ERROR, "invalid preamble");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
access_addr = btohl(hdr->access_addr);
|
||||
|
||||
pdu_data = data + sizeof(*hdr);
|
||||
pdu_len = size - sizeof(*hdr) - 3;
|
||||
|
||||
pdu_crc = pdu_data[pdu_len + 0] | (pdu_data[pdu_len + 1] << 8) |
|
||||
(pdu_data[pdu_len + 2] << 16);
|
||||
|
||||
if (access_addr == 0x8e89bed6) {
|
||||
channel_label = "Advertising channel: ";
|
||||
channel_color = COLOR_MAGENTA;
|
||||
} else {
|
||||
channel_label = "Data channel: ";
|
||||
channel_color = COLOR_CYAN;
|
||||
}
|
||||
|
||||
sprintf(access_str, "0x%8.8x", access_addr);
|
||||
|
||||
print_indent(6, channel_color, channel_label, access_str, COLOR_OFF,
|
||||
" (channel %d) len %d crc 0x%6.6x", channel, pdu_len, pdu_crc);
|
||||
|
||||
if (access_addr == 0x8e89bed6)
|
||||
crc_init = 0xaaaaaa;
|
||||
else
|
||||
crc_init = get_crc_init(access_addr);
|
||||
|
||||
if (crc_init) {
|
||||
crc = crc24_calculate(crc_init, pdu_data, pdu_len);
|
||||
|
||||
if (crc != pdu_crc) {
|
||||
print_text(COLOR_ERROR, "invalid checksum");
|
||||
packet_hexdump(pdu_data, pdu_len);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
print_text(COLOR_ERROR, "unknown access address");
|
||||
|
||||
if (access_addr == 0x8e89bed6)
|
||||
advertising_packet(pdu_data, pdu_len);
|
||||
else
|
||||
data_packet(pdu_data, pdu_len);
|
||||
}
|
||||
|
||||
static void null_pdu(const void *data, uint8_t size)
|
||||
{
|
||||
}
|
||||
|
||||
static void conn_update_req(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_conn_update_req *pdu = data;
|
||||
|
||||
print_field("Transmit window size: %u", pdu->win_size);
|
||||
print_field("Transmit window offset: %u", btohs(pdu->win_offset));
|
||||
print_field("Connection interval: %u", btohs(pdu->interval));
|
||||
print_field("Connection slave latency: %u", btohs(pdu->latency));
|
||||
print_field("Connection supervision timeout: %u", btohs(pdu->timeout));;
|
||||
print_field("Connection instant: %u", btohs(pdu->instant));
|
||||
}
|
||||
|
||||
static void channel_map_req(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_channel_map_req *pdu = data;
|
||||
|
||||
packet_print_channel_map_ll(pdu->map);
|
||||
print_field("Connection instant: %u", btohs(pdu->instant));
|
||||
}
|
||||
|
||||
static void terminate_ind(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_terminate_ind *pdu = data;
|
||||
|
||||
print_field("Error code: 0x%2.2x", pdu->error);
|
||||
}
|
||||
|
||||
static void enc_req(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_enc_req *pdu = data;
|
||||
|
||||
print_field("Rand: 0x%16.16" PRIx64, btohll(pdu->rand));
|
||||
print_field("EDIV: 0x%4.4x", btohs(pdu->ediv));
|
||||
print_field("SKD (master): 0x%16.16" PRIx64, btohll(pdu->skd));
|
||||
print_field("IV (master): 0x%8.8x", btohl(pdu->iv));
|
||||
}
|
||||
|
||||
static void enc_rsp(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_enc_rsp *pdu = data;
|
||||
|
||||
print_field("SKD (slave): 0x%16.16" PRIx64, btohll(pdu->skd));
|
||||
print_field("IV (slave): 0x%8.8x", btohl(pdu->iv));
|
||||
}
|
||||
|
||||
static const char *opcode_to_string(uint8_t opcode);
|
||||
|
||||
static void unknown_rsp(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_unknown_rsp *pdu = data;
|
||||
|
||||
print_field("Unknown type: %s (0x%2.2x)",
|
||||
opcode_to_string(pdu->type), pdu->type);
|
||||
}
|
||||
|
||||
static void feature_req(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_feature_req *pdu = data;
|
||||
|
||||
packet_print_features_ll(pdu->features);
|
||||
}
|
||||
|
||||
static void feature_rsp(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_feature_rsp *pdu = data;
|
||||
|
||||
packet_print_features_ll(pdu->features);
|
||||
}
|
||||
|
||||
static void version_ind(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_version_ind *pdu = data;
|
||||
|
||||
packet_print_version("Version", pdu->version,
|
||||
"Subversion", btohs(pdu->subversion));
|
||||
packet_print_company("Company", btohs(pdu->company));
|
||||
}
|
||||
|
||||
static void reject_ind(const void *data, uint8_t size)
|
||||
{
|
||||
const struct bt_ll_reject_ind *pdu = data;
|
||||
|
||||
print_field("Error code: 0x%2.2x", pdu->error);
|
||||
}
|
||||
|
||||
struct llcp_data {
|
||||
uint8_t opcode;
|
||||
const char *str;
|
||||
void (*func) (const void *data, uint8_t size);
|
||||
uint8_t size;
|
||||
bool fixed;
|
||||
};
|
||||
|
||||
static const struct llcp_data llcp_table[] = {
|
||||
{ 0x00, "LL_CONNECTION_UPDATE_REQ", conn_update_req, 11, true },
|
||||
{ 0x01, "LL_CHANNEL_MAP_REQ", channel_map_req, 7, true },
|
||||
{ 0x02, "LL_TERMINATE_IND", terminate_ind, 1, true },
|
||||
{ 0x03, "LL_ENC_REQ", enc_req, 22, true },
|
||||
{ 0x04, "LL_ENC_RSP", enc_rsp, 12, true },
|
||||
{ 0x05, "LL_START_ENC_REQ", null_pdu, 0, true },
|
||||
{ 0x06, "LL_START_ENC_RSP", null_pdu, 0, true },
|
||||
{ 0x07, "LL_UNKNOWN_RSP", unknown_rsp, 1, true },
|
||||
{ 0x08, "LL_FEATURE_REQ", feature_req, 8, true },
|
||||
{ 0x09, "LL_FEATURE_RSP", feature_rsp, 8, true },
|
||||
{ 0x0a, "LL_PAUSE_ENC_REQ", null_pdu, 0, true },
|
||||
{ 0x0b, "LL_PAUSE_ENC_RSP", null_pdu, 0, true },
|
||||
{ 0x0c, "LL_VERSION_IND", version_ind, 5, true },
|
||||
{ 0x0d, "LL_REJECT_IND", reject_ind, 1, true },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const char *opcode_to_string(uint8_t opcode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; llcp_table[i].str; i++) {
|
||||
if (llcp_table[i].opcode == opcode)
|
||||
return llcp_table[i].str;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void llcp_packet(const void *data, uint8_t size)
|
||||
{
|
||||
uint8_t opcode = ((const uint8_t *) data)[0];
|
||||
const struct llcp_data *llcp_data = NULL;
|
||||
const char *opcode_color, *opcode_str;
|
||||
int i;
|
||||
|
||||
for (i = 0; llcp_table[i].str; i++) {
|
||||
if (llcp_table[i].opcode == opcode) {
|
||||
llcp_data = &llcp_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (llcp_data) {
|
||||
if (llcp_data->func)
|
||||
opcode_color = COLOR_OPCODE;
|
||||
else
|
||||
opcode_color = COLOR_OPCODE_UNKNOWN;
|
||||
opcode_str = llcp_data->str;
|
||||
} else {
|
||||
opcode_color = COLOR_OPCODE_UNKNOWN;
|
||||
opcode_str = "Unknown";
|
||||
}
|
||||
|
||||
print_indent(6, opcode_color, "", opcode_str, COLOR_OFF,
|
||||
" (0x%2.2x)", opcode);
|
||||
|
||||
if (!llcp_data || !llcp_data->func) {
|
||||
packet_hexdump(data + 1, size - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (llcp_data->fixed) {
|
||||
if (size - 1 != llcp_data->size) {
|
||||
print_text(COLOR_ERROR, "invalid packet size");
|
||||
packet_hexdump(data + 1, size - 1);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (size - 1 < llcp_data->size) {
|
||||
print_text(COLOR_ERROR, "too short packet");
|
||||
packet_hexdump(data + 1, size - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
llcp_data->func(data + 1, size - 1);
|
||||
}
|
||||
28
external/cache/sources/hcitools/monitor/ll.h
vendored
Normal file
28
external/cache/sources/hcitools/monitor/ll.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void ll_packet(uint16_t frequency, const void *data, uint8_t size);
|
||||
void llcp_packet(const void *data, uint8_t size);
|
||||
215
external/cache/sources/hcitools/monitor/lmp.c
vendored
Normal file
215
external/cache/sources/hcitools/monitor/lmp.c
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 "display.h"
|
||||
#include "packet.h"
|
||||
#include "lmp.h"
|
||||
|
||||
#define COLOR_OPCODE COLOR_MAGENTA
|
||||
#define COLOR_OPCODE_UNKNOWN COLOR_WHITE_BG
|
||||
|
||||
#define ESC4(x) ((127 << 8) | (x))
|
||||
|
||||
struct lmp_data {
|
||||
uint16_t opcode;
|
||||
const char *str;
|
||||
void (*func) (const void *data, uint8_t size);
|
||||
uint8_t size;
|
||||
bool fixed;
|
||||
};
|
||||
|
||||
static const struct lmp_data lmp_table[] = {
|
||||
{ 1, "LMP_name_req" },
|
||||
{ 2, "LMP_name_res" },
|
||||
{ 3, "LMP_accepted" },
|
||||
{ 4, "LMP_not_accepted" },
|
||||
{ 5, "LMP_clkoffset_req" },
|
||||
{ 6, "LMP_clkoffset_res" },
|
||||
{ 7, "LMP_detach" },
|
||||
{ 8, "LMP_in_rand" },
|
||||
{ 9, "LMP_comb_key" },
|
||||
{ 10, "LMP_unit_key" },
|
||||
{ 11, "LMP_au_rand" },
|
||||
{ 12, "LMP_sres" },
|
||||
{ 13, "LMP_temp_rand" },
|
||||
{ 14, "LMP_temp_key" },
|
||||
{ 15, "LMP_encryption_mode_req" },
|
||||
{ 16, "LMP_encryption_key_size_req" },
|
||||
{ 17, "LMP_start_encryption_req" },
|
||||
{ 18, "LMP_stop_encryption_req" },
|
||||
{ 19, "LMP_switch_req" },
|
||||
{ 20, "LMP_hold" },
|
||||
{ 21, "LMP_hold_req" },
|
||||
{ 22, "LMP_sniff" },
|
||||
{ 23, "LMP_sniff_req" },
|
||||
{ 24, "LMP_unsniff_req" },
|
||||
{ 25, "LMP_park_req" },
|
||||
{ 26, "LMP_park" },
|
||||
{ 27, "LMP_set_broadcast_scan_window" },
|
||||
{ 28, "LMP_modify_beacon" },
|
||||
{ 29, "LMP_unpark_BD_ADDR_req" },
|
||||
{ 30, "LMP_unpark_PM_ADDR_req" },
|
||||
{ 31, "LMP_incr_power_req" },
|
||||
{ 32, "LMP_decr_power_req" },
|
||||
{ 33, "LMP_max_power" },
|
||||
{ 34, "LMP_min_power" },
|
||||
{ 35, "LMP_auto_rate" },
|
||||
{ 36, "LMP_preferred_rate" },
|
||||
{ 37, "LMP_version_req" },
|
||||
{ 38, "LMP_version_res" },
|
||||
{ 39, "LMP_features_req" },
|
||||
{ 40, "LMP_features_res" },
|
||||
{ 41, "LMP_quality_of_service" },
|
||||
{ 42, "LMP_quality_of_service_req" },
|
||||
{ 43, "LMP_SCO_link_req" },
|
||||
{ 44, "LMP_remove_SCO_link_req" },
|
||||
{ 45, "LMP_max_slot" },
|
||||
{ 46, "LMP_max_slot_req" },
|
||||
{ 47, "LMP_timing_accuracy_req" },
|
||||
{ 48, "LMP_timing_accuracy_res" },
|
||||
{ 49, "LMP_setup_complete" },
|
||||
{ 50, "LMP_use_semi_permanent_key" },
|
||||
{ 51, "LMP_host_connection_req" },
|
||||
{ 52, "LMP_slot_offset" },
|
||||
{ 53, "LMP_page_mode_req" },
|
||||
{ 54, "LMP_Page_scan_mode_req" },
|
||||
{ 55, "LMP_supervision_timeout" },
|
||||
{ 56, "LMP_test_activate" },
|
||||
{ 57, "LMP_test_control" },
|
||||
{ 58, "LMP_encryption_key_size_mask_req" },
|
||||
{ 59, "LMP_encryption_key_size_mask_res" },
|
||||
{ 60, "LMP_set_AFH" },
|
||||
{ 61, "LMP_encapsulated_header" },
|
||||
{ 62, "LMP_encapsulated_payload" },
|
||||
{ 63, "LMP_simple_pairing_confirm" },
|
||||
{ 64, "LMP_simple_pairing_number" },
|
||||
{ 65, "LMP_DHkey_check" },
|
||||
{ 66, "LMP_pause_encryption_aes_req" },
|
||||
{ ESC4(1), "LMP_accepted_ext" },
|
||||
{ ESC4(2), "LMP_not_accepted_ext" },
|
||||
{ ESC4(3), "LMP_features_req_ext" },
|
||||
{ ESC4(4), "LMP_features_res_ext" },
|
||||
{ ESC4(5), "LMP_clk_adj" },
|
||||
{ ESC4(6), "LMP_clk_adj_ack" },
|
||||
{ ESC4(7), "LMP_clk_adj_req" },
|
||||
{ ESC4(11), "LMP_packet_type_table" },
|
||||
{ ESC4(12), "LMP_eSCO_link_req" },
|
||||
{ ESC4(13), "LMP_remove_eSCO_link_req" },
|
||||
{ ESC4(16), "LMP_channel_classification_req" },
|
||||
{ ESC4(17), "LMP_channel_classification" },
|
||||
{ ESC4(21), "LMP_sniff_subrating_req" },
|
||||
{ ESC4(22), "LMP_sniff_subrating_res" },
|
||||
{ ESC4(23), "LMP_pause_encryption_req" },
|
||||
{ ESC4(24), "LMP_resume_encryption_req" },
|
||||
{ ESC4(25), "LMP_IO_capability_req" },
|
||||
{ ESC4(26), "LMP_IO_capability_res" },
|
||||
{ ESC4(27), "LMP_numeric_comparision_failed" },
|
||||
{ ESC4(28), "LMP_passkey_failed" },
|
||||
{ ESC4(29), "LMP_oob_failed" },
|
||||
{ ESC4(30), "LMP_keypress_notification" },
|
||||
{ ESC4(31), "LMP_power_control_req" },
|
||||
{ ESC4(32), "LMP_power_control_res" },
|
||||
{ ESC4(33), "LMP_ping_req" },
|
||||
{ ESC4(34), "LMP_ping_res" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
void lmp_packet(const void *data, uint8_t size)
|
||||
{
|
||||
const struct lmp_data *lmp_data = NULL;
|
||||
const char *opcode_color, *opcode_str;
|
||||
uint16_t opcode;
|
||||
uint8_t tid, off;
|
||||
int i;
|
||||
|
||||
tid = ((const uint8_t *) data)[0] & 0x01;
|
||||
opcode = (((const uint8_t *) data)[0] & 0xfe) >> 1;
|
||||
|
||||
switch (opcode) {
|
||||
case 127:
|
||||
opcode = ESC4(((const uint8_t *) data)[1]);
|
||||
off = 2;
|
||||
break;
|
||||
case 126:
|
||||
case 125:
|
||||
case 124:
|
||||
return;
|
||||
default:
|
||||
off = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; lmp_table[i].str; i++) {
|
||||
if (lmp_table[i].opcode == opcode) {
|
||||
lmp_data = &lmp_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lmp_data) {
|
||||
if (lmp_data->func)
|
||||
opcode_color = COLOR_OPCODE;
|
||||
else
|
||||
opcode_color = COLOR_OPCODE_UNKNOWN;
|
||||
opcode_str = lmp_data->str;
|
||||
} else {
|
||||
opcode_color = COLOR_OPCODE_UNKNOWN;
|
||||
opcode_str = "Unknown";
|
||||
}
|
||||
|
||||
if (opcode & 0xff00)
|
||||
print_indent(6, opcode_color, "", opcode_str, COLOR_OFF,
|
||||
" (%d/%d) TID %d", opcode >> 8, opcode & 0xff, tid);
|
||||
else
|
||||
print_indent(6, opcode_color, "", opcode_str, COLOR_OFF,
|
||||
" (%d) TID %d", opcode, tid);
|
||||
|
||||
if (!lmp_data || !lmp_data->func) {
|
||||
packet_hexdump(data + off, size - off);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lmp_data->fixed) {
|
||||
if (size - 1 != lmp_data->size) {
|
||||
print_text(COLOR_ERROR, "invalid packet size");
|
||||
packet_hexdump(data + off, size - off);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (size - 1 < lmp_data->size) {
|
||||
print_text(COLOR_ERROR, "too short packet");
|
||||
packet_hexdump(data + off, size - off);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lmp_data->func(data + off, size - off);
|
||||
}
|
||||
27
external/cache/sources/hcitools/monitor/lmp.h
vendored
Normal file
27
external/cache/sources/hcitools/monitor/lmp.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void lmp_packet(const void *data, uint8_t size);
|
||||
167
external/cache/sources/hcitools/monitor/main.c
vendored
Normal file
167
external/cache/sources/hcitools/monitor/main.c
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "mainloop.h"
|
||||
#include "packet.h"
|
||||
#include "control.h"
|
||||
|
||||
static void signal_callback(int signum, void *user_data)
|
||||
{
|
||||
switch (signum) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
mainloop_quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("btmon - Bluetooth monitor\n"
|
||||
"Usage:\n");
|
||||
printf("\tbtmon [options]\n");
|
||||
printf("options:\n"
|
||||
"\t-r, --read <file> Read traces in btsnoop format\n"
|
||||
"\t-w, --write <file> Save traces in btsnoop format\n"
|
||||
"\t-s, --server <socket> Start monitor server socket\n"
|
||||
"\t-i, --index <num> Show only specified controller\n"
|
||||
"\t-t, --time Show time instead of time offset\n"
|
||||
"\t-T, --date Show time and date information\n"
|
||||
"\t-S, --sco Dump SCO traffic\n"
|
||||
"\t-h, --help Show help options\n");
|
||||
}
|
||||
|
||||
static const struct option main_options[] = {
|
||||
{ "read", required_argument, NULL, 'r' },
|
||||
{ "write", required_argument, NULL, 'w' },
|
||||
{ "server", required_argument, NULL, 's' },
|
||||
{ "index", required_argument, NULL, 'i' },
|
||||
{ "time", no_argument, NULL, 't' },
|
||||
{ "date", no_argument, NULL, 'T' },
|
||||
{ "sco", no_argument, NULL, 'S' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ }
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned long filter_mask = 0;
|
||||
const char *str, *reader_path = NULL, *writer_path = NULL;
|
||||
sigset_t mask;
|
||||
|
||||
mainloop_init();
|
||||
|
||||
filter_mask |= PACKET_FILTER_SHOW_TIME_OFFSET;
|
||||
|
||||
for (;;) {
|
||||
int opt;
|
||||
|
||||
opt = getopt_long(argc, argv, "r:w:s:i:tTSvh",
|
||||
main_options, NULL);
|
||||
if (opt < 0)
|
||||
break;
|
||||
|
||||
switch (opt) {
|
||||
case 'r':
|
||||
reader_path = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
writer_path = optarg;
|
||||
break;
|
||||
case 's':
|
||||
control_server(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
if (strlen(optarg) > 3 && !strncmp(optarg, "hci", 3))
|
||||
str = optarg + 3;
|
||||
else
|
||||
str = optarg;
|
||||
if (!isdigit(*str)) {
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
packet_select_index(atoi(str));
|
||||
break;
|
||||
case 't':
|
||||
filter_mask &= ~PACKET_FILTER_SHOW_TIME_OFFSET;
|
||||
filter_mask |= PACKET_FILTER_SHOW_TIME;
|
||||
break;
|
||||
case 'T':
|
||||
filter_mask &= ~PACKET_FILTER_SHOW_TIME_OFFSET;
|
||||
filter_mask |= PACKET_FILTER_SHOW_TIME;
|
||||
filter_mask |= PACKET_FILTER_SHOW_DATE;
|
||||
break;
|
||||
case 'S':
|
||||
filter_mask |= PACKET_FILTER_SHOW_SCO_DATA;
|
||||
break;
|
||||
case 'v':
|
||||
printf("%s\n", VERSION);
|
||||
return EXIT_SUCCESS;
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
default:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - optind > 0) {
|
||||
fprintf(stderr, "Invalid command line parameters\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
|
||||
mainloop_set_signal(&mask, signal_callback, NULL, NULL);
|
||||
|
||||
printf("Bluetooth monitor ver %s\n", VERSION);
|
||||
|
||||
packet_set_filter(filter_mask);
|
||||
|
||||
if (reader_path) {
|
||||
control_reader(reader_path);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (writer_path)
|
||||
control_writer(writer_path);
|
||||
|
||||
if (control_tracing() < 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
return mainloop_run();
|
||||
}
|
||||
389
external/cache/sources/hcitools/monitor/mainloop.c
vendored
Normal file
389
external/cache/sources/hcitools/monitor/mainloop.c
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "mainloop.h"
|
||||
|
||||
#define MAX_EPOLL_EVENTS 10
|
||||
|
||||
static int epoll_fd;
|
||||
static int epoll_terminate;
|
||||
|
||||
struct mainloop_data {
|
||||
int fd;
|
||||
uint32_t events;
|
||||
mainloop_event_func callback;
|
||||
mainloop_destroy_func destroy;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#define MAX_MAINLOOP_ENTRIES 128
|
||||
|
||||
static struct mainloop_data *mainloop_list[MAX_MAINLOOP_ENTRIES];
|
||||
|
||||
struct timeout_data {
|
||||
int fd;
|
||||
mainloop_timeout_func callback;
|
||||
mainloop_destroy_func destroy;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct signal_data {
|
||||
int fd;
|
||||
sigset_t mask;
|
||||
mainloop_signal_func callback;
|
||||
mainloop_destroy_func destroy;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
static struct signal_data *signal_data;
|
||||
|
||||
void mainloop_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
|
||||
for (i = 0; i < MAX_MAINLOOP_ENTRIES; i++)
|
||||
mainloop_list[i] = NULL;
|
||||
|
||||
epoll_terminate = 0;
|
||||
}
|
||||
|
||||
void mainloop_quit(void)
|
||||
{
|
||||
epoll_terminate = 1;
|
||||
}
|
||||
|
||||
static void signal_callback(int fd, uint32_t events, void *user_data)
|
||||
{
|
||||
struct signal_data *data = user_data;
|
||||
struct signalfd_siginfo si;
|
||||
ssize_t result;
|
||||
|
||||
if (events & (EPOLLERR | EPOLLHUP)) {
|
||||
mainloop_quit();
|
||||
return;
|
||||
}
|
||||
|
||||
result = read(fd, &si, sizeof(si));
|
||||
if (result != sizeof(si))
|
||||
return;
|
||||
|
||||
if (data->callback)
|
||||
data->callback(si.ssi_signo, data->user_data);
|
||||
}
|
||||
|
||||
int mainloop_run(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (signal_data) {
|
||||
if (sigprocmask(SIG_BLOCK, &signal_data->mask, NULL) < 0)
|
||||
return 1;
|
||||
|
||||
signal_data->fd = signalfd(-1, &signal_data->mask,
|
||||
SFD_NONBLOCK | SFD_CLOEXEC);
|
||||
if (signal_data->fd < 0)
|
||||
return 1;
|
||||
|
||||
if (mainloop_add_fd(signal_data->fd, EPOLLIN,
|
||||
signal_callback, signal_data, NULL) < 0) {
|
||||
close(signal_data->fd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (!epoll_terminate) {
|
||||
struct epoll_event events[MAX_EPOLL_EVENTS];
|
||||
int n, nfds;
|
||||
|
||||
nfds = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS, -1);
|
||||
if (nfds < 0)
|
||||
continue;
|
||||
|
||||
for (n = 0; n < nfds; n++) {
|
||||
struct mainloop_data *data = events[n].data.ptr;
|
||||
|
||||
data->callback(data->fd, events[n].events,
|
||||
data->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (signal_data) {
|
||||
mainloop_remove_fd(signal_data->fd);
|
||||
close(signal_data->fd);
|
||||
|
||||
if (signal_data->destroy)
|
||||
signal_data->destroy(signal_data->user_data);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MAINLOOP_ENTRIES; i++) {
|
||||
struct mainloop_data *data = mainloop_list[i];
|
||||
|
||||
mainloop_list[i] = NULL;
|
||||
|
||||
if (data) {
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, data->fd, NULL);
|
||||
|
||||
if (data->destroy)
|
||||
data->destroy(data->user_data);
|
||||
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
close(epoll_fd);
|
||||
epoll_fd = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
|
||||
void *user_data, mainloop_destroy_func destroy)
|
||||
{
|
||||
struct mainloop_data *data;
|
||||
struct epoll_event ev;
|
||||
int err;
|
||||
|
||||
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1 || !callback)
|
||||
return -EINVAL;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->fd = fd;
|
||||
data->events = events;
|
||||
data->callback = callback;
|
||||
data->destroy = destroy;
|
||||
data->user_data = user_data;
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.events = events;
|
||||
ev.data.ptr = data;
|
||||
|
||||
err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, data->fd, &ev);
|
||||
if (err < 0) {
|
||||
free(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
mainloop_list[fd] = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainloop_modify_fd(int fd, uint32_t events)
|
||||
{
|
||||
struct mainloop_data *data;
|
||||
struct epoll_event ev;
|
||||
int err;
|
||||
|
||||
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1)
|
||||
return -EINVAL;
|
||||
|
||||
data = mainloop_list[fd];
|
||||
if (!data)
|
||||
return -ENXIO;
|
||||
|
||||
if (data->events == events)
|
||||
return 0;
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.events = events;
|
||||
ev.data.ptr = data;
|
||||
|
||||
err = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, data->fd, &ev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
data->events = events;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainloop_remove_fd(int fd)
|
||||
{
|
||||
struct mainloop_data *data;
|
||||
int err;
|
||||
|
||||
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1)
|
||||
return -EINVAL;
|
||||
|
||||
data = mainloop_list[fd];
|
||||
if (!data)
|
||||
return -ENXIO;
|
||||
|
||||
mainloop_list[fd] = NULL;
|
||||
|
||||
err = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, data->fd, NULL);
|
||||
|
||||
if (data->destroy)
|
||||
data->destroy(data->user_data);
|
||||
|
||||
free(data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void timeout_destroy(void *user_data)
|
||||
{
|
||||
struct timeout_data *data = user_data;
|
||||
|
||||
close(data->fd);
|
||||
data->fd = -1;
|
||||
|
||||
if (data->destroy)
|
||||
data->destroy(data->user_data);
|
||||
}
|
||||
|
||||
static void timeout_callback(int fd, uint32_t events, void *user_data)
|
||||
{
|
||||
struct timeout_data *data = user_data;
|
||||
uint64_t expired;
|
||||
ssize_t result;
|
||||
|
||||
if (events & (EPOLLERR | EPOLLHUP))
|
||||
return;
|
||||
|
||||
result = read(data->fd, &expired, sizeof(expired));
|
||||
if (result != sizeof(expired))
|
||||
return;
|
||||
|
||||
if (data->callback)
|
||||
data->callback(data->fd, data->user_data);
|
||||
}
|
||||
|
||||
static inline int timeout_set(int fd, unsigned int seconds)
|
||||
{
|
||||
struct itimerspec itimer;
|
||||
|
||||
memset(&itimer, 0, sizeof(itimer));
|
||||
itimer.it_interval.tv_sec = 0;
|
||||
itimer.it_interval.tv_nsec = 0;
|
||||
itimer.it_value.tv_sec = seconds;
|
||||
itimer.it_value.tv_nsec = 0;
|
||||
|
||||
return timerfd_settime(fd, 0, &itimer, NULL);
|
||||
}
|
||||
|
||||
int mainloop_add_timeout(unsigned int seconds, mainloop_timeout_func callback,
|
||||
void *user_data, mainloop_destroy_func destroy)
|
||||
{
|
||||
struct timeout_data *data;
|
||||
|
||||
if (!callback)
|
||||
return -EINVAL;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->callback = callback;
|
||||
data->destroy = destroy;
|
||||
data->user_data = user_data;
|
||||
|
||||
data->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
if (data->fd < 0) {
|
||||
free(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (seconds > 0) {
|
||||
if (timeout_set(data->fd, seconds) < 0) {
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (mainloop_add_fd(data->fd, EPOLLIN | EPOLLONESHOT,
|
||||
timeout_callback, data, timeout_destroy) < 0) {
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return data->fd;
|
||||
}
|
||||
|
||||
int mainloop_modify_timeout(int id, unsigned int seconds)
|
||||
{
|
||||
if (seconds > 0) {
|
||||
if (timeout_set(id, seconds) < 0)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (mainloop_modify_fd(id, EPOLLIN | EPOLLONESHOT) < 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainloop_remove_timeout(int id)
|
||||
{
|
||||
return mainloop_remove_fd(id);
|
||||
}
|
||||
|
||||
int mainloop_set_signal(sigset_t *mask, mainloop_signal_func callback,
|
||||
void *user_data, mainloop_destroy_func destroy)
|
||||
{
|
||||
struct signal_data *data;
|
||||
|
||||
if (!mask || !callback)
|
||||
return -EINVAL;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->callback = callback;
|
||||
data->destroy = destroy;
|
||||
data->user_data = user_data;
|
||||
|
||||
data->fd = -1;
|
||||
memcpy(&data->mask, mask, sizeof(sigset_t));
|
||||
|
||||
free(signal_data);
|
||||
signal_data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
49
external/cache/sources/hcitools/monitor/mainloop.h
vendored
Normal file
49
external/cache/sources/hcitools/monitor/mainloop.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
typedef void (*mainloop_destroy_func) (void *user_data);
|
||||
|
||||
typedef void (*mainloop_event_func) (int fd, uint32_t events, void *user_data);
|
||||
typedef void (*mainloop_timeout_func) (int id, void *user_data);
|
||||
typedef void (*mainloop_signal_func) (int signum, void *user_data);
|
||||
|
||||
void mainloop_init(void);
|
||||
void mainloop_quit(void);
|
||||
int mainloop_run(void);
|
||||
|
||||
int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
|
||||
void *user_data, mainloop_destroy_func destroy);
|
||||
int mainloop_modify_fd(int fd, uint32_t events);
|
||||
int mainloop_remove_fd(int fd);
|
||||
|
||||
int mainloop_add_timeout(unsigned int seconds, mainloop_timeout_func callback,
|
||||
void *user_data, mainloop_destroy_func destroy);
|
||||
int mainloop_modify_timeout(int fd, unsigned int seconds);
|
||||
int mainloop_remove_timeout(int id);
|
||||
|
||||
int mainloop_set_signal(sigset_t *mask, mainloop_signal_func callback,
|
||||
void *user_data, mainloop_destroy_func destroy);
|
||||
6474
external/cache/sources/hcitools/monitor/packet.c
vendored
Normal file
6474
external/cache/sources/hcitools/monitor/packet.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
69
external/cache/sources/hcitools/monitor/packet.h
vendored
Normal file
69
external/cache/sources/hcitools/monitor/packet.h
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define PACKET_FILTER_SHOW_INDEX (1 << 0)
|
||||
#define PACKET_FILTER_SHOW_DATE (1 << 1)
|
||||
#define PACKET_FILTER_SHOW_TIME (1 << 2)
|
||||
#define PACKET_FILTER_SHOW_TIME_OFFSET (1 << 3)
|
||||
#define PACKET_FILTER_SHOW_ACL_DATA (1 << 4)
|
||||
#define PACKET_FILTER_SHOW_SCO_DATA (1 << 5)
|
||||
|
||||
void packet_set_filter(unsigned long filter);
|
||||
void packet_add_filter(unsigned long filter);
|
||||
void packet_del_filter(unsigned long filter);
|
||||
|
||||
void packet_select_index(uint16_t index);
|
||||
|
||||
void packet_hexdump(const unsigned char *buf, uint16_t len);
|
||||
void packet_print_version(const char *label, uint8_t version,
|
||||
const char *sublabel, uint16_t subversion);
|
||||
void packet_print_company(const char *label, uint16_t company);
|
||||
void packet_print_addr(const char *label, const void *data, bool random);
|
||||
void packet_print_ad(const void *data, uint8_t size);
|
||||
void packet_print_features_ll(const uint8_t *features);
|
||||
void packet_print_channel_map_ll(const uint8_t *map);
|
||||
|
||||
void packet_control(struct timeval *tv, uint16_t index, uint16_t opcode,
|
||||
const void *data, uint16_t size);
|
||||
void packet_monitor(struct timeval *tv, uint16_t index, uint16_t opcode,
|
||||
const void *data, uint16_t size);
|
||||
void packet_simulator(struct timeval *tv, uint16_t frequency,
|
||||
const void *data, uint16_t size);
|
||||
|
||||
void packet_new_index(struct timeval *tv, uint16_t index, const char *label,
|
||||
uint8_t type, uint8_t bus, const char *name);
|
||||
void packet_del_index(struct timeval *tv, uint16_t index, const char *label);
|
||||
|
||||
void packet_hci_command(struct timeval *tv, uint16_t index,
|
||||
const void *data, uint16_t size);
|
||||
void packet_hci_event(struct timeval *tv, uint16_t index,
|
||||
const void *data, uint16_t size);
|
||||
void packet_hci_acldata(struct timeval *tv, uint16_t index, bool in,
|
||||
const void *data, uint16_t size);
|
||||
void packet_hci_scodata(struct timeval *tv, uint16_t index, bool in,
|
||||
const void *data, uint16_t size);
|
||||
748
external/cache/sources/hcitools/monitor/sdp.c
vendored
Normal file
748
external/cache/sources/hcitools/monitor/sdp.c
vendored
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
||||
#include "bt.h"
|
||||
#include "packet.h"
|
||||
#include "display.h"
|
||||
#include "l2cap.h"
|
||||
#include "uuid.h"
|
||||
#include "sdp.h"
|
||||
|
||||
#define MAX_TID 16
|
||||
|
||||
struct tid_data {
|
||||
bool inuse;
|
||||
uint16_t tid;
|
||||
uint16_t channel;
|
||||
uint8_t cont[17];
|
||||
};
|
||||
|
||||
static struct tid_data tid_list[MAX_TID];
|
||||
|
||||
static struct tid_data *get_tid(uint16_t tid, uint16_t channel)
|
||||
{
|
||||
int i, n = -1;
|
||||
|
||||
for (i = 0; i < MAX_TID; i++) {
|
||||
if (!tid_list[i].inuse) {
|
||||
if (n < 0)
|
||||
n = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tid_list[i].tid == tid && tid_list[i].channel == channel)
|
||||
return &tid_list[i];
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
|
||||
tid_list[n].inuse = true;
|
||||
tid_list[n].tid = tid;
|
||||
tid_list[n].channel = channel;
|
||||
|
||||
return &tid_list[n];
|
||||
}
|
||||
|
||||
static void clear_tid(struct tid_data *tid)
|
||||
{
|
||||
if (tid)
|
||||
tid->inuse = false;
|
||||
}
|
||||
|
||||
static void print_uint(uint8_t indent, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
print_field("%*c0x%2.2x", indent, ' ', data[0]);
|
||||
break;
|
||||
case 2:
|
||||
print_field("%*c0x%4.4x", indent, ' ', bt_get_be16(data));
|
||||
break;
|
||||
case 4:
|
||||
print_field("%*c0x%8.8x", indent, ' ', bt_get_be32(data));
|
||||
break;
|
||||
case 8:
|
||||
print_field("%*c0x%16.16" PRIx64, indent, ' ',
|
||||
bt_get_be64(data));
|
||||
break;
|
||||
default:
|
||||
packet_hexdump(data, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_sint(uint8_t indent, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
packet_hexdump(data, size);
|
||||
}
|
||||
|
||||
static void print_uuid(uint8_t indent, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
switch (size) {
|
||||
case 2:
|
||||
print_field("%*c%s (0x%4.4x)", indent, ' ',
|
||||
uuid16_to_str(bt_get_be16(data)), bt_get_be16(data));
|
||||
break;
|
||||
case 4:
|
||||
print_field("%*c%s (0x%8.8x)", indent, ' ',
|
||||
uuid32_to_str(bt_get_be32(data)), bt_get_be32(data));
|
||||
break;
|
||||
case 16:
|
||||
/* BASE_UUID = 00000000-0000-1000-8000-00805F9B34FB */
|
||||
print_field("%*c%8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.4x",
|
||||
indent, ' ',
|
||||
bt_get_be32(data), bt_get_be16(data + 4),
|
||||
bt_get_be16(data + 6), bt_get_be16(data + 8),
|
||||
bt_get_be16(data + 10), bt_get_be32(data + 12));
|
||||
if (bt_get_be16(data + 4) == 0x0000 &&
|
||||
bt_get_be16(data + 6) == 0x1000 &&
|
||||
bt_get_be16(data + 8) == 0x8000 &&
|
||||
bt_get_be16(data + 10) == 0x0080 &&
|
||||
bt_get_be32(data + 12) == 0x5F9B34FB)
|
||||
print_field("%*c%s", indent, ' ',
|
||||
uuid32_to_str(bt_get_be32(data)));
|
||||
break;
|
||||
default:
|
||||
packet_hexdump(data, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_string(uint8_t indent, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
char *str = alloca(size + 1);
|
||||
|
||||
str[size] = '\0';
|
||||
strncpy(str, (const char *) data, size);
|
||||
|
||||
print_field("%*c%s [len %d]", indent, ' ', str, size);
|
||||
}
|
||||
|
||||
static void print_boolean(uint8_t indent, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
print_field("%*c%s", indent, ' ', data[0] ? "true" : "false");
|
||||
}
|
||||
|
||||
#define SIZES(args...) ((uint8_t[]) { args, 0xff } )
|
||||
|
||||
static struct {
|
||||
uint8_t value;
|
||||
uint8_t *sizes;
|
||||
bool recurse;
|
||||
const char *str;
|
||||
void (*print) (uint8_t indent, const uint8_t *data, uint32_t size);
|
||||
} type_table[] = {
|
||||
{ 0, SIZES(0), false, "Nil" },
|
||||
{ 1, SIZES(0, 1, 2, 3, 4), false, "Unsigned Integer", print_uint },
|
||||
{ 2, SIZES(0, 1, 2, 3, 4), false, "Signed Integer", print_sint },
|
||||
{ 3, SIZES(1, 2, 4), false, "UUID", print_uuid },
|
||||
{ 4, SIZES(5, 6, 7), false, "String", print_string },
|
||||
{ 5, SIZES(0), false, "Boolean", print_boolean },
|
||||
{ 6, SIZES(5, 6, 7), true, "Sequence" },
|
||||
{ 7, SIZES(5, 6, 7), true, "Alternative" },
|
||||
{ 8, SIZES(5, 6, 7), false, "URL", print_string },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct {
|
||||
uint8_t index;
|
||||
uint8_t bits;
|
||||
uint8_t size;
|
||||
const char *str;
|
||||
} size_table[] = {
|
||||
{ 0, 0, 1, "1 byte" },
|
||||
{ 1, 0, 2, "2 bytes" },
|
||||
{ 2, 0, 4, "4 bytes" },
|
||||
{ 3, 0, 8, "8 bytes" },
|
||||
{ 4, 0, 16, "16 bytes" },
|
||||
{ 5, 8, 0, "8 bits" },
|
||||
{ 6, 16, 0, "16 bits" },
|
||||
{ 7, 32, 0, "32 bits" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static bool valid_size(uint8_t size, uint8_t *sizes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; sizes[i] != 0xff; i++) {
|
||||
if (sizes[i] == size)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t get_bits(const uint8_t *data, uint32_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; size_table[i].str; i++) {
|
||||
if (size_table[i].index == (data[0] & 0x07))
|
||||
return size_table[i].bits;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t get_size(const uint8_t *data, uint32_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; size_table[i].str; i++) {
|
||||
if (size_table[i].index == (data[0] & 0x07)) {
|
||||
switch (size_table[i].bits) {
|
||||
case 0:
|
||||
if ((data[0] & 0xf8) == 0)
|
||||
return 0;
|
||||
else
|
||||
return size_table[i].size;
|
||||
case 8:
|
||||
return data[1];
|
||||
case 16:
|
||||
return bt_get_be16(data + 1);
|
||||
case 32:
|
||||
return bt_get_be32(data + 1);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode_data_elements(uint32_t position, uint8_t indent,
|
||||
const uint8_t *data, uint32_t size,
|
||||
void (*print_func) (uint32_t, uint8_t, uint8_t,
|
||||
const uint8_t *, uint32_t))
|
||||
|
||||
{
|
||||
uint32_t datalen, elemlen, extrabits;
|
||||
int i;
|
||||
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
extrabits = get_bits(data, size);
|
||||
|
||||
if (size < 1 + (extrabits / 8)) {
|
||||
print_text(COLOR_ERROR, "data element descriptor too short");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
datalen = get_size(data, size);
|
||||
|
||||
if (size < 1 + (extrabits / 8) + datalen) {
|
||||
print_text(COLOR_ERROR, "data element size too short");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
elemlen = 1 + (extrabits / 8) + datalen;
|
||||
|
||||
for (i = 0; type_table[i].str; i++) {
|
||||
uint8_t type = (data[0] & 0xf8) >> 3;
|
||||
|
||||
if (type_table[i].value != type)
|
||||
continue;
|
||||
|
||||
if (print_func) {
|
||||
print_func(position, indent, type,
|
||||
data + 1 + (extrabits / 8), datalen);
|
||||
break;
|
||||
}
|
||||
|
||||
print_field("%*c%s (%d) with %u byte%s [%u extra bits] len %u",
|
||||
indent, ' ', type_table[i].str, type,
|
||||
datalen, datalen == 1 ? "" : "s",
|
||||
extrabits, elemlen);
|
||||
if (!valid_size(data[0] & 0x07, type_table[i].sizes)) {
|
||||
print_text(COLOR_ERROR, "invalid data element size");
|
||||
packet_hexdump(data + 1 + (extrabits / 8), datalen);
|
||||
break;
|
||||
}
|
||||
|
||||
if (type_table[i].recurse)
|
||||
decode_data_elements(0, indent + 2,
|
||||
data + 1 + (extrabits / 8), datalen,
|
||||
print_func);
|
||||
else if (type_table[i].print)
|
||||
type_table[i].print(indent + 2,
|
||||
data + 1 + (extrabits / 8), datalen);
|
||||
break;
|
||||
}
|
||||
|
||||
data += elemlen;
|
||||
size -= elemlen;
|
||||
|
||||
decode_data_elements(position + 1, indent, data, size, print_func);
|
||||
}
|
||||
|
||||
static uint32_t get_bytes(const uint8_t *data, uint32_t size)
|
||||
{
|
||||
switch (data[0] & 0x07) {
|
||||
case 5:
|
||||
return 2 + data[1];
|
||||
case 6:
|
||||
return 3 + bt_get_be16(data + 1);
|
||||
case 7:
|
||||
return 5 + bt_get_be32(data + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct {
|
||||
uint16_t id;
|
||||
const char *str;
|
||||
} attribute_table[] = {
|
||||
{ 0x0000, "Service Record Handle" },
|
||||
{ 0x0001, "Service Class ID List" },
|
||||
{ 0x0002, "Service Record State" },
|
||||
{ 0x0003, "Service ID" },
|
||||
{ 0x0004, "Protocol Descriptor List" },
|
||||
{ 0x0005, "Browse Group List" },
|
||||
{ 0x0006, "Language Base Attribute ID List" },
|
||||
{ 0x0007, "Service Info Time To Live" },
|
||||
{ 0x0008, "Service Availability" },
|
||||
{ 0x0009, "Bluetooth Profile Descriptor List" },
|
||||
{ 0x000a, "Documentation URL" },
|
||||
{ 0x000b, "Client Executable URL" },
|
||||
{ 0x000c, "Icon URL" },
|
||||
{ 0x000d, "Additional Protocol Descriptor List" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void print_attr(uint32_t position, uint8_t indent, uint8_t type,
|
||||
const uint8_t *data, uint32_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((position % 2) == 0) {
|
||||
uint16_t id = bt_get_be16(data);
|
||||
const char *str = "Unknown";
|
||||
|
||||
for (i = 0; attribute_table[i].str; i++) {
|
||||
if (attribute_table[i].id == id)
|
||||
str = attribute_table[i].str;
|
||||
}
|
||||
|
||||
print_field("%*cAttribute: %s (0x%4.4x) [len %d]",
|
||||
indent, ' ', str, id, size);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; type_table[i].str; i++) {
|
||||
if (type_table[i].value != type)
|
||||
continue;
|
||||
|
||||
if (type_table[i].recurse)
|
||||
decode_data_elements(0, indent + 2, data, size, NULL);
|
||||
else if (type_table[i].print)
|
||||
type_table[i].print(indent + 2, data, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_attr_list(uint32_t position, uint8_t indent, uint8_t type,
|
||||
const uint8_t *data, uint32_t size)
|
||||
{
|
||||
print_field("%*cAttribute list: [len %d] {position %d}",
|
||||
indent, ' ', size, position);
|
||||
|
||||
decode_data_elements(0, indent + 2, data, size, print_attr);
|
||||
}
|
||||
|
||||
static void print_attr_lists(uint32_t position, uint8_t indent, uint8_t type,
|
||||
const uint8_t *data, uint32_t size)
|
||||
{
|
||||
decode_data_elements(0, indent, data, size, print_attr_list);
|
||||
}
|
||||
|
||||
static void print_continuation(const uint8_t *data, uint16_t size)
|
||||
{
|
||||
if (data[0] != size - 1) {
|
||||
print_text(COLOR_ERROR, "invalid continuation state");
|
||||
packet_hexdump(data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
print_field("Continuation state: %d", data[0]);
|
||||
packet_hexdump(data + 1, size - 1);
|
||||
}
|
||||
|
||||
static void store_continuation(struct tid_data *tid,
|
||||
const uint8_t *data, uint16_t size)
|
||||
{
|
||||
memcpy(tid->cont, data, size);
|
||||
print_continuation(data, size);
|
||||
}
|
||||
|
||||
#define MAX_CONT 8
|
||||
|
||||
struct cont_data {
|
||||
uint16_t channel;
|
||||
uint8_t cont[17];
|
||||
void *data;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
static struct cont_data cont_list[MAX_CONT];
|
||||
|
||||
static void handle_continuation(struct tid_data *tid, bool nested,
|
||||
uint16_t bytes, const uint8_t *data, uint16_t size)
|
||||
{
|
||||
uint8_t *newdata;
|
||||
int i, n = -1;
|
||||
|
||||
if (bytes + 1 > size) {
|
||||
print_text(COLOR_ERROR, "missing continuation state");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tid->cont[0] == 0x00 && data[bytes] == 0x00) {
|
||||
decode_data_elements(0, 2, data, bytes,
|
||||
nested ? print_attr_lists : print_attr_list);
|
||||
|
||||
print_continuation(data + bytes, size - bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CONT; i++) {
|
||||
if (cont_list[i].cont[0] == 0x00) {
|
||||
if (n < 0)
|
||||
n = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cont_list[i].channel != tid->channel)
|
||||
continue;
|
||||
|
||||
if (cont_list[i].cont[0] != tid->cont[0])
|
||||
continue;
|
||||
|
||||
if (!memcmp(cont_list[i].cont + 1,
|
||||
tid->cont + 1, tid->cont[0])) {
|
||||
n = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print_continuation(data + bytes, size - bytes);
|
||||
|
||||
if (n < 0)
|
||||
return;
|
||||
|
||||
newdata = realloc(cont_list[n].data, cont_list[n].size + bytes);
|
||||
if (!newdata) {
|
||||
print_text(COLOR_ERROR, "failed buffer allocation");
|
||||
free(cont_list[n].data);
|
||||
cont_list[n].data = NULL;
|
||||
cont_list[n].size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
cont_list[n].channel = tid->channel;
|
||||
cont_list[n].data = newdata;
|
||||
|
||||
if (bytes > 0) {
|
||||
memcpy(cont_list[n].data + cont_list[n].size, data, bytes);
|
||||
cont_list[n].size += bytes;
|
||||
}
|
||||
|
||||
if (data[bytes] == 0x00) {
|
||||
print_field("Combined attribute bytes: %d", cont_list[n].size);
|
||||
|
||||
decode_data_elements(0, 2, cont_list[n].data, cont_list[n].size,
|
||||
nested ? print_attr_lists : print_attr_list);
|
||||
|
||||
free(cont_list[n].data);
|
||||
cont_list[n].data = NULL;
|
||||
cont_list[n].size = 0;
|
||||
} else
|
||||
memcpy(cont_list[i].cont, data + bytes, data[bytes] + 1);
|
||||
}
|
||||
|
||||
static uint16_t common_rsp(const struct l2cap_frame *frame,
|
||||
struct tid_data *tid)
|
||||
{
|
||||
uint16_t bytes;
|
||||
|
||||
if (frame->size < 2) {
|
||||
print_text(COLOR_ERROR, "invalid size");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes = bt_get_be16(frame->data);
|
||||
print_field("Attribute bytes: %d", bytes);
|
||||
|
||||
if (bytes > frame->size - 2) {
|
||||
print_text(COLOR_ERROR, "invalid attribute size");
|
||||
packet_hexdump(frame->data + 2, frame->size - 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static void error_rsp(const struct l2cap_frame *frame, struct tid_data *tid)
|
||||
{
|
||||
uint16_t error;
|
||||
|
||||
clear_tid(tid);
|
||||
|
||||
if (frame->size < 2) {
|
||||
print_text(COLOR_ERROR, "invalid size");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
error = bt_get_be16(frame->data);
|
||||
|
||||
print_field("Error code: 0x%2.2x", error);
|
||||
}
|
||||
|
||||
static void service_req(const struct l2cap_frame *frame, struct tid_data *tid)
|
||||
{
|
||||
uint32_t search_bytes;
|
||||
|
||||
search_bytes = get_bytes(frame->data, frame->size);
|
||||
print_field("Search pattern: [len %d]", search_bytes);
|
||||
|
||||
if (search_bytes + 2 > frame->size) {
|
||||
print_text(COLOR_ERROR, "invalid search list length");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
decode_data_elements(0, 2, frame->data, search_bytes, NULL);
|
||||
|
||||
print_field("Max record count: %d",
|
||||
bt_get_be16(frame->data + search_bytes));
|
||||
|
||||
print_continuation(frame->data + search_bytes + 2,
|
||||
frame->size - search_bytes - 2);
|
||||
}
|
||||
|
||||
static void service_rsp(const struct l2cap_frame *frame, struct tid_data *tid)
|
||||
{
|
||||
uint16_t count;
|
||||
int i;
|
||||
|
||||
clear_tid(tid);
|
||||
|
||||
if (frame->size < 4) {
|
||||
print_text(COLOR_ERROR, "invalid size");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
count = bt_get_be16(frame->data + 2);
|
||||
|
||||
print_field("Total record count: %d", bt_get_be16(frame->data));
|
||||
print_field("Current record count: %d", count);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
print_field("Record handle: 0x%4.4x",
|
||||
bt_get_be32(frame->data + 4 + (i * 4)));
|
||||
|
||||
print_continuation(frame->data + 4 + (count * 4),
|
||||
frame->size - 4 - (count * 4));
|
||||
}
|
||||
|
||||
static void attr_req(const struct l2cap_frame *frame, struct tid_data *tid)
|
||||
{
|
||||
uint32_t attr_bytes;
|
||||
|
||||
if (frame->size < 6) {
|
||||
print_text(COLOR_ERROR, "invalid size");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
print_field("Record handle: 0x%4.4x", bt_get_be32(frame->data));
|
||||
print_field("Max attribute bytes: %d", bt_get_be16(frame->data + 4));
|
||||
|
||||
attr_bytes = get_bytes(frame->data + 6, frame->size - 6);
|
||||
print_field("Attribute list: [len %d]", attr_bytes);
|
||||
|
||||
if (attr_bytes + 6 > frame->size) {
|
||||
print_text(COLOR_ERROR, "invalid attribute list length");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
decode_data_elements(0, 2, frame->data + 6, attr_bytes, NULL);
|
||||
|
||||
store_continuation(tid, frame->data + 6 + attr_bytes,
|
||||
frame->size - 6 - attr_bytes);
|
||||
}
|
||||
|
||||
static void attr_rsp(const struct l2cap_frame *frame, struct tid_data *tid)
|
||||
{
|
||||
uint16_t bytes;
|
||||
|
||||
bytes = common_rsp(frame, tid);
|
||||
|
||||
handle_continuation(tid, false, bytes,
|
||||
frame->data + 2, frame->size - 2);
|
||||
|
||||
clear_tid(tid);
|
||||
}
|
||||
|
||||
static void search_attr_req(const struct l2cap_frame *frame,
|
||||
struct tid_data *tid)
|
||||
{
|
||||
uint32_t search_bytes, attr_bytes;
|
||||
|
||||
search_bytes = get_bytes(frame->data, frame->size);
|
||||
print_field("Search pattern: [len %d]", search_bytes);
|
||||
|
||||
if (search_bytes + 2 > frame->size) {
|
||||
print_text(COLOR_ERROR, "invalid search list length");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
decode_data_elements(0, 2, frame->data, search_bytes, NULL);
|
||||
|
||||
print_field("Max record count: %d",
|
||||
bt_get_be16(frame->data + search_bytes));
|
||||
|
||||
attr_bytes = get_bytes(frame->data + search_bytes + 2,
|
||||
frame->size - search_bytes - 2);
|
||||
print_field("Attribute list: [len %d]", attr_bytes);
|
||||
|
||||
decode_data_elements(0, 2, frame->data + search_bytes + 2,
|
||||
attr_bytes, NULL);
|
||||
|
||||
store_continuation(tid, frame->data + search_bytes + 2 + attr_bytes,
|
||||
frame->size - search_bytes - 2 - attr_bytes);
|
||||
}
|
||||
|
||||
static void search_attr_rsp(const struct l2cap_frame *frame,
|
||||
struct tid_data *tid)
|
||||
{
|
||||
uint16_t bytes;
|
||||
|
||||
bytes = common_rsp(frame, tid);
|
||||
|
||||
handle_continuation(tid, true, bytes, frame->data + 2, frame->size - 2);
|
||||
|
||||
clear_tid(tid);
|
||||
}
|
||||
|
||||
struct sdp_data {
|
||||
uint8_t pdu;
|
||||
const char *str;
|
||||
void (*func) (const struct l2cap_frame *frame, struct tid_data *tid);
|
||||
};
|
||||
|
||||
static const struct sdp_data sdp_table[] = {
|
||||
{ 0x01, "Error Response", error_rsp },
|
||||
{ 0x02, "Service Search Request", service_req },
|
||||
{ 0x03, "Service Search Response", service_rsp },
|
||||
{ 0x04, "Service Attribute Request", attr_req },
|
||||
{ 0x05, "Service Attribute Response", attr_rsp },
|
||||
{ 0x06, "Service Search Attribute Request", search_attr_req },
|
||||
{ 0x07, "Service Search Attribute Response", search_attr_rsp },
|
||||
{ }
|
||||
};
|
||||
|
||||
void sdp_packet(const struct l2cap_frame *frame, uint16_t channel)
|
||||
{
|
||||
uint8_t pdu;
|
||||
uint16_t tid, plen;
|
||||
struct l2cap_frame sdp_frame;
|
||||
struct tid_data *tid_info;
|
||||
const struct sdp_data *sdp_data = NULL;
|
||||
const char *pdu_color, *pdu_str;
|
||||
|
||||
int i;
|
||||
|
||||
if (frame->size < 5) {
|
||||
print_text(COLOR_ERROR, "frame too short");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
pdu = *((uint8_t *) frame->data);
|
||||
tid = bt_get_be16(frame->data + 1);
|
||||
plen = bt_get_be16(frame->data + 3);
|
||||
|
||||
if (frame->size != plen + 5) {
|
||||
print_text(COLOR_ERROR, "invalid frame size");
|
||||
packet_hexdump(frame->data, frame->size);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; sdp_table[i].str; i++) {
|
||||
if (sdp_table[i].pdu == pdu) {
|
||||
sdp_data = &sdp_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sdp_data) {
|
||||
if (sdp_data->func) {
|
||||
if (frame->in)
|
||||
pdu_color = COLOR_MAGENTA;
|
||||
else
|
||||
pdu_color = COLOR_BLUE;
|
||||
} else
|
||||
pdu_color = COLOR_WHITE_BG;
|
||||
pdu_str = sdp_data->str;
|
||||
} else {
|
||||
pdu_color = COLOR_WHITE_BG;
|
||||
pdu_str = "Unknown";
|
||||
}
|
||||
|
||||
print_indent(6, pdu_color, "SDP: ", pdu_str, COLOR_OFF,
|
||||
" (0x%2.2x) tid %d len %d", pdu, tid, plen);
|
||||
|
||||
if (!sdp_data || !sdp_data->func) {
|
||||
packet_hexdump(frame->data + 5, frame->size - 5);
|
||||
return;
|
||||
}
|
||||
|
||||
tid_info = get_tid(tid, channel);
|
||||
|
||||
l2cap_frame_pull(&sdp_frame, frame, 5);
|
||||
sdp_data->func(&sdp_frame, tid_info);
|
||||
}
|
||||
25
external/cache/sources/hcitools/monitor/sdp.h
vendored
Normal file
25
external/cache/sources/hcitools/monitor/sdp.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
void sdp_packet(const struct l2cap_frame *frame, uint16_t channel);
|
||||
284
external/cache/sources/hcitools/monitor/uuid.c
vendored
Normal file
284
external/cache/sources/hcitools/monitor/uuid.c
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 <string.h>
|
||||
|
||||
#include "uuid.h"
|
||||
|
||||
static struct {
|
||||
uint16_t uuid;
|
||||
const char *str;
|
||||
} uuid16_table[] = {
|
||||
{ 0x0001, "SDP" },
|
||||
{ 0x0003, "RFCOMM" },
|
||||
{ 0x0005, "TCS-BIN" },
|
||||
{ 0x0007, "ATT" },
|
||||
{ 0x0008, "OBEX" },
|
||||
{ 0x000f, "BNEP" },
|
||||
{ 0x0010, "UPNP" },
|
||||
{ 0x0011, "HIDP" },
|
||||
{ 0x0012, "Hardcopy Control Channel" },
|
||||
{ 0x0014, "Hardcopy Data Channel" },
|
||||
{ 0x0016, "Hardcopy Notification" },
|
||||
{ 0x0017, "AVCTP" },
|
||||
{ 0x0019, "AVDTP" },
|
||||
{ 0x001b, "CMTP" },
|
||||
{ 0x001e, "MCAP Control Channel" },
|
||||
{ 0x001f, "MCAP Data Channel" },
|
||||
{ 0x0100, "L2CAP" },
|
||||
{ 0x1000, "Service Discovery Server Service Class" },
|
||||
{ 0x1001, "Browse Group Descriptor Service Class" },
|
||||
{ 0x1002, "Public Browse Root" },
|
||||
{ 0x1101, "Serial Port" },
|
||||
{ 0x1102, "LAN Access Using PPP" },
|
||||
{ 0x1103, "Dialup Networking" },
|
||||
{ 0x1104, "IrMC Sync" },
|
||||
{ 0x1105, "OBEX Object Push" },
|
||||
{ 0x1106, "OBEX File Transfer" },
|
||||
{ 0x1107, "IrMC Sync Command" },
|
||||
{ 0x1108, "Headset" },
|
||||
{ 0x1109, "Cordless Telephony" },
|
||||
{ 0x110a, "Audio Source" },
|
||||
{ 0x110b, "Audio Sink" },
|
||||
{ 0x110c, "A/V Remote Control Target" },
|
||||
{ 0x110d, "Advanced Audio Distribution" },
|
||||
{ 0x110e, "A/V Remote Control" },
|
||||
{ 0x110f, "A/V Remote Control Controller" },
|
||||
{ 0x1110, "Intercom" },
|
||||
{ 0x1111, "Fax" },
|
||||
{ 0x1112, "Headset AG" },
|
||||
{ 0x1113, "WAP" },
|
||||
{ 0x1114, "WAP Client" },
|
||||
{ 0x1115, "PANU" },
|
||||
{ 0x1116, "NAP" },
|
||||
{ 0x1117, "GN" },
|
||||
{ 0x1118, "Direct Printing" },
|
||||
{ 0x1119, "Reference Printing" },
|
||||
{ 0x111a, "Basic Imaging Profile" },
|
||||
{ 0x111b, "Imaging Responder" },
|
||||
{ 0x111c, "Imaging Automatic Archive" },
|
||||
{ 0x111d, "Imaging Referenced Objects" },
|
||||
{ 0x111e, "Handsfree" },
|
||||
{ 0x111f, "Handsfree Audio Gateway" },
|
||||
{ 0x1120, "Direct Printing Refrence Objects Service" },
|
||||
{ 0x1121, "Reflected UI" },
|
||||
{ 0x1122, "Basic Printing" },
|
||||
{ 0x1123, "Printing Status" },
|
||||
{ 0x1124, "Human Interface Device Service" },
|
||||
{ 0x1125, "Hardcopy Cable Replacement" },
|
||||
{ 0x1126, "HCR Print" },
|
||||
{ 0x1127, "HCR Scan" },
|
||||
{ 0x1128, "Common ISDN Access" },
|
||||
{ 0x112d, "SIM Access" },
|
||||
{ 0x112e, "Phonebook Access Client" },
|
||||
{ 0x112f, "Phonebook Access Server" },
|
||||
{ 0x1130, "Phonebook Access" },
|
||||
{ 0x1131, "Headset HS" },
|
||||
{ 0x1132, "Message Access Server" },
|
||||
{ 0x1133, "Message Notification Server" },
|
||||
{ 0x1134, "Message Access Profile" },
|
||||
{ 0x1135, "GNSS" },
|
||||
{ 0x1136, "GNSS Server" },
|
||||
{ 0x1200, "PnP Information" },
|
||||
{ 0x1201, "Generic Networking" },
|
||||
{ 0x1202, "Generic File Transfer" },
|
||||
{ 0x1203, "Generic Audio" },
|
||||
{ 0x1204, "Generic Telephony" },
|
||||
{ 0x1205, "UPNP Service" },
|
||||
{ 0x1206, "UPNP IP Service" },
|
||||
{ 0x1300, "UPNP IP PAN" },
|
||||
{ 0x1301, "UPNP IP LAP" },
|
||||
{ 0x1302, "UPNP IP L2CAP" },
|
||||
{ 0x1303, "Video Source" },
|
||||
{ 0x1304, "Video Sink" },
|
||||
{ 0x1305, "Video Distribution" },
|
||||
{ 0x1400, "HDP" },
|
||||
{ 0x1401, "HDP Source" },
|
||||
{ 0x1402, "HDP Sink" },
|
||||
{ 0x1800, "Generic Access Profile" },
|
||||
{ 0x1801, "Generic Attribute Profile" },
|
||||
{ 0x1802, "Immediate Alert" },
|
||||
{ 0x1803, "Link Loss" },
|
||||
{ 0x1804, "Tx Power" },
|
||||
{ 0x1805, "Current Time Service" },
|
||||
{ 0x1806, "Reference Time Update Service" },
|
||||
{ 0x1807, "Next DST Change Service" },
|
||||
{ 0x1808, "Glucose" },
|
||||
{ 0x1809, "Health Thermometer" },
|
||||
{ 0x180a, "Device Information" },
|
||||
/* 0x180b and 0x180c undefined */
|
||||
{ 0x180d, "Heart Rate" },
|
||||
{ 0x180e, "Phone Alert Status Service" },
|
||||
{ 0x180f, "Battery Service" },
|
||||
{ 0x1810, "Blood Pressure" },
|
||||
{ 0x1811, "Alert Notification Service" },
|
||||
{ 0x1812, "Human Interface Device" },
|
||||
{ 0x1813, "Scan Parameters" },
|
||||
{ 0x1814, "Running Speed and Cadence" },
|
||||
/* 0x1815 undefined */
|
||||
{ 0x1816, "Cycling Speed and Cadence" },
|
||||
{ 0x2800, "Primary Service" },
|
||||
{ 0x2801, "Secondary Service" },
|
||||
{ 0x2802, "Include" },
|
||||
{ 0x2803, "Characteristic" },
|
||||
{ 0x2900, "Characteristic Extended Properties" },
|
||||
{ 0x2901, "Characteristic User Description" },
|
||||
{ 0x2902, "Client Characteristic Configuration" },
|
||||
{ 0x2903, "Server Characteristic Configuration" },
|
||||
{ 0x2904, "Characteristic Format" },
|
||||
{ 0x2905, "Characteristic Aggregate Formate" },
|
||||
{ 0x2906, "Valid Range" },
|
||||
{ 0x2907, "External Report Reference" },
|
||||
{ 0x2908, "Report Reference" },
|
||||
{ 0x2a00, "Device Name" },
|
||||
{ 0x2a01, "Appearance" },
|
||||
{ 0x2a02, "Peripheral Privacy Flag" },
|
||||
{ 0x2a03, "Reconnection Address" },
|
||||
{ 0x2a04, "Peripheral Preferred Connection Parameters" },
|
||||
{ 0x2a05, "Service Changed" },
|
||||
{ 0x2a06, "Alert Level" },
|
||||
{ 0x2a07, "Tx Power Level" },
|
||||
{ 0x2a08, "Date Time" },
|
||||
{ 0x2a09, "Day of Week" },
|
||||
{ 0x2a0a, "Day Date Time" },
|
||||
/* 0x2a0b undefined */
|
||||
{ 0x2a0c, "Exact Time 256" },
|
||||
{ 0x2a0d, "DST Offset" },
|
||||
{ 0x2a0e, "Time Zone" },
|
||||
{ 0x2a0f, "Local Time Information" },
|
||||
/* 0x2a10 undefined */
|
||||
{ 0x2a11, "Time with DST" },
|
||||
{ 0x2a12, "Time Accuracy" },
|
||||
{ 0x2a13, "Time Source" },
|
||||
{ 0x2a14, "Reference Time Information" },
|
||||
/* 0x2a15 undefined */
|
||||
{ 0x2a16, "Time Update Control Point" },
|
||||
{ 0x2a17, "Time Update State" },
|
||||
{ 0x2a18, "Glucose Measurement" },
|
||||
{ 0x2a19, "Battery Level" },
|
||||
/* 0x2a1a and 0x2a1b undefined */
|
||||
{ 0x2a1c, "Temperature Measurement" },
|
||||
{ 0x2a1d, "Temperature Type" },
|
||||
{ 0x2a1e, "Intermediate Temperature" },
|
||||
/* 0x2a1f and 0x2a20 undefined */
|
||||
{ 0x2a21, "Measurement Interval" },
|
||||
{ 0x2a22, "Boot Keyboard Input Report" },
|
||||
{ 0x2a23, "System ID" },
|
||||
{ 0x2a24, "Model Number String" },
|
||||
{ 0x2a25, "Serial Number String" },
|
||||
{ 0x2a26, "Firmware Revision String" },
|
||||
{ 0x2a27, "Hardware Revision String" },
|
||||
{ 0x2a28, "Software Revision String" },
|
||||
{ 0x2a29, "Manufacturer Name String" },
|
||||
{ 0x2a2a, "IEEE 11073-20601 Regulatory Cert. Data List" },
|
||||
{ 0x2a2b, "Current Time" },
|
||||
/* 0x2a2c to 0x2a30 undefined */
|
||||
{ 0x2a31, "Scan Refresh" },
|
||||
{ 0x2a32, "Boot Keyboard Output Report" },
|
||||
{ 0x2a33, "Boot Mouse Input Report" },
|
||||
{ 0x2a34, "Glucose Measurement Context" },
|
||||
{ 0x2a35, "Blood Pressure Measurement" },
|
||||
{ 0x2a36, "Intermediate Cuff Pressure" },
|
||||
{ 0x2a37, "Heart Rate Measurement" },
|
||||
{ 0x2a38, "Body Sensor Location" },
|
||||
{ 0x2a39, "Heart Rate Control Point" },
|
||||
/* 0x2a3a to 0x2a3e undefined */
|
||||
{ 0x2a3f, "Alert Status" },
|
||||
{ 0x2a40, "Ringer Control Point" },
|
||||
{ 0x2a41, "Ringer Setting" },
|
||||
{ 0x2a42, "Alert Category ID Bit Mask" },
|
||||
{ 0x2a43, "Alert Category ID" },
|
||||
{ 0x2a44, "Alert Notification Control Point" },
|
||||
{ 0x2a45, "Unread Alert Status" },
|
||||
{ 0x2a46, "New Alert" },
|
||||
{ 0x2a47, "Supported New Alert Category" },
|
||||
{ 0x2a48, "Supported Unread Alert Category" },
|
||||
{ 0x2a49, "Blood Pressure Feature" },
|
||||
{ 0x2a4a, "HID Information" },
|
||||
{ 0x2a4b, "Report Map" },
|
||||
{ 0x2a4c, "HID Control Point" },
|
||||
{ 0x2a4d, "Report" },
|
||||
{ 0x2a4e, "Protocol Mode" },
|
||||
{ 0x2a4f, "Scan Interval Window" },
|
||||
{ 0x2a50, "PnP ID" },
|
||||
{ 0x2a51, "Glucose Feature" },
|
||||
{ 0x2a52, "Record Access Control Point" },
|
||||
{ 0x2a53, "RSC Measurement" },
|
||||
{ 0x2a54, "RSC Feature" },
|
||||
{ 0x2a55, "SC Control Point" },
|
||||
/* 0x2a56 to 0x2a5a undefined */
|
||||
{ 0x2a5b, "CSC Measurement" },
|
||||
{ 0x2a5c, "CSC Feature" },
|
||||
{ 0x2a5d, "Sensor Location" },
|
||||
{ }
|
||||
};
|
||||
|
||||
const char *uuid16_to_str(uint16_t uuid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; uuid16_table[i].str; i++) {
|
||||
if (uuid16_table[i].uuid == uuid)
|
||||
return uuid16_table[i].str;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
const char *uuid32_to_str(uint32_t uuid)
|
||||
{
|
||||
if ((uuid & 0xffff0000) == 0x0000)
|
||||
return uuid16_to_str(uuid & 0x0000ffff);
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
const char *uuid128_to_str(const unsigned char *uuid)
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
const char *uuidstr_to_str(const char *uuid)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
if (!uuid)
|
||||
return NULL;
|
||||
|
||||
if (strlen(uuid) != 36)
|
||||
return NULL;
|
||||
|
||||
if (strncasecmp(uuid + 8, "-0000-1000-8000-00805f9b34fb", 28))
|
||||
return "Vendor specific";
|
||||
|
||||
if (sscanf(uuid, "%08x-0000-1000-8000-00805f9b34fb", &val) != 1)
|
||||
return NULL;
|
||||
|
||||
return uuid32_to_str(val);
|
||||
}
|
||||
31
external/cache/sources/hcitools/monitor/uuid.h
vendored
Normal file
31
external/cache/sources/hcitools/monitor/uuid.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
const char *uuid16_to_str(uint16_t uuid);
|
||||
const char *uuid32_to_str(uint32_t uuid);
|
||||
const char *uuid128_to_str(const unsigned char *uuid);
|
||||
|
||||
const char *uuidstr_to_str(const char *uuid);
|
||||
35
external/cache/sources/hcitools/monitor/vendor.c
vendored
Normal file
35
external/cache/sources/hcitools/monitor/vendor.c
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; 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 "packet.h"
|
||||
#include "vendor.h"
|
||||
|
||||
void vendor_event(uint16_t manufacturer, const void *data, uint8_t size)
|
||||
{
|
||||
packet_hexdump(data, size);
|
||||
}
|
||||
27
external/cache/sources/hcitools/monitor/vendor.h
vendored
Normal file
27
external/cache/sources/hcitools/monitor/vendor.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void vendor_event(uint16_t manufacturer, const void *data, uint8_t size);
|
||||
Reference in New Issue
Block a user