1 /****************************************************************************** 2 * 3 * Copyright 2015, The linux Foundation. All rights reserved. 4 * 5 * Not a Contribution. 6 * 7 * Copyright 2009-2012 Broadcom Corporation 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at: 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 ******************************************************************************/ 22 23 /************************************************************************************ 24 * 25 * Filename: mcap_tool.cc 26 * 27 * Description: Fluoride MCAP Test Tool application 28 * 29 ***********************************************************************************/ 30 #include <pthread.h> 31 #include <signal.h> 32 #include <stdarg.h> 33 #include <stdint.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #ifndef OS_GENERIC 38 #include <sys/capability.h> 39 #endif 40 #include <sys/prctl.h> 41 #include <time.h> 42 #include <unistd.h> 43 44 #include <hardware/bluetooth.h> 45 #ifndef OS_GENERIC 46 #include <private/android_filesystem_config.h> 47 #endif 48 #include <base/logging.h> 49 50 #include "bt_types.h" 51 #include "l2c_api.h" 52 #include "mca_api.h" 53 #include "mca_defs.h" 54 #include "osi/include/compat.h" 55 #include "hal_util.h" 56 #include "mcap_test_app.h" 57 #include "mcap_test_mcl.h" 58 #include "mcap_test_mdep.h" 59 #include "mcap_test_mdl.h" 60 61 using SYSTEM_BT_TOOLS_MCAP_TOOL::McapTestApp; 62 using SYSTEM_BT_TOOLS_MCAP_TOOL::McapMcl; 63 using SYSTEM_BT_TOOLS_MCAP_TOOL::McapMdep; 64 using SYSTEM_BT_TOOLS_MCAP_TOOL::McapMdl; 65 66 /****************************************************************************** 67 * Constants & Macros 68 *****************************************************************************/ 69 #define PID_FILE "/data/.bdt_pid" 70 71 #ifndef MAX 72 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 73 #endif 74 75 #ifndef MIN 76 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 77 #endif 78 79 #define CASE_RETURN_STR(const) \ 80 case const: \ 81 return #const; 82 83 #ifndef OS_GENERIC 84 /* Permission Groups */ 85 static gid_t groups[] = {AID_NET_BT, AID_INET, AID_NET_BT_ADMIN, 86 AID_SYSTEM, AID_MISC, AID_SDCARD_RW, 87 AID_NET_ADMIN, AID_VPN}; 88 #endif 89 /****************************************************************************** 90 * Static variables 91 *****************************************************************************/ 92 /* Console loop states */ 93 static bool global_main_done = false; 94 static bt_status_t global_status; 95 static bool global_strict_mode = false; 96 97 /* Device and Profile Interfaces */ 98 const bt_interface_t* sBtInterface = nullptr; 99 static btmcap_test_interface_t* sMcapTestInterface = nullptr; 100 static McapTestApp* sMcapTestApp = nullptr; 101 102 /* Bluetooth stack states */ 103 static bool global_bt_enabled = false; 104 static int global_adapter_state = BT_STATE_OFF; 105 static int global_pair_state = BT_BOND_STATE_NONE; 106 /************************************************************************************ 107 ** Static functions 108 ************************************************************************************/ 109 static void process_cmd(char* p, bool is_job); 110 111 /******************************************************************************* 112 ** Misc helper functions 113 *******************************************************************************/ 114 static const char* dump_bt_status(const bt_status_t status) { 115 switch (status) { 116 CASE_RETURN_STR(BT_STATUS_SUCCESS) 117 CASE_RETURN_STR(BT_STATUS_FAIL) 118 CASE_RETURN_STR(BT_STATUS_NOT_READY) 119 CASE_RETURN_STR(BT_STATUS_NOMEM) 120 CASE_RETURN_STR(BT_STATUS_BUSY) 121 CASE_RETURN_STR(BT_STATUS_UNSUPPORTED) 122 default: 123 return "unknown status code"; 124 } 125 } 126 127 /************************************************************************************ 128 ** MCAP Callbacks 129 ************************************************************************************/ 130 static void mcap_ctrl_callback(tMCA_HANDLE handle, tMCA_CL mcl, uint8_t event, 131 tMCA_CTRL* p_data) { 132 sMcapTestApp->ControlCallback(handle, mcl, event, p_data); 133 } 134 135 static void mcap_data_cb(tMCA_DL mdl, BT_HDR* p_pkt) { 136 printf("%s: mdl=%d, event=%d, len=%d, offset=%d, layer_specific=%d\n", 137 __func__, mdl, p_pkt->event, p_pkt->len, p_pkt->offset, 138 p_pkt->layer_specific); 139 printf("%s: HEXDUMP OF DATA LENGTH %u:\n", __func__, p_pkt->len); 140 printf("=========================Begin=========================\n"); 141 bool newline = false; 142 for (int i = 0; i < p_pkt->len; ++i) { 143 printf("%02x", p_pkt->data[i]); 144 if (i > 0 && (i % 25) == 0) { 145 printf("\n"); 146 newline = true; 147 } else { 148 printf(" "); 149 newline = false; 150 } 151 } 152 if (!newline) printf("\n"); 153 printf("=========================End===========================\n"); 154 } 155 156 /************************************************************************************ 157 ** Shutdown helper functions 158 ************************************************************************************/ 159 160 static void console_shutdown(void) { 161 LOG(INFO) << __func__ << ": Shutdown Fluoride MCAP test app"; 162 global_main_done = true; 163 } 164 165 /***************************************************************************** 166 ** Android's init.rc does not yet support applying linux capabilities 167 *****************************************************************************/ 168 169 #ifndef OS_GENERIC 170 static void config_permissions(void) { 171 struct __user_cap_header_struct header; 172 struct __user_cap_data_struct cap[2]; 173 174 printf("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), 175 getgid()); 176 177 header.pid = 0; 178 179 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 180 181 setuid(AID_BLUETOOTH); 182 setgid(AID_BLUETOOTH); 183 184 header.version = _LINUX_CAPABILITY_VERSION_3; 185 186 cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW); 187 cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN); 188 cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= 189 CAP_TO_MASK(CAP_NET_BIND_SERVICE); 190 cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO); 191 cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE); 192 cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); 193 cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM); 194 195 cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW); 196 cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN); 197 cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= 198 CAP_TO_MASK(CAP_NET_BIND_SERVICE); 199 cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO); 200 cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE); 201 cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID); 202 cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM); 203 204 capset(&header, &cap[0]); 205 setgroups(sizeof(groups) / sizeof(groups[0]), groups); 206 } 207 #endif 208 209 /******************************************************************************* 210 ** Console helper functions 211 *******************************************************************************/ 212 213 void skip_blanks(char** p) { 214 while (**p == ' ') (*p)++; 215 } 216 217 uint32_t get_int(char** p, int DefaultValue) { 218 uint32_t Value = 0; 219 unsigned char UseDefault; 220 221 UseDefault = 1; 222 skip_blanks(p); 223 224 while (((**p) <= '9' && (**p) >= '0')) { 225 Value = Value * 10 + (**p) - '0'; 226 UseDefault = 0; 227 (*p)++; 228 } 229 230 if (UseDefault) 231 return DefaultValue; 232 else 233 return Value; 234 } 235 236 int get_signed_int(char** p, int DefaultValue) { 237 int Value = 0; 238 unsigned char UseDefault; 239 unsigned char NegativeNum = 0; 240 241 UseDefault = 1; 242 skip_blanks(p); 243 244 if ((**p) == '-') { 245 NegativeNum = 1; 246 (*p)++; 247 } 248 while (((**p) <= '9' && (**p) >= '0')) { 249 Value = Value * 10 + (**p) - '0'; 250 UseDefault = 0; 251 (*p)++; 252 } 253 254 if (UseDefault) 255 return DefaultValue; 256 else 257 return ((NegativeNum == 0) ? Value : -Value); 258 } 259 260 void get_str(char** p, char* Buffer) { 261 skip_blanks(p); 262 263 while (**p != 0 && **p != ' ') { 264 *Buffer = **p; 265 (*p)++; 266 Buffer++; 267 } 268 269 *Buffer = 0; 270 } 271 272 uint32_t get_hex_any(char** p, int DefaultValue, unsigned int NumOfNibble) { 273 uint32_t Value = 0; 274 unsigned char UseDefault; 275 // unsigned char NumOfNibble = 8; //Since we are returning uint32, max 276 // allowed is 4 bytes(8 nibbles). 277 278 UseDefault = 1; 279 skip_blanks(p); 280 281 while ((NumOfNibble) && 282 (((**p) <= '9' && (**p) >= '0') || ((**p) <= 'f' && (**p) >= 'a') || 283 ((**p) <= 'F' && (**p) >= 'A'))) { 284 if (**p >= 'a') 285 Value = Value * 16 + (**p) - 'a' + 10; 286 else if (**p >= 'A') 287 Value = Value * 16 + (**p) - 'A' + 10; 288 else 289 Value = Value * 16 + (**p) - '0'; 290 UseDefault = 0; 291 (*p)++; 292 NumOfNibble--; 293 } 294 295 if (UseDefault) 296 return DefaultValue; 297 else 298 return Value; 299 } 300 uint32_t get_hex(char** p, int DefaultValue) { 301 return get_hex_any(p, DefaultValue, 8); 302 } 303 uint8_t get_hex_byte(char** p, int DefaultValue) { 304 return get_hex_any(p, DefaultValue, 2); 305 } 306 307 bool is_cmd(const char* cmd, const char* str) { 308 return (strlen(str) == strlen(cmd)) && (strncmp(cmd, str, strlen(str)) == 0); 309 } 310 311 typedef void(console_cmd_handler_t)(char* p); 312 313 typedef struct { 314 const char* name; 315 console_cmd_handler_t* handler; 316 const char* help; 317 bool is_job; 318 } cmd_t; 319 320 extern const cmd_t console_cmd_list[]; 321 static int console_cmd_maxlen = 0; 322 323 static void* cmdjob_handler(void* param) { 324 char* job_cmd = (char*)param; 325 LOG(INFO) << "cmdjob starting: " << job_cmd; 326 process_cmd(job_cmd, true); 327 LOG(INFO) << "cmdjob terminating"; 328 free(job_cmd); 329 return nullptr; 330 } 331 332 static int create_cmdjob(char* cmd) { 333 CHECK(cmd); 334 char* job_cmd = (char*)calloc(1, strlen(cmd) + 1); /* freed in job handler */ 335 if (job_cmd) { 336 strlcpy(job_cmd, cmd, strlen(job_cmd) + 1); 337 pthread_t thread_id; 338 int ret = 339 pthread_create(&thread_id, nullptr, cmdjob_handler, (void*)job_cmd); 340 LOG_IF(ERROR, ret != 0) << "Error during pthread_create"; 341 } else { 342 LOG(INFO) << "Cannot Allocate memory for cmdjob: " << cmd; 343 } 344 return 0; 345 } 346 347 /******************************************************************************* 348 ** Load stack lib 349 *******************************************************************************/ 350 351 int HAL_load(void) { 352 LOG(INFO) << "Loading HAL library and extensions"; 353 bt_interface_t* interface; 354 int err = hal_util_load_bt_library((const bt_interface_t**)&interface); 355 if (err) { 356 LOG(ERROR) << "Error loading HAL library: " << strerror(err); 357 return err; 358 } 359 sBtInterface = interface; 360 LOG(INFO) << "HAL library loaded"; 361 return err; 362 } 363 364 int HAL_unload(void) { 365 int err = 0; 366 LOG(INFO) << "Unloading HAL lib"; 367 sBtInterface = nullptr; 368 LOG(INFO) << "HAL library unloaded, status: " << strerror(err); 369 return err; 370 } 371 372 /******************************************************************************* 373 ** HAL test functions & callbacks 374 *******************************************************************************/ 375 376 void setup_test_env(void) { 377 int i = 0; 378 while (console_cmd_list[i].name) { 379 console_cmd_maxlen = 380 MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name)); 381 i++; 382 } 383 } 384 385 void check_return_status(bt_status_t status) { 386 if (status != BT_STATUS_SUCCESS) { 387 LOG(INFO) << "HAL REQUEST FAILED status : " << status << " (" 388 << dump_bt_status(status) << ")"; 389 } else { 390 LOG(INFO) << "HAL REQUEST SUCCESS"; 391 } 392 } 393 394 static void adapter_state_changed(bt_state_t state) { 395 int V1 = 1000, V2 = 2; 396 bt_property_t property = {BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, 4, &V1}; 397 bt_property_t property1 = {BT_PROPERTY_ADAPTER_SCAN_MODE, 2, &V2}; 398 bt_property_t property2 = {BT_PROPERTY_BDNAME, 6, (void*)"Fluoride_Test"}; 399 400 global_adapter_state = state; 401 402 if (state == BT_STATE_ON) { 403 global_bt_enabled = true; 404 global_status = (bt_status_t)sBtInterface->set_adapter_property(&property1); 405 global_status = (bt_status_t)sBtInterface->set_adapter_property(&property); 406 global_status = (bt_status_t)sBtInterface->set_adapter_property(&property2); 407 } else { 408 global_bt_enabled = false; 409 } 410 } 411 412 static void adapter_properties_changed(bt_status_t status, int num_properties, 413 bt_property_t* properties) { 414 RawAddress bd_addr; 415 if (!properties) { 416 printf("properties is null\n"); 417 return; 418 } 419 switch (properties->type) { 420 case BT_PROPERTY_BDADDR: 421 memcpy(bd_addr.address, properties->val, 422 MIN((size_t)properties->len, sizeof(bd_addr))); 423 LOG(INFO) << "Local Bd Addr = " << bd_addr; 424 break; 425 default: 426 break; 427 } 428 return; 429 } 430 431 static void discovery_state_changed(bt_discovery_state_t state) { 432 LOG(INFO) << "Discovery State Updated: " 433 << (state == BT_DISCOVERY_STOPPED ? "STOPPED" : "STARTED"); 434 } 435 436 static void pin_request_cb(RawAddress* remote_bd_addr, bt_bdname_t* bd_name, 437 uint32_t cod, bool min_16_digit) { 438 bt_pin_code_t pincode = {{0x31, 0x32, 0x33, 0x34}}; 439 440 if (BT_STATUS_SUCCESS != 441 sBtInterface->pin_reply(remote_bd_addr, true, 4, &pincode)) { 442 LOG(INFO) << "Pin Reply failed"; 443 } 444 } 445 446 static void ssp_request_cb(RawAddress* remote_bd_addr, bt_bdname_t* bd_name, 447 uint32_t cod, bt_ssp_variant_t pairing_variant, 448 uint32_t pass_key) { 449 LOG(INFO) << __func__ << ": device_name:" << bd_name->name 450 << ", pairing_variant: " << (int)pairing_variant 451 << ", passkey: " << unsigned(pass_key); 452 if (BT_STATUS_SUCCESS != 453 sBtInterface->ssp_reply(remote_bd_addr, pairing_variant, true, 454 pass_key)) { 455 LOG(ERROR) << "SSP Reply failed"; 456 } 457 } 458 459 static void bond_state_changed_cb(bt_status_t status, 460 RawAddress* remote_bd_addr, 461 bt_bond_state_t state) { 462 LOG(INFO) << "Bond State Changed = " << state; 463 global_pair_state = state; 464 } 465 466 static void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr, 467 bt_acl_state_t state) { 468 LOG(INFO) << __func__ << ": remote_bd_addr=" << *remote_bd_addr 469 << ", acl status=" << (state == BT_ACL_STATE_CONNECTED 470 ? "ACL Connected" 471 : "ACL Disconnected"); 472 } 473 474 static void dut_mode_recv(uint16_t opcode, uint8_t* buf, uint8_t len) { 475 LOG(INFO) << "DUT MODE RECV : NOT IMPLEMENTED"; 476 } 477 478 static bt_callbacks_t bt_callbacks = { 479 sizeof(bt_callbacks_t), 480 adapter_state_changed, 481 adapter_properties_changed, /*adapter_properties_cb */ 482 nullptr, /* remote_device_properties_cb */ 483 nullptr, /* device_found_cb */ 484 discovery_state_changed, /* discovery_state_changed_cb */ 485 pin_request_cb, /* pin_request_cb */ 486 ssp_request_cb, /* ssp_request_cb */ 487 bond_state_changed_cb, /*bond_state_changed_cb */ 488 acl_state_changed, /* acl_state_changed_cb */ 489 nullptr, /* thread_evt_cb */ 490 dut_mode_recv, /*dut_mode_recv_cb */ 491 nullptr, /* le_test_mode_cb */ 492 nullptr /* energy_info_cb */ 493 }; 494 495 static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, 496 void* data) { 497 static timer_t timer; 498 static bool timer_created; 499 500 if (!timer_created) { 501 struct sigevent sigevent; 502 memset(&sigevent, 0, sizeof(sigevent)); 503 sigevent.sigev_notify = SIGEV_THREAD; 504 sigevent.sigev_notify_function = (void (*)(union sigval))cb; 505 sigevent.sigev_value.sival_ptr = data; 506 timer_create(CLOCK_MONOTONIC, &sigevent, &timer); 507 timer_created = true; 508 } 509 510 struct itimerspec new_value; 511 new_value.it_value.tv_sec = delay_millis / 1000; 512 new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000; 513 new_value.it_interval.tv_sec = 0; 514 new_value.it_interval.tv_nsec = 0; 515 timer_settime(timer, 0, &new_value, nullptr); 516 517 return true; 518 } 519 520 static int acquire_wake_lock(const char* lock_name) { 521 return BT_STATUS_SUCCESS; 522 } 523 524 static int release_wake_lock(const char* lock_name) { 525 return BT_STATUS_SUCCESS; 526 } 527 528 static bt_os_callouts_t callouts = { 529 sizeof(bt_os_callouts_t), set_wake_alarm, acquire_wake_lock, 530 release_wake_lock, 531 }; 532 533 void adapter_init(void) { 534 LOG(INFO) << __func__; 535 global_status = (bt_status_t)sBtInterface->init(&bt_callbacks); 536 if (global_status == BT_STATUS_SUCCESS) { 537 global_status = (bt_status_t)sBtInterface->set_os_callouts(&callouts); 538 } 539 check_return_status(global_status); 540 } 541 542 void adapter_enable(void) { 543 LOG(INFO) << __func__; 544 if (global_bt_enabled) { 545 LOG(INFO) << __func__ << ": Bluetooth is already enabled"; 546 return; 547 } 548 global_status = (bt_status_t)sBtInterface->enable(global_strict_mode); 549 check_return_status(global_status); 550 } 551 552 void adapter_disable(void) { 553 LOG(INFO) << __func__; 554 if (!global_bt_enabled) { 555 LOG(INFO) << __func__ << ": Bluetooth is already disabled"; 556 return; 557 } 558 global_status = (bt_status_t)sBtInterface->disable(); 559 check_return_status(global_status); 560 } 561 void adapter_dut_mode_configure(char* p) { 562 LOG(INFO) << __func__; 563 if (!global_bt_enabled) { 564 LOG(INFO) << __func__ 565 << ": Bluetooth must be enabled for test_mode to work."; 566 return; 567 } 568 int32_t mode = get_signed_int(&p, -1); // arg1 569 if ((mode != 0) && (mode != 1)) { 570 LOG(INFO) << __func__ << "Please specify mode: 1 to enter, 0 to exit"; 571 return; 572 } 573 global_status = (bt_status_t)sBtInterface->dut_mode_configure(mode); 574 check_return_status(global_status); 575 } 576 577 void adapter_cleanup(void) { 578 LOG(INFO) << __func__; 579 sBtInterface->cleanup(); 580 } 581 582 /******************************************************************************* 583 ** Console commands 584 *******************************************************************************/ 585 586 void do_help(char* p) { 587 int i = 0; 588 char line[128]; 589 int pos = 0; 590 591 while (console_cmd_list[i].name != nullptr) { 592 pos = snprintf(line, sizeof(line), "%s", (char*)console_cmd_list[i].name); 593 printf("%s %s\n", (char*)line, (char*)console_cmd_list[i].help); 594 i++; 595 } 596 } 597 598 void do_quit(char* p) { console_shutdown(); } 599 600 /******************************************************************* 601 * 602 * BT TEST CONSOLE COMMANDS 603 * 604 * Parses argument lists and passes to API test function 605 * 606 */ 607 608 void do_init(char* p) { adapter_init(); } 609 610 void do_enable(char* p) { adapter_enable(); } 611 612 void do_disable(char* p) { adapter_disable(); } 613 614 void do_cleanup(char* p) { adapter_cleanup(); } 615 616 /** 617 * MCAP API commands 618 */ 619 void do_mcap_register(char* p) { 620 uint16_t ctrl_psm = get_hex(&p, 0); // arg1 621 uint16_t data_psm = get_hex(&p, 0); // arg2 622 uint16_t sec_mask = get_int(&p, 0); // arg3 623 printf("%s: ctrl_psm=0x%04x, data_psm=0x%04x, sec_mask=0x%04x\n", __func__, 624 ctrl_psm, data_psm, sec_mask); 625 if (!ctrl_psm || !data_psm) { 626 printf("%s: Invalid Parameters\n", __func__); 627 return; 628 } 629 sMcapTestApp->Register(ctrl_psm, data_psm, sec_mask, mcap_ctrl_callback); 630 printf("%s: mcap_handle=%d\n", __func__, sMcapTestApp->GetHandle()); 631 } 632 633 void do_mcap_deregister(char* p) { 634 printf("%s: mcap_handle=%d\n", __func__, sMcapTestApp->GetHandle()); 635 sMcapTestApp->Deregister(); 636 printf("%s: handle=%d\n", __func__, sMcapTestApp->GetHandle()); 637 } 638 639 void do_mcap_create_mdep(char* p) { 640 int type = get_int(&p, -1); // arg1 641 printf("%s: mcap_handle=%d, type=%d\n", __func__, sMcapTestApp->GetHandle(), 642 type); 643 bool ret = sMcapTestApp->CreateMdep(type, MCA_NUM_MDLS, mcap_data_cb); 644 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 645 } 646 647 static void do_mcap_delete_mdep(char* p) { 648 uint8_t mdep_handle = get_int(&p, 0); 649 printf("%s: mcap_handle=%d, mdep_handle=%d\n", __func__, 650 sMcapTestApp->GetHandle(), mdep_handle); 651 if (!mdep_handle) { 652 printf("%s: Invalid Parameters\n", __func__); 653 return; 654 } 655 McapMdep* mcap_mdep = sMcapTestApp->FindMdepByHandle(mdep_handle); 656 if (!mcap_mdep) { 657 LOG(ERROR) << "No MDEP for handle " << (int)mdep_handle; 658 return; 659 } 660 bool ret = mcap_mdep->Delete(); 661 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 662 } 663 664 static void do_mcap_connect_mcl(char* p) { 665 char buf[64]; 666 get_str(&p, buf); // arg1 667 RawAddress bd_addr; 668 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 669 uint16_t ctrl_psm = get_hex(&p, 0); // arg2 670 uint16_t sec_mask = get_int(&p, 0); // arg3 671 printf("%s: mcap_handle=%d, ctrl_psm=0x%04x, secMask=0x%04x, bd_addr=%s\n", 672 __func__, sMcapTestApp->GetHandle(), ctrl_psm, sec_mask, buf); 673 if (!ctrl_psm || !valid_bd_addr) { 674 printf("%s: Invalid Parameters\n", __func__); 675 return; 676 } 677 bool ret = sMcapTestApp->ConnectMcl(bd_addr, ctrl_psm, sec_mask); 678 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 679 } 680 681 static void do_mcap_disconnect_mcl(char* p) { 682 char buf[64]; 683 get_str(&p, buf); // arg1 684 RawAddress bd_addr; 685 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 686 printf("%s: bd_addr=%s\n", __func__, buf); 687 if (!valid_bd_addr) { 688 printf("%s: Invalid Parameters\n", __func__); 689 return; 690 } 691 McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr); 692 if (!mcap_mcl) { 693 LOG(ERROR) << "No MCL for bd_addr " << buf; 694 return; 695 } 696 bool ret = mcap_mcl->Disconnect(); 697 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 698 } 699 700 static void do_mcap_create_mdl(char* p) { 701 char buf[64]; 702 get_str(&p, buf); // arg1 703 RawAddress bd_addr; 704 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 705 uint16_t mdep_handle = get_int(&p, 0); // arg2 706 uint16_t data_psm = get_hex(&p, 0); // arg3 707 uint16_t mdl_id = get_int(&p, 0); // arg4 708 uint8_t peer_dep_id = get_int(&p, 0); // arg5 709 uint8_t cfg = get_hex(&p, 0); // arg6 710 int do_not_connect = get_int(&p, 0); // arg7 711 printf( 712 "%s: bd_addr=%s, mdep_handle=%d, data_psm=0x%04x, mdl_id=%d," 713 " peer_dep_id=%d, cfg=0x%02x, do_not_connect=%d\n", 714 __func__, buf, mdep_handle, data_psm, mdl_id, peer_dep_id, cfg, 715 do_not_connect); 716 if (!data_psm || !peer_dep_id || !valid_bd_addr || !mdep_handle) { 717 printf("%s: Invalid Parameters\n", __func__); 718 return; 719 } 720 McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr); 721 if (!mcap_mcl) { 722 LOG(ERROR) << "No MCL for bd_addr " << buf; 723 return; 724 } 725 bool ret = mcap_mcl->CreateMdl(mdep_handle, data_psm, mdl_id, peer_dep_id, 726 cfg, !do_not_connect); 727 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 728 } 729 730 static void do_mcap_data_channel_config(char* p) { 731 char buf[64]; 732 get_str(&p, buf); // arg1 733 RawAddress bd_addr; 734 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 735 printf("%s: bd_addr=%s\n", __func__, buf); 736 if (!valid_bd_addr) { 737 printf("%s: Invalid Parameters\n", __func__); 738 return; 739 } 740 McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr); 741 if (!mcap_mcl) { 742 LOG(ERROR) << "No MCL for bd_addr " << buf; 743 return; 744 } 745 bool ret = mcap_mcl->DataChannelConfig(); 746 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 747 } 748 749 static void do_mcap_abort_mdl(char* p) { 750 char buf[64]; 751 get_str(&p, buf); // arg1 752 RawAddress bd_addr; 753 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 754 printf("%s: bd_addr=%s\n", __func__, buf); 755 if (!valid_bd_addr) { 756 printf("%s: Invalid Parameters\n", __func__); 757 return; 758 } 759 McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr); 760 if (!mcap_mcl) { 761 LOG(ERROR) << "No MCL for bd_addr " << buf; 762 return; 763 } 764 bool ret = mcap_mcl->AbortMdl(); 765 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 766 } 767 768 static void do_mcap_delete_mdl(char* p) { 769 char buf[64]; 770 get_str(&p, buf); // arg1 771 RawAddress bd_addr; 772 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 773 uint16_t mdl_id = get_int(&p, 0); // arg2 774 printf("%s: bd_addr=%s, mdl_id=%d\n", __func__, buf, mdl_id); 775 if (!valid_bd_addr) { 776 printf("%s: Invalid Parameters\n", __func__); 777 return; 778 } 779 McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr); 780 if (!mcap_mcl) { 781 LOG(ERROR) << "No MCL for bd_addr " << buf; 782 return; 783 } 784 bool ret = mcap_mcl->DeleteMdl(mdl_id); 785 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 786 } 787 788 static void do_mcap_close_mdl(char* p) { 789 char buf[64]; 790 get_str(&p, buf); // arg1 791 RawAddress bd_addr; 792 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 793 uint16_t mdl_id = get_int(&p, 0); // arg2 794 printf("%s: bd_addr=%s, mdl_id=%d\n", __func__, buf, mdl_id); 795 if (!valid_bd_addr || !mdl_id) { 796 printf("%s: Invalid Parameters\n", __func__); 797 return; 798 } 799 McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr); 800 if (!mcap_mcl) { 801 LOG(ERROR) << "No MCL for bd_addr " << buf; 802 return; 803 } 804 McapMdl* mcap_mdl = mcap_mcl->FindMdlById(mdl_id); 805 if (!mcap_mdl) { 806 LOG(ERROR) << "No MDL for ID " << (int)mdl_id; 807 return; 808 } 809 bool ret = mcap_mdl->Close(); 810 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 811 } 812 813 static void do_mcap_reconnect_mdl(char* p) { 814 char buf[64]; 815 get_str(&p, buf); // arg1 816 RawAddress bd_addr; 817 bool valid_bd_addr = RawAddress::FromString(buf, bd_addr); 818 uint16_t data_psm = get_hex(&p, 0); // arg1 819 uint16_t mdl_id = get_int(&p, 0); // arg2 820 printf("%s: data_psm=0x%04x, mdl_id=%d\n", __func__, data_psm, mdl_id); 821 if (!valid_bd_addr) { 822 printf("%s: Invalid Parameters\n", __func__); 823 return; 824 } 825 McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr); 826 if (!mcap_mcl) { 827 LOG(ERROR) << "No MCL for bd_addr " << buf; 828 return; 829 } 830 McapMdl* mcap_mdl = mcap_mcl->FindMdlById(mdl_id); 831 if (!mcap_mdl) { 832 LOG(ERROR) << "No MDL for ID " << (int)mdl_id; 833 return; 834 } 835 bool ret = mcap_mdl->Reconnect(data_psm); 836 printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL"); 837 } 838 839 static void do_pairing(char* p) { 840 RawAddress bd_addr; 841 if (!RawAddress::FromString(p, bd_addr)) { 842 LOG(ERROR) << "Invalid Bluetooth address " << p; 843 return; 844 } 845 if (BT_STATUS_SUCCESS != 846 sBtInterface->create_bond(&bd_addr, BT_TRANSPORT_BR_EDR)) { 847 LOG(ERROR) << "Failed to Initiate Pairing"; 848 return; 849 } 850 } 851 852 /** CONSOLE COMMAND TABLE */ 853 854 const cmd_t console_cmd_list[] = { 855 /* INTERNAL */ 856 {"help", do_help, "", 0}, 857 {"quit", do_quit, "", 0}, 858 /* API CONSOLE COMMANDS */ 859 /* Init and Cleanup shall be called automatically */ 860 {"enable_bluetooth", do_enable, "", 0}, 861 {"disable_bluetooth", do_disable, "", 0}, 862 {"pair", do_pairing, "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0}, 863 {"register", do_mcap_register, 864 "ctrl_psm<hex> data_psm<hex> security_mask<0-10>", 0}, 865 {"deregister", do_mcap_deregister, "", 0}, 866 {"create_mdep", do_mcap_create_mdep, "type<0-Echo, 1-Normal>", 0}, 867 {"delete_mdep", do_mcap_delete_mdep, "mdep_handle<int>", 0}, 868 {"connect_mcl", do_mcap_connect_mcl, 869 "BD_ADDR<xx:xx:xx:xx:xx:xx> ctrl_psm<hex> security_mask<0-10>", 0}, 870 {"disconnect_mcl", do_mcap_disconnect_mcl, "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0}, 871 {"create_mdl", do_mcap_create_mdl, 872 "BD_ADDR<xx:xx:xx:xx:xx:xx> mdep_handle<int> data_psm<hex> mdl_id<int> " 873 "peer_dep_id<int> cfg<hex> " 874 "do_not_connect<0-connect,1-wait_for_data_channel_config>", 875 0}, 876 {"data_channel_config", do_mcap_data_channel_config, 877 "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0}, 878 {"abort_mdl", do_mcap_abort_mdl, "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0}, 879 {"close_mdl", do_mcap_close_mdl, "BD_ADDR<xx:xx:xx:xx:xx:xx> mdl_id<int>", 880 0}, 881 {"delete_mdl", do_mcap_delete_mdl, "BD_ADDR<xx:xx:xx:xx:xx:xx> mdl_id<int>", 882 0}, 883 {"reconnect_mdl", do_mcap_reconnect_mdl, 884 "BD_ADDR<xx:xx:xx:xx:xx:xx> data_psm<hex> mdl_id<int>", 0}, 885 /* last entry */ 886 {nullptr, nullptr, "", 0}, 887 }; 888 889 /** Main console command handler */ 890 891 static void process_cmd(char* p, bool is_job) { 892 char cmd[2048]; 893 int i = 0; 894 char* p_saved = p; 895 896 get_str(&p, cmd); // arg1 897 898 /* table commands */ 899 while (console_cmd_list[i].name != nullptr) { 900 if (is_cmd(cmd, console_cmd_list[i].name)) { 901 if (!is_job && console_cmd_list[i].is_job) 902 create_cmdjob(p_saved); 903 else { 904 console_cmd_list[i].handler(p); 905 } 906 return; 907 } 908 i++; 909 } 910 LOG(ERROR) << "Unknown command: " << p_saved; 911 do_help(nullptr); 912 } 913 914 int main(int argc, char* argv[]) { 915 setbuf(stdout, NULL); 916 #if !defined(OS_GENERIC) 917 config_permissions(); 918 #endif 919 LOG(INFO) << "Fluoride MCAP test app is starting"; 920 921 if (HAL_load() < 0) { 922 fprintf(stderr, "%s: HAL failed to initialize, exit\n", __func__); 923 unlink(PID_FILE); 924 exit(0); 925 } 926 927 setup_test_env(); 928 929 /* Automatically perform the init */ 930 adapter_init(); 931 sleep(2); 932 adapter_enable(); 933 sleep(2); 934 sMcapTestInterface = 935 (btmcap_test_interface_t*)sBtInterface->get_profile_interface( 936 BT_TEST_INTERFACE_MCAP_ID); 937 sMcapTestInterface->init(); 938 sMcapTestApp = new McapTestApp(sMcapTestInterface); 939 940 /* Main loop */ 941 char line[2048]; 942 while (!global_main_done) { 943 memset(line, '\0', sizeof(line)); 944 /* command prompt */ 945 printf(">"); 946 fflush(stdout); 947 fgets(line, sizeof(line), stdin); 948 if (line[0] != '\0') { 949 /* Remove line feed */ 950 line[strlen(line) - 1] = 0; 951 if (strlen(line) != 0) process_cmd(line, false); 952 } 953 } 954 adapter_cleanup(); 955 HAL_unload(); 956 LOG(INFO) << "Fluoride MCAP test app is terminating"; 957 958 return 0; 959 } 960