diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2014-01-01 20:53:29 -0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-01-01 20:53:58 -0800 |
commit | 28a3044d617bcd2f3969ac4971b193ce2f6391ce (patch) | |
tree | 6a264fe6f0d14ccd19b5f5956fb0bc111bda6183 /tools/btinfo.c | |
parent | 54c0afae729b08c7c21c5740765ca44ec6edbe19 (diff) | |
download | bluez-28a3044d617bcd2f3969ac4971b193ce2f6391ce.tar.gz |
tools: Use shared HCI code for information tool
Diffstat (limited to 'tools/btinfo.c')
-rw-r--r-- | tools/btinfo.c | 275 |
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; } |