📄 hciconfig.c
字号:
} hci_close_dev(dd);}static void cmd_inq_parms(int ctl, int hdev, char *opt){ struct hci_request rq; int s; if ((s = hci_open_dev(hdev)) < 0) { fprintf(stderr, "Can't open device hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } memset(&rq, 0, sizeof(rq)); if (opt) { unsigned int window, interval; write_inq_activity_cp cp; if (sscanf(opt,"%4u:%4u", &window, &interval) != 2) { printf("Invalid argument format\n"); exit(1); } rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_WRITE_INQ_ACTIVITY; rq.cparam = &cp; rq.clen = WRITE_INQ_ACTIVITY_CP_SIZE; cp.window = htobs((uint16_t) window); cp.interval = htobs((uint16_t) interval); if (window < 0x12 || window > 0x1000) printf("Warning: inquiry window out of range!\n"); if (interval < 0x12 || interval > 0x1000) printf("Warning: inquiry interval out of range!\n"); if (hci_send_req(s, &rq, 2000) < 0) { fprintf(stderr, "Can't set inquiry parameters name on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } } else { uint16_t window, interval; read_inq_activity_rp rp; rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_READ_INQ_ACTIVITY; rq.rparam = &rp; rq.rlen = READ_INQ_ACTIVITY_RP_SIZE; if (hci_send_req(s, &rq, 1000) < 0) { fprintf(stderr, "Can't read inquiry parameters on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } if (rp.status) { printf("Read inquiry parameters on hci%d returned status %d\n", hdev, rp.status); exit(1); } print_dev_hdr(&di); window = btohs(rp.window); interval = btohs(rp.interval); printf("\tInquiry interval: %u slots (%.2f ms), window: %u slots (%.2f ms)\n", interval, (float)interval * 0.625, window, (float)window * 0.625); }}static void cmd_page_parms(int ctl, int hdev, char *opt){ struct hci_request rq; int s; if ((s = hci_open_dev(hdev)) < 0) { fprintf(stderr, "Can't open device hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } memset(&rq, 0, sizeof(rq)); if (opt) { unsigned int window, interval; write_page_activity_cp cp; if (sscanf(opt,"%4u:%4u", &window, &interval) != 2) { printf("Invalid argument format\n"); exit(1); } rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_WRITE_PAGE_ACTIVITY; rq.cparam = &cp; rq.clen = WRITE_PAGE_ACTIVITY_CP_SIZE; cp.window = htobs((uint16_t) window); cp.interval = htobs((uint16_t) interval); if (window < 0x12 || window > 0x1000) printf("Warning: page window out of range!\n"); if (interval < 0x12 || interval > 0x1000) printf("Warning: page interval out of range!\n"); if (hci_send_req(s, &rq, 2000) < 0) { fprintf(stderr, "Can't set page parameters name on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } } else { uint16_t window, interval; read_page_activity_rp rp; rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_READ_PAGE_ACTIVITY; rq.rparam = &rp; rq.rlen = READ_PAGE_ACTIVITY_RP_SIZE; if (hci_send_req(s, &rq, 1000) < 0) { fprintf(stderr, "Can't read page parameters on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } if (rp.status) { printf("Read page parameters on hci%d returned status %d\n", hdev, rp.status); exit(1); } print_dev_hdr(&di); window = btohs(rp.window); interval = btohs(rp.interval); printf("\tPage interval: %u slots (%.2f ms), window: %u slots (%.2f ms)\n", interval, (float)interval * 0.625, window, (float)window * 0.625); }}static void cmd_page_to(int ctl, int hdev, char *opt){ struct hci_request rq; int s; if ((s = hci_open_dev(hdev)) < 0) { fprintf(stderr, "Can't open device hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } memset(&rq, 0, sizeof(rq)); if (opt) { unsigned int timeout; write_page_timeout_cp cp; if (sscanf(opt,"%5u", &timeout) != 1) { printf("Invalid argument format\n"); exit(1); } rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_WRITE_PAGE_TIMEOUT; rq.cparam = &cp; rq.clen = WRITE_PAGE_TIMEOUT_CP_SIZE; cp.timeout = htobs((uint16_t) timeout); if (timeout < 0x01 || timeout > 0xFFFF) printf("Warning: page timeout out of range!\n"); if (hci_send_req(s, &rq, 2000) < 0) { fprintf(stderr, "Can't set page timeout on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } } else { uint16_t timeout; read_page_timeout_rp rp; rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_READ_PAGE_TIMEOUT; rq.rparam = &rp; rq.rlen = READ_PAGE_TIMEOUT_RP_SIZE; if (hci_send_req(s, &rq, 1000) < 0) { fprintf(stderr, "Can't read page timeout on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } if (rp.status) { printf("Read page timeout on hci%d returned status %d\n", hdev, rp.status); exit(1); } print_dev_hdr(&di); timeout = btohs(rp.timeout); printf("\tPage timeout: %u slots (%.2f ms)\n", timeout, (float)timeout * 0.625); }}static void cmd_afh_mode(int ctl, int hdev, char *opt){ int dd; dd = hci_open_dev(hdev); if (dd < 0) { fprintf(stderr, "Can't open device hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } if (opt) { uint8_t mode = atoi(opt); if (hci_write_afh_mode(dd, mode, 2000) < 0) { fprintf(stderr, "Can't set AFH mode on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } } else { uint8_t mode; if (hci_read_afh_mode(dd, &mode, 1000) < 0) { fprintf(stderr, "Can't read AFH mode on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } print_dev_hdr(&di); printf("\tAFH mode: %s\n", mode == 1 ? "Enabled" : "Disabled"); }}static void cmd_ssp_mode(int ctl, int hdev, char *opt){ int dd; dd = hci_open_dev(hdev); if (dd < 0) { fprintf(stderr, "Can't open device hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } if (opt) { uint8_t mode = atoi(opt); if (hci_write_simple_pairing_mode(dd, mode, 2000) < 0) { fprintf(stderr, "Can't set Simple Pairing mode on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } } else { uint8_t mode; if (hci_read_simple_pairing_mode(dd, &mode, 1000) < 0) { fprintf(stderr, "Can't read Simple Pairing mode on hci%d: %s (%d)\n", hdev, strerror(errno), errno); exit(1); } print_dev_hdr(&di); printf("\tSimple Pairing mode: %s\n", mode == 1 ? "Enabled" : "Disabled"); }}static void print_rev_ericsson(int dd){ struct hci_request rq; unsigned char buf[102]; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = 0x000f; rq.cparam = NULL; rq.clen = 0; rq.rparam = &buf; rq.rlen = sizeof(buf); if (hci_send_req(dd, &rq, 1000) < 0) { printf("\nCan't read revision info: %s (%d)\n", strerror(errno), errno); return; } printf("\t%s\n", buf + 1);}static void print_rev_csr(int dd, uint16_t rev){ uint16_t buildid, chipver, chiprev, maxkeylen, mapsco; if (csr_read_varid_uint16(dd, 0, CSR_VARID_BUILDID, &buildid) < 0) { printf("\t%s\n", csr_buildidtostr(rev)); return; } printf("\t%s\n", csr_buildidtostr(buildid)); if (!csr_read_varid_uint16(dd, 1, CSR_VARID_CHIPVER, &chipver)) { if (csr_read_varid_uint16(dd, 2, CSR_VARID_CHIPREV, &chiprev) < 0) chiprev = 0; printf("\tChip version: %s\n", csr_chipvertostr(chipver, chiprev)); } if (!csr_read_varid_uint16(dd, 3, CSR_VARID_MAX_CRYPT_KEY_LENGTH, &maxkeylen)) printf("\tMax key size: %d bit\n", maxkeylen * 8); if (!csr_read_pskey_uint16(dd, 4, CSR_PSKEY_HOSTIO_MAP_SCO_PCM, 0x0000, &mapsco)) printf("\tSCO mapping: %s\n", mapsco ? "PCM" : "HCI");}static void print_rev_digianswer(int dd){ struct hci_request rq; unsigned char req[] = { 0x07 }; unsigned char buf[102]; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = 0x000e; rq.cparam = req; rq.clen = sizeof(req); rq.rparam = &buf; rq.rlen = sizeof(buf); if (hci_send_req(dd, &rq, 1000) < 0) { printf("\nCan't read revision info: %s (%d)\n", strerror(errno), errno); return; } printf("\t%s\n", buf + 1);}static void print_rev_broadcom(uint16_t hci_rev, uint16_t lmp_subver){ printf("\tFirmware %d.%d / %d\n", hci_rev & 0xff, lmp_subver >> 8, lmp_subver & 0xff);}static void print_rev_avm(uint16_t hci_rev, uint16_t lmp_subver){ if (lmp_subver == 0x01) printf("\tFirmware 03.%d.%d\n", hci_rev >> 8, hci_rev & 0xff); else printf("\tUnknown type\n");}static void cmd_revision(int ctl, int hdev, char *opt){ struct hci_version ver; int dd; dd = hci_open_dev(hdev); if (dd < 0) { fprintf(stderr, "Can't open device hci%d: %s (%d)\n", hdev, strerror(errno), errno); return; } if (hci_read_local_version(dd, &ver, 1000) < 0) { fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n", hdev, strerror(errno), errno); return; } print_dev_hdr(&di); switch (ver.manufacturer) { case 0: case 37: case 48: print_rev_ericsson(dd); break; case 10: print_rev_csr(dd, ver.hci_rev); break; case 12: print_rev_digianswer(dd); break; case 15: print_rev_broadcom(ver.hci_rev, ver.lmp_subver); break; case 31: print_rev_avm(ver.hci_rev, ver.lmp_subver); break; default: printf("\tUnsupported manufacturer\n"); break; } return;}static void print_dev_hdr(struct hci_dev_info *di){ static int hdr = -1; char addr[18]; if (hdr == di->dev_id) return; hdr = di->dev_id; ba2str(&di->bdaddr, addr); printf("%s:\tType: %s\n", di->name, hci_dtypetostr(di->type) ); printf("\tBD Address: %s ACL MTU: %d:%d SCO MTU: %d:%d\n", addr, di->acl_mtu, di->acl_pkts, di->sco_mtu, di->sco_pkts);}static void print_dev_info(int ctl, struct hci_dev_info *di){ struct hci_dev_stats *st = &di->stat; print_dev_hdr(di); printf("\t%s\n", hci_dflagstostr(di->flags) ); printf("\tRX bytes:%d acl:%d sco:%d events:%d errors:%d\n", st->byte_rx, st->acl_rx, st->sco_rx, st->evt_rx, st->err_rx); printf("\tTX bytes:%d acl:%d sco:%d commands:%d errors:%d\n", st->byte_tx, st->acl_tx, st->sco_tx, st->cmd_tx, st->err_tx); if (all && !hci_test_bit(HCI_RAW, &di->flags) && bacmp(&di->bdaddr, BDADDR_ANY)) { print_dev_features(di, 0); print_pkt_type(di); print_link_policy(di); print_link_mode(di); if (hci_test_bit(HCI_UP, &di->flags)) { cmd_name(ctl, di->dev_id, NULL); cmd_class(ctl, di->dev_id, NULL); cmd_version(ctl, di->dev_id, NULL); } } printf("\n");}static struct { char *cmd; void (*func)(int ctl, int hdev, char *opt); char *opt; char *doc;} command[] = { { "up", cmd_up, 0, "Open and initialize HCI device" }, { "down", cmd_down, 0, "Close HCI device" }, { "reset", cmd_reset, 0, "Reset HCI device" }, { "rstat", cmd_rstat, 0, "Reset statistic counters" }, { "auth", cmd_auth, 0, "Enable Authentication" }, { "noauth", cmd_auth, 0, "Disable Authentication" }, { "encrypt", cmd_encrypt, 0, "Enable Encryption" }, { "noencrypt", cmd_encrypt, 0, "Disable Encryption" }, { "piscan", cmd_scan, 0, "Enable Page and Inquiry scan" }, { "noscan", cmd_scan, 0, "Disable scan" }, { "iscan", cmd_scan, 0, "Enable Inquiry scan" }, { "pscan", cmd_scan, 0, "Enable Page scan" }, { "ptype", cmd_ptype, "[type]", "Get/Set default packet type" }, { "lm", cmd_lm, "[mode]", "Get/Set default link mode" }, { "lp", cmd_lp, "[policy]", "Get/Set default link policy" }, { "name", cmd_name, "[name]", "Get/Set local name" }, { "class", cmd_class, "[class]", "Get/Set class of device" }, { "voice", cmd_voice, "[voice]", "Get/Set voice setting" }, { "iac", cmd_iac, "[iac]", "Get/Set inquiry access code" }, { "inqtpl", cmd_inq_tpl, "[level]", "Get/Set inquiry transmit power level" }, { "inqmode", cmd_inq_mode, "[mode]", "Get/Set inquiry mode" }, { "inqdata", cmd_inq_data, "[data]", "Get/Set inquiry data" }, { "inqtype", cmd_inq_type, "[type]", "Get/Set inquiry scan type" }, { "inqparms", cmd_inq_parms, "[win:int]", "Get/Set inquiry scan window and interval" }, { "pageparms", cmd_page_parms, "[win:int]", "Get/Set page scan window and interval" }, { "pageto", cmd_page_to, "[to]", "Get/Set page timeout" }, { "afhmode", cmd_afh_mode, "[mode]", "Get/Set AFH mode" }, { "sspmode", cmd_ssp_mode, "[mode]", "Get/Set Simple Pairing Mode" }, { "aclmtu", cmd_aclmtu, "<mtu:pkt>", "Set ACL MTU and number of packets" }, { "scomtu", cmd_scomtu, "<mtu:pkt>", "Set SCO MTU and number of packets" }, { "putkey", cmd_putkey, "<bdaddr>", "Store link key on the device" }, { "delkey", cmd_delkey, "<bdaddr>", "Delete link key from the device" }, { "oobdata", cmd_oob_data, 0, "Display local OOB data" }, { "commands", cmd_commands, 0, "Display supported commands" }, { "features", cmd_features, 0, "Display device features" }, { "version", cmd_version, 0, "Display version information" }, { "revision", cmd_revision, 0, "Display revision information" }, { NULL, NULL, 0 }};static void usage(void){ int i; printf("hciconfig - HCI device configuration utility\n"); printf("Usage:\n" "\thciconfig\n" "\thciconfig [-a] hciX [command]\n"); printf("Commands:\n"); for (i=0; command[i].cmd; i++) printf("\t%-10s %-8s\t%s\n", command[i].cmd, command[i].opt ? command[i].opt : " ", command[i].doc);}static struct option main_options[] = { { "help", 0, 0, 'h' }, { "all", 0, 0, 'a' }, { 0, 0, 0, 0 }};int main(int argc, char *argv[]){ int opt, ctl, i, cmd=0; while ((opt=getopt_long(argc, argv, "ah", main_options, NULL)) != -1) { switch(opt) { case 'a': all = 1; break; case 'h': default: usage(); exit(0); } } argc -= optind; argv += optind; optind = 0; /* Open HCI socket */ if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) { perror("Can't open HCI socket."); exit(1); } if (argc < 1) { print_dev_list(ctl, 0); exit(0); } di.dev_id = atoi(argv[0] + 3); argc--; argv++; if (ioctl(ctl, HCIGETDEVINFO, (void *) &di)) { perror("Can't get device info"); exit(1); } if (hci_test_bit(HCI_RAW, &di.flags) && !bacmp(&di.bdaddr, BDADDR_ANY)) { int dd = hci_open_dev(di.dev_id); hci_read_bd_addr(dd, &di.bdaddr, 1000); hci_close_dev(dd); } while (argc > 0) { for (i = 0; command[i].cmd; i++) { if (strncmp(command[i].cmd, *argv, 5)) continue; if (command[i].opt) { argc--; argv++; } command[i].func(ctl, di.dev_id, *argv); cmd = 1; break; } argc--; argv++; } if (!cmd) print_dev_info(ctl, &di); close(ctl); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -