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