if-hl.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. // SPDX-License-Identifier: Apache-2.0
  2. /*
  3. * Copyright (C) 2014 Intel Corporation
  4. *
  5. */
  6. #define _GNU_SOURCE
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include <hardware/bluetooth.h>
  12. #include <hardware/bt_hl.h>
  13. #include "if-main.h"
  14. #include "pollhandler.h"
  15. #include "../hal-utils.h"
  16. SINTMAP(bthl_mdep_role_t, -1, "(unknown)")
  17. DELEMENT(BTHL_MDEP_ROLE_SOURCE),
  18. DELEMENT(BTHL_MDEP_ROLE_SINK),
  19. ENDMAP
  20. SINTMAP(bthl_channel_type_t, -1, "(unknown)")
  21. DELEMENT(BTHL_CHANNEL_TYPE_RELIABLE),
  22. DELEMENT(BTHL_CHANNEL_TYPE_STREAMING),
  23. DELEMENT(BTHL_CHANNEL_TYPE_ANY),
  24. ENDMAP
  25. SINTMAP(bthl_app_reg_state_t, -1, "(unknown)")
  26. DELEMENT(BTHL_APP_REG_STATE_REG_SUCCESS),
  27. DELEMENT(BTHL_APP_REG_STATE_REG_FAILED),
  28. DELEMENT(BTHL_APP_REG_STATE_DEREG_SUCCESS),
  29. DELEMENT(BTHL_APP_REG_STATE_DEREG_FAILED),
  30. ENDMAP
  31. SINTMAP(bthl_channel_state_t, -1, "(unknown)")
  32. DELEMENT(BTHL_CONN_STATE_CONNECTING),
  33. DELEMENT(BTHL_CONN_STATE_CONNECTED),
  34. DELEMENT(BTHL_CONN_STATE_DISCONNECTING),
  35. DELEMENT(BTHL_CONN_STATE_DISCONNECTED),
  36. DELEMENT(BTHL_CONN_STATE_DESTROYED),
  37. ENDMAP
  38. #define APP_ID_SIZE 20
  39. #define MDEP_CFG_SIZE 10
  40. #define CHANNEL_ID_SIZE 50
  41. struct channel_info {
  42. int fd;
  43. };
  44. struct mdep_cfg {
  45. uint8_t role;
  46. struct channel_info channel[CHANNEL_ID_SIZE];
  47. };
  48. struct {
  49. struct mdep_cfg mdep[MDEP_CFG_SIZE];
  50. } app[APP_ID_SIZE];
  51. const bthl_interface_t *if_hl = NULL;
  52. static void app_reg_state_cb(int app_id, bthl_app_reg_state_t state)
  53. {
  54. haltest_info("%s: app_id=%d app_reg_state=%s\n", __func__,
  55. app_id, bthl_app_reg_state_t2str(state));
  56. }
  57. static void channel_state_cb(int app_id, bt_bdaddr_t *bd_addr,
  58. int index, int channel_id,
  59. bthl_channel_state_t state, int fd)
  60. {
  61. char addr[MAX_ADDR_STR_LEN];
  62. haltest_info("%s: app_id=%d bd_addr=%s mdep_cfg_index=%d\n"
  63. "channel_id=%d channel_state=%s fd=%d\n", __func__,
  64. app_id, bt_bdaddr_t2str(bd_addr, addr), index,
  65. channel_id, bthl_channel_state_t2str(state), fd);
  66. if (app_id >= APP_ID_SIZE || index >= MDEP_CFG_SIZE
  67. || channel_id >= CHANNEL_ID_SIZE) {
  68. haltest_error("exceeds maximum limit");
  69. return;
  70. }
  71. if (state == BTHL_CONN_STATE_CONNECTED) {
  72. app[app_id].mdep[index].channel[channel_id].fd = fd;
  73. /*
  74. * PTS expects dummy data on fd when it
  75. * connects in source role.
  76. */
  77. if (app[app_id].mdep[index].role == BTHL_MDEP_ROLE_SOURCE)
  78. if (write(fd, "0", sizeof("0")) < 0)
  79. haltest_error("writing data on fd failed\n");
  80. return;
  81. }
  82. if (state == BTHL_CONN_STATE_DISCONNECTED ||
  83. state == BTHL_CONN_STATE_DESTROYED) {
  84. if (app[app_id].mdep[index].channel[channel_id].fd >= 0) {
  85. close(app[app_id].mdep[index].channel[channel_id].fd);
  86. app[app_id].mdep[index].channel[channel_id].fd = -1;
  87. }
  88. }
  89. }
  90. static bthl_callbacks_t hl_cbacks = {
  91. .size = sizeof(hl_cbacks),
  92. .app_reg_state_cb = app_reg_state_cb,
  93. .channel_state_cb = channel_state_cb,
  94. };
  95. /* init */
  96. static void init_p(int argc, const char **argv)
  97. {
  98. int i, j, k;
  99. for (i = 0; i < APP_ID_SIZE; i++) {
  100. for (j = 0; j < MDEP_CFG_SIZE; j++) {
  101. app[i].mdep[j].role = 0;
  102. for (k = 0; k < CHANNEL_ID_SIZE; k++)
  103. app[i].mdep[j].channel[k].fd = -1;
  104. }
  105. }
  106. RETURN_IF_NULL(if_hl);
  107. EXEC(if_hl->init, &hl_cbacks);
  108. }
  109. /* register_application */
  110. static void register_application_p(int argc, const char **argv)
  111. {
  112. bthl_reg_param_t reg;
  113. uint16_t mdep_argc_init, mdep_argc_off;
  114. int app_id = -1;
  115. int i;
  116. RETURN_IF_NULL(if_hl);
  117. if (argc <= 2) {
  118. haltest_error("No app name is specified\n");
  119. return;
  120. }
  121. if (argc <= 3) {
  122. haltest_error("No provider is specified\n");
  123. return;
  124. }
  125. if (argc <= 4) {
  126. haltest_error("No service name is specified\n");
  127. return;
  128. }
  129. if (argc <= 5) {
  130. haltest_error("No service description is specified\n");
  131. return;
  132. }
  133. if (argc <= 6) {
  134. haltest_error("No num of mdeps is specified\n");
  135. return;
  136. }
  137. memset(&reg, 0, sizeof(reg));
  138. if (argc != ((atoi(argv[6]) * 4) + 7)) {
  139. haltest_error("mdep cfg argumetns are not proper\n");
  140. return;
  141. }
  142. reg.application_name = argv[2];
  143. if (strcmp("-", argv[3]))
  144. reg.provider_name = argv[3];
  145. if (strcmp("-", argv[4]))
  146. reg.srv_name = argv[4];
  147. if (strcmp("-", argv[5]))
  148. reg.srv_desp = argv[5];
  149. reg.number_of_mdeps = atoi(argv[6]);
  150. reg.mdep_cfg = malloc(reg.number_of_mdeps * sizeof(bthl_mdep_cfg_t));
  151. if (!reg.mdep_cfg) {
  152. haltest_error("malloc failed\n");
  153. return;
  154. }
  155. mdep_argc_init = 7;
  156. for (i = 0; i < reg.number_of_mdeps; i++) {
  157. mdep_argc_off = mdep_argc_init + (4 * i);
  158. reg.mdep_cfg[i].mdep_role =
  159. str2bthl_mdep_role_t(argv[mdep_argc_off]);
  160. reg.mdep_cfg[i].data_type = atoi(argv[mdep_argc_off + 1]);
  161. reg.mdep_cfg[i].channel_type =
  162. str2bthl_channel_type_t(argv[mdep_argc_off + 2]);
  163. if (!strcmp("-", argv[mdep_argc_off + 3])) {
  164. reg.mdep_cfg[i].mdep_description = NULL;
  165. continue;
  166. }
  167. reg.mdep_cfg[i].mdep_description = argv[mdep_argc_off + 3];
  168. }
  169. EXEC(if_hl->register_application, &reg, &app_id);
  170. for (i = 0; i < reg.number_of_mdeps; i++)
  171. app[app_id].mdep[i].role = reg.mdep_cfg[i].mdep_role;
  172. free(reg.mdep_cfg);
  173. }
  174. /* unregister_application */
  175. static void unregister_application_p(int argc, const char **argv)
  176. {
  177. uint32_t app_id;
  178. RETURN_IF_NULL(if_hl);
  179. if (argc <= 2) {
  180. haltest_error("No app id is specified");
  181. return;
  182. }
  183. app_id = (uint32_t) atoi(argv[2]);
  184. EXEC(if_hl->unregister_application, app_id);
  185. }
  186. /* connect_channel */
  187. static void connect_channel_p(int argc, const char **argv)
  188. {
  189. uint32_t app_id, mdep_cfg_index;
  190. int channel_id = -1;
  191. bt_bdaddr_t bd_addr;
  192. RETURN_IF_NULL(if_hl);
  193. if (argc <= 2) {
  194. haltest_error("No app id is specified");
  195. return;
  196. }
  197. VERIFY_ADDR_ARG(3, &bd_addr);
  198. if (argc <= 4) {
  199. haltest_error("No mdep cfg index is specified");
  200. return;
  201. }
  202. app_id = (uint32_t) atoi(argv[2]);
  203. mdep_cfg_index = (uint32_t) atoi(argv[4]);
  204. EXEC(if_hl->connect_channel, app_id, &bd_addr, mdep_cfg_index,
  205. &channel_id);
  206. }
  207. /* destroy_channel */
  208. static void destroy_channel_p(int argc, const char **argv)
  209. {
  210. uint32_t channel_id;
  211. RETURN_IF_NULL(if_hl);
  212. if (argc <= 2) {
  213. haltest_error("No channel id is specified");
  214. return;
  215. }
  216. channel_id = (uint32_t) atoi(argv[2]);
  217. EXEC(if_hl->destroy_channel, channel_id);
  218. }
  219. /* close_channel */
  220. static void close_channel_p(int argc, const char **argv)
  221. {
  222. uint32_t app_id;
  223. uint8_t index;
  224. int channel_id;
  225. RETURN_IF_NULL(if_hl);
  226. if (argc <= 2) {
  227. haltest_error("No app id is specified");
  228. return;
  229. }
  230. if (argc <= 3) {
  231. haltest_error("No mdep_cfg_index is specified");
  232. return;
  233. }
  234. if (argc <= 4) {
  235. haltest_error("No channel_id is specified");
  236. return;
  237. }
  238. app_id = (uint32_t) atoi(argv[2]);
  239. if (app_id >= APP_ID_SIZE) {
  240. haltest_error("Wrong app_id specified: %u\n", app_id);
  241. return;
  242. }
  243. index = (uint8_t) atoi(argv[3]);
  244. if (index >= MDEP_CFG_SIZE) {
  245. haltest_error("Wrong mdep cfg index: %u\n", index);
  246. return;
  247. }
  248. channel_id = atoi(argv[4]);
  249. if (channel_id >= CHANNEL_ID_SIZE) {
  250. haltest_error("Wrong channel id: %u\n", channel_id);
  251. return;
  252. }
  253. if (app[app_id].mdep[index].channel[channel_id].fd >= 0) {
  254. shutdown(app[app_id].mdep[index].channel[channel_id].fd,
  255. SHUT_RDWR);
  256. app[app_id].mdep[index].channel[channel_id].fd = -1;
  257. }
  258. }
  259. /* cleanup */
  260. static void cleanup_p(int argc, const char **argv)
  261. {
  262. RETURN_IF_NULL(if_hl);
  263. EXECV(if_hl->cleanup);
  264. if_hl = NULL;
  265. }
  266. static struct method methods[] = {
  267. STD_METHOD(init),
  268. STD_METHODH(register_application,
  269. "<app_name> <provider_name> <srv_name> <srv_descr>\n"
  270. "<num_of_mdeps>\n"
  271. "[[<mdep_role>] [<data_type>] [<channel_type>] [<mdep_descr>]]"
  272. "..."),
  273. STD_METHODH(unregister_application, "<app_id>"),
  274. STD_METHODH(connect_channel, "<app_id> <bd_addr> <mdep_cfg_index>"),
  275. STD_METHODH(destroy_channel, "<channel_id>"),
  276. STD_METHODH(close_channel, "<app_id> <mdep_cfg_index> <channel_id>"),
  277. STD_METHOD(cleanup),
  278. END_METHOD
  279. };
  280. const struct interface hl_if = {
  281. .name = "hl",
  282. .methods = methods
  283. };