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  *******************************************************************************/
dump_bt_status(const bt_status_t status)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 ************************************************************************************/
mcap_ctrl_callback(tMCA_HANDLE handle,tMCA_CL mcl,uint8_t event,tMCA_CTRL * p_data)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 
mcap_data_cb(tMCA_DL mdl,BT_HDR * p_pkt)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 
console_shutdown(void)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
config_permissions(void)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 
skip_blanks(char ** p)213 void skip_blanks(char** p) {
214   while (**p == ' ') (*p)++;
215 }
216 
get_int(char ** p,int DefaultValue)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 
get_signed_int(char ** p,int DefaultValue)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 
get_str(char ** p,char * Buffer)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 
get_hex_any(char ** p,int DefaultValue,unsigned int NumOfNibble)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 }
get_hex(char ** p,int DefaultValue)300 uint32_t get_hex(char** p, int DefaultValue) {
301   return get_hex_any(p, DefaultValue, 8);
302 }
get_hex_byte(char ** p,int DefaultValue)303 uint8_t get_hex_byte(char** p, int DefaultValue) {
304   return get_hex_any(p, DefaultValue, 2);
305 }
306 
is_cmd(const char * cmd,const char * str)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 
cmdjob_handler(void * param)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 
create_cmdjob(char * cmd)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 
HAL_load(void)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 
HAL_unload(void)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 
setup_test_env(void)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 
check_return_status(bt_status_t status)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 
adapter_state_changed(bt_state_t state)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 
adapter_properties_changed(bt_status_t status,int num_properties,bt_property_t * properties)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 
discovery_state_changed(bt_discovery_state_t state)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 
pin_request_cb(RawAddress * remote_bd_addr,bt_bdname_t * bd_name,uint32_t cod,bool min_16_digit)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 
ssp_request_cb(RawAddress * remote_bd_addr,bt_bdname_t * bd_name,uint32_t cod,bt_ssp_variant_t pairing_variant,uint32_t pass_key)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 
bond_state_changed_cb(bt_status_t status,RawAddress * remote_bd_addr,bt_bond_state_t state)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 
acl_state_changed(bt_status_t status,RawAddress * remote_bd_addr,bt_acl_state_t state)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 
dut_mode_recv(uint16_t opcode,uint8_t * buf,uint8_t len)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 
set_wake_alarm(uint64_t delay_millis,bool should_wake,alarm_cb cb,void * data)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 
acquire_wake_lock(const char * lock_name)520 static int acquire_wake_lock(const char* lock_name) {
521   return BT_STATUS_SUCCESS;
522 }
523 
release_wake_lock(const char * lock_name)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 
adapter_init(void)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 
adapter_enable(void)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 
adapter_disable(void)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 }
adapter_dut_mode_configure(char * p)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 
adapter_cleanup(void)577 void adapter_cleanup(void) {
578   LOG(INFO) << __func__;
579   sBtInterface->cleanup();
580 }
581 
582 /*******************************************************************************
583  ** Console commands
584  *******************************************************************************/
585 
do_help(char * p)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 
do_quit(char * p)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 
do_init(char * p)608 void do_init(char* p) { adapter_init(); }
609 
do_enable(char * p)610 void do_enable(char* p) { adapter_enable(); }
611 
do_disable(char * p)612 void do_disable(char* p) { adapter_disable(); }
613 
do_cleanup(char * p)614 void do_cleanup(char* p) { adapter_cleanup(); }
615 
616 /**
617  * MCAP API commands
618  */
do_mcap_register(char * p)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 
do_mcap_deregister(char * p)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 
do_mcap_create_mdep(char * p)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 
do_mcap_delete_mdep(char * p)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 
do_mcap_connect_mcl(char * p)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 
do_mcap_disconnect_mcl(char * p)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 
do_mcap_create_mdl(char * p)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 
do_mcap_data_channel_config(char * p)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 
do_mcap_abort_mdl(char * p)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 
do_mcap_delete_mdl(char * p)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 
do_mcap_close_mdl(char * p)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 
do_mcap_reconnect_mdl(char * p)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 
do_pairing(char * p)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 
process_cmd(char * p,bool is_job)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 
main(int argc,char * argv[])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