📄 hcitool.c
字号:
} if (hci_read_remote_name(dd, &bdaddr, sizeof(name), name, 25000) == 0) printf("%s\n", name); close(dd);}/* Info about remote device */static struct option info_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *info_help = "Usage:\n" "\tinfo <bdaddr>\n";static void cmd_info(int dev_id, int argc, char **argv){ bdaddr_t bdaddr; uint16_t handle; uint8_t max_page, features[8]; char name[249], oui[9], *comp; struct hci_version version; struct hci_dev_info di; struct hci_conn_info_req *cr; int opt, dd, cc = 0; for_each_opt(opt, info_options, NULL) { switch (opt) { default: printf(info_help); return; } } argc -= optind; argv += optind; if (argc < 1) { printf(info_help); return; } str2ba(argv[0], &bdaddr); if (dev_id < 0) dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); if (dev_id < 0) dev_id = hci_get_route(&bdaddr); if (dev_id < 0) { fprintf(stderr, "Device is not available or not connected.\n"); exit(1); } if (hci_devinfo(dev_id, &di) < 0) { perror("Can't get device info"); exit(1); } printf("Requesting information ...\n"); dd = hci_open_dev(dev_id); if (dd < 0) { perror("HCI device open failed"); exit(1); } cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); if (!cr) { perror("Can't get connection info"); close(dd); exit(1); } bacpy(&cr->bdaddr, &bdaddr); cr->type = ACL_LINK; if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { if (hci_create_connection(dd, &bdaddr, htobs(di.pkt_type & ACL_PTYPE_MASK), 0, 0x01, &handle, 25000) < 0) { perror("Can't create connection"); close(dd); exit(1); } cc = 1; } else handle = htobs(cr->conn_info->handle); printf("\tBD Address: %s\n", argv[0]); ba2oui(&bdaddr, oui); comp = ouitocomp(oui); if (comp) { printf("\tOUI Company: %s (%s)\n", comp, oui); free(comp); } if (hci_read_remote_name(dd, &bdaddr, sizeof(name), name, 25000) == 0) printf("\tDevice Name: %s\n", name); if (hci_read_remote_version(dd, handle, &version, 20000) == 0) { char *ver = lmp_vertostr(version.lmp_ver); printf("\tLMP Version: %s (0x%x) LMP Subversion: 0x%x\n" "\tManufacturer: %s (%d)\n", ver ? ver : "n/a", version.lmp_ver, version.lmp_subver, bt_compidtostr(version.manufacturer), version.manufacturer); if (ver) bt_free(ver); } if (hci_read_remote_features(dd, handle, features, 20000) == 0) { char *tmp = lmp_featurestostr(features, "\t\t", 63); printf("\tFeatures: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n%s\n", features[0], features[1], features[2], features[3], features[4], features[5], features[6], features[7], tmp); bt_free(tmp); } if (features[7] & LMP_EXT_FEAT) { if (hci_read_remote_ext_features(dd, handle, 0, &max_page, features, 20000) == 0) if (max_page > 0) printf("\tExtended features: %d pages\n", max_page); } if (cc) { usleep(10000); hci_disconnect(dd, handle, HCI_OE_USER_ENDED_CONNECTION, 10000); } close(dd);}/* Send arbitrary HCI commands */static struct option cmd_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *cmd_help = "Usage:\n" "\tcmd <ogf> <ocf> [parameters]\n" "Example:\n" "\tcmd 0x03 0x0013 0x41 0x42 0x43 0x44\n";static void cmd_cmd(int dev_id, int argc, char **argv){ unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf; struct hci_filter flt; hci_event_hdr *hdr; int i, opt, len, dd; uint16_t ocf; uint8_t ogf; for_each_opt(opt, cmd_options, NULL) { switch (opt) { default: printf(cmd_help); return; } } argc -= optind; argv += optind; if (argc < 2) { printf(cmd_help); return; } if (dev_id < 0) dev_id = hci_get_route(NULL); errno = 0; ogf = strtol(argv[0], NULL, 16); ocf = strtol(argv[1], NULL, 16); if (errno == ERANGE || (ogf > 0x3f) || (ocf > 0x3ff)) { printf(cmd_help); return; } for (i = 2, len = 0; i < argc && len < sizeof(buf); i++, len++) *ptr++ = (uint8_t) strtol(argv[i], NULL, 16); dd = hci_open_dev(dev_id); if (dd < 0) { perror("Device open failed"); exit(EXIT_FAILURE); } /* Setup filter */ hci_filter_clear(&flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_all_events(&flt); if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { perror("HCI filter setup failed"); exit(EXIT_FAILURE); } printf("< HCI Command: ogf 0x%02x, ocf 0x%04x, plen %d\n", ogf, ocf, len); hex_dump(" ", 20, buf, len); fflush(stdout); if (hci_send_cmd(dd, ogf, ocf, len, buf) < 0) { perror("Send failed"); exit(EXIT_FAILURE); } len = read(dd, buf, sizeof(buf)); if (len < 0) { perror("Read failed"); exit(EXIT_FAILURE); } hdr = (void *)(buf + 1); ptr = buf + (1 + HCI_EVENT_HDR_SIZE); len -= (1 + HCI_EVENT_HDR_SIZE); printf("> HCI Event: 0x%02x plen %d\n", hdr->evt, hdr->plen); hex_dump(" ", 20, ptr, len); fflush(stdout); hci_close_dev(dd);}/* Display active connections */static struct option con_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *con_help = "Usage:\n" "\tcon\n";static void cmd_con(int dev_id, int argc, char **argv){ int opt; for_each_opt(opt, con_options, NULL) { switch (opt) { default: printf(con_help); return; } } printf("Connections:\n"); hci_for_each_dev(HCI_UP, conn_list, dev_id);}/* Create connection */static struct option cc_options[] = { { "help", 0, 0, 'h' }, { "role", 1, 0, 'r' }, { "ptype", 1, 0, 'p' }, { 0, 0, 0, 0 }};static char *cc_help = "Usage:\n" "\tcc [--role=m|s] [--ptype=pkt_types] <bdaddr>\n" "Example:\n" "\tcc --ptype=dm1,dh3,dh5 01:02:03:04:05:06\n" "\tcc --role=m 01:02:03:04:05:06\n";static void cmd_cc(int dev_id, int argc, char **argv){ bdaddr_t bdaddr; uint16_t handle; uint8_t role; unsigned int ptype; int dd, opt; role = 0x01; ptype = HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5; for_each_opt(opt, cc_options, NULL) { switch (opt) { case 'p': hci_strtoptype(optarg, &ptype); break; case 'r': role = optarg[0] == 'm' ? 0 : 1; break; default: printf(cc_help); return; } } argc -= optind; argv += optind; if (argc < 1) { printf(cc_help); return; } str2ba(argv[0], &bdaddr); if (dev_id < 0) { dev_id = hci_get_route(&bdaddr); if (dev_id < 0) { fprintf(stderr, "Device is not available.\n"); exit(1); } } dd = hci_open_dev(dev_id); if (dd < 0) { perror("HCI device open failed"); exit(1); } if (hci_create_connection(dd, &bdaddr, htobs(ptype), htobs(0x0000), role, &handle, 25000) < 0) perror("Can't create connection"); hci_close_dev(dd);}/* Close connection */static struct option dc_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *dc_help = "Usage:\n" "\tdc <bdaddr>\n";static void cmd_dc(int dev_id, int argc, char **argv){ struct hci_conn_info_req *cr; bdaddr_t bdaddr; int opt, dd; for_each_opt(opt, dc_options, NULL) { switch (opt) { default: printf(dc_help); return; } } argc -= optind; argv += optind; if (argc < 1) { printf(dc_help); return; } str2ba(argv[0], &bdaddr); if (dev_id < 0) { dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); if (dev_id < 0) { fprintf(stderr, "Not connected.\n"); exit(1); } } dd = hci_open_dev(dev_id); if (dd < 0) { perror("HCI device open failed"); exit(1); } cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); if (!cr) { perror("Can't allocate memory"); exit(1); } bacpy(&cr->bdaddr, &bdaddr); cr->type = ACL_LINK; if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { perror("Get connection info failed"); exit(1); } if (hci_disconnect(dd, htobs(cr->conn_info->handle), HCI_OE_USER_ENDED_CONNECTION, 10000) < 0) perror("Disconnect failed"); close(dd); free(cr);}/* Role switch */static struct option sr_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *sr_help = "Usage:\n" "\tsr <bdaddr> <role>\n";static void cmd_sr(int dev_id, int argc, char **argv){ bdaddr_t bdaddr; uint8_t role; int opt, dd; for_each_opt(opt, sr_options, NULL) { switch (opt) { default: printf(sr_help); return; } } argc -= optind; argv += optind; if (argc < 2) { printf(sr_help); return; } str2ba(argv[0], &bdaddr); switch (argv[1][0]) { case 'm': role = 0; break; case 's': role = 1; break; default: role = atoi(argv[1]); break; } if (dev_id < 0) { dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); if (dev_id < 0) { fprintf(stderr, "Not connected.\n"); exit(1); } } dd = hci_open_dev(dev_id); if (dd < 0) { perror("HCI device open failed"); exit(1); } if (hci_switch_role(dd, &bdaddr, role, 10000) < 0) { perror("Switch role request failed"); exit(1); } close(dd);}/* Read RSSI */static struct option rssi_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *rssi_help = "Usage:\n" "\trssi <bdaddr>\n";static void cmd_rssi(int dev_id, int argc, char **argv){ struct hci_conn_info_req *cr; bdaddr_t bdaddr; int8_t rssi; int opt, dd; for_each_opt(opt, rssi_options, NULL) { switch (opt) { default: printf(rssi_help); return; } } argc -= optind; argv += optind; if (argc < 1) { printf(rssi_help); return; } str2ba(argv[0], &bdaddr); if (dev_id < 0) { dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); if (dev_id < 0) { fprintf(stderr, "Not connected.\n"); exit(1); } } dd = hci_open_dev(dev_id); if (dd < 0) { perror("HCI device open failed"); exit(1); } cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); if (!cr) { perror("Can't allocate memory"); exit(1); } bacpy(&cr->bdaddr, &bdaddr); cr->type = ACL_LINK; if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { perror("Get connection info failed"); exit(1); } if (hci_read_rssi(dd, htobs(cr->conn_info->handle), &rssi, 1000) < 0) { perror("Read RSSI failed"); exit(1); } printf("RSSI return value: %d\n", rssi); close(dd); free(cr);}/* Get link quality */static struct option lq_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *lq_help = "Usage:\n" "\tlq <bdaddr>\n";static void cmd_lq(int dev_id, int argc, char **argv){ struct hci_conn_info_req *cr; bdaddr_t bdaddr; uint8_t lq; int opt, dd; for_each_opt(opt, lq_options, NULL) { switch (opt) { default: printf(lq_help); return; } } argc -= optind; argv += optind; if (argc < 1) { printf(lq_help); return; } str2ba(argv[0], &bdaddr); if (dev_id < 0) { dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); if (dev_id < 0) { fprintf(stderr, "Not connected.\n"); exit(1); } } dd = hci_open_dev(dev_id); if (dd < 0) { perror("HCI device open failed"); exit(1); } cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); if (!cr) { perror("Can't allocate memory"); exit(1); } bacpy(&cr->bdaddr, &bdaddr); cr->type = ACL_LINK; if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { perror("Get connection info failed"); exit(1); } if (hci_read_link_quality(dd, htobs(cr->conn_info->handle), &lq, 1000) < 0) { perror("HCI read_link_quality request failed"); exit(1); } printf("Link quality: %d\n", lq); close(dd); free(cr);}/* Get transmit power level */static struct option tpl_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *tpl_help = "Usage:\n" "\ttpl <bdaddr> [type]\n";static void cmd_tpl(int dev_id, int argc, char **argv){ struct hci_conn_info_req *cr; bdaddr_t bdaddr; uint8_t type; int8_t level; int opt, dd; for_each_opt(opt, tpl_options, NULL) { switch (opt) { default: printf(tpl_help); return; } } argc -= optind; argv += optind; if (argc < 1) { printf(tpl_help); return; } str2ba(argv[0], &bdaddr); type = (argc > 1) ? atoi(argv[1]) : 0; if (dev_id < 0) { dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); if (dev_id < 0) { fprintf(stderr, "Not connected.\n"); exit(1); } } dd = hci_open_dev(dev_id); if (dd < 0) { perror("HCI device open failed"); exit(1); } cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); if (!cr) { perror("Can't allocate memory"); exit(1); } bacpy(&cr->bdaddr, &bdaddr); cr->type = ACL_LINK; if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { perror("Get connection info failed"); exit(1); } if (hci_read_transmit_power_level(dd, htobs(cr->conn_info->handle), type, &level, 1000) < 0) { perror("HCI read transmit power level request failed"); exit(1); } printf("%s transmit power level: %d\n", (type == 0) ? "Current" : "Maximum", level); close(dd); free(cr);}/* Get AFH channel map */static struct option afh_options[] = { { "help", 0, 0, 'h' }, { 0, 0, 0, 0 }};static char *afh_help = "Usage:\n" "\tafh <bdaddr>\n";static void cmd_afh(int dev_id, int argc, char **argv){ struct hci_conn_info_req *cr; bdaddr_t bdaddr; uint16_t handle; uint8_t mode, map[10]; int opt, dd; for_each_opt(opt, afh_options, NULL) { switch (opt) { default: printf(afh_help); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -