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