1 /* $NetBSD: btconfig.c,v 1.16 2009/09/01 18:04:33 plunky Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Itronix Inc. 5 * All rights reserved. 6 * 7 * Written by Iain Hibbert for Itronix Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of Itronix Inc. may not be used to endorse 18 * or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __COPYRIGHT("@(#) Copyright (c) 2006 Itronix, Inc. All rights reserved."); 36 __RCSID("$NetBSD: btconfig.c,v 1.16 2009/09/01 18:04:33 plunky Exp $"); 37 38 #include <sys/ioctl.h> 39 #include <sys/param.h> 40 #include <sys/socket.h> 41 42 #include <bluetooth.h> 43 #include <err.h> 44 #include <errno.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 #include <util.h> 50 51 /* inquiry results storage */ 52 struct result { 53 bdaddr_t bdaddr; 54 uint8_t page_scan_rep_mode; 55 uint8_t uclass[HCI_CLASS_SIZE]; 56 uint16_t clock_offset; 57 int8_t rssi; 58 }; 59 60 int main(int, char *[]); 61 void badarg(const char *); 62 void badparam(const char *); 63 void badval(const char *, const char *); 64 void usage(void); 65 int set_unit(unsigned long); 66 void config_unit(void); 67 void print_val(const char *, const char **, int); 68 void print_info(int); 69 void print_stats(void); 70 void print_class(const char *); 71 void print_voice(int); 72 void tag(const char *); 73 void print_features(const char *, uint8_t *); 74 void do_inquiry(void); 75 void print_result(int, struct result *, int); 76 77 void hci_req(uint16_t, uint8_t , void *, size_t, void *, size_t); 78 #define save_value(opcode, cbuf, clen) hci_req(opcode, 0, cbuf, clen, NULL, 0) 79 #define load_value(opcode, rbuf, rlen) hci_req(opcode, 0, NULL, 0, rbuf, rlen) 80 #define hci_cmd(opcode, cbuf, clen) hci_req(opcode, 0, cbuf, clen, NULL, 0) 81 82 #define MAX_STR_SIZE 0xff 83 84 /* print width */ 85 int width = 0; 86 #define MAX_WIDTH 70 87 88 /* global variables */ 89 int hci; 90 struct btreq btr; 91 92 /* command line flags */ 93 int verbose = 0; /* more info */ 94 int lflag = 0; /* list devices */ 95 int sflag = 0; /* get/zero stats */ 96 97 /* device up/down (flag) */ 98 int opt_enable = 0; 99 int opt_reset = 0; 100 #define FLAGS_FMT "\20" \ 101 "\001UP" \ 102 "\002RUNNING" \ 103 "\003XMIT_CMD" \ 104 "\004XMIT_ACL" \ 105 "\005XMIT_SCO" \ 106 "\006INIT_BDADDR" \ 107 "\007INIT_BUFFER_SIZE" \ 108 "\010INIT_FEATURES" \ 109 "\011POWER_UP_NOOP" \ 110 "\012INIT_COMMANDS" \ 111 "\013MASTER" \ 112 "" 113 114 /* authorisation (flag) */ 115 int opt_auth = 0; 116 117 /* encryption (flag) */ 118 int opt_encrypt = 0; 119 120 /* scan enable options (flags) */ 121 int opt_pscan = 0; 122 int opt_iscan = 0; 123 124 /* master role option */ 125 int opt_master = 0; 126 127 /* link policy options (flags) */ 128 int opt_switch = 0; 129 int opt_hold = 0; 130 int opt_sniff = 0; 131 int opt_park = 0; 132 133 /* class of device (hex value) */ 134 int opt_class = 0; 135 uint32_t class; 136 137 /* packet type mask (hex value) */ 138 int opt_ptype = 0; 139 uint32_t ptype; 140 141 /* unit name (string) */ 142 int opt_name = 0; 143 char name[MAX_STR_SIZE]; 144 145 /* pin type */ 146 int opt_pin = 0; 147 148 /* Inquiry */ 149 int opt_rssi = 0; /* inquiry_with_rssi (obsolete flag) */ 150 int opt_imode = 0; /* inquiry mode */ 151 int opt_inquiry = 0; 152 #define INQUIRY_LENGTH 10 /* about 12 seconds */ 153 #define INQUIRY_MAX_RESPONSES 10 154 const char *imodes[] = { "std", "rssi", "ext", NULL }; 155 156 /* Voice Settings */ 157 int opt_voice = 0; 158 uint32_t voice; 159 160 /* Page Timeout */ 161 int opt_pto = 0; 162 uint32_t pto; 163 164 /* set SCO mtu */ 165 int opt_scomtu; 166 uint32_t scomtu; 167 168 struct parameter { 169 const char *name; 170 enum { P_SET, P_CLR, P_STR, P_HEX, P_NUM, P_VAL } type; 171 int *opt; 172 void *val; 173 } parameters[] = { 174 { "up", P_SET, &opt_enable, NULL }, 175 { "enable", P_SET, &opt_enable, NULL }, 176 { "down", P_CLR, &opt_enable, NULL }, 177 { "disable", P_CLR, &opt_enable, NULL }, 178 { "name", P_STR, &opt_name, name }, 179 { "pscan", P_SET, &opt_pscan, NULL }, 180 { "-pscan", P_CLR, &opt_pscan, NULL }, 181 { "iscan", P_SET, &opt_iscan, NULL }, 182 { "-iscan", P_CLR, &opt_iscan, NULL }, 183 { "master", P_SET, &opt_master, NULL }, 184 { "-master", P_CLR, &opt_master, NULL }, 185 { "switch", P_SET, &opt_switch, NULL }, 186 { "-switch", P_CLR, &opt_switch, NULL }, 187 { "hold", P_SET, &opt_hold, NULL }, 188 { "-hold", P_CLR, &opt_hold, NULL }, 189 { "sniff", P_SET, &opt_sniff, NULL }, 190 { "-sniff", P_CLR, &opt_sniff, NULL }, 191 { "park", P_SET, &opt_park, NULL }, 192 { "-park", P_CLR, &opt_park, NULL }, 193 { "auth", P_SET, &opt_auth, NULL }, 194 { "-auth", P_CLR, &opt_auth, NULL }, 195 { "encrypt", P_SET, &opt_encrypt, NULL }, 196 { "-encrypt", P_CLR, &opt_encrypt, NULL }, 197 { "ptype", P_HEX, &opt_ptype, &ptype }, 198 { "class", P_HEX, &opt_class, &class }, 199 { "fixed", P_SET, &opt_pin, NULL }, 200 { "variable", P_CLR, &opt_pin, NULL }, 201 { "inq", P_SET, &opt_inquiry, NULL }, 202 { "inquiry", P_SET, &opt_inquiry, NULL }, 203 { "imode", P_VAL, &opt_imode, imodes }, 204 { "rssi", P_SET, &opt_rssi, NULL }, 205 { "-rssi", P_CLR, &opt_rssi, NULL }, 206 { "reset", P_SET, &opt_reset, NULL }, 207 { "voice", P_HEX, &opt_voice, &voice }, 208 { "pto", P_NUM, &opt_pto, &pto }, 209 { "scomtu", P_NUM, &opt_scomtu, &scomtu }, 210 { NULL, 0, NULL, NULL } 211 }; 212 213 int 214 main(int ac, char *av[]) 215 { 216 int ch; 217 struct parameter *p; 218 219 while ((ch = getopt(ac, av, "hlsvz")) != -1) { 220 switch(ch) { 221 case 'l': 222 lflag = 1; 223 break; 224 225 case 's': 226 sflag = 1; 227 break; 228 229 case 'v': 230 verbose++; 231 break; 232 233 case 'z': 234 sflag = 2; 235 break; 236 237 case 'h': 238 default: 239 usage(); 240 } 241 } 242 av += optind; 243 ac -= optind; 244 245 if (lflag && sflag) 246 usage(); 247 248 hci = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 249 if (hci == -1) 250 err(EXIT_FAILURE, "socket"); 251 252 if (ac == 0) { 253 verbose++; 254 255 memset(&btr, 0, sizeof(btr)); 256 while (set_unit(SIOCNBTINFO) != -1) { 257 print_info(verbose); 258 print_stats(); 259 } 260 261 tag(NULL); 262 } else { 263 strlcpy(btr.btr_name, *av, HCI_DEVNAME_SIZE); 264 av++, ac--; 265 266 if (set_unit(SIOCGBTINFO) < 0) 267 err(EXIT_FAILURE, "%s", btr.btr_name); 268 269 if (ac == 0) 270 verbose += 2; 271 272 while (ac > 0) { 273 for (p = parameters ; ; p++) { 274 if (p->name == NULL) 275 badparam(*av); 276 277 if (strcmp(*av, p->name) == 0) 278 break; 279 } 280 281 switch(p->type) { 282 case P_SET: 283 *(p->opt) = 1; 284 break; 285 286 case P_CLR: 287 *(p->opt) = -1; 288 break; 289 290 case P_STR: 291 if (--ac < 1) badarg(p->name); 292 strlcpy((char *)(p->val), *++av, MAX_STR_SIZE); 293 *(p->opt) = 1; 294 break; 295 296 case P_HEX: 297 if (--ac < 1) badarg(p->name); 298 *(uint32_t *)(p->val) = strtoul(*++av, NULL, 16); 299 *(p->opt) = 1; 300 break; 301 302 case P_NUM: 303 if (--ac < 1) badarg(p->name); 304 *(uint32_t *)(p->val) = strtoul(*++av, NULL, 10); 305 *(p->opt) = 1; 306 break; 307 308 case P_VAL: 309 if (--ac < 1) badarg(p->name); 310 ++av; 311 ch = 0; 312 do { 313 if (((char **)(p->val))[ch] == NULL) 314 badval(p->name, *av); 315 } while (strcmp(((char **)(p->val))[ch++], *av)); 316 *(p->opt) = ch; 317 break; 318 } 319 320 av++, ac--; 321 } 322 323 config_unit(); 324 print_info(verbose); 325 print_stats(); 326 do_inquiry(); 327 } 328 329 close(hci); 330 return EXIT_SUCCESS; 331 } 332 333 void 334 badparam(const char *param) 335 { 336 337 fprintf(stderr, "unknown parameter '%s'\n", param); 338 exit(EXIT_FAILURE); 339 } 340 341 void 342 badarg(const char *param) 343 { 344 345 fprintf(stderr, "parameter '%s' needs argument\n", param); 346 exit(EXIT_FAILURE); 347 } 348 349 void 350 badval(const char *param, const char *value) 351 { 352 353 fprintf(stderr, "bad value '%s' for parameter '%s'\n", value, param); 354 exit(EXIT_FAILURE); 355 } 356 357 void 358 usage(void) 359 { 360 361 fprintf(stderr, "usage: %s [-svz] [device [parameters]]\n", getprogname()); 362 fprintf(stderr, " %s -l\n", getprogname()); 363 exit(EXIT_FAILURE); 364 } 365 366 /* 367 * pretty printing feature 368 */ 369 void 370 tag(const char *f) 371 { 372 373 if (f == NULL) { 374 if (width > 0) 375 printf("\n"); 376 377 width = 0; 378 } else { 379 width += printf("%*s%s", 380 (width == 0 ? (lflag ? 0 : 8) : 1), 381 "", f); 382 383 if (width > MAX_WIDTH) { 384 printf("\n"); 385 width = 0; 386 } 387 } 388 } 389 390 /* 391 * basic HCI cmd request function with argument return. 392 * 393 * Normally, this will return on COMMAND_STATUS or COMMAND_COMPLETE for the given 394 * opcode, but if event is given then it will ignore COMMAND_STATUS (unless error) 395 * and wait for the specified event. 396 * 397 * if rbuf/rlen is given, results will be copied into the result buffer for 398 * COMMAND_COMPLETE/event responses. 399 */ 400 void 401 hci_req(uint16_t opcode, uint8_t event, void *cbuf, size_t clen, void *rbuf, size_t rlen) 402 { 403 uint8_t msg[sizeof(hci_cmd_hdr_t) + HCI_CMD_PKT_SIZE]; 404 hci_event_hdr_t *ep; 405 hci_cmd_hdr_t *cp; 406 407 cp = (hci_cmd_hdr_t *)msg; 408 cp->type = HCI_CMD_PKT; 409 cp->opcode = opcode = htole16(opcode); 410 cp->length = clen = MIN(clen, sizeof(msg) - sizeof(hci_cmd_hdr_t)); 411 412 if (clen) memcpy((cp + 1), cbuf, clen); 413 414 if (send(hci, msg, sizeof(hci_cmd_hdr_t) + clen, 0) < 0) 415 err(EXIT_FAILURE, "HCI Send"); 416 417 ep = (hci_event_hdr_t *)msg; 418 for(;;) { 419 if (recv(hci, msg, sizeof(msg), 0) < 0) { 420 if (errno == EAGAIN || errno == EINTR) 421 continue; 422 423 err(EXIT_FAILURE, "HCI Recv"); 424 } 425 426 if (ep->event == HCI_EVENT_COMMAND_STATUS) { 427 hci_command_status_ep *cs; 428 429 cs = (hci_command_status_ep *)(ep + 1); 430 if (cs->opcode != opcode) 431 continue; 432 433 if (cs->status) 434 errx(EXIT_FAILURE, 435 "HCI cmd (%4.4x) failed (status %d)", 436 opcode, cs->status); 437 438 if (event == 0) 439 break; 440 441 continue; 442 } 443 444 if (ep->event == HCI_EVENT_COMMAND_COMPL) { 445 hci_command_compl_ep *cc; 446 uint8_t *ptr; 447 448 cc = (hci_command_compl_ep *)(ep + 1); 449 if (cc->opcode != opcode) 450 continue; 451 452 if (rbuf == NULL) 453 break; 454 455 ptr = (uint8_t *)(cc + 1); 456 if (*ptr) 457 errx(EXIT_FAILURE, 458 "HCI cmd (%4.4x) failed (status %d)", 459 opcode, *ptr); 460 461 memcpy(rbuf, ++ptr, rlen); 462 break; 463 } 464 465 if (ep->event == event) { 466 if (rbuf == NULL) 467 break; 468 469 memcpy(rbuf, (ep + 1), rlen); 470 break; 471 } 472 } 473 } 474 475 int 476 set_unit(unsigned long cmd) 477 { 478 479 if (ioctl(hci, cmd, &btr) == -1) 480 return -1; 481 482 if (btr.btr_flags & BTF_UP) { 483 struct sockaddr_bt sa; 484 485 sa.bt_len = sizeof(sa); 486 sa.bt_family = AF_BLUETOOTH; 487 bdaddr_copy(&sa.bt_bdaddr, &btr.btr_bdaddr); 488 489 if (bind(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0) 490 err(EXIT_FAILURE, "bind"); 491 492 if (connect(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0) 493 err(EXIT_FAILURE, "connect"); 494 } 495 496 return 0; 497 } 498 499 /* 500 * apply configuration parameters to unit 501 */ 502 void 503 config_unit(void) 504 { 505 506 if (opt_enable) { 507 if (opt_enable > 0) 508 btr.btr_flags |= BTF_UP; 509 else 510 btr.btr_flags &= ~BTF_UP; 511 512 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0) 513 err(EXIT_FAILURE, "SIOCSBTFLAGS"); 514 515 if (set_unit(SIOCGBTINFO) < 0) 516 err(EXIT_FAILURE, "%s", btr.btr_name); 517 } 518 519 if (opt_reset) { 520 hci_cmd(HCI_CMD_RESET, NULL, 0); 521 522 btr.btr_flags |= BTF_INIT; 523 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0) 524 err(EXIT_FAILURE, "SIOCSBTFLAGS"); 525 526 /* 527 * although the reset command will automatically 528 * carry out these commands, we do them manually 529 * just so we can wait for completion. 530 */ 531 hci_cmd(HCI_CMD_READ_BDADDR, NULL, 0); 532 hci_cmd(HCI_CMD_READ_BUFFER_SIZE, NULL, 0); 533 hci_cmd(HCI_CMD_READ_LOCAL_FEATURES, NULL, 0); 534 535 if (set_unit(SIOCGBTINFO) < 0) 536 err(EXIT_FAILURE, "%s", btr.btr_name); 537 } 538 539 if (opt_master) { 540 if (opt_master > 0) 541 btr.btr_flags |= BTF_MASTER; 542 else 543 btr.btr_flags &= ~BTF_MASTER; 544 545 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0) 546 err(EXIT_FAILURE, "SIOCSBTFLAGS"); 547 } 548 549 if (opt_switch || opt_hold || opt_sniff || opt_park) { 550 uint16_t val = btr.btr_link_policy; 551 552 if (opt_switch > 0) val |= HCI_LINK_POLICY_ENABLE_ROLE_SWITCH; 553 if (opt_switch < 0) val &= ~HCI_LINK_POLICY_ENABLE_ROLE_SWITCH; 554 if (opt_hold > 0) val |= HCI_LINK_POLICY_ENABLE_HOLD_MODE; 555 if (opt_hold < 0) val &= ~HCI_LINK_POLICY_ENABLE_HOLD_MODE; 556 if (opt_sniff > 0) val |= HCI_LINK_POLICY_ENABLE_SNIFF_MODE; 557 if (opt_sniff < 0) val &= ~HCI_LINK_POLICY_ENABLE_SNIFF_MODE; 558 if (opt_park > 0) val |= HCI_LINK_POLICY_ENABLE_PARK_MODE; 559 if (opt_park < 0) val &= ~HCI_LINK_POLICY_ENABLE_PARK_MODE; 560 561 btr.btr_link_policy = val; 562 if (ioctl(hci, SIOCSBTPOLICY, &btr) < 0) 563 err(EXIT_FAILURE, "SIOCSBTPOLICY"); 564 } 565 566 if (opt_ptype) { 567 btr.btr_packet_type = ptype; 568 if (ioctl(hci, SIOCSBTPTYPE, &btr) < 0) 569 err(EXIT_FAILURE, "SIOCSBTPTYPE"); 570 } 571 572 if (opt_pscan || opt_iscan) { 573 uint8_t val; 574 575 load_value(HCI_CMD_READ_SCAN_ENABLE, &val, sizeof(val)); 576 if (opt_pscan > 0) val |= HCI_PAGE_SCAN_ENABLE; 577 if (opt_pscan < 0) val &= ~HCI_PAGE_SCAN_ENABLE; 578 if (opt_iscan > 0) val |= HCI_INQUIRY_SCAN_ENABLE; 579 if (opt_iscan < 0) val &= ~HCI_INQUIRY_SCAN_ENABLE; 580 save_value(HCI_CMD_WRITE_SCAN_ENABLE, &val, sizeof(val)); 581 } 582 583 if (opt_auth) { 584 uint8_t val = (opt_auth > 0 ? 1 : 0); 585 586 save_value(HCI_CMD_WRITE_AUTH_ENABLE, &val, sizeof(val)); 587 } 588 589 if (opt_encrypt) { 590 uint8_t val = (opt_encrypt > 0 ? 1 : 0); 591 592 save_value(HCI_CMD_WRITE_ENCRYPTION_MODE, &val, sizeof(val)); 593 } 594 595 if (opt_name) 596 save_value(HCI_CMD_WRITE_LOCAL_NAME, name, HCI_UNIT_NAME_SIZE); 597 598 if (opt_class) { 599 uint8_t val[HCI_CLASS_SIZE]; 600 601 val[0] = (class >> 0) & 0xff; 602 val[1] = (class >> 8) & 0xff; 603 val[2] = (class >> 16) & 0xff; 604 605 save_value(HCI_CMD_WRITE_UNIT_CLASS, val, HCI_CLASS_SIZE); 606 } 607 608 if (opt_pin) { 609 uint8_t val; 610 611 if (opt_pin > 0) val = 1; 612 else val = 0; 613 614 save_value(HCI_CMD_WRITE_PIN_TYPE, &val, sizeof(val)); 615 } 616 617 if (opt_voice) { 618 uint16_t val; 619 620 val = htole16(voice & 0x03ff); 621 save_value(HCI_CMD_WRITE_VOICE_SETTING, &val, sizeof(val)); 622 } 623 624 if (opt_pto) { 625 uint16_t val; 626 627 val = htole16(pto * 8 / 5); 628 save_value(HCI_CMD_WRITE_PAGE_TIMEOUT, &val, sizeof(val)); 629 } 630 631 if (opt_scomtu) { 632 if (scomtu > 0xff) { 633 warnx("Invalid SCO mtu %d", scomtu); 634 } else { 635 btr.btr_sco_mtu = scomtu; 636 637 if (ioctl(hci, SIOCSBTSCOMTU, &btr) < 0) 638 warn("SIOCSBTSCOMTU"); 639 } 640 } 641 642 if (opt_imode | opt_rssi) { 643 uint8_t val = (opt_rssi > 0 ? 1 : 0); 644 645 if (opt_imode) 646 val = opt_imode - 1; 647 648 save_value(HCI_CMD_WRITE_INQUIRY_MODE, &val, sizeof(val)); 649 } 650 } 651 652 /* 653 * print value from NULL terminated array given index 654 */ 655 void 656 print_val(const char *hdr, const char **argv, int idx) 657 { 658 int i = 0; 659 660 while (i < idx && *argv != NULL) 661 i++, argv++; 662 663 printf("\t%s: %s\n", hdr, *argv == NULL ? "unknown" : *argv); 664 } 665 666 /* 667 * Print info for Bluetooth Device with varying verbosity levels 668 */ 669 void 670 print_info(int level) 671 { 672 uint8_t version, val, buf[MAX_STR_SIZE]; 673 uint16_t val16; 674 675 if (lflag) { 676 tag(btr.btr_name); 677 return; 678 } 679 680 if (level-- < 1) 681 return; 682 683 snprintb((char *)buf, MAX_STR_SIZE, FLAGS_FMT, btr.btr_flags); 684 685 printf("%s: bdaddr %s flags %s\n", btr.btr_name, 686 bt_ntoa(&btr.btr_bdaddr, NULL), buf); 687 688 if (level-- < 1) 689 return; 690 691 printf("\tnum_cmd = %d\n" 692 "\tnum_acl = %d, acl_mtu = %d\n" 693 "\tnum_sco = %d, sco_mtu = %d\n", 694 btr.btr_num_cmd, 695 btr.btr_num_acl, btr.btr_acl_mtu, 696 btr.btr_num_sco, btr.btr_sco_mtu); 697 698 if (level-- < 1 || (btr.btr_flags & BTF_UP) == 0) 699 return; 700 701 load_value(HCI_CMD_READ_LOCAL_VER, &version, sizeof(version)); 702 printf("\tHCI version: "); 703 switch(version) { 704 case HCI_SPEC_V10: printf("1.0b\n"); break; 705 case HCI_SPEC_V11: printf("1.1\n"); break; 706 case HCI_SPEC_V12: printf("1.2\n"); break; 707 case HCI_SPEC_V20: printf("2.0 + EDR\n"); break; 708 case HCI_SPEC_V21: printf("2.1 + EDR\n"); break; 709 case HCI_SPEC_V30: printf("3.0 + HS\n"); break; 710 default: printf("unknown\n"); break; 711 } 712 713 load_value(HCI_CMD_READ_UNIT_CLASS, buf, HCI_CLASS_SIZE); 714 class = (buf[2] << 16) | (buf[1] << 8) | (buf[0]); 715 print_class("\t"); 716 717 load_value(HCI_CMD_READ_LOCAL_NAME, buf, HCI_UNIT_NAME_SIZE); 718 printf("\tname: \"%s\"\n", buf); 719 720 load_value(HCI_CMD_READ_VOICE_SETTING, buf, sizeof(uint16_t)); 721 voice = (buf[1] << 8) | buf[0]; 722 print_voice(level); 723 724 load_value(HCI_CMD_READ_PIN_TYPE, &val, sizeof(val)); 725 printf("\tpin: %s\n", val ? "fixed" : "variable"); 726 727 val = 0; 728 if (version >= HCI_SPEC_V12) 729 load_value(HCI_CMD_READ_INQUIRY_MODE, &val, sizeof(val)); 730 731 print_val("inquiry mode", imodes, val); 732 733 width = printf("\toptions:"); 734 735 load_value(HCI_CMD_READ_SCAN_ENABLE, &val, sizeof(val)); 736 if (val & HCI_INQUIRY_SCAN_ENABLE) tag("iscan"); 737 else if (level > 0) tag("-iscan"); 738 739 if (val & HCI_PAGE_SCAN_ENABLE) tag("pscan"); 740 else if (level > 0) tag("-pscan"); 741 742 load_value(HCI_CMD_READ_AUTH_ENABLE, &val, sizeof(val)); 743 if (val) tag("auth"); 744 else if (level > 0) tag("-auth"); 745 746 load_value(HCI_CMD_READ_ENCRYPTION_MODE, &val, sizeof(val)); 747 if (val) tag("encrypt"); 748 else if (level > 0) tag("-encrypt"); 749 750 val = btr.btr_link_policy; 751 if (val & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH) tag("switch"); 752 else if (level > 0) tag("-switch"); 753 if (val & HCI_LINK_POLICY_ENABLE_HOLD_MODE) tag("hold"); 754 else if (level > 0) tag("-hold"); 755 if (val & HCI_LINK_POLICY_ENABLE_SNIFF_MODE) tag("sniff"); 756 else if (level > 0) tag("-sniff"); 757 if (val & HCI_LINK_POLICY_ENABLE_PARK_MODE) tag("park"); 758 else if (level > 0) tag("-park"); 759 760 tag(NULL); 761 762 if (level-- < 1) 763 return; 764 765 ptype = btr.btr_packet_type; 766 width = printf("\tptype: [0x%04x]", ptype); 767 if (ptype & HCI_PKT_DM1) tag("DM1"); 768 if (ptype & HCI_PKT_DH1) tag("DH1"); 769 if (ptype & HCI_PKT_DM3) tag("DM3"); 770 if (ptype & HCI_PKT_DH3) tag("DH3"); 771 if (ptype & HCI_PKT_DM5) tag("DM5"); 772 if (ptype & HCI_PKT_DH5) tag("DH5"); 773 if ((ptype & HCI_PKT_2MBPS_DH1) == 0) tag("2-DH1"); 774 if ((ptype & HCI_PKT_3MBPS_DH1) == 0) tag("3-DH1"); 775 if ((ptype & HCI_PKT_2MBPS_DH3) == 0) tag("2-DH3"); 776 if ((ptype & HCI_PKT_3MBPS_DH3) == 0) tag("3-DH3"); 777 if ((ptype & HCI_PKT_2MBPS_DH5) == 0) tag("2-DH5"); 778 if ((ptype & HCI_PKT_3MBPS_DH5) == 0) tag("3-DH5"); 779 tag(NULL); 780 781 load_value(HCI_CMD_READ_PAGE_TIMEOUT, &val16, sizeof(val16)); 782 printf("\tpage timeout: %d ms\n", val16 * 5 / 8); 783 784 if (level-- < 1) 785 return; 786 787 load_value(HCI_CMD_READ_LOCAL_FEATURES, buf, HCI_FEATURES_SIZE); 788 print_features("\tfeatures:", buf); 789 } 790 791 void 792 print_stats(void) 793 { 794 795 if (sflag == 0) 796 return; 797 798 if (sflag == 1) { 799 if (ioctl(hci, SIOCGBTSTATS, &btr) < 0) 800 err(EXIT_FAILURE, "SIOCGBTSTATS"); 801 } else { 802 if (ioctl(hci, SIOCZBTSTATS, &btr) < 0) 803 err(EXIT_FAILURE, "SIOCZBTSTATS"); 804 } 805 806 printf( "\tTotal bytes sent %d, recieved %d\n" 807 "\tCommands sent %d, Events received %d\n" 808 "\tACL data packets sent %d, received %d\n" 809 "\tSCO data packets sent %d, received %d\n" 810 "\tInput errors %d, Output errors %d\n", 811 btr.btr_stats.byte_tx, btr.btr_stats.byte_rx, 812 btr.btr_stats.cmd_tx, btr.btr_stats.evt_rx, 813 btr.btr_stats.acl_tx, btr.btr_stats.acl_rx, 814 btr.btr_stats.sco_tx, btr.btr_stats.sco_rx, 815 btr.btr_stats.err_rx, btr.btr_stats.err_tx); 816 } 817 818 void 819 print_features(const char *str, uint8_t *f) 820 { 821 822 width = printf("%s", str); 823 824 /* ------------------- byte 0 --------------------*/ 825 if (*f & HCI_LMP_3SLOT) tag("<3 slot>"); 826 if (*f & HCI_LMP_5SLOT) tag("<5 slot>"); 827 if (*f & HCI_LMP_ENCRYPTION) tag("<encryption>"); 828 if (*f & HCI_LMP_SLOT_OFFSET) tag("<slot offset>"); 829 if (*f & HCI_LMP_TIMIACCURACY) tag("<timing accuracy>"); 830 if (*f & HCI_LMP_ROLE_SWITCH) tag("<role switch>"); 831 if (*f & HCI_LMP_HOLD_MODE) tag("<hold mode>"); 832 if (*f & HCI_LMP_SNIFF_MODE) tag("<sniff mode>"); 833 f++; 834 835 /* ------------------- byte 1 --------------------*/ 836 if (*f & HCI_LMP_PARK_MODE) tag("<park mode>"); 837 if (*f & HCI_LMP_RSSI) tag("<RSSI>"); 838 if (*f & HCI_LMP_CHANNEL_QUALITY) tag("<channel quality>"); 839 if (*f & HCI_LMP_SCO_LINK) tag("<SCO link>"); 840 if (*f & HCI_LMP_HV2_PKT) tag("<HV2>"); 841 if (*f & HCI_LMP_HV3_PKT) tag("<HV3>"); 842 if (*f & HCI_LMP_ULAW_LOG) tag("<u-Law log>"); 843 if (*f & HCI_LMP_ALAW_LOG) tag("<A-Law log>"); 844 f++; 845 846 /* ------------------- byte 1 --------------------*/ 847 if (*f & HCI_LMP_CVSD) tag("<CVSD data>"); 848 if (*f & HCI_LMP_PAGISCHEME) tag("<paging parameter>"); 849 if (*f & HCI_LMP_POWER_CONTROL) tag("<power control>"); 850 if (*f & HCI_LMP_TRANSPARENT_SCO) tag("<transparent SCO>"); 851 if (*f & HCI_LMP_FLOW_CONTROL_LAG0) tag("<flow control lag 0>"); 852 if (*f & HCI_LMP_FLOW_CONTROL_LAG1) tag("<flow control lag 1>"); 853 if (*f & HCI_LMP_FLOW_CONTROL_LAG2) tag("<flow control lag 2>"); 854 if (*f & HCI_LMP_BC_ENCRYPTION) tag("<broadcast encryption>"); 855 f++; 856 857 /* ------------------- byte 3 --------------------*/ 858 if (*f & HCI_LMP_EDR_ACL_2MBPS) tag("<EDR ACL 2Mbps>"); 859 if (*f & HCI_LMP_EDR_ACL_3MBPS) tag("<EDR ACL 3Mbps>"); 860 if (*f & HCI_LMP_ENHANCED_ISCAN) tag("<enhanced inquiry scan>"); 861 if (*f & HCI_LMP_INTERLACED_ISCAN) tag("<interlaced inquiry scan>"); 862 if (*f & HCI_LMP_INTERLACED_PSCAN) tag("<interlaced page scan>"); 863 if (*f & HCI_LMP_RSSI_INQUIRY) tag("<RSSI with inquiry result>"); 864 if (*f & HCI_LMP_EV3_PKT) tag("<EV3 packets>"); 865 f++; 866 867 /* ------------------- byte 4 --------------------*/ 868 if (*f & HCI_LMP_EV4_PKT) tag("<EV4 packets>"); 869 if (*f & HCI_LMP_EV5_PKT) tag("<EV5 packets>"); 870 if (*f & HCI_LMP_AFH_CAPABLE_SLAVE) tag("<AFH capable slave>"); 871 if (*f & HCI_LMP_AFH_CLASS_SLAVE) tag("<AFH class slave>"); 872 if (*f & HCI_LMP_3SLOT_EDR_ACL) tag("<3 slot EDR ACL>"); 873 f++; 874 875 /* ------------------- byte 5 --------------------*/ 876 if (*f & HCI_LMP_5SLOT_EDR_ACL) tag("<5 slot EDR ACL>"); 877 if (*f & HCI_LMP_SNIFF_SUBRATING) tag("<sniff subrating>"); 878 if (*f & HCI_LMP_PAUSE_ENCRYPTION) tag("<pause encryption>"); 879 if (*f & HCI_LMP_AFH_CAPABLE_MASTER)tag("<AFH capable master>"); 880 if (*f & HCI_LMP_AFH_CLASS_MASTER) tag("<AFH class master>"); 881 if (*f & HCI_LMP_EDR_eSCO_2MBPS) tag("<EDR eSCO 2Mbps>"); 882 if (*f & HCI_LMP_EDR_eSCO_3MBPS) tag("<EDR eSCO 3Mbps>"); 883 if (*f & HCI_LMP_3SLOT_EDR_eSCO) tag("<3 slot EDR eSCO>"); 884 f++; 885 886 /* ------------------- byte 6 --------------------*/ 887 if (*f & HCI_LMP_EXTENDED_INQUIRY) tag("<extended inquiry>"); 888 if (*f & HCI_LMP_SIMPLE_PAIRING) tag("<secure simple pairing>"); 889 if (*f & HCI_LMP_ENCAPSULATED_PDU) tag("<encapsulated PDU>"); 890 if (*f & HCI_LMP_ERRDATA_REPORTING) tag("<errdata reporting>"); 891 if (*f & HCI_LMP_NOFLUSH_PB_FLAG) tag("<no flush PB flag>"); 892 f++; 893 894 /* ------------------- byte 7 --------------------*/ 895 if (*f & HCI_LMP_LINK_SUPERVISION_TO)tag("<link supervision timeout changed>"); 896 if (*f & HCI_LMP_INQ_RSP_TX_POWER) tag("<inquiry rsp TX power level>"); 897 if (*f & HCI_LMP_EXTENDED_FEATURES) tag("<extended features>"); 898 899 tag(NULL); 900 } 901 902 void 903 print_class(const char *str) 904 { 905 int major, minor; 906 907 major = (class & 0x1f00) >> 8; 908 minor = (class & 0x00fc) >> 2; 909 910 width = printf("%sclass: [0x%6.6x]", str, class); 911 912 switch (major) { 913 case 1: /* Computer */ 914 switch (minor) { 915 case 1: tag("Desktop"); break; 916 case 2: tag("Server"); break; 917 case 3: tag("Laptop"); break; 918 case 4: tag("Handheld"); break; 919 case 5: tag("Palm Sized"); break; 920 case 6: tag("Wearable"); break; 921 } 922 tag("Computer"); 923 break; 924 925 case 2: /* Phone */ 926 switch (minor) { 927 case 1: tag("Cellular Phone"); break; 928 case 2: tag("Cordless Phone"); break; 929 case 3: tag("Smart Phone"); break; 930 case 4: tag("Wired Modem/Phone Gateway"); break; 931 case 5: tag("Common ISDN"); break; 932 default:tag("Phone"); break; 933 } 934 break; 935 936 case 3: /* LAN */ 937 tag("LAN"); 938 switch ((minor & 0x38) >> 3) { 939 case 0: tag("[Fully available]"); break; 940 case 1: tag("[1-17% utilised]"); break; 941 case 2: tag("[17-33% utilised]"); break; 942 case 3: tag("[33-50% utilised]"); break; 943 case 4: tag("[50-67% utilised]"); break; 944 case 5: tag("[67-83% utilised]"); break; 945 case 6: tag("[83-99% utilised]"); break; 946 case 7: tag("[No service available]"); break; 947 } 948 break; 949 950 case 4: /* Audio/Visual */ 951 switch (minor) { 952 case 1: tag("Wearable Headset"); break; 953 case 2: tag("Hands-free Audio"); break; 954 case 4: tag("Microphone"); break; 955 case 5: tag("Loudspeaker"); break; 956 case 6: tag("Headphones"); break; 957 case 7: tag("Portable Audio"); break; 958 case 8: tag("Car Audio"); break; 959 case 9: tag("Set-top Box"); break; 960 case 10: tag("HiFi Audio"); break; 961 case 11: tag("VCR"); break; 962 case 12: tag("Video Camera"); break; 963 case 13: tag("Camcorder"); break; 964 case 14: tag("Video Monitor"); break; 965 case 15: tag("Video Display and Loudspeaker"); break; 966 case 16: tag("Video Conferencing"); break; 967 case 18: tag("A/V [Gaming/Toy]"); break; 968 default: tag("Audio/Visual"); break; 969 } 970 break; 971 972 case 5: /* Peripheral */ 973 switch (minor & 0x0f) { 974 case 1: tag("Joystick"); break; 975 case 2: tag("Gamepad"); break; 976 case 3: tag("Remote Control"); break; 977 case 4: tag("Sensing Device"); break; 978 case 5: tag("Digitiser Tablet"); break; 979 case 6: tag("Card Reader"); break; 980 default: tag("Peripheral"); break; 981 } 982 983 if (minor & 0x10) tag("Keyboard"); 984 if (minor & 0x20) tag("Mouse"); 985 break; 986 987 case 6: /* Imaging */ 988 if (minor & 0x20) tag("Printer"); 989 if (minor & 0x10) tag("Scanner"); 990 if (minor & 0x08) tag("Camera"); 991 if (minor & 0x04) tag("Display"); 992 if ((minor & 0x3c) == 0) tag("Imaging"); 993 break; 994 995 case 7: /* Wearable */ 996 switch (minor) { 997 case 1: tag("Wrist Watch"); break; 998 case 2: tag("Pager"); break; 999 case 3: tag("Jacket"); break; 1000 case 4: tag("Helmet"); break; 1001 case 5: tag("Glasses"); break; 1002 default: tag("Wearable"); break; 1003 } 1004 break; 1005 1006 case 8: /* Toy */ 1007 switch (minor) { 1008 case 1: tag("Robot"); break; 1009 case 2: tag("Vehicle"); break; 1010 case 3: tag("Doll / Action Figure"); break; 1011 case 4: tag("Controller"); break; 1012 case 5: tag("Game"); break; 1013 default: tag("Toy"); break; 1014 } 1015 break; 1016 1017 default: 1018 break; 1019 } 1020 1021 if (class & 0x002000) tag("<Limited Discoverable>"); 1022 if (class & 0x010000) tag("<Positioning>"); 1023 if (class & 0x020000) tag("<Networking>"); 1024 if (class & 0x040000) tag("<Rendering>"); 1025 if (class & 0x080000) tag("<Capturing>"); 1026 if (class & 0x100000) tag("<Object Transfer>"); 1027 if (class & 0x200000) tag("<Audio>"); 1028 if (class & 0x400000) tag("<Telephony>"); 1029 if (class & 0x800000) tag("<Information>"); 1030 tag(NULL); 1031 } 1032 1033 void 1034 print_voice(int level) 1035 { 1036 printf("\tvoice: [0x%4.4x]\n", voice); 1037 1038 if (level == 0) 1039 return; 1040 1041 printf("\t\tInput Coding: "); 1042 switch ((voice & 0x0300) >> 8) { 1043 case 0x00: printf("Linear PCM [%d-bit, pos %d]", 1044 (voice & 0x0020 ? 16 : 8), 1045 (voice & 0x001c) >> 2); break; 1046 case 0x01: printf("u-Law"); break; 1047 case 0x02: printf("A-Law"); break; 1048 case 0x03: printf("unknown"); break; 1049 } 1050 1051 switch ((voice & 0x00c0) >> 6) { 1052 case 0x00: printf(", 1's complement"); break; 1053 case 0x01: printf(", 2's complement"); break; 1054 case 0x02: printf(", sign magnitude"); break; 1055 case 0x03: printf(", unsigned"); break; 1056 } 1057 1058 printf("\n\t\tAir Coding: "); 1059 switch (voice & 0x0003) { 1060 case 0x00: printf("CVSD"); break; 1061 case 0x01: printf("u-Law"); break; 1062 case 0x02: printf("A-Law"); break; 1063 case 0x03: printf("Transparent"); break; 1064 } 1065 1066 printf("\n"); 1067 } 1068 1069 void 1070 print_result(int num, struct result *r, int rssi) 1071 { 1072 hci_remote_name_req_cp ncp; 1073 hci_remote_name_req_compl_ep nep; 1074 struct hostent *hp; 1075 1076 printf("%3d: bdaddr %s", 1077 num, 1078 bt_ntoa(&r->bdaddr, NULL)); 1079 1080 hp = bt_gethostbyaddr((const char *)&r->bdaddr, sizeof(bdaddr_t), AF_BLUETOOTH); 1081 if (hp != NULL) 1082 printf(" (%s)", hp->h_name); 1083 1084 printf("\n"); 1085 1086 memset(&ncp, 0, sizeof(ncp)); 1087 bdaddr_copy(&ncp.bdaddr, &r->bdaddr); 1088 ncp.page_scan_rep_mode = r->page_scan_rep_mode; 1089 ncp.clock_offset = r->clock_offset; 1090 1091 hci_req(HCI_CMD_REMOTE_NAME_REQ, 1092 HCI_EVENT_REMOTE_NAME_REQ_COMPL, 1093 &ncp, sizeof(ncp), 1094 &nep, sizeof(nep)); 1095 1096 printf(" : name \"%s\"\n", nep.name); 1097 1098 class = (r->uclass[2] << 16) | (r->uclass[1] << 8) | (r->uclass[0]); 1099 print_class(" : "); 1100 1101 printf(" : page scan rep mode 0x%02x\n", r->page_scan_rep_mode); 1102 printf(" : clock offset %d\n", le16toh(r->clock_offset)); 1103 1104 if (rssi) 1105 printf(" : rssi %d\n", r->rssi); 1106 1107 printf("\n"); 1108 } 1109 1110 void 1111 do_inquiry(void) 1112 { 1113 uint8_t buf[HCI_EVENT_PKT_SIZE]; 1114 struct result result[INQUIRY_MAX_RESPONSES]; 1115 hci_inquiry_cp inq; 1116 struct hci_filter f; 1117 hci_event_hdr_t *hh; 1118 int i, j, num, rssi; 1119 1120 if (opt_inquiry == 0) 1121 return; 1122 1123 printf("Device Discovery from device: %s ...", btr.btr_name); 1124 fflush(stdout); 1125 1126 memset(&f, 0, sizeof(f)); 1127 hci_filter_set(HCI_EVENT_COMMAND_STATUS, &f); 1128 hci_filter_set(HCI_EVENT_COMMAND_COMPL, &f); 1129 hci_filter_set(HCI_EVENT_INQUIRY_RESULT, &f); 1130 hci_filter_set(HCI_EVENT_RSSI_RESULT, &f); 1131 hci_filter_set(HCI_EVENT_INQUIRY_COMPL, &f); 1132 hci_filter_set(HCI_EVENT_REMOTE_NAME_REQ_COMPL, &f); 1133 hci_filter_set(HCI_EVENT_READ_REMOTE_FEATURES_COMPL, &f); 1134 if (setsockopt(hci, BTPROTO_HCI, SO_HCI_EVT_FILTER, &f, sizeof(f)) < 0) 1135 err(EXIT_FAILURE, "Can't set event filter"); 1136 1137 /* General Inquiry LAP is 0x9e8b33 */ 1138 inq.lap[0] = 0x33; 1139 inq.lap[1] = 0x8b; 1140 inq.lap[2] = 0x9e; 1141 inq.inquiry_length = INQUIRY_LENGTH; 1142 inq.num_responses = INQUIRY_MAX_RESPONSES; 1143 1144 hci_cmd(HCI_CMD_INQUIRY, &inq, sizeof(inq)); 1145 1146 num = 0; 1147 rssi = 0; 1148 hh = (hci_event_hdr_t *)buf; 1149 1150 for (;;) { 1151 if (recv(hci, buf, sizeof(buf), 0) <= 0) 1152 err(EXIT_FAILURE, "recv"); 1153 1154 if (hh->event == HCI_EVENT_INQUIRY_COMPL) 1155 break; 1156 1157 if (hh->event == HCI_EVENT_INQUIRY_RESULT) { 1158 hci_inquiry_result_ep *ep = (hci_inquiry_result_ep *)(hh + 1); 1159 hci_inquiry_response *ir = (hci_inquiry_response *)(ep + 1); 1160 1161 for (i = 0 ; i < ep->num_responses ; i++) { 1162 if (num == INQUIRY_MAX_RESPONSES) 1163 break; 1164 1165 /* some devices keep responding, ignore dupes */ 1166 for (j = 0 ; j < num ; j++) 1167 if (bdaddr_same(&result[j].bdaddr, &ir[i].bdaddr)) 1168 break; 1169 1170 if (j < num) 1171 continue; 1172 1173 bdaddr_copy(&result[num].bdaddr, &ir[i].bdaddr); 1174 memcpy(&result[num].uclass, &ir[i].uclass, HCI_CLASS_SIZE); 1175 result[num].page_scan_rep_mode = ir[i].page_scan_rep_mode; 1176 result[num].clock_offset = ir[i].clock_offset; 1177 result[num].rssi = 0; 1178 num++; 1179 printf("."); 1180 fflush(stdout); 1181 } 1182 continue; 1183 } 1184 1185 if (hh->event == HCI_EVENT_RSSI_RESULT) { 1186 hci_rssi_result_ep *ep = (hci_rssi_result_ep *)(hh + 1); 1187 hci_rssi_response *rr = (hci_rssi_response *)(ep + 1); 1188 1189 for (i = 0 ; i < ep->num_responses ; i++) { 1190 if (num == INQUIRY_MAX_RESPONSES) 1191 break; 1192 1193 /* some devices keep responding, ignore dupes */ 1194 for (j = 0 ; j < num ; j++) 1195 if (bdaddr_same(&result[j].bdaddr, &rr[i].bdaddr)) 1196 break; 1197 1198 if (j < num) 1199 continue; 1200 1201 bdaddr_copy(&result[num].bdaddr, &rr[i].bdaddr); 1202 memcpy(&result[num].uclass, &rr[i].uclass, HCI_CLASS_SIZE); 1203 result[num].page_scan_rep_mode = rr[i].page_scan_rep_mode; 1204 result[num].clock_offset = rr[i].clock_offset; 1205 result[num].rssi = rr[i].rssi; 1206 rssi = 1; 1207 num++; 1208 printf("."); 1209 fflush(stdout); 1210 } 1211 continue; 1212 } 1213 } 1214 1215 printf(" %d response%s\n", num, (num == 1 ? "" : "s")); 1216 1217 for (i = 0 ; i < num ; i++) 1218 print_result(i + 1, &result[i], rssi); 1219 } 1220