Diff between 54c0afae729b08c7c21c5740765ca44ec6edbe19 and 28a3044d617bcd2f3969ac4971b193ce2f6391ce

Changed Files

File Additions Deletions Status
Makefile.tools +5 -1 modified
tools/btinfo.c +92 -183 modified

Full Patch

diff --git a/Makefile.tools b/Makefile.tools
index 662612f..627e3d9 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -215,7 +215,11 @@ tools_btmgmt_SOURCES = tools/btmgmt.c src/glib-helper.c src/eir.c \
 				src/shared/mgmt.h src/shared/mgmt.c
 tools_btmgmt_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
-tools_btinfo_SOURCES = tools/btinfo.c
+tools_btinfo_SOURCES = tools/btinfo.c monitor/bt.h \
+				monitor/mainloop.h monitor/mainloop.c \
+				src/shared/util.h src/shared/util.c \
+				src/shared/queue.h src/shared/queue.c \
+				src/shared/hci.h src/shared/hci.c
 
 tools_btsnoop_SOURCES = tools/btsnoop.c \
 				src/shared/pcap.h src/shared/pcap.c \
diff --git a/tools/btinfo.c b/tools/btinfo.c
index ed434e6..7b7ca42 100644
--- a/tools/btinfo.c
+++ b/tools/btinfo.c
@@ -26,189 +26,73 @@
 #include <config.h>
 #endif
 
-#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
 #include <stdlib.h>
-#include <alloca.h>
+#include <string.h>
 #include <getopt.h>
-#include <stdbool.h>
-#include <poll.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
 
+#include "monitor/mainloop.h"
 #include "monitor/bt.h"
+#include "src/shared/util.h"
+#include "src/shared/hci.h"
 
 #define le16_to_cpu(val) (val)
 #define le32_to_cpu(val) (val)
 #define cpu_to_le16(val) (val)
 #define cpu_to_le32(val) (val)
 
-struct bt_h4_pkt {
-	uint8_t type;
-	union {
-		struct {
-			uint16_t opcode;
-			uint8_t plen;
-			union {
-				uint8_t data;
-			};
-		} cmd;
-		struct {
-			uint8_t event;
-			uint8_t plen;
-			union {
-				uint8_t data;
-				struct bt_hci_evt_cmd_complete cmd_complete;
-				struct bt_hci_evt_cmd_status cmd_status;
-			};
-		} evt;
-	};
-} __attribute__ ((packed));
-
-static bool hci_request(int fd, uint16_t opcode,
-			const void *cmd_data, uint8_t cmd_len,
-			void *rsp_data, uint8_t rsp_size, uint8_t *rsp_len)
-{
-	struct bt_h4_pkt *cmd = alloca(4 + cmd_len);
-	struct bt_h4_pkt *rsp = alloca(2048);
-	ssize_t len;
-
-	cmd->type = BT_H4_CMD_PKT;
-	cmd->cmd.opcode = cpu_to_le16(opcode);
-	cmd->cmd.plen = cpu_to_le16(cmd_len);
-	if (cmd_len > 0)
-		memcpy(&cmd->cmd.data, cmd_data, cmd_len);
-
-	if (write(fd, cmd, 4 + cmd_len) < 0) {
-		perror("Failed to write command");
-		return false;
-	}
-
-	len = read(fd, rsp, 2048);
-	if (len < 0) {
-		perror("Failed to read event");
-		return false;
-	}
-
-	if (rsp->type != BT_H4_EVT_PKT) {
-		fprintf(stderr, "Unexpected packet type %d\n", rsp->type);
-		return false;
-	}
-
-	if (rsp->evt.event == BT_HCI_EVT_CMD_COMPLETE) {
-		if (opcode != le16_to_cpu(rsp->evt.cmd_complete.opcode))
-			return false;
-
-		if (rsp_data)
-			memcpy(rsp_data, (&rsp->evt.data) + 3, rsp->evt.plen - 3);
-
-		if (rsp_len)
-			*rsp_len = rsp->evt.plen - 3;
-
-		return true;
-	} else if (rsp->evt.event == BT_HCI_EVT_CMD_STATUS) {
-		if (opcode == le16_to_cpu(rsp->evt.cmd_status.opcode))
-			return false;
-
-		if (rsp->evt.cmd_status.status != BT_HCI_ERR_SUCCESS)
-			return false;
-
-		if (rsp_len)
-			*rsp_len = 0;
+static struct bt_hci *hci_dev;
+static bool reset_required = false;
 
-		return true;
-	}
+static void shutdown_timeout(int id, void *user_data)
+{
+	mainloop_remove_timeout(id);
 
-	return false;
+	mainloop_quit();
 }
 
-static int cmd_local(int fd, int argc, char *argv[])
+static void shutdown_complete(const void *data, uint8_t size, void *user_data)
 {
-	struct bt_hci_rsp_read_local_features lf;
-	struct bt_hci_rsp_read_local_version lv;
-	struct bt_hci_rsp_read_local_commands lc;
-	struct bt_hci_cmd_read_local_ext_features lef_cmd;
-	struct bt_hci_rsp_read_local_ext_features lef;
-	uint8_t len;
-
-	if (!hci_request(fd, BT_HCI_CMD_RESET, NULL, 0, NULL, 0, &len))
-		return EXIT_FAILURE;
-
-	if (!hci_request(fd, BT_HCI_CMD_READ_LOCAL_FEATURES, NULL, 0,
-						&lf, sizeof(lf), &len))
-		return EXIT_FAILURE;
-
-	if (lf.status != BT_HCI_ERR_SUCCESS)
-		return EXIT_FAILURE;
-
-	printf("Features: 0x%02x 0x%02x 0x%02x 0x%02x "
-					"0x%02x 0x%02x 0x%02x 0x%02x\n",
-					lf.features[0], lf.features[1],
-					lf.features[2], lf.features[3],
-					lf.features[4], lf.features[5],
-					lf.features[6], lf.features[7]);
-
-	if (!hci_request(fd, BT_HCI_CMD_READ_LOCAL_VERSION, NULL, 0,
-						&lv, sizeof(lv), &len))
-		return EXIT_FAILURE;
-
-	if (lv.status != BT_HCI_ERR_SUCCESS)
-		return EXIT_FAILURE;
-
-	printf("Version: %d\n", lv.hci_ver);
-	printf("Manufacturer: %d\n", le16_to_cpu(lv.manufacturer));
+	unsigned int id = PTR_TO_UINT(user_data);
 
-	if (!hci_request(fd, BT_HCI_CMD_READ_LOCAL_COMMANDS, NULL, 0,
-						&lc, sizeof(lc), &len))
-		return EXIT_FAILURE;
-
-	if (lc.status != BT_HCI_ERR_SUCCESS)
-		return EXIT_FAILURE;
-
-	if (!(lf.features[7] & 0x80))
-		return EXIT_SUCCESS;
-
-	lef_cmd.page = 0x01;
-
-	if (!hci_request(fd, BT_HCI_CMD_READ_LOCAL_EXT_FEATURES,
-						&lef_cmd, sizeof(lef_cmd),
-						&lef, sizeof(lef), &len))
-		return EXIT_FAILURE;
+	shutdown_timeout(id, NULL);
+}
 
-	if (lef.status != BT_HCI_ERR_SUCCESS)
-		return EXIT_FAILURE;
+static void shutdown_device(void)
+{
+	unsigned int id;
 
-	printf("Host features: 0x%02x 0x%02x 0x%02x 0x%02x "
-					"0x%02x 0x%02x 0x%02x 0x%02x\n",
-					lef.features[0], lef.features[1],
-					lef.features[2], lef.features[3],
-					lef.features[4], lef.features[5],
-					lef.features[6], lef.features[7]);
+	bt_hci_flush(hci_dev);
 
-	if (lef.max_page < 0x02)
-		return EXIT_SUCCESS;
+	if (reset_required) {
+		id = mainloop_add_timeout(5, shutdown_timeout, NULL, NULL);
 
-	lef_cmd.page = 0x02;
+		bt_hci_send(hci_dev, BT_HCI_CMD_RESET, NULL, 0,
+				shutdown_complete, UINT_TO_PTR(id), NULL);
+	} else
+		mainloop_quit();
+}
 
-	if (!hci_request(fd, BT_HCI_CMD_READ_LOCAL_EXT_FEATURES,
-						&lef_cmd, sizeof(lef_cmd),
-						&lef, sizeof(lef), &len))
-		return EXIT_FAILURE;
+static void local_features_callback(const void *data, uint8_t size,
+							void *user_data)
+{
+	shutdown_device();
+}
 
-	if (lef.status != BT_HCI_ERR_SUCCESS)
-		return EXIT_FAILURE;
+static bool cmd_local(int argc, char *argv[])
+{
+	if (reset_required)
+		bt_hci_send(hci_dev, BT_HCI_CMD_RESET, NULL, 0,
+						NULL, NULL, NULL);
 
-	printf("Extended features: 0x%02x 0x%02x 0x%02x 0x%02x "
-					"0x%02x 0x%02x 0x%02x 0x%02x\n",
-					lef.features[0], lef.features[1],
-					lef.features[2], lef.features[3],
-					lef.features[4], lef.features[5],
-					lef.features[6], lef.features[7]);
+	bt_hci_send(hci_dev, BT_HCI_CMD_READ_LOCAL_FEATURES, NULL, 0,
+					local_features_callback, NULL, NULL);
 
-	return EXIT_SUCCESS;
+	return true;
 }
 
-typedef int (*cmd_func_t)(int fd, int argc, char *argv[]);
+typedef bool (*cmd_func_t)(int argc, char *argv[]);
 
 static const struct {
 	const char *name;
@@ -219,6 +103,21 @@ static const struct {
 	{ }
 };
 
+static void signal_callback(int signum, void *user_data)
+{
+	static bool terminated = false;
+
+	switch (signum) {
+	case SIGINT:
+	case SIGTERM:
+		if (!terminated) {
+			shutdown_device();
+			terminated = true;
+		}
+		break;
+	}
+}
+
 static void usage(void)
 {
 	int i;
@@ -227,15 +126,15 @@ static void usage(void)
 		"Usage:\n");
 	printf("\tbtinfo [options] <command>\n");
 	printf("options:\n"
-		"\t-i, --device <hcidev>    Use local HCI device\n"
-		"\t-h, --help               Show help options\n");
+		"\t-i, --index <num>      Use specified controller\n"
+		"\t-h, --help             Show help options\n");
 	printf("commands:\n");
 	for (i = 0; cmd_table[i].name; i++)
 		printf("\t%-25s%s\n", cmd_table[i].name, cmd_table[i].help);
 }
 
 static const struct option main_options[] = {
-	{ "device",  required_argument, NULL, 'i' },
+	{ "index",   required_argument, NULL, 'i' },
 	{ "version", no_argument,       NULL, 'v' },
 	{ "help",    no_argument,       NULL, 'h' },
 	{ }
@@ -243,22 +142,30 @@ static const struct option main_options[] = {
 
 int main(int argc, char *argv[])
 {
-	const char *device = NULL;
 	cmd_func_t func = NULL;
-	struct sockaddr_hci addr;
-	int result, fd, i;
+	uint16_t index = 0;
+	const char *str;
+	sigset_t mask;
+	int i, exit_status;
 
 	for (;;) {
 		int opt;
 
-		opt = getopt_long(argc, argv, "i:vh",
-						main_options, NULL);
+		opt = getopt_long(argc, argv, "i:vh", main_options, NULL);
 		if (opt < 0)
 			break;
 
 		switch (opt) {
 		case 'i':
-			device = optarg;
+			if (strlen(optarg) > 3 && !strncmp(optarg, "hci", 3))
+				str = optarg + 3;
+			else
+				str = optarg;
+			if (!isdigit(*str)) {
+				usage();
+				return EXIT_FAILURE;
+			}
+			index = atoi(str);
 			break;
 		case 'v':
 			printf("%s\n", VERSION);
@@ -288,30 +195,32 @@ int main(int argc, char *argv[])
 		return EXIT_FAILURE;
 	}
 
-	fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
-	if (fd < 0) {
-		perror("Failed to open channel");
+	mainloop_init();
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	mainloop_set_signal(&mask, signal_callback, NULL, NULL);
+
+	printf("3D Synchronization Profile testing ver %s\n", VERSION);
+
+	hci_dev = bt_hci_new_user_channel(index);
+	if (!hci_dev) {
+		fprintf(stderr, "Failed to open HCI user channel\n");
 		return EXIT_FAILURE;
 	}
 
-	memset(&addr, 0, sizeof(addr));
-	addr.hci_family = AF_BLUETOOTH;
-	addr.hci_channel = HCI_CHANNEL_USER;
-
-	if (device)
-		addr.hci_dev = atoi(device);
-	else
-		addr.hci_dev = 0;
+	reset_required = true;
 
-	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("Failed to bind channel");
-		close(fd);
+	if (!func(argc - optind - 1, argv + optind + 1)) {
+		bt_hci_unref(hci_dev);
 		return EXIT_FAILURE;
 	}
 
-	result = func(fd, argc - optind - 1, argv + optind + 1);
+	exit_status = mainloop_run();
 
-	close(fd);
+	bt_hci_unref(hci_dev);
 
-	return result;
+	return exit_status;
 }