test-avctp.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2014 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <unistd.h>
  14. #include <stdlib.h>
  15. #include <stdbool.h>
  16. #include <inttypes.h>
  17. #include <string.h>
  18. #include <fcntl.h>
  19. #include <sys/socket.h>
  20. #include <glib.h>
  21. #include "src/shared/util.h"
  22. #include "src/shared/tester.h"
  23. #include "src/log.h"
  24. #include "android/avctp.h"
  25. struct test_pdu {
  26. bool valid;
  27. uint8_t *data;
  28. size_t size;
  29. };
  30. struct test_data {
  31. char *test_name;
  32. struct test_pdu *pdu_list;
  33. };
  34. struct context {
  35. struct avctp *session;
  36. guint source;
  37. guint process;
  38. int fd;
  39. unsigned int pdu_offset;
  40. const struct test_data *data;
  41. };
  42. #define data(args...) ((const unsigned char[]) { args })
  43. #define raw_pdu(args...) \
  44. { \
  45. .valid = true, \
  46. .data = g_memdup(data(args), sizeof(data(args))), \
  47. .size = sizeof(data(args)), \
  48. }
  49. #define define_test(name, function, args...) \
  50. do { \
  51. const struct test_pdu pdus[] = { \
  52. args, { } \
  53. }; \
  54. static struct test_data data; \
  55. data.test_name = g_strdup(name); \
  56. data.pdu_list = g_memdup(pdus, sizeof(pdus)); \
  57. tester_add(name, &data, NULL, function, NULL); \
  58. } while (0)
  59. static void test_free(gconstpointer user_data)
  60. {
  61. const struct test_data *data = user_data;
  62. struct test_pdu *pdu;
  63. int i;
  64. for (i = 0; (pdu = &data->pdu_list[i]) && pdu->valid; i++)
  65. g_free(pdu->data);
  66. g_free(data->test_name);
  67. g_free(data->pdu_list);
  68. }
  69. static void destroy_context(struct context *context)
  70. {
  71. if (context->source > 0)
  72. g_source_remove(context->source);
  73. avctp_shutdown(context->session);
  74. test_free(context->data);
  75. g_free(context);
  76. }
  77. static gboolean context_quit(gpointer user_data)
  78. {
  79. struct context *context = user_data;
  80. if (context->process > 0)
  81. g_source_remove(context->process);
  82. destroy_context(context);
  83. tester_test_passed();
  84. return FALSE;
  85. }
  86. static gboolean send_pdu(gpointer user_data)
  87. {
  88. struct context *context = user_data;
  89. const struct test_pdu *pdu;
  90. ssize_t len;
  91. pdu = &context->data->pdu_list[context->pdu_offset++];
  92. len = write(context->fd, pdu->data, pdu->size);
  93. tester_monitor('<', 0x0000, 0x0017, pdu->data, len);
  94. g_assert_cmpint(len, ==, pdu->size);
  95. context->process = 0;
  96. return FALSE;
  97. }
  98. static void context_process(struct context *context)
  99. {
  100. if (!context->data->pdu_list[context->pdu_offset].valid) {
  101. context_quit(context);
  102. return;
  103. }
  104. context->process = g_idle_add(send_pdu, context);
  105. }
  106. static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
  107. gpointer user_data)
  108. {
  109. struct context *context = user_data;
  110. const struct test_pdu *pdu;
  111. unsigned char buf[512];
  112. ssize_t len;
  113. int fd;
  114. pdu = &context->data->pdu_list[context->pdu_offset++];
  115. if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
  116. context->source = 0;
  117. g_print("%s: cond %x\n", __func__, cond);
  118. return FALSE;
  119. }
  120. fd = g_io_channel_unix_get_fd(channel);
  121. len = read(fd, buf, sizeof(buf));
  122. g_assert(len > 0);
  123. tester_monitor('>', 0x0000, 0x0017, buf, len);
  124. g_assert_cmpint(len, ==, pdu->size);
  125. g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
  126. context_process(context);
  127. return TRUE;
  128. }
  129. static struct context *create_context(uint16_t version, gconstpointer data)
  130. {
  131. struct context *context = g_new0(struct context, 1);
  132. GIOChannel *channel;
  133. int err, sv[2];
  134. err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
  135. g_assert(err == 0);
  136. context->session = avctp_new(sv[0], 672, 672, version);
  137. g_assert(context->session != NULL);
  138. channel = g_io_channel_unix_new(sv[1]);
  139. g_io_channel_set_close_on_unref(channel, TRUE);
  140. g_io_channel_set_encoding(channel, NULL, NULL);
  141. g_io_channel_set_buffered(channel, FALSE);
  142. context->source = g_io_add_watch(channel,
  143. G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  144. test_handler, context);
  145. g_assert(context->source > 0);
  146. g_io_channel_unref(channel);
  147. context->fd = sv[1];
  148. context->data = data;
  149. return context;
  150. }
  151. static ssize_t handler(struct avctp *session,
  152. uint8_t transaction, uint8_t *code,
  153. uint8_t *subunit, uint8_t *operands,
  154. size_t operand_count, void *user_data)
  155. {
  156. g_assert_cmpint(transaction, ==, 0);
  157. g_assert_cmpint(*code, ==, 0);
  158. g_assert_cmpint(*subunit, ==, 0);
  159. g_assert_cmpint(operand_count, ==, 0);
  160. return operand_count;
  161. }
  162. static gboolean handler_response(struct avctp *session,
  163. uint8_t code, uint8_t subunit,
  164. uint8_t *operands, size_t operand_count,
  165. void *user_data)
  166. {
  167. struct context *context = user_data;
  168. g_assert_cmpint(code, ==, 0x0a);
  169. g_assert_cmpint(subunit, ==, 0);
  170. g_assert_cmpint(operand_count, ==, 0);
  171. return context_quit(context);
  172. }
  173. static void test_client(gconstpointer data)
  174. {
  175. struct context *context = create_context(0x0100, data);
  176. avctp_send_vendor_req(context->session, AVC_CTYPE_CONTROL, 0, NULL,
  177. 0, handler_response, context);
  178. }
  179. static void test_server(gconstpointer data)
  180. {
  181. struct context *context = create_context(0x0100, data);
  182. if (g_str_equal(context->data->test_name, "/TP/NFR/BV-03-C")) {
  183. int ret;
  184. ret = avctp_register_pdu_handler(context->session,
  185. AVC_OP_VENDORDEP, handler, NULL);
  186. g_assert_cmpint(ret, !=, 0);
  187. }
  188. g_idle_add(send_pdu, context);
  189. }
  190. static void test_dummy(gconstpointer data)
  191. {
  192. struct context *context = create_context(0x0100, data);
  193. context_quit(context);
  194. }
  195. int main(int argc, char *argv[])
  196. {
  197. tester_init(&argc, &argv);
  198. __btd_log_init("*", 0);
  199. /* Connection Channel Management tests */
  200. /*
  201. * Tests are checking that IUT is able to request establishing
  202. * channels, since we already have connection through socketpair
  203. * the tests are dummy.
  204. */
  205. define_test("/TP/CCM/BV-01-C", test_dummy, raw_pdu(0x00));
  206. define_test("/TP/CCM/BV-02-C", test_dummy, raw_pdu(0x00));
  207. define_test("/TP/CCM/BV-03-C", test_dummy, raw_pdu(0x00));
  208. define_test("/TP/CCM/BV-04-C", test_dummy, raw_pdu(0x00));
  209. /* Non-Fragmented Messages tests */
  210. define_test("/TP/NFR/BV-01-C", test_client,
  211. raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x00, 0x00));
  212. define_test("/TP/NFR/BV-02-C", test_server,
  213. raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x00, 0x00),
  214. raw_pdu(0x02, 0x11, 0x0e, 0x0a, 0x00, 0x00));
  215. define_test("/TP/NFR/BV-03-C", test_server,
  216. raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x00, 0x00),
  217. raw_pdu(0x02, 0x11, 0x0e, 0x00, 0x00, 0x00));
  218. define_test("/TP/NFR/BV-04-C", test_client,
  219. raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x00, 0x00),
  220. raw_pdu(0x02, 0x11, 0x0e, 0x0a, 0x00, 0x00));
  221. define_test("/TP/NFR/BI-01-C", test_server,
  222. raw_pdu(0x00, 0xff, 0xff, 0x00, 0x00, 0x00),
  223. raw_pdu(0x03, 0xff, 0xff));
  224. return tester_run();
  225. }