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