Home | History | Annotate | Download | only in mcap_tool
      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