haltest.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. // SPDX-License-Identifier: Apache-2.0
  2. /*
  3. * Copyright (C) 2013 Intel Corporation
  4. *
  5. */
  6. #ifdef HAVE_CONFIG_H
  7. #include <config.h>
  8. #endif
  9. #define _GNU_SOURCE
  10. #include <stdlib.h>
  11. #include <stdbool.h>
  12. #include <string.h>
  13. #include <stdio.h>
  14. #include <stdarg.h>
  15. #include <unistd.h>
  16. #include <poll.h>
  17. #include <unistd.h>
  18. #include <getopt.h>
  19. #include "if-main.h"
  20. #include "terminal.h"
  21. #include "pollhandler.h"
  22. #include "history.h"
  23. static void process_line(char *line_buffer);
  24. const struct interface *interfaces[] = {
  25. &audio_if,
  26. &sco_if,
  27. &bluetooth_if,
  28. &av_if,
  29. &rc_if,
  30. &gatt_if,
  31. &gatt_client_if,
  32. &gatt_server_if,
  33. &hf_if,
  34. &hh_if,
  35. &pan_if,
  36. &hl_if,
  37. &sock_if,
  38. #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
  39. &hf_client_if,
  40. &mce_if,
  41. &ctrl_rc_if,
  42. &av_sink_if,
  43. #endif
  44. NULL
  45. };
  46. static struct method commands[];
  47. struct method *get_method(struct method *methods, const char *name)
  48. {
  49. while (strcmp(methods->name, "") != 0) {
  50. if (strcmp(methods->name, name) == 0)
  51. return methods;
  52. methods++;
  53. }
  54. return NULL;
  55. }
  56. /* function returns interface of given name or NULL if not found */
  57. const struct interface *get_interface(const char *name)
  58. {
  59. int i;
  60. for (i = 0; interfaces[i] != NULL; ++i) {
  61. if (strcmp(interfaces[i]->name, name) == 0)
  62. break;
  63. }
  64. return interfaces[i];
  65. }
  66. int haltest_error(const char *format, ...)
  67. {
  68. va_list args;
  69. int ret;
  70. va_start(args, format);
  71. ret = terminal_vprint(format, args);
  72. va_end(args);
  73. return ret;
  74. }
  75. int haltest_info(const char *format, ...)
  76. {
  77. va_list args;
  78. int ret;
  79. va_start(args, format);
  80. ret = terminal_vprint(format, args);
  81. va_end(args);
  82. return ret;
  83. }
  84. int haltest_warn(const char *format, ...)
  85. {
  86. va_list args;
  87. int ret;
  88. va_start(args, format);
  89. ret = terminal_vprint(format, args);
  90. va_end(args);
  91. return ret;
  92. }
  93. static void help_print_interface(const struct interface *i)
  94. {
  95. struct method *m;
  96. for (m = i->methods; strcmp(m->name, "") != 0; m++)
  97. haltest_info("%s %s %s\n", i->name, m->name,
  98. (m->help ? m->help : ""));
  99. }
  100. /* Help completion */
  101. static void help_c(int argc, const char **argv, enum_func *enum_func,
  102. void **user)
  103. {
  104. if (argc == 2)
  105. *enum_func = interface_name;
  106. }
  107. /* Help execution */
  108. static void help_p(int argc, const char **argv)
  109. {
  110. const struct method *m = commands;
  111. const struct interface **ip = interfaces;
  112. const struct interface *i;
  113. if (argc == 1) {
  114. terminal_print("haltest allows to call Android HAL methods.\n");
  115. terminal_print("\nAvailable commands:\n");
  116. while (0 != strcmp(m->name, "")) {
  117. terminal_print("\t%s %s\n", m->name,
  118. (m->help ? m->help : ""));
  119. m++;
  120. }
  121. terminal_print("\nAvailable interfaces to use:\n");
  122. while (NULL != *ip) {
  123. terminal_print("\t%s\n", (*ip)->name);
  124. ip++;
  125. }
  126. terminal_print("\nTo get help on methods for each interface type:\n");
  127. terminal_print("\n\thelp <inerface>\n");
  128. terminal_print("\nBasic scenario:\n\tbluetooth init\n");
  129. terminal_print("\tbluetooth enable\n\tbluetooth start_discovery\n");
  130. terminal_print("\tbluetooth get_profile_interface handsfree\n");
  131. terminal_print("\thandsfree init\n\n");
  132. return;
  133. }
  134. i = get_interface(argv[1]);
  135. if (i == NULL) {
  136. haltest_error("No such interface\n");
  137. return;
  138. }
  139. help_print_interface(i);
  140. }
  141. /* quit/exit execution */
  142. static void quit_p(int argc, const char **argv)
  143. {
  144. char cleanup_audio[] = "audio cleanup";
  145. close_hw_bt_dev();
  146. process_line(cleanup_audio);
  147. exit(0);
  148. }
  149. static int fd_stack[10];
  150. static int fd_stack_pointer = 0;
  151. static void stdin_handler(struct pollfd *pollfd);
  152. static void process_file(const char *name)
  153. {
  154. int fd = open(name, O_RDONLY);
  155. if (fd < 0) {
  156. haltest_error("Can't open file: %s for reading\n", name);
  157. return;
  158. }
  159. if (fd_stack_pointer >= 10) {
  160. haltest_error("To many open files\n");
  161. close(fd);
  162. return;
  163. }
  164. fd_stack[fd_stack_pointer++] = fd;
  165. poll_unregister_fd(fd_stack[fd_stack_pointer - 2], stdin_handler);
  166. poll_register_fd(fd_stack[fd_stack_pointer - 1], POLLIN, stdin_handler);
  167. }
  168. static void source_p(int argc, const char **argv)
  169. {
  170. if (argc < 2) {
  171. haltest_error("No file specified");
  172. return;
  173. }
  174. process_file(argv[1]);
  175. }
  176. /* Commands available without interface */
  177. static struct method commands[] = {
  178. STD_METHODCH(help, "[<interface>]"),
  179. STD_METHOD(quit),
  180. METHOD("exit", quit_p, NULL, NULL),
  181. STD_METHODH(source, "<file>"),
  182. END_METHOD
  183. };
  184. /* Gets comman by name */
  185. struct method *get_command(const char *name)
  186. {
  187. return get_method(commands, name);
  188. }
  189. /* Function to enumerate interface names */
  190. const char *interface_name(void *v, int i)
  191. {
  192. return interfaces[i] ? interfaces[i]->name : NULL;
  193. }
  194. /* Function to enumerate command and interface names */
  195. const char *command_name(void *v, int i)
  196. {
  197. int cmd_cnt = NELEM(commands);
  198. if (i >= cmd_cnt)
  199. return interface_name(v, i - cmd_cnt);
  200. else
  201. return commands[i].name;
  202. }
  203. /*
  204. * This function changes input parameter line_buffer so it has
  205. * null termination after each token (due to strtok)
  206. * Output argv is filled with pointers to arguments
  207. * returns number of tokens parsed - argc
  208. */
  209. static int command_line_to_argv(char *line_buffer, char *argv[], int argv_size)
  210. {
  211. static const char *token_breaks = "\r\n\t ";
  212. char *token;
  213. int argc = 0;
  214. token = strtok(line_buffer, token_breaks);
  215. while (token != NULL && argc < (int) argv_size) {
  216. argv[argc++] = token;
  217. token = strtok(NULL, token_breaks);
  218. }
  219. return argc;
  220. }
  221. static void process_line(char *line_buffer)
  222. {
  223. char *argv[50];
  224. int argc;
  225. int i = 0;
  226. struct method *m;
  227. argc = command_line_to_argv(line_buffer, argv, 50);
  228. if (argc < 1)
  229. return;
  230. while (interfaces[i] != NULL) {
  231. if (strcmp(interfaces[i]->name, argv[0])) {
  232. i++;
  233. continue;
  234. }
  235. if (argc < 2 || strcmp(argv[1], "?") == 0) {
  236. help_print_interface(interfaces[i]);
  237. return;
  238. }
  239. m = get_method(interfaces[i]->methods, argv[1]);
  240. if (m != NULL) {
  241. m->func(argc, (const char **) argv);
  242. return;
  243. }
  244. haltest_error("No function %s found\n", argv[1]);
  245. return;
  246. }
  247. /* No interface, try commands */
  248. m = get_command(argv[0]);
  249. if (m == NULL)
  250. haltest_error("No such command %s\n", argv[0]);
  251. else
  252. m->func(argc, (const char **) argv);
  253. }
  254. /* called when there is something on stdin */
  255. static void stdin_handler(struct pollfd *pollfd)
  256. {
  257. char buf[10];
  258. if (pollfd->revents & POLLIN) {
  259. int count = read(fd_stack[fd_stack_pointer - 1], buf, 10);
  260. if (count > 0) {
  261. int i;
  262. for (i = 0; i < count; ++i)
  263. terminal_process_char(buf[i], process_line);
  264. return;
  265. }
  266. }
  267. if (fd_stack_pointer > 1)
  268. poll_register_fd(fd_stack[fd_stack_pointer - 2], POLLIN,
  269. stdin_handler);
  270. if (fd_stack_pointer > 0) {
  271. poll_unregister_fd(fd_stack[--fd_stack_pointer], stdin_handler);
  272. if (fd_stack[fd_stack_pointer])
  273. close(fd_stack[fd_stack_pointer]);
  274. }
  275. }
  276. static void usage(void)
  277. {
  278. printf("haltest Android Bluetooth HAL testing tool\n"
  279. "Usage:\n");
  280. printf("\thaltest [options]\n");
  281. printf("options:\n"
  282. "\t-i --ivi Initialize only IVI interfaces\n"
  283. "\t-n, --no-init Don't initialize any interfaces\n"
  284. "\t-v --version Print version\n"
  285. "\t-h, --help Show help options\n");
  286. }
  287. static void print_version(void)
  288. {
  289. printf("haltest version %s\n", VERSION);
  290. }
  291. static const struct option main_options[] = {
  292. { "no-init", no_argument, NULL, 'n' },
  293. { "ivi", no_argument, NULL, 'i' },
  294. { "help", no_argument, NULL, 'h' },
  295. { "version", no_argument, NULL, 'v' },
  296. { NULL }
  297. };
  298. static bool no_init = false;
  299. static bool ivi_only = false;
  300. static void parse_command_line(int argc, char *argv[])
  301. {
  302. for (;;) {
  303. int opt;
  304. opt = getopt_long(argc, argv, "inhv", main_options, NULL);
  305. if (opt < 0)
  306. break;
  307. switch (opt) {
  308. case 'n':
  309. no_init = true;
  310. break;
  311. case 'i':
  312. ivi_only = true;
  313. break;
  314. case 'h':
  315. usage();
  316. exit(0);
  317. case 'v':
  318. print_version();
  319. exit(0);
  320. default:
  321. putchar('\n');
  322. exit(-1);
  323. break;
  324. }
  325. }
  326. }
  327. static const char * const interface_names[] = {
  328. BT_PROFILE_HANDSFREE_ID,
  329. BT_PROFILE_ADVANCED_AUDIO_ID,
  330. BT_PROFILE_AV_RC_ID,
  331. BT_PROFILE_HEALTH_ID,
  332. BT_PROFILE_HIDHOST_ID,
  333. BT_PROFILE_PAN_ID,
  334. BT_PROFILE_GATT_ID,
  335. BT_PROFILE_SOCKETS_ID,
  336. NULL
  337. };
  338. static const char * const ivi_interface_inames[] = {
  339. #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
  340. BT_PROFILE_HANDSFREE_CLIENT_ID,
  341. BT_PROFILE_MAP_CLIENT_ID,
  342. BT_PROFILE_AV_RC_CTRL_ID,
  343. BT_PROFILE_ADVANCED_AUDIO_SINK_ID,
  344. #endif
  345. NULL
  346. };
  347. static void init(const char * const *inames)
  348. {
  349. const struct method *m;
  350. const char *argv[4];
  351. char init_audio[] = "audio init";
  352. char init_sco[] = "sco init";
  353. char init_bt[] = "bluetooth init";
  354. uint32_t i;
  355. process_line(init_audio);
  356. process_line(init_sco);
  357. process_line(init_bt);
  358. m = get_interface_method("bluetooth", "get_profile_interface");
  359. while (*inames) {
  360. argv[2] = *inames;
  361. m->func(3, argv);
  362. inames++;
  363. }
  364. /* Init what is available to init */
  365. for (i = 3; i < NELEM(interfaces) - 1; ++i) {
  366. m = get_interface_method(interfaces[i]->name, "init");
  367. if (m != NULL)
  368. m->func(2, argv);
  369. }
  370. }
  371. int main(int argc, char **argv)
  372. {
  373. struct stat rcstat;
  374. parse_command_line(argc, argv);
  375. terminal_setup();
  376. if (!no_init) {
  377. if (ivi_only)
  378. init(ivi_interface_inames);
  379. else
  380. init(interface_names);
  381. }
  382. history_restore(".haltest_history");
  383. fd_stack[fd_stack_pointer++] = 0;
  384. /* Register command line handler */
  385. poll_register_fd(0, POLLIN, stdin_handler);
  386. if (stat(".haltestrc", &rcstat) == 0 && (rcstat.st_mode & S_IFREG) != 0)
  387. process_file(".haltestrc");
  388. poll_dispatch_loop();
  389. return 0;
  390. }