summaryrefslogtreecommitdiff
path: root/tools/btinfo.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-01-01 20:53:29 -0800
committerMarcel Holtmann <marcel@holtmann.org>2014-01-01 20:53:58 -0800
commit28a3044d617bcd2f3969ac4971b193ce2f6391ce (patch)
tree6a264fe6f0d14ccd19b5f5956fb0bc111bda6183 /tools/btinfo.c
parent54c0afae729b08c7c21c5740765ca44ec6edbe19 (diff)
downloadbluez-28a3044d617bcd2f3969ac4971b193ce2f6391ce.tar.gz
tools: Use shared HCI code for information tool
Diffstat (limited to 'tools/btinfo.c')
-rw-r--r--tools/btinfo.c275
1 files changed, 92 insertions, 183 deletions
diff --git a/tools/btinfo.c b/tools/btinfo.c
index ed434e6a9..7b7ca42f2 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;
}