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