1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2009 Marcel Holtmann <marcel (at) holtmann.org> 6 * 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #ifdef HAVE_CONFIG_H 25 #include <config.h> 26 #endif 27 28 #include <stdio.h> 29 #include <errno.h> 30 #include <stdlib.h> 31 #include <getopt.h> 32 #include <sys/socket.h> 33 34 #include <bluetooth/bluetooth.h> 35 #include <bluetooth/hci.h> 36 #include <bluetooth/hci_lib.h> 37 38 #include "csr.h" 39 40 #define CSR_TRANSPORT_UNKNOWN 0 41 #define CSR_TRANSPORT_HCI 1 42 #define CSR_TRANSPORT_USB 2 43 #define CSR_TRANSPORT_BCSP 3 44 #define CSR_TRANSPORT_H4 4 45 #define CSR_TRANSPORT_3WIRE 5 46 47 #define CSR_STORES_PSI (0x0001) 48 #define CSR_STORES_PSF (0x0002) 49 #define CSR_STORES_PSROM (0x0004) 50 #define CSR_STORES_PSRAM (0x0008) 51 #define CSR_STORES_DEFAULT (CSR_STORES_PSI | CSR_STORES_PSF) 52 53 #define CSR_TYPE_NULL 0 54 #define CSR_TYPE_COMPLEX 1 55 #define CSR_TYPE_UINT8 2 56 #define CSR_TYPE_UINT16 3 57 #define CSR_TYPE_UINT32 4 58 59 #define CSR_TYPE_ARRAY CSR_TYPE_COMPLEX 60 #define CSR_TYPE_BDADDR CSR_TYPE_COMPLEX 61 62 static inline int transport_open(int transport, char *device) 63 { 64 switch (transport) { 65 case CSR_TRANSPORT_HCI: 66 return csr_open_hci(device); 67 #ifdef HAVE_LIBUSB 68 case CSR_TRANSPORT_USB: 69 return csr_open_usb(device); 70 #endif 71 case CSR_TRANSPORT_BCSP: 72 return csr_open_bcsp(device); 73 case CSR_TRANSPORT_H4: 74 return csr_open_h4(device); 75 case CSR_TRANSPORT_3WIRE: 76 return csr_open_3wire(device); 77 default: 78 fprintf(stderr, "Unsupported transport\n"); 79 return -1; 80 } 81 } 82 83 static inline int transport_read(int transport, uint16_t varid, uint8_t *value, uint16_t length) 84 { 85 switch (transport) { 86 case CSR_TRANSPORT_HCI: 87 return csr_read_hci(varid, value, length); 88 #ifdef HAVE_LIBUSB 89 case CSR_TRANSPORT_USB: 90 return csr_read_usb(varid, value, length); 91 #endif 92 case CSR_TRANSPORT_BCSP: 93 return csr_read_bcsp(varid, value, length); 94 case CSR_TRANSPORT_H4: 95 return csr_read_h4(varid, value, length); 96 case CSR_TRANSPORT_3WIRE: 97 return csr_read_3wire(varid, value, length); 98 default: 99 errno = EOPNOTSUPP; 100 return -1; 101 } 102 } 103 104 static inline int transport_write(int transport, uint16_t varid, uint8_t *value, uint16_t length) 105 { 106 switch (transport) { 107 case CSR_TRANSPORT_HCI: 108 return csr_write_hci(varid, value, length); 109 #ifdef HAVE_LIBUSB 110 case CSR_TRANSPORT_USB: 111 return csr_write_usb(varid, value, length); 112 #endif 113 case CSR_TRANSPORT_BCSP: 114 return csr_write_bcsp(varid, value, length); 115 case CSR_TRANSPORT_H4: 116 return csr_write_h4(varid, value, length); 117 case CSR_TRANSPORT_3WIRE: 118 return csr_write_3wire(varid, value, length); 119 default: 120 errno = EOPNOTSUPP; 121 return -1; 122 } 123 } 124 125 static inline void transport_close(int transport) 126 { 127 switch (transport) { 128 case CSR_TRANSPORT_HCI: 129 csr_close_hci(); 130 break; 131 #ifdef HAVE_LIBUSB 132 case CSR_TRANSPORT_USB: 133 csr_close_usb(); 134 break; 135 #endif 136 case CSR_TRANSPORT_BCSP: 137 csr_close_bcsp(); 138 break; 139 case CSR_TRANSPORT_H4: 140 csr_close_h4(); 141 break; 142 case CSR_TRANSPORT_3WIRE: 143 csr_close_3wire(); 144 break; 145 } 146 } 147 148 static struct { 149 uint16_t pskey; 150 int type; 151 int size; 152 char *str; 153 } storage[] = { 154 { CSR_PSKEY_BDADDR, CSR_TYPE_BDADDR, 8, "bdaddr" }, 155 { CSR_PSKEY_COUNTRYCODE, CSR_TYPE_UINT16, 0, "country" }, 156 { CSR_PSKEY_CLASSOFDEVICE, CSR_TYPE_UINT32, 0, "devclass" }, 157 { CSR_PSKEY_ENC_KEY_LMIN, CSR_TYPE_UINT16, 0, "keymin" }, 158 { CSR_PSKEY_ENC_KEY_LMAX, CSR_TYPE_UINT16, 0, "keymax" }, 159 { CSR_PSKEY_LOCAL_SUPPORTED_FEATURES, CSR_TYPE_ARRAY, 8, "features" }, 160 { CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS, CSR_TYPE_ARRAY, 18, "commands" }, 161 { CSR_PSKEY_HCI_LMP_LOCAL_VERSION, CSR_TYPE_UINT16, 0, "version" }, 162 { CSR_PSKEY_LMP_REMOTE_VERSION, CSR_TYPE_UINT8, 0, "remver" }, 163 { CSR_PSKEY_HOSTIO_USE_HCI_EXTN, CSR_TYPE_UINT16, 0, "hciextn" }, 164 { CSR_PSKEY_HOSTIO_MAP_SCO_PCM, CSR_TYPE_UINT16, 0, "mapsco" }, 165 { CSR_PSKEY_UART_BAUDRATE, CSR_TYPE_UINT16, 0, "baudrate" }, 166 { CSR_PSKEY_HOST_INTERFACE, CSR_TYPE_UINT16, 0, "hostintf" }, 167 { CSR_PSKEY_ANA_FREQ, CSR_TYPE_UINT16, 0, "anafreq" }, 168 { CSR_PSKEY_ANA_FTRIM, CSR_TYPE_UINT16, 0, "anaftrim" }, 169 { CSR_PSKEY_USB_VENDOR_ID, CSR_TYPE_UINT16, 0, "usbvid" }, 170 { CSR_PSKEY_USB_PRODUCT_ID, CSR_TYPE_UINT16, 0, "usbpid" }, 171 { CSR_PSKEY_USB_DFU_PRODUCT_ID, CSR_TYPE_UINT16, 0, "dfupid" }, 172 { CSR_PSKEY_INITIAL_BOOTMODE, CSR_TYPE_UINT16, 0, "bootmode" }, 173 { 0x0000 }, 174 }; 175 176 static char *storestostr(uint16_t stores) 177 { 178 switch (stores) { 179 case 0x0000: 180 return "Default"; 181 case 0x0001: 182 return "psi"; 183 case 0x0002: 184 return "psf"; 185 case 0x0004: 186 return "psrom"; 187 case 0x0008: 188 return "psram"; 189 default: 190 return "Unknown"; 191 } 192 } 193 194 static char *memorytostr(uint16_t type) 195 { 196 switch (type) { 197 case 0x0000: 198 return "Flash memory"; 199 case 0x0001: 200 return "EEPROM"; 201 case 0x0002: 202 return "RAM (transient)"; 203 case 0x0003: 204 return "ROM (or \"read-only\" flash memory)"; 205 default: 206 return "Unknown"; 207 } 208 } 209 210 #define OPT_RANGE(min, max) \ 211 if (argc < (min)) { errno = EINVAL; return -1; } \ 212 if (argc > (max)) { errno = E2BIG; return -1; } 213 214 static struct option help_options[] = { 215 { "help", 0, 0, 'h' }, 216 { 0, 0, 0, 0 } 217 }; 218 219 static int opt_help(int argc, char *argv[], int *help) 220 { 221 int opt; 222 223 while ((opt=getopt_long(argc, argv, "+h", help_options, NULL)) != EOF) { 224 switch (opt) { 225 case 'h': 226 if (help) 227 *help = 1; 228 break; 229 } 230 } 231 232 return optind; 233 } 234 235 #define OPT_HELP(range, help) \ 236 opt_help(argc, argv, (help)); \ 237 argc -= optind; argv += optind; optind = 0; \ 238 OPT_RANGE((range), (range)) 239 240 static int cmd_builddef(int transport, int argc, char *argv[]) 241 { 242 uint8_t array[8]; 243 uint16_t def = 0x0000, nextdef = 0x0000; 244 int err = 0; 245 246 OPT_HELP(0, NULL); 247 248 printf("Build definitions:\n"); 249 250 while (1) { 251 memset(array, 0, sizeof(array)); 252 array[0] = def & 0xff; 253 array[1] = def >> 8; 254 255 err = transport_read(transport, CSR_VARID_GET_NEXT_BUILDDEF, array, 8); 256 if (err < 0) { 257 errno = -err; 258 break; 259 } 260 261 nextdef = array[2] | (array[3] << 8); 262 263 if (nextdef == 0x0000) 264 break; 265 266 def = nextdef; 267 268 printf("0x%04x - %s\n", def, csr_builddeftostr(def)); 269 } 270 271 return err; 272 } 273 274 static int cmd_keylen(int transport, int argc, char *argv[]) 275 { 276 uint8_t array[8]; 277 uint16_t handle, keylen; 278 int err; 279 280 OPT_HELP(1, NULL); 281 282 handle = atoi(argv[0]); 283 284 memset(array, 0, sizeof(array)); 285 array[0] = handle & 0xff; 286 array[1] = handle >> 8; 287 288 err = transport_read(transport, CSR_VARID_CRYPT_KEY_LENGTH, array, 8); 289 if (err < 0) { 290 errno = -err; 291 return -1; 292 } 293 294 handle = array[0] | (array[1] << 8); 295 keylen = array[2] | (array[3] << 8); 296 297 printf("Crypt key length: %d bit\n", keylen * 8); 298 299 return 0; 300 } 301 302 static int cmd_clock(int transport, int argc, char *argv[]) 303 { 304 uint8_t array[8]; 305 uint32_t clock; 306 int err; 307 308 OPT_HELP(0, NULL); 309 310 memset(array, 0, sizeof(array)); 311 312 err = transport_read(transport, CSR_VARID_BT_CLOCK, array, 8); 313 if (err < 0) { 314 errno = -err; 315 return -1; 316 } 317 318 clock = array[2] | (array[3] << 8) | (array[0] << 16) | (array[1] << 24); 319 320 printf("Bluetooth clock: 0x%04x (%d)\n", clock, clock); 321 322 return 0; 323 } 324 325 static int cmd_rand(int transport, int argc, char *argv[]) 326 { 327 uint8_t array[8]; 328 uint16_t rand; 329 int err; 330 331 OPT_HELP(0, NULL); 332 333 memset(array, 0, sizeof(array)); 334 335 err = transport_read(transport, CSR_VARID_RAND, array, 8); 336 if (err < 0) { 337 errno = -err; 338 return -1; 339 } 340 341 rand = array[0] | (array[1] << 8); 342 343 printf("Random number: 0x%02x (%d)\n", rand, rand); 344 345 return 0; 346 } 347 348 static int cmd_chiprev(int transport, int argc, char *argv[]) 349 { 350 uint8_t array[8]; 351 uint16_t rev; 352 char *str; 353 int err; 354 355 OPT_HELP(0, NULL); 356 357 memset(array, 0, sizeof(array)); 358 359 err = transport_read(transport, CSR_VARID_CHIPREV, array, 8); 360 if (err < 0) { 361 errno = -err; 362 return -1; 363 } 364 365 rev = array[0] | (array[1] << 8); 366 367 switch (rev) { 368 case 0x64: 369 str = "BC1 ES"; 370 break; 371 case 0x65: 372 str = "BC1"; 373 break; 374 case 0x89: 375 str = "BC2-External A"; 376 break; 377 case 0x8a: 378 str = "BC2-External B"; 379 break; 380 case 0x28: 381 str = "BC2-ROM"; 382 break; 383 case 0x43: 384 str = "BC3-Multimedia"; 385 break; 386 case 0x15: 387 str = "BC3-ROM"; 388 break; 389 case 0xe2: 390 str = "BC3-Flash"; 391 break; 392 case 0x26: 393 str = "BC4-External"; 394 break; 395 case 0x30: 396 str = "BC4-ROM"; 397 break; 398 default: 399 str = "NA"; 400 break; 401 } 402 403 printf("Chip revision: 0x%04x (%s)\n", rev, str); 404 405 return 0; 406 } 407 408 static int cmd_buildname(int transport, int argc, char *argv[]) 409 { 410 uint8_t array[130]; 411 char name[64]; 412 unsigned int i; 413 int err; 414 415 OPT_HELP(0, NULL); 416 417 memset(array, 0, sizeof(array)); 418 419 err = transport_read(transport, CSR_VARID_READ_BUILD_NAME, array, 128); 420 if (err < 0) { 421 errno = -err; 422 return -1; 423 } 424 425 for (i = 0; i < sizeof(name); i++) 426 name[i] = array[(i * 2) + 4]; 427 428 printf("Build name: %s\n", name); 429 430 return 0; 431 } 432 433 static int cmd_panicarg(int transport, int argc, char *argv[]) 434 { 435 uint8_t array[8]; 436 uint16_t error; 437 int err; 438 439 OPT_HELP(0, NULL); 440 441 memset(array, 0, sizeof(array)); 442 443 err = transport_read(transport, CSR_VARID_PANIC_ARG, array, 8); 444 if (err < 0) { 445 errno = -err; 446 return -1; 447 } 448 449 error = array[0] | (array[1] << 8); 450 451 printf("Panic code: 0x%02x (%s)\n", error, 452 error < 0x100 ? "valid" : "invalid"); 453 454 return 0; 455 } 456 457 static int cmd_faultarg(int transport, int argc, char *argv[]) 458 { 459 uint8_t array[8]; 460 uint16_t error; 461 int err; 462 463 OPT_HELP(0, NULL); 464 465 memset(array, 0, sizeof(array)); 466 467 err = transport_read(transport, CSR_VARID_FAULT_ARG, array, 8); 468 if (err < 0) { 469 errno = -err; 470 return -1; 471 } 472 473 error = array[0] | (array[1] << 8); 474 475 printf("Fault code: 0x%02x (%s)\n", error, 476 error < 0x100 ? "valid" : "invalid"); 477 478 return 0; 479 } 480 481 static int cmd_coldreset(int transport, int argc, char *argv[]) 482 { 483 return transport_write(transport, CSR_VARID_COLD_RESET, NULL, 0); 484 } 485 486 static int cmd_warmreset(int transport, int argc, char *argv[]) 487 { 488 return transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0); 489 } 490 491 static int cmd_disabletx(int transport, int argc, char *argv[]) 492 { 493 return transport_write(transport, CSR_VARID_DISABLE_TX, NULL, 0); 494 } 495 496 static int cmd_enabletx(int transport, int argc, char *argv[]) 497 { 498 return transport_write(transport, CSR_VARID_ENABLE_TX, NULL, 0); 499 } 500 501 static int cmd_singlechan(int transport, int argc, char *argv[]) 502 { 503 uint8_t array[8]; 504 uint16_t channel; 505 506 OPT_HELP(1, NULL); 507 508 channel = atoi(argv[0]); 509 510 if (channel > 2401 && channel < 2481) 511 channel -= 2402; 512 513 if (channel > 78) { 514 errno = EINVAL; 515 return -1; 516 } 517 518 memset(array, 0, sizeof(array)); 519 array[0] = channel & 0xff; 520 array[1] = channel >> 8; 521 522 return transport_write(transport, CSR_VARID_SINGLE_CHAN, array, 8); 523 } 524 525 static int cmd_hoppingon(int transport, int argc, char *argv[]) 526 { 527 return transport_write(transport, CSR_VARID_HOPPING_ON, NULL, 0); 528 } 529 530 static int cmd_rttxdata1(int transport, int argc, char *argv[]) 531 { 532 uint8_t array[8]; 533 uint16_t freq, level; 534 535 OPT_HELP(2, NULL); 536 537 freq = atoi(argv[0]); 538 539 if (!strncasecmp(argv[1], "0x", 2)) 540 level = strtol(argv[1], NULL, 16); 541 else 542 level = atoi(argv[1]); 543 544 memset(array, 0, sizeof(array)); 545 array[0] = 0x04; 546 array[1] = 0x00; 547 array[2] = freq & 0xff; 548 array[3] = freq >> 8; 549 array[4] = level & 0xff; 550 array[5] = level >> 8; 551 552 return transport_write(transport, CSR_VARID_RADIOTEST, array, 8); 553 } 554 555 static int cmd_radiotest(int transport, int argc, char *argv[]) 556 { 557 uint8_t array[8]; 558 uint16_t freq, level, test; 559 560 OPT_HELP(3, NULL); 561 562 freq = atoi(argv[0]); 563 564 if (!strncasecmp(argv[1], "0x", 2)) 565 level = strtol(argv[1], NULL, 16); 566 else 567 level = atoi(argv[1]); 568 569 test = atoi(argv[2]); 570 571 memset(array, 0, sizeof(array)); 572 array[0] = test & 0xff; 573 array[1] = test >> 8; 574 array[2] = freq & 0xff; 575 array[3] = freq >> 8; 576 array[4] = level & 0xff; 577 array[5] = level >> 8; 578 579 return transport_write(transport, CSR_VARID_RADIOTEST, array, 8); 580 } 581 582 static int cmd_memtypes(int transport, int argc, char *argv[]) 583 { 584 uint8_t array[8]; 585 uint16_t type, stores[4] = { 0x0001, 0x0002, 0x0004, 0x0008 }; 586 int i, err; 587 588 OPT_HELP(0, NULL); 589 590 for (i = 0; i < 4; i++) { 591 memset(array, 0, sizeof(array)); 592 array[0] = stores[i] & 0xff; 593 array[1] = stores[i] >> 8; 594 595 err = transport_read(transport, CSR_VARID_PS_MEMORY_TYPE, array, 8); 596 if (err < 0) 597 continue; 598 599 type = array[2] + (array[3] << 8); 600 601 printf("%s (0x%04x) = %s (%d)\n", storestostr(stores[i]), 602 stores[i], memorytostr(type), type); 603 } 604 605 return 0; 606 } 607 608 static struct option pskey_options[] = { 609 { "stores", 1, 0, 's' }, 610 { "reset", 0, 0, 'r' }, 611 { "help", 0, 0, 'h' }, 612 { 0, 0, 0, 0 } 613 }; 614 615 static int opt_pskey(int argc, char *argv[], uint16_t *stores, int *reset, int *help) 616 { 617 int opt; 618 619 while ((opt=getopt_long(argc, argv, "+s:rh", pskey_options, NULL)) != EOF) { 620 switch (opt) { 621 case 's': 622 if (!stores) 623 break; 624 if (!strcasecmp(optarg, "default")) 625 *stores = 0x0000; 626 else if (!strcasecmp(optarg, "implementation")) 627 *stores = 0x0001; 628 else if (!strcasecmp(optarg, "factory")) 629 *stores = 0x0002; 630 else if (!strcasecmp(optarg, "rom")) 631 *stores = 0x0004; 632 else if (!strcasecmp(optarg, "ram")) 633 *stores = 0x0008; 634 else if (!strcasecmp(optarg, "psi")) 635 *stores = 0x0001; 636 else if (!strcasecmp(optarg, "psf")) 637 *stores = 0x0002; 638 else if (!strcasecmp(optarg, "psrom")) 639 *stores = 0x0004; 640 else if (!strcasecmp(optarg, "psram")) 641 *stores = 0x0008; 642 else if (!strncasecmp(optarg, "0x", 2)) 643 *stores = strtol(optarg, NULL, 16); 644 else 645 *stores = atoi(optarg); 646 break; 647 648 case 'r': 649 if (reset) 650 *reset = 1; 651 break; 652 653 case 'h': 654 if (help) 655 *help = 1; 656 break; 657 } 658 } 659 660 return optind; 661 } 662 663 #define OPT_PSKEY(min, max, stores, reset, help) \ 664 opt_pskey(argc, argv, (stores), (reset), (help)); \ 665 argc -= optind; argv += optind; optind = 0; \ 666 OPT_RANGE((min), (max)) 667 668 static int cmd_psget(int transport, int argc, char *argv[]) 669 { 670 uint8_t array[128]; 671 uint16_t pskey, length, value, stores = CSR_STORES_DEFAULT; 672 uint32_t val32; 673 int i, err, reset = 0; 674 675 memset(array, 0, sizeof(array)); 676 677 OPT_PSKEY(1, 1, &stores, &reset, NULL); 678 679 if (strncasecmp(argv[0], "0x", 2)) { 680 pskey = atoi(argv[0]); 681 682 for (i = 0; storage[i].pskey; i++) { 683 if (strcasecmp(storage[i].str, argv[0])) 684 continue; 685 686 pskey = storage[i].pskey; 687 break; 688 } 689 } else 690 pskey = strtol(argv[0] + 2, NULL, 16); 691 692 memset(array, 0, sizeof(array)); 693 array[0] = pskey & 0xff; 694 array[1] = pskey >> 8; 695 array[2] = stores & 0xff; 696 array[3] = stores >> 8; 697 698 err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8); 699 if (err < 0) 700 return err; 701 702 length = array[2] + (array[3] << 8); 703 if (length + 6 > (int) sizeof(array) / 2) 704 return -EIO; 705 706 memset(array, 0, sizeof(array)); 707 array[0] = pskey & 0xff; 708 array[1] = pskey >> 8; 709 array[2] = length & 0xff; 710 array[3] = length >> 8; 711 array[4] = stores & 0xff; 712 array[5] = stores >> 8; 713 714 err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2); 715 if (err < 0) 716 return err; 717 718 switch (length) { 719 case 1: 720 value = array[6] | (array[7] << 8); 721 printf("%s: 0x%04x (%d)\n", csr_pskeytostr(pskey), value, value); 722 break; 723 724 case 2: 725 val32 = array[8] | (array[9] << 8) | (array[6] << 16) | (array[7] << 24); 726 printf("%s: 0x%08x (%d)\n", csr_pskeytostr(pskey), val32, val32); 727 break; 728 729 default: 730 printf("%s:", csr_pskeytostr(pskey)); 731 for (i = 0; i < length; i++) 732 printf(" 0x%02x%02x", array[(i * 2) + 6], array[(i * 2) + 7]); 733 printf("\n"); 734 break; 735 } 736 737 if (reset) 738 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0); 739 740 return err; 741 } 742 743 static int cmd_psset(int transport, int argc, char *argv[]) 744 { 745 uint8_t array[128]; 746 uint16_t pskey, length, value, stores = CSR_STORES_PSRAM; 747 uint32_t val32; 748 int i, err, reset = 0; 749 750 memset(array, 0, sizeof(array)); 751 752 OPT_PSKEY(2, 81, &stores, &reset, NULL); 753 754 if (strncasecmp(argv[0], "0x", 2)) { 755 pskey = atoi(argv[0]); 756 757 for (i = 0; storage[i].pskey; i++) { 758 if (strcasecmp(storage[i].str, argv[0])) 759 continue; 760 761 pskey = storage[i].pskey; 762 break; 763 } 764 } else 765 pskey = strtol(argv[0] + 2, NULL, 16); 766 767 memset(array, 0, sizeof(array)); 768 array[0] = pskey & 0xff; 769 array[1] = pskey >> 8; 770 array[2] = stores & 0xff; 771 array[3] = stores >> 8; 772 773 err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8); 774 if (err < 0) 775 return err; 776 777 length = array[2] + (array[3] << 8); 778 if (length + 6 > (int) sizeof(array) / 2) 779 return -EIO; 780 781 memset(array, 0, sizeof(array)); 782 array[0] = pskey & 0xff; 783 array[1] = pskey >> 8; 784 array[2] = length & 0xff; 785 array[3] = length >> 8; 786 array[4] = stores & 0xff; 787 array[5] = stores >> 8; 788 789 argc--; 790 argv++; 791 792 switch (length) { 793 case 1: 794 if (argc != 1) { 795 errno = E2BIG; 796 return -1; 797 } 798 799 if (!strncasecmp(argv[0], "0x", 2)) 800 value = strtol(argv[0] + 2, NULL, 16); 801 else 802 value = atoi(argv[0]); 803 804 array[6] = value & 0xff; 805 array[7] = value >> 8; 806 break; 807 808 case 2: 809 if (argc != 1) { 810 errno = E2BIG; 811 return -1; 812 } 813 814 if (!strncasecmp(argv[0], "0x", 2)) 815 val32 = strtol(argv[0] + 2, NULL, 16); 816 else 817 val32 = atoi(argv[0]); 818 819 array[6] = (val32 & 0xff0000) >> 16; 820 array[7] = val32 >> 24; 821 array[8] = val32 & 0xff; 822 array[9] = (val32 & 0xff00) >> 8; 823 break; 824 825 default: 826 if (argc != length * 2) { 827 errno = EINVAL; 828 return -1; 829 } 830 831 for (i = 0; i < length * 2; i++) 832 if (!strncasecmp(argv[0], "0x", 2)) 833 array[i + 6] = strtol(argv[i] + 2, NULL, 16); 834 else 835 array[i + 6] = atoi(argv[i]); 836 break; 837 } 838 839 err = transport_write(transport, CSR_VARID_PS, array, (length + 3) * 2); 840 if (err < 0) 841 return err; 842 843 if (reset) 844 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0); 845 846 return err; 847 } 848 849 static int cmd_psclr(int transport, int argc, char *argv[]) 850 { 851 uint8_t array[8]; 852 uint16_t pskey, stores = CSR_STORES_PSRAM; 853 int i, err, reset = 0; 854 855 OPT_PSKEY(1, 1, &stores, &reset, NULL); 856 857 if (strncasecmp(argv[0], "0x", 2)) { 858 pskey = atoi(argv[0]); 859 860 for (i = 0; storage[i].pskey; i++) { 861 if (strcasecmp(storage[i].str, argv[0])) 862 continue; 863 864 pskey = storage[i].pskey; 865 break; 866 } 867 } else 868 pskey = strtol(argv[0] + 2, NULL, 16); 869 870 memset(array, 0, sizeof(array)); 871 array[0] = pskey & 0xff; 872 array[1] = pskey >> 8; 873 array[2] = stores & 0xff; 874 array[3] = stores >> 8; 875 876 err = transport_write(transport, CSR_VARID_PS_CLR_STORES, array, 8); 877 if (err < 0) 878 return err; 879 880 if (reset) 881 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0); 882 883 return err; 884 } 885 886 static int cmd_pslist(int transport, int argc, char *argv[]) 887 { 888 uint8_t array[8]; 889 uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT; 890 int err, reset = 0; 891 892 OPT_PSKEY(0, 0, &stores, &reset, NULL); 893 894 while (1) { 895 memset(array, 0, sizeof(array)); 896 array[0] = pskey & 0xff; 897 array[1] = pskey >> 8; 898 array[2] = stores & 0xff; 899 array[3] = stores >> 8; 900 901 err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8); 902 if (err < 0) 903 break; 904 905 pskey = array[4] + (array[5] << 8); 906 if (pskey == 0x0000) 907 break; 908 909 memset(array, 0, sizeof(array)); 910 array[0] = pskey & 0xff; 911 array[1] = pskey >> 8; 912 array[2] = stores & 0xff; 913 array[3] = stores >> 8; 914 915 err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8); 916 if (err < 0) 917 continue; 918 919 length = array[2] + (array[3] << 8); 920 921 printf("0x%04x - %s (%d bytes)\n", pskey, 922 csr_pskeytostr(pskey), length * 2); 923 } 924 925 if (reset) 926 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0); 927 928 return 0; 929 } 930 931 static int cmd_psread(int transport, int argc, char *argv[]) 932 { 933 uint8_t array[256]; 934 uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT; 935 char *str, val[7]; 936 int i, err, reset = 0; 937 938 OPT_PSKEY(0, 0, &stores, &reset, NULL); 939 940 while (1) { 941 memset(array, 0, sizeof(array)); 942 array[0] = pskey & 0xff; 943 array[1] = pskey >> 8; 944 array[2] = stores & 0xff; 945 array[3] = stores >> 8; 946 947 err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8); 948 if (err < 0) 949 break; 950 951 pskey = array[4] + (array[5] << 8); 952 if (pskey == 0x0000) 953 break; 954 955 memset(array, 0, sizeof(array)); 956 array[0] = pskey & 0xff; 957 array[1] = pskey >> 8; 958 array[2] = stores & 0xff; 959 array[3] = stores >> 8; 960 961 err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8); 962 if (err < 0) 963 continue; 964 965 length = array[2] + (array[3] << 8); 966 if (length + 6 > (int) sizeof(array) / 2) 967 continue; 968 969 memset(array, 0, sizeof(array)); 970 array[0] = pskey & 0xff; 971 array[1] = pskey >> 8; 972 array[2] = length & 0xff; 973 array[3] = length >> 8; 974 array[4] = stores & 0xff; 975 array[5] = stores >> 8; 976 977 err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2); 978 if (err < 0) 979 continue; 980 981 str = csr_pskeytoval(pskey); 982 if (!strcasecmp(str, "UNKNOWN")) { 983 sprintf(val, "0x%04x", pskey); 984 str = NULL; 985 } 986 987 printf("// %s%s\n&%04x =", str ? "PSKEY_" : "", 988 str ? str : val, pskey); 989 for (i = 0; i < length; i++) 990 printf(" %02x%02x", array[(i * 2) + 7], array[(i * 2) + 6]); 991 printf("\n"); 992 } 993 994 if (reset) 995 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0); 996 997 return 0; 998 } 999 1000 static int cmd_psload(int transport, int argc, char *argv[]) 1001 { 1002 uint8_t array[256]; 1003 uint16_t pskey, length, size, stores = CSR_STORES_PSRAM; 1004 char *str, val[7]; 1005 int err, reset = 0; 1006 1007 OPT_PSKEY(1, 1, &stores, &reset, NULL); 1008 1009 psr_read(argv[0]); 1010 1011 memset(array, 0, sizeof(array)); 1012 size = sizeof(array) - 6; 1013 1014 while (psr_get(&pskey, array + 6, &size) == 0) { 1015 str = csr_pskeytoval(pskey); 1016 if (!strcasecmp(str, "UNKNOWN")) { 1017 sprintf(val, "0x%04x", pskey); 1018 str = NULL; 1019 } 1020 1021 printf("Loading %s%s ... ", str ? "PSKEY_" : "", 1022 str ? str : val); 1023 fflush(stdout); 1024 1025 length = size / 2; 1026 1027 array[0] = pskey & 0xff; 1028 array[1] = pskey >> 8; 1029 array[2] = length & 0xff; 1030 array[3] = length >> 8; 1031 array[4] = stores & 0xff; 1032 array[5] = stores >> 8; 1033 1034 err = transport_write(transport, CSR_VARID_PS, array, size + 6); 1035 1036 printf("%s\n", err < 0 ? "failed" : "done"); 1037 1038 memset(array, 0, sizeof(array)); 1039 size = sizeof(array) - 6; 1040 } 1041 1042 if (reset) 1043 transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0); 1044 1045 return 0; 1046 } 1047 1048 static int cmd_pscheck(int transport, int argc, char *argv[]) 1049 { 1050 uint8_t array[256]; 1051 uint16_t pskey, size; 1052 int i; 1053 1054 OPT_HELP(1, NULL); 1055 1056 psr_read(argv[0]); 1057 1058 while (psr_get(&pskey, array, &size) == 0) { 1059 printf("0x%04x =", pskey); 1060 for (i = 0; i < size; i++) 1061 printf(" 0x%02x", array[i]); 1062 printf("\n"); 1063 } 1064 1065 return 0; 1066 } 1067 1068 static struct { 1069 char *str; 1070 int (*func)(int transport, int argc, char *argv[]); 1071 char *arg; 1072 char *doc; 1073 } commands[] = { 1074 { "builddef", cmd_builddef, "", "Get build definitions" }, 1075 { "keylen", cmd_keylen, "<handle>", "Get current crypt key length" }, 1076 { "clock", cmd_clock, "", "Get local Bluetooth clock" }, 1077 { "rand", cmd_rand, "", "Get random number" }, 1078 { "chiprev", cmd_chiprev, "", "Get chip revision" }, 1079 { "buildname", cmd_buildname, "", "Get the full build name" }, 1080 { "panicarg", cmd_panicarg, "", "Get panic code argument" }, 1081 { "faultarg", cmd_faultarg, "", "Get fault code argument" }, 1082 { "coldreset", cmd_coldreset, "", "Perform cold reset" }, 1083 { "warmreset", cmd_warmreset, "", "Perform warm reset" }, 1084 { "disabletx", cmd_disabletx, "", "Disable TX on the device" }, 1085 { "enabletx", cmd_enabletx, "", "Enable TX on the device" }, 1086 { "singlechan",cmd_singlechan,"<channel>", "Lock radio on specific channel" }, 1087 { "hoppingon", cmd_hoppingon, "", "Revert to channel hopping" }, 1088 { "rttxdata1", cmd_rttxdata1, "<freq> <level>", "TXData1 radio test" }, 1089 { "radiotest", cmd_radiotest, "<freq> <level> <id>", "Run radio tests" }, 1090 { "memtypes", cmd_memtypes, NULL, "Get memory types" }, 1091 { "psget", cmd_psget, "<key>", "Get value for PS key" }, 1092 { "psset", cmd_psset, "<key> <value>", "Set value for PS key" }, 1093 { "psclr", cmd_psclr, "<key>", "Clear value for PS key" }, 1094 { "pslist", cmd_pslist, NULL, "List all PS keys" }, 1095 { "psread", cmd_psread, NULL, "Read all PS keys" }, 1096 { "psload", cmd_psload, "<file>", "Load all PS keys from PSR file" }, 1097 { "pscheck", cmd_pscheck, "<file>", "Check PSR file" }, 1098 { NULL } 1099 }; 1100 1101 static void usage(void) 1102 { 1103 int i, pos = 0; 1104 1105 printf("bccmd - Utility for the CSR BCCMD interface\n\n"); 1106 printf("Usage:\n" 1107 "\tbccmd [options] <command>\n\n"); 1108 1109 printf("Options:\n" 1110 "\t-t <transport> Select the transport\n" 1111 "\t-d <device> Select the device\n" 1112 "\t-h, --help Display help\n" 1113 "\n"); 1114 1115 printf("Transports:\n" 1116 "\tHCI USB BCSP H4 3WIRE\n\n"); 1117 1118 printf("Commands:\n"); 1119 for (i = 0; commands[i].str; i++) 1120 printf("\t%-10s %-20s\t%s\n", commands[i].str, 1121 commands[i].arg ? commands[i].arg : " ", 1122 commands[i].doc); 1123 printf("\n"); 1124 1125 printf("Keys:\n\t"); 1126 for (i = 0; storage[i].pskey; i++) { 1127 printf("%s ", storage[i].str); 1128 pos += strlen(storage[i].str) + 1; 1129 if (pos > 60) { 1130 printf("\n\t"); 1131 pos = 0; 1132 } 1133 } 1134 printf("\n"); 1135 } 1136 1137 static struct option main_options[] = { 1138 { "transport", 1, 0, 't' }, 1139 { "device", 1, 0, 'd' }, 1140 { "help", 0, 0, 'h' }, 1141 { 0, 0, 0, 0 } 1142 }; 1143 1144 int main(int argc, char *argv[]) 1145 { 1146 char *device = NULL; 1147 int i, err, opt, transport = CSR_TRANSPORT_HCI; 1148 1149 while ((opt=getopt_long(argc, argv, "+t:d:i:h", main_options, NULL)) != EOF) { 1150 switch (opt) { 1151 case 't': 1152 if (!strcasecmp(optarg, "hci")) 1153 transport = CSR_TRANSPORT_HCI; 1154 else if (!strcasecmp(optarg, "usb")) 1155 transport = CSR_TRANSPORT_USB; 1156 else if (!strcasecmp(optarg, "bcsp")) 1157 transport = CSR_TRANSPORT_BCSP; 1158 else if (!strcasecmp(optarg, "h4")) 1159 transport = CSR_TRANSPORT_H4; 1160 else if (!strcasecmp(optarg, "h5")) 1161 transport = CSR_TRANSPORT_3WIRE; 1162 else if (!strcasecmp(optarg, "3wire")) 1163 transport = CSR_TRANSPORT_3WIRE; 1164 else if (!strcasecmp(optarg, "twutl")) 1165 transport = CSR_TRANSPORT_3WIRE; 1166 else 1167 transport = CSR_TRANSPORT_UNKNOWN; 1168 break; 1169 1170 case 'd': 1171 case 'i': 1172 device = strdup(optarg); 1173 break; 1174 1175 case 'h': 1176 default: 1177 usage(); 1178 exit(0); 1179 } 1180 } 1181 1182 argc -= optind; 1183 argv += optind; 1184 optind = 0; 1185 1186 if (argc < 1) { 1187 usage(); 1188 exit(1); 1189 } 1190 1191 if (transport_open(transport, device) < 0) 1192 exit(1); 1193 1194 if (device) 1195 free(device); 1196 1197 for (i = 0; commands[i].str; i++) { 1198 if (strcasecmp(commands[i].str, argv[0])) 1199 continue; 1200 1201 err = commands[i].func(transport, argc, argv); 1202 1203 transport_close(transport); 1204 1205 if (err < 0) { 1206 fprintf(stderr, "Can't execute command: %s (%d)\n", 1207 strerror(errno), errno); 1208 exit(1); 1209 } 1210 1211 exit(0); 1212 } 1213 1214 fprintf(stderr, "Unsupported command\n"); 1215 1216 transport_close(transport); 1217 1218 exit(1); 1219 } 1220