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