1 /****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /************************************************************************************ 20 * 21 * Filename: bluedroidtest.c 22 * 23 * Description: Bluedroid Test application 24 * 25 ***********************************************************************************/ 26 27 #include <stdio.h> 28 #include <dlfcn.h> 29 #include <stdlib.h> 30 #include <errno.h> 31 #include <string.h> 32 #include <pthread.h> 33 #include <unistd.h> 34 #include <ctype.h> 35 #include <fcntl.h> 36 #include <sys/prctl.h> 37 #include <sys/capability.h> 38 39 #include <arpa/inet.h> 40 #include <netinet/in.h> 41 #include <netdb.h> 42 43 #include <private/android_filesystem_config.h> 44 #include <android/log.h> 45 46 #include <hardware/hardware.h> 47 #include <hardware/bluetooth.h> 48 49 /************************************************************************************ 50 ** Constants & Macros 51 ************************************************************************************/ 52 53 #define PID_FILE "/data/.bdt_pid" 54 55 #ifndef MAX 56 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 57 #endif 58 59 #define CASE_RETURN_STR(const) case const: return #const; 60 61 #define UNUSED __attribute__((unused)) 62 63 /************************************************************************************ 64 ** Local type definitions 65 ************************************************************************************/ 66 67 /************************************************************************************ 68 ** Static variables 69 ************************************************************************************/ 70 71 static unsigned char main_done = 0; 72 static bt_status_t status; 73 74 /* Main API */ 75 static bluetooth_device_t* bt_device; 76 77 const bt_interface_t* sBtInterface = NULL; 78 79 static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN, 80 AID_SYSTEM, AID_MISC, AID_SDCARD_RW, 81 AID_NET_ADMIN, AID_VPN}; 82 83 /* Set to 1 when the Bluedroid stack is enabled */ 84 static unsigned char bt_enabled = 0; 85 86 /************************************************************************************ 87 ** Static functions 88 ************************************************************************************/ 89 90 static void process_cmd(char *p, unsigned char is_job); 91 static void job_handler(void *param); 92 static void bdt_log(const char *fmt_str, ...); 93 94 95 /************************************************************************************ 96 ** Externs 97 ************************************************************************************/ 98 99 /************************************************************************************ 100 ** Functions 101 ************************************************************************************/ 102 103 104 /************************************************************************************ 105 ** Shutdown helper functions 106 ************************************************************************************/ 107 108 static void bdt_shutdown(void) 109 { 110 bdt_log("shutdown bdroid test app\n"); 111 main_done = 1; 112 } 113 114 115 /***************************************************************************** 116 ** Android's init.rc does not yet support applying linux capabilities 117 *****************************************************************************/ 118 119 static void config_permissions(void) 120 { 121 struct __user_cap_header_struct header; 122 struct __user_cap_data_struct cap; 123 124 bdt_log("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid()); 125 126 header.pid = 0; 127 128 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 129 130 setuid(AID_BLUETOOTH); 131 setgid(AID_BLUETOOTH); 132 133 header.version = _LINUX_CAPABILITY_VERSION; 134 135 cap.effective = cap.permitted = cap.inheritable = 136 1 << CAP_NET_RAW | 137 1 << CAP_NET_ADMIN | 138 1 << CAP_NET_BIND_SERVICE | 139 1 << CAP_SYS_RAWIO | 140 1 << CAP_SYS_NICE | 141 1 << CAP_SETGID; 142 143 capset(&header, &cap); 144 setgroups(sizeof(groups)/sizeof(groups[0]), groups); 145 } 146 147 148 149 /***************************************************************************** 150 ** Logger API 151 *****************************************************************************/ 152 153 void bdt_log(const char *fmt_str, ...) 154 { 155 static char buffer[1024]; 156 va_list ap; 157 158 va_start(ap, fmt_str); 159 vsnprintf(buffer, 1024, fmt_str, ap); 160 va_end(ap); 161 162 fprintf(stdout, "%s\n", buffer); 163 } 164 165 /******************************************************************************* 166 ** Misc helper functions 167 *******************************************************************************/ 168 static const char* dump_bt_status(bt_status_t status) 169 { 170 switch(status) 171 { 172 CASE_RETURN_STR(BT_STATUS_SUCCESS) 173 CASE_RETURN_STR(BT_STATUS_FAIL) 174 CASE_RETURN_STR(BT_STATUS_NOT_READY) 175 CASE_RETURN_STR(BT_STATUS_NOMEM) 176 CASE_RETURN_STR(BT_STATUS_BUSY) 177 CASE_RETURN_STR(BT_STATUS_UNSUPPORTED) 178 179 default: 180 return "unknown status code"; 181 } 182 } 183 184 static void hex_dump(char *msg, void *data, int size, int trunc) 185 { 186 unsigned char *p = data; 187 unsigned char c; 188 int n; 189 char bytestr[4] = {0}; 190 char addrstr[10] = {0}; 191 char hexstr[ 16*3 + 5] = {0}; 192 char charstr[16*1 + 5] = {0}; 193 194 bdt_log("%s \n", msg); 195 196 /* truncate */ 197 if(trunc && (size>32)) 198 size = 32; 199 200 for(n=1;n<=size;n++) { 201 if (n%16 == 1) { 202 /* store address for this line */ 203 snprintf(addrstr, sizeof(addrstr), "%.4x", 204 (unsigned int)((uintptr_t)p-(uintptr_t)data) ); 205 } 206 207 c = *p; 208 if (isalnum(c) == 0) { 209 c = '.'; 210 } 211 212 /* store hex str (for left side) */ 213 snprintf(bytestr, sizeof(bytestr), "%02X ", *p); 214 strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1); 215 216 /* store char str (for right side) */ 217 snprintf(bytestr, sizeof(bytestr), "%c", c); 218 strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1); 219 220 if(n%16 == 0) { 221 /* line completed */ 222 bdt_log("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); 223 hexstr[0] = 0; 224 charstr[0] = 0; 225 } else if(n%8 == 0) { 226 /* half line: add whitespaces */ 227 strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1); 228 strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1); 229 } 230 p++; /* next byte */ 231 } 232 233 if (strlen(hexstr) > 0) { 234 /* print rest of buffer if not empty */ 235 bdt_log("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); 236 } 237 } 238 239 /******************************************************************************* 240 ** Console helper functions 241 *******************************************************************************/ 242 243 void skip_blanks(char **p) 244 { 245 while (**p == ' ') 246 (*p)++; 247 } 248 249 uint32_t get_int(char **p, int DefaultValue) 250 { 251 uint32_t Value = 0; 252 unsigned char UseDefault; 253 254 UseDefault = 1; 255 skip_blanks(p); 256 257 while ( ((**p)<= '9' && (**p)>= '0') ) 258 { 259 Value = Value * 10 + (**p) - '0'; 260 UseDefault = 0; 261 (*p)++; 262 } 263 264 if (UseDefault) 265 return DefaultValue; 266 else 267 return Value; 268 } 269 270 int get_signed_int(char **p, int DefaultValue) 271 { 272 int Value = 0; 273 unsigned char UseDefault; 274 unsigned char NegativeNum = 0; 275 276 UseDefault = 1; 277 skip_blanks(p); 278 279 if ( (**p) == '-') 280 { 281 NegativeNum = 1; 282 (*p)++; 283 } 284 while ( ((**p)<= '9' && (**p)>= '0') ) 285 { 286 Value = Value * 10 + (**p) - '0'; 287 UseDefault = 0; 288 (*p)++; 289 } 290 291 if (UseDefault) 292 return DefaultValue; 293 else 294 return ((NegativeNum == 0)? Value : -Value); 295 } 296 297 void get_str(char **p, char *Buffer) 298 { 299 skip_blanks(p); 300 301 while (**p != 0 && **p != ' ') 302 { 303 *Buffer = **p; 304 (*p)++; 305 Buffer++; 306 } 307 308 *Buffer = 0; 309 } 310 311 uint32_t get_hex(char **p, int DefaultValue) 312 { 313 uint32_t Value = 0; 314 unsigned char UseDefault; 315 316 UseDefault = 1; 317 skip_blanks(p); 318 319 while ( ((**p)<= '9' && (**p)>= '0') || 320 ((**p)<= 'f' && (**p)>= 'a') || 321 ((**p)<= 'F' && (**p)>= 'A') ) 322 { 323 if (**p >= 'a') 324 Value = Value * 16 + (**p) - 'a' + 10; 325 else if (**p >= 'A') 326 Value = Value * 16 + (**p) - 'A' + 10; 327 else 328 Value = Value * 16 + (**p) - '0'; 329 UseDefault = 0; 330 (*p)++; 331 } 332 333 if (UseDefault) 334 return DefaultValue; 335 else 336 return Value; 337 } 338 339 void get_bdaddr(const char *str, bt_bdaddr_t *bd) { 340 char *d = ((char *)bd), *endp; 341 int i; 342 for(i = 0; i < 6; i++) { 343 *d++ = strtol(str, &endp, 16); 344 if (*endp != ':' && i != 5) { 345 memset(bd, 0, sizeof(bt_bdaddr_t)); 346 return; 347 } 348 str = endp + 1; 349 } 350 } 351 352 #define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0) 353 #define if_cmd(str) if (is_cmd(str)) 354 355 typedef void (t_console_cmd_handler) (char *p); 356 357 typedef struct { 358 const char *name; 359 t_console_cmd_handler *handler; 360 const char *help; 361 unsigned char is_job; 362 } t_cmd; 363 364 365 const t_cmd console_cmd_list[]; 366 static int console_cmd_maxlen = 0; 367 368 static void cmdjob_handler(void *param) 369 { 370 char *job_cmd = (char*)param; 371 372 bdt_log("cmdjob starting (%s)", job_cmd); 373 374 process_cmd(job_cmd, 1); 375 376 bdt_log("cmdjob terminating"); 377 378 free(job_cmd); 379 } 380 381 static int create_cmdjob(char *cmd) 382 { 383 pthread_t thread_id; 384 char *job_cmd; 385 386 job_cmd = malloc(strlen(cmd)+1); /* freed in job handler */ 387 strcpy(job_cmd, cmd); 388 389 if (pthread_create(&thread_id, NULL, 390 (void*)cmdjob_handler, (void*)job_cmd)!=0) 391 perror("pthread_create"); 392 393 return 0; 394 } 395 396 /******************************************************************************* 397 ** Load stack lib 398 *******************************************************************************/ 399 400 int HAL_load(void) 401 { 402 int err = 0; 403 404 hw_module_t* module; 405 hw_device_t* device; 406 407 bdt_log("Loading HAL lib + extensions"); 408 409 err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module); 410 if (err == 0) 411 { 412 err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device); 413 if (err == 0) { 414 bt_device = (bluetooth_device_t *)device; 415 sBtInterface = bt_device->get_bluetooth_interface(); 416 } 417 } 418 419 bdt_log("HAL library loaded (%s)", strerror(err)); 420 421 return err; 422 } 423 424 int HAL_unload(void) 425 { 426 int err = 0; 427 428 bdt_log("Unloading HAL lib"); 429 430 sBtInterface = NULL; 431 432 bdt_log("HAL library unloaded (%s)", strerror(err)); 433 434 return err; 435 } 436 437 /******************************************************************************* 438 ** HAL test functions & callbacks 439 *******************************************************************************/ 440 441 void setup_test_env(void) 442 { 443 int i = 0; 444 445 while (console_cmd_list[i].name != NULL) 446 { 447 console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name)); 448 i++; 449 } 450 } 451 452 void check_return_status(bt_status_t status) 453 { 454 if (status != BT_STATUS_SUCCESS) 455 { 456 bdt_log("HAL REQUEST FAILED status : %d (%s)", status, dump_bt_status(status)); 457 } 458 else 459 { 460 bdt_log("HAL REQUEST SUCCESS"); 461 } 462 } 463 464 static void adapter_state_changed(bt_state_t state) 465 { 466 bdt_log("ADAPTER STATE UPDATED : %s", (state == BT_STATE_OFF)?"OFF":"ON"); 467 if (state == BT_STATE_ON) { 468 bt_enabled = 1; 469 } else { 470 bt_enabled = 0; 471 } 472 } 473 474 static void dut_mode_recv(uint16_t UNUSED opcode, uint8_t UNUSED *buf, uint8_t UNUSED len) 475 { 476 bdt_log("DUT MODE RECV : NOT IMPLEMENTED"); 477 } 478 479 static void le_test_mode(bt_status_t status, uint16_t packet_count) 480 { 481 bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count); 482 } 483 484 static bt_callbacks_t bt_callbacks = { 485 sizeof(bt_callbacks_t), 486 adapter_state_changed, 487 NULL, /* adapter_properties_cb */ 488 NULL, /* remote_device_properties_cb */ 489 NULL, /* device_found_cb */ 490 NULL, /* discovery_state_changed_cb */ 491 NULL, /* pin_request_cb */ 492 NULL, /* ssp_request_cb */ 493 NULL, /* bond_state_changed_cb */ 494 NULL, /* acl_state_changed_cb */ 495 NULL, /* thread_evt_cb */ 496 dut_mode_recv, /* dut_mode_recv_cb */ 497 #if BLE_INCLUDED == TRUE 498 le_test_mode, /* le_test_mode_cb */ 499 #else 500 NULL, /* le_test_mode_cb */ 501 #endif 502 NULL /* energy_info_cb */ 503 }; 504 505 static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data) { 506 static timer_t timer; 507 static bool timer_created; 508 509 if (!timer_created) { 510 struct sigevent sigevent; 511 memset(&sigevent, 0, sizeof(sigevent)); 512 sigevent.sigev_notify = SIGEV_THREAD; 513 sigevent.sigev_notify_function = (void (*)(union sigval))cb; 514 sigevent.sigev_value.sival_ptr = data; 515 timer_create(CLOCK_MONOTONIC, &sigevent, &timer); 516 timer_created = true; 517 } 518 519 struct itimerspec new_value; 520 new_value.it_value.tv_sec = delay_millis / 1000; 521 new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000; 522 new_value.it_interval.tv_sec = 0; 523 new_value.it_interval.tv_nsec = 0; 524 timer_settime(timer, 0, &new_value, NULL); 525 526 return true; 527 } 528 529 static int acquire_wake_lock(const char *lock_name) { 530 return BT_STATUS_SUCCESS; 531 } 532 533 static int release_wake_lock(const char *lock_name) { 534 return BT_STATUS_SUCCESS; 535 } 536 537 static bt_os_callouts_t callouts = { 538 sizeof(bt_os_callouts_t), 539 set_wake_alarm, 540 acquire_wake_lock, 541 release_wake_lock, 542 }; 543 544 void bdt_init(void) 545 { 546 bdt_log("INIT BT "); 547 status = sBtInterface->init(&bt_callbacks); 548 549 if (status == BT_STATUS_SUCCESS) { 550 status = sBtInterface->set_os_callouts(&callouts); 551 } 552 553 check_return_status(status); 554 } 555 556 void bdt_enable(void) 557 { 558 bdt_log("ENABLE BT"); 559 if (bt_enabled) { 560 bdt_log("Bluetooth is already enabled"); 561 return; 562 } 563 status = sBtInterface->enable(); 564 565 check_return_status(status); 566 } 567 568 void bdt_disable(void) 569 { 570 bdt_log("DISABLE BT"); 571 if (!bt_enabled) { 572 bdt_log("Bluetooth is already disabled"); 573 return; 574 } 575 status = sBtInterface->disable(); 576 577 check_return_status(status); 578 } 579 void bdt_dut_mode_configure(char *p) 580 { 581 int32_t mode = -1; 582 583 bdt_log("BT DUT MODE CONFIGURE"); 584 if (!bt_enabled) { 585 bdt_log("Bluetooth must be enabled for test_mode to work."); 586 return; 587 } 588 mode = get_signed_int(&p, mode); 589 if ((mode != 0) && (mode != 1)) { 590 bdt_log("Please specify mode: 1 to enter, 0 to exit"); 591 return; 592 } 593 status = sBtInterface->dut_mode_configure(mode); 594 595 check_return_status(status); 596 } 597 598 #define HCI_LE_RECEIVER_TEST_OPCODE 0x201D 599 #define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E 600 #define HCI_LE_END_TEST_OPCODE 0x201F 601 602 void bdt_le_test_mode(char *p) 603 { 604 int cmd; 605 unsigned char buf[3]; 606 int arg1, arg2, arg3; 607 608 bdt_log("BT LE TEST MODE"); 609 if (!bt_enabled) { 610 bdt_log("Bluetooth must be enabled for le_test to work."); 611 return; 612 } 613 614 memset(buf, 0, sizeof(buf)); 615 cmd = get_int(&p, 0); 616 switch (cmd) 617 { 618 case 0x1: /* RX TEST */ 619 arg1 = get_int(&p, -1); 620 if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__); 621 buf[0] = arg1; 622 status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1); 623 break; 624 case 0x2: /* TX TEST */ 625 arg1 = get_int(&p, -1); 626 arg2 = get_int(&p, -1); 627 arg3 = get_int(&p, -1); 628 if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0)) 629 bdt_log("%s Invalid arguments", __FUNCTION__); 630 buf[0] = arg1; 631 buf[1] = arg2; 632 buf[2] = arg3; 633 status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3); 634 break; 635 case 0x3: /* END TEST */ 636 status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0); 637 break; 638 default: 639 bdt_log("Unsupported command"); 640 return; 641 break; 642 } 643 if (status != BT_STATUS_SUCCESS) 644 { 645 bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status); 646 } 647 return; 648 } 649 650 void bdt_cleanup(void) 651 { 652 bdt_log("CLEANUP"); 653 sBtInterface->cleanup(); 654 } 655 656 /******************************************************************************* 657 ** Console commands 658 *******************************************************************************/ 659 660 void do_help(char UNUSED *p) 661 { 662 int i = 0; 663 int max = 0; 664 char line[128]; 665 int pos = 0; 666 667 while (console_cmd_list[i].name != NULL) 668 { 669 pos = sprintf(line, "%s", (char*)console_cmd_list[i].name); 670 bdt_log("%s %s\n", (char*)line, (char*)console_cmd_list[i].help); 671 i++; 672 } 673 } 674 675 void do_quit(char UNUSED *p) 676 { 677 bdt_shutdown(); 678 } 679 680 /******************************************************************* 681 * 682 * BT TEST CONSOLE COMMANDS 683 * 684 * Parses argument lists and passes to API test function 685 * 686 */ 687 688 void do_init(char UNUSED *p) 689 { 690 bdt_init(); 691 } 692 693 void do_enable(char UNUSED *p) 694 { 695 bdt_enable(); 696 } 697 698 void do_disable(char UNUSED *p) 699 { 700 bdt_disable(); 701 } 702 void do_dut_mode_configure(char *p) 703 { 704 bdt_dut_mode_configure(p); 705 } 706 707 void do_le_test_mode(char *p) 708 { 709 bdt_le_test_mode(p); 710 } 711 712 void do_cleanup(char UNUSED *p) 713 { 714 bdt_cleanup(); 715 } 716 717 /******************************************************************* 718 * 719 * CONSOLE COMMAND TABLE 720 * 721 */ 722 723 const t_cmd console_cmd_list[] = 724 { 725 /* 726 * INTERNAL 727 */ 728 729 { "help", do_help, "lists all available console commands", 0 }, 730 { "quit", do_quit, "", 0}, 731 732 /* 733 * API CONSOLE COMMANDS 734 */ 735 736 /* Init and Cleanup shall be called automatically */ 737 { "enable", do_enable, ":: enables bluetooth", 0 }, 738 { "disable", do_disable, ":: disables bluetooth", 0 }, 739 { "dut_mode_configure", do_dut_mode_configure, ":: DUT mode - 1 to enter,0 to exit", 0 }, 740 { "le_test_mode", do_le_test_mode, ":: LE Test Mode - RxTest - 1 <rx_freq>, \n\t \ 741 TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>, \n\t \ 742 End Test - 3 <no_args>", 0 }, 743 /* add here */ 744 745 /* last entry */ 746 {NULL, NULL, "", 0}, 747 }; 748 749 /* 750 * Main console command handler 751 */ 752 753 static void process_cmd(char *p, unsigned char is_job) 754 { 755 char cmd[64]; 756 int i = 0; 757 char *p_saved = p; 758 759 get_str(&p, cmd); 760 761 /* table commands */ 762 while (console_cmd_list[i].name != NULL) 763 { 764 if (is_cmd(console_cmd_list[i].name)) 765 { 766 if (!is_job && console_cmd_list[i].is_job) 767 create_cmdjob(p_saved); 768 else 769 { 770 console_cmd_list[i].handler(p); 771 } 772 return; 773 } 774 i++; 775 } 776 bdt_log("%s : unknown command\n", p_saved); 777 do_help(NULL); 778 } 779 780 int main (int UNUSED argc, char UNUSED *argv[]) 781 { 782 int opt; 783 char cmd[128]; 784 int args_processed = 0; 785 int pid = -1; 786 787 config_permissions(); 788 bdt_log("\n:::::::::::::::::::::::::::::::::::::::::::::::::::"); 789 bdt_log(":: Bluedroid test app starting"); 790 791 if ( HAL_load() < 0 ) { 792 perror("HAL failed to initialize, exit\n"); 793 unlink(PID_FILE); 794 exit(0); 795 } 796 797 setup_test_env(); 798 799 /* Automatically perform the init */ 800 bdt_init(); 801 802 while(!main_done) 803 { 804 char line[128]; 805 806 /* command prompt */ 807 printf( ">" ); 808 fflush(stdout); 809 810 fgets (line, 128, stdin); 811 812 if (line[0]!= '\0') 813 { 814 /* remove linefeed */ 815 line[strlen(line)-1] = 0; 816 817 process_cmd(line, 0); 818 memset(line, '\0', 128); 819 } 820 } 821 822 /* FIXME: Commenting this out as for some reason, the application does not exit otherwise*/ 823 //bdt_cleanup(); 824 825 HAL_unload(); 826 827 bdt_log(":: Bluedroid test app terminating"); 828 829 return 0; 830 } 831