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