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