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