avdtptest.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  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
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <getopt.h>
  17. #include <unistd.h>
  18. #include <stdbool.h>
  19. #include <errno.h>
  20. #include <glib.h>
  21. #include "lib/bluetooth.h"
  22. #include "lib/hci.h"
  23. #include "lib/hci_lib.h"
  24. #include "btio/btio.h"
  25. #include "src/shared/util.h"
  26. #include "src/shared/queue.h"
  27. #include "avdtp.h"
  28. static GMainLoop *mainloop = NULL;
  29. static int dev_role = AVDTP_SEP_TYPE_SOURCE;
  30. static bool preconf = false;
  31. static struct avdtp *avdtp = NULL;
  32. struct avdtp_stream *avdtp_stream = NULL;
  33. struct avdtp_local_sep *local_sep = NULL;
  34. struct avdtp_remote_sep *remote_sep = NULL;
  35. static GIOChannel *io = NULL;
  36. static bool reject = false;
  37. static bdaddr_t src;
  38. static bdaddr_t dst;
  39. static uint16_t version = 0x0103;
  40. static guint media_player = 0;
  41. static guint media_recorder = 0;
  42. static guint idle_id = 0;
  43. static struct queue *lseps = NULL;
  44. static bool fragment = false;
  45. static enum {
  46. CMD_GET_CONF,
  47. CMD_OPEN,
  48. CMD_START,
  49. CMD_SUSPEND,
  50. CMD_CLOSE,
  51. CMD_ABORT,
  52. CMD_DELAY,
  53. CMD_NONE,
  54. } command = CMD_NONE;
  55. static const char sbc_codec[] = {0x00, 0x00, 0x11, 0x15, 0x02, 0x40};
  56. static const char sbc_media_frame[] = {
  57. 0x00, 0x60, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  58. 0x01, 0x9c, 0xfd, 0x40, 0xbd, 0xde, 0xa9, 0x75, 0x43, 0x20, 0x87, 0x64,
  59. 0x44, 0x32, 0x7f, 0xbe, 0xf7, 0x76, 0xfe, 0xf7, 0xbb, 0xbb, 0x7f, 0xbe,
  60. 0xf7, 0x76, 0xfe, 0xf7, 0xbb, 0xbb, 0x7f, 0xbe, 0xf7, 0x76, 0xfe, 0xf7,
  61. 0xbb, 0xbb, 0x80, 0x3e, 0xf7, 0x76, 0xfe, 0xf7, 0xbb, 0xbb, 0x83, 0x41,
  62. 0x07, 0x77, 0x09, 0x07, 0x43, 0xb3, 0x81, 0xbc, 0xf8, 0x77, 0x02, 0xe5,
  63. 0xa4, 0x3a, 0xa0, 0xcb, 0x38, 0xbb, 0x57, 0x90, 0xd9, 0x08, 0x9c, 0x1d,
  64. 0x86, 0x59, 0x01, 0x0c, 0x21, 0x44, 0x68, 0x35, 0xa8, 0x57, 0x97, 0x0e,
  65. 0x9b, 0xbb, 0x62, 0xc4, 0xca, 0x57, 0x04, 0xa1, 0xca, 0x3b, 0xa3, 0x48,
  66. 0xd2, 0x66, 0x11, 0x33, 0x6a, 0x3b, 0xb4, 0xbb, 0x08, 0x77, 0x17, 0x03,
  67. 0xb4, 0x3b, 0x79, 0x3b, 0x46, 0x97, 0x0e, 0xf7, 0x3d, 0xbb, 0x3d, 0x49,
  68. 0x25, 0x86, 0x88, 0xb4, 0xad, 0x3b, 0x62, 0xbb, 0xa4, 0x47, 0x29, 0x99,
  69. 0x3b, 0x3b, 0xaf, 0xc6, 0xd4, 0x37, 0x68, 0x94, 0x0a, 0xbb
  70. };
  71. static void parse_command(const char *cmd)
  72. {
  73. if (!strncmp(cmd, "getconf", sizeof("getconf"))) {
  74. command = CMD_GET_CONF;
  75. } else if (!strncmp(cmd, "open", sizeof("open"))) {
  76. command = CMD_OPEN;
  77. } else if (!strncmp(cmd, "start", sizeof("start"))) {
  78. command = CMD_START;
  79. } else if (!strncmp(cmd, "suspend", sizeof("suspend"))) {
  80. command = CMD_SUSPEND;
  81. } else if (!strncmp(cmd, "close", sizeof("close"))) {
  82. command = CMD_CLOSE;
  83. } else if (!strncmp(cmd, "abort", sizeof("abort"))) {
  84. command = CMD_ABORT;
  85. } else if (!strncmp(cmd, "delay", sizeof("delay"))) {
  86. command = CMD_DELAY;
  87. } else {
  88. printf("Unknown command '%s'\n", cmd);
  89. printf("(getconf open start suspend close abort delay)\n");
  90. exit(1);
  91. }
  92. }
  93. static void send_command(void)
  94. {
  95. avdtp_state_t state = avdtp_sep_get_state(local_sep);
  96. switch (command) {
  97. case CMD_GET_CONF:
  98. avdtp_get_configuration(avdtp, avdtp_stream);
  99. break;
  100. case CMD_OPEN:
  101. if (state == AVDTP_STATE_CONFIGURED)
  102. avdtp_open(avdtp, avdtp_stream);
  103. break;
  104. case CMD_START:
  105. if (state == AVDTP_STATE_OPEN)
  106. avdtp_start(avdtp, avdtp_stream);
  107. break;
  108. case CMD_SUSPEND:
  109. if (state == AVDTP_STATE_STREAMING)
  110. avdtp_suspend(avdtp , avdtp_stream);
  111. break;
  112. case CMD_CLOSE:
  113. if (state == AVDTP_STATE_STREAMING)
  114. avdtp_close(avdtp, avdtp_stream, FALSE);
  115. break;
  116. case CMD_ABORT:
  117. avdtp_abort(avdtp , avdtp_stream);
  118. break;
  119. case CMD_DELAY:
  120. avdtp_delay_report(avdtp , avdtp_stream , 250);
  121. break;
  122. case CMD_NONE:
  123. default:
  124. break;
  125. }
  126. }
  127. static gboolean media_writer(gpointer user_data)
  128. {
  129. uint16_t omtu;
  130. int fd;
  131. int to_write;
  132. if (!avdtp_stream_get_transport(avdtp_stream, &fd, NULL, &omtu, NULL))
  133. return TRUE;
  134. if (omtu < sizeof(sbc_media_frame))
  135. to_write = omtu;
  136. else
  137. to_write = sizeof(sbc_media_frame);
  138. if (write(fd, sbc_media_frame, to_write) < 0)
  139. return TRUE;
  140. send_command();
  141. return TRUE;
  142. }
  143. static bool start_media_player(void)
  144. {
  145. int fd;
  146. uint16_t omtu;
  147. printf("Media streaming started\n");
  148. if (media_player || !avdtp_stream)
  149. return false;
  150. if (!avdtp_stream_get_transport(avdtp_stream, &fd, NULL, &omtu, NULL))
  151. return false;
  152. media_player = g_timeout_add(200, media_writer, NULL);
  153. if (!media_player)
  154. return false;
  155. return true;
  156. }
  157. static void stop_media_player(void)
  158. {
  159. if (!media_player)
  160. return;
  161. printf("Media streaming stopped\n");
  162. g_source_remove(media_player);
  163. media_player = 0;
  164. }
  165. #if __BYTE_ORDER == __LITTLE_ENDIAN
  166. struct rtp_header {
  167. unsigned cc:4;
  168. unsigned x:1;
  169. unsigned p:1;
  170. unsigned v:2;
  171. unsigned pt:7;
  172. unsigned m:1;
  173. uint16_t sequence_number;
  174. uint32_t timestamp;
  175. uint32_t ssrc;
  176. uint32_t csrc[0];
  177. } __attribute__ ((packed));
  178. #elif __BYTE_ORDER == __BIG_ENDIAN
  179. struct rtp_header {
  180. unsigned v:2;
  181. unsigned p:1;
  182. unsigned x:1;
  183. unsigned cc:4;
  184. unsigned m:1;
  185. unsigned pt:7;
  186. uint16_t sequence_number;
  187. uint32_t timestamp;
  188. uint32_t ssrc;
  189. uint32_t csrc[0];
  190. } __attribute__ ((packed));
  191. #else
  192. #error "Unknown byte order"
  193. #endif
  194. static gboolean media_reader(GIOChannel *source, GIOCondition condition,
  195. gpointer data)
  196. {
  197. char buf[UINT16_MAX];
  198. struct rtp_header *rtp = (void *) buf;
  199. static bool decode = false;
  200. uint16_t imtu;
  201. int fd, ret;
  202. if (!avdtp_stream_get_transport(avdtp_stream, &fd, &imtu, NULL, NULL))
  203. return TRUE;
  204. ret = read(fd, buf, imtu);
  205. if (ret < 0) {
  206. printf("Reading failed (%s)\n", strerror(errno));
  207. return TRUE;
  208. }
  209. if (ret < (int) sizeof(*rtp)) {
  210. printf("Not enough media data received (%u bytes)", ret);
  211. return TRUE;
  212. }
  213. if (!decode) {
  214. printf("V=%u P=%u X=%u CC=%u M=%u PT=%u SeqNr=%d\n",
  215. rtp->v, rtp->p, rtp->x, rtp->cc, rtp->m, rtp->pt,
  216. be16_to_cpu(rtp->sequence_number));
  217. decode = true;
  218. }
  219. send_command();
  220. return TRUE;
  221. }
  222. static bool start_media_recorder(void)
  223. {
  224. int fd;
  225. uint16_t omtu;
  226. GIOChannel *chan;
  227. printf("Media recording started\n");
  228. if (media_recorder || !avdtp_stream)
  229. return false;
  230. if (!avdtp_stream_get_transport(avdtp_stream, &fd, NULL, &omtu, NULL))
  231. return false;
  232. chan = g_io_channel_unix_new(fd);
  233. media_recorder = g_io_add_watch(chan, G_IO_IN, media_reader, NULL);
  234. g_io_channel_unref(chan);
  235. if (!media_recorder)
  236. return false;
  237. return true;
  238. }
  239. static void stop_media_recorder(void)
  240. {
  241. if (!media_recorder)
  242. return;
  243. printf("Media recording stopped\n");
  244. g_source_remove(media_recorder);
  245. media_recorder = 0;
  246. }
  247. static void set_configuration_cfm(struct avdtp *session,
  248. struct avdtp_local_sep *lsep,
  249. struct avdtp_stream *stream,
  250. struct avdtp_error *err,
  251. void *user_data)
  252. {
  253. printf("%s\n", __func__);
  254. if (preconf)
  255. avdtp_open(avdtp, avdtp_stream);
  256. }
  257. static void get_configuration_cfm(struct avdtp *session,
  258. struct avdtp_local_sep *lsep,
  259. struct avdtp_stream *stream,
  260. struct avdtp_error *err,
  261. void *user_data)
  262. {
  263. printf("%s\n", __func__);
  264. }
  265. static void disconnect_cb(void *user_data)
  266. {
  267. printf("Disconnected\n");
  268. g_main_loop_quit(mainloop);
  269. }
  270. static void discover_cb(struct avdtp *session, GSList *seps,
  271. struct avdtp_error *err, void *user_data)
  272. {
  273. struct avdtp_service_capability *service;
  274. GSList *caps = NULL;
  275. int ret;
  276. remote_sep = avdtp_find_remote_sep(avdtp, local_sep);
  277. if (!remote_sep) {
  278. printf("Unable to find matching endpoint\n");
  279. avdtp_shutdown(session);
  280. return;
  281. }
  282. printf("Matching endpoint found\n");
  283. service = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT, NULL, 0);
  284. caps = g_slist_append(caps, service);
  285. service = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, sbc_codec,
  286. sizeof(sbc_codec));
  287. caps = g_slist_append(caps, service);
  288. ret = avdtp_set_configuration(avdtp, remote_sep, local_sep, caps,
  289. &avdtp_stream);
  290. g_slist_free_full(caps, g_free);
  291. if (ret < 0) {
  292. printf("Failed to set configuration (%s)\n", strerror(-ret));
  293. avdtp_shutdown(session);
  294. }
  295. }
  296. static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
  297. {
  298. uint16_t imtu, omtu;
  299. GError *gerr = NULL;
  300. int fd;
  301. if (err) {
  302. printf("%s\n", err->message);
  303. g_main_loop_quit(mainloop);
  304. return;
  305. }
  306. bt_io_get(chan, &gerr,
  307. BT_IO_OPT_IMTU, &imtu,
  308. BT_IO_OPT_OMTU, &omtu,
  309. BT_IO_OPT_DEST_BDADDR, &dst,
  310. BT_IO_OPT_INVALID);
  311. if (gerr) {
  312. printf("%s\n", gerr->message);
  313. g_main_loop_quit(mainloop);
  314. return;
  315. }
  316. printf("Connected (imtu=%d omtu=%d)\n", imtu, omtu);
  317. fd = g_io_channel_unix_get_fd(chan);
  318. if (avdtp && avdtp_stream) {
  319. if (!avdtp_stream_set_transport(avdtp_stream, fd, imtu, omtu)) {
  320. printf("avdtp_stream_set_transport: failed\n");
  321. g_main_loop_quit(mainloop);
  322. }
  323. g_io_channel_set_close_on_unref(chan, FALSE);
  324. send_command();
  325. return;
  326. }
  327. avdtp = avdtp_new(fd, imtu, omtu, version, lseps);
  328. if (!avdtp) {
  329. printf("Failed to create avdtp instance\n");
  330. g_main_loop_quit(mainloop);
  331. return;
  332. }
  333. avdtp_add_disconnect_cb(avdtp, disconnect_cb, NULL);
  334. if (preconf) {
  335. int ret;
  336. ret = avdtp_discover(avdtp, discover_cb, NULL);
  337. if (ret < 0) {
  338. printf("avdtp_discover failed: %s", strerror(-ret));
  339. g_main_loop_quit(mainloop);
  340. }
  341. }
  342. }
  343. static GIOChannel *do_connect(GError **err)
  344. {
  345. if (fragment)
  346. return bt_io_connect(connect_cb, NULL, NULL, err,
  347. BT_IO_OPT_SOURCE_BDADDR, &src,
  348. BT_IO_OPT_DEST_BDADDR, &dst,
  349. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
  350. BT_IO_OPT_PSM, AVDTP_PSM,
  351. BT_IO_OPT_MTU, 48,
  352. BT_IO_OPT_INVALID);
  353. return bt_io_connect(connect_cb, NULL, NULL, err,
  354. BT_IO_OPT_SOURCE_BDADDR, &src,
  355. BT_IO_OPT_DEST_BDADDR, &dst,
  356. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
  357. BT_IO_OPT_PSM, AVDTP_PSM,
  358. BT_IO_OPT_INVALID);
  359. }
  360. static void open_cfm(struct avdtp *session, struct avdtp_local_sep *lsep,
  361. struct avdtp_stream *stream, struct avdtp_error *err,
  362. void *user_data)
  363. {
  364. GError *gerr = NULL;
  365. printf("%s\n", __func__);
  366. do_connect(&gerr);
  367. if (gerr) {
  368. printf("connect failed: %s\n", gerr->message);
  369. g_error_free(gerr);
  370. g_main_loop_quit(mainloop);
  371. }
  372. }
  373. static void start_cfm(struct avdtp *session, struct avdtp_local_sep *lsep,
  374. struct avdtp_stream *stream, struct avdtp_error *err,
  375. void *user_data)
  376. {
  377. printf("%s\n", __func__);
  378. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  379. start_media_player();
  380. else
  381. start_media_recorder();
  382. }
  383. static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *lsep,
  384. struct avdtp_stream *stream,
  385. struct avdtp_error *err, void *user_data)
  386. {
  387. printf("%s\n", __func__);
  388. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  389. stop_media_player();
  390. else
  391. stop_media_recorder();
  392. }
  393. static void close_cfm(struct avdtp *session, struct avdtp_local_sep *lsep,
  394. struct avdtp_stream *stream,
  395. struct avdtp_error *err, void *user_data)
  396. {
  397. printf("%s\n", __func__);
  398. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  399. stop_media_player();
  400. else
  401. stop_media_recorder();
  402. avdtp_stream = NULL;
  403. }
  404. static void abort_cfm(struct avdtp *session, struct avdtp_local_sep *lsep,
  405. struct avdtp_stream *stream,
  406. struct avdtp_error *err, void *user_data)
  407. {
  408. printf("%s\n", __func__);
  409. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  410. stop_media_player();
  411. else
  412. stop_media_recorder();
  413. avdtp_stream = NULL;
  414. }
  415. static void reconfigure_cfm(struct avdtp *session,
  416. struct avdtp_local_sep *lsep,
  417. struct avdtp_stream *stream,
  418. struct avdtp_error *err, void *user_data)
  419. {
  420. printf("%s\n", __func__);
  421. }
  422. static void delay_report_cfm(struct avdtp *session,
  423. struct avdtp_local_sep *lsep,
  424. struct avdtp_stream *stream,
  425. struct avdtp_error *err, void *user_data)
  426. {
  427. printf("%s\n", __func__);
  428. }
  429. static struct avdtp_sep_cfm sep_cfm = {
  430. .set_configuration = set_configuration_cfm,
  431. .get_configuration = get_configuration_cfm,
  432. .open = open_cfm,
  433. .start = start_cfm,
  434. .suspend = suspend_cfm,
  435. .close = close_cfm,
  436. .abort = abort_cfm,
  437. .reconfigure = reconfigure_cfm,
  438. .delay_report = delay_report_cfm,
  439. };
  440. static gboolean get_capability_ind(struct avdtp *session,
  441. struct avdtp_local_sep *sep,
  442. GSList **caps, uint8_t *err,
  443. void *user_data)
  444. {
  445. struct avdtp_service_capability *service;
  446. int i;
  447. printf("%s\n", __func__);
  448. if (idle_id > 0) {
  449. g_source_remove(idle_id);
  450. idle_id = 0;
  451. }
  452. if (reject)
  453. return FALSE;
  454. *caps = NULL;
  455. service = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT, NULL, 0);
  456. *caps = g_slist_append(*caps, service);
  457. service = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, sbc_codec,
  458. sizeof(sbc_codec));
  459. *caps = g_slist_append(*caps, service);
  460. if (fragment)
  461. for (i = 0; i < 10; i++) {
  462. service = avdtp_service_cap_new(AVDTP_MEDIA_CODEC,
  463. sbc_codec,
  464. sizeof(sbc_codec));
  465. *caps = g_slist_append(*caps, service);
  466. }
  467. return TRUE;
  468. }
  469. static gboolean set_configuration_ind(struct avdtp *session,
  470. struct avdtp_local_sep *lsep,
  471. struct avdtp_stream *stream,
  472. GSList *caps,
  473. avdtp_set_configuration_cb cb,
  474. void *user_data)
  475. {
  476. printf("%s\n", __func__);
  477. if (reject)
  478. return FALSE;
  479. if (idle_id > 0) {
  480. g_source_remove(idle_id);
  481. idle_id = 0;
  482. }
  483. avdtp_stream = stream;
  484. cb(session, stream, NULL);
  485. send_command();
  486. return TRUE;
  487. }
  488. static gboolean get_configuration_ind(struct avdtp *session,
  489. struct avdtp_local_sep *lsep,
  490. uint8_t *err, void *user_data)
  491. {
  492. printf("%s\n", __func__);
  493. if (reject)
  494. return FALSE;
  495. return TRUE;
  496. }
  497. static gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *lsep,
  498. struct avdtp_stream *stream, uint8_t *err,
  499. void *user_data)
  500. {
  501. printf("%s\n", __func__);
  502. if (reject)
  503. return FALSE;
  504. send_command();
  505. return TRUE;
  506. }
  507. static gboolean start_ind(struct avdtp *session, struct avdtp_local_sep *lsep,
  508. struct avdtp_stream *stream, uint8_t *err,
  509. void *user_data)
  510. {
  511. printf("%s\n", __func__);
  512. if (reject)
  513. return FALSE;
  514. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  515. start_media_player();
  516. else
  517. start_media_recorder();
  518. send_command();
  519. return TRUE;
  520. }
  521. static gboolean suspend_ind(struct avdtp *session,
  522. struct avdtp_local_sep *sep,
  523. struct avdtp_stream *stream, uint8_t *err,
  524. void *user_data)
  525. {
  526. printf("%s\n", __func__);
  527. if (reject)
  528. return FALSE;
  529. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  530. stop_media_player();
  531. else
  532. stop_media_recorder();
  533. return TRUE;
  534. }
  535. static gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
  536. struct avdtp_stream *stream, uint8_t *err,
  537. void *user_data)
  538. {
  539. printf("%s\n", __func__);
  540. if (reject)
  541. return FALSE;
  542. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  543. stop_media_player();
  544. else
  545. stop_media_recorder();
  546. avdtp_stream = NULL;
  547. return TRUE;
  548. }
  549. static void abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
  550. struct avdtp_stream *stream, uint8_t *err,
  551. void *user_data)
  552. {
  553. printf("%s\n", __func__);
  554. if (dev_role == AVDTP_SEP_TYPE_SOURCE)
  555. stop_media_player();
  556. else
  557. stop_media_recorder();
  558. avdtp_stream = NULL;
  559. }
  560. static gboolean reconfigure_ind(struct avdtp *session,
  561. struct avdtp_local_sep *lsep,
  562. uint8_t *err, void *user_data)
  563. {
  564. printf("%s\n", __func__);
  565. if (reject)
  566. return FALSE;
  567. return TRUE;
  568. }
  569. static gboolean delayreport_ind(struct avdtp *session,
  570. struct avdtp_local_sep *lsep,
  571. uint8_t rseid, uint16_t delay,
  572. uint8_t *err, void *user_data)
  573. {
  574. printf("%s\n", __func__);
  575. if (reject)
  576. return FALSE;
  577. return TRUE;
  578. }
  579. static struct avdtp_sep_ind sep_ind = {
  580. .get_capability = get_capability_ind,
  581. .set_configuration = set_configuration_ind,
  582. .get_configuration = get_configuration_ind,
  583. .open = open_ind,
  584. .close = close_ind,
  585. .start = start_ind,
  586. .suspend = suspend_ind,
  587. .abort = abort_ind,
  588. .reconfigure = reconfigure_ind,
  589. .delayreport = delayreport_ind,
  590. };
  591. static void usage(void)
  592. {
  593. printf("avdtptest - AVDTP testing ver %s\n", VERSION);
  594. printf("Usage:\n"
  595. "\tavdtptest [options]\n");
  596. printf("options:\n"
  597. "\t-d <device_role> SRC (source) or SINK (sink)\n"
  598. "\t-i <hcidev> HCI adapter\n"
  599. "\t-c <bdaddr> connect\n"
  600. "\t-l listen\n"
  601. "\t-r reject commands\n"
  602. "\t-f fragment\n"
  603. "\t-p configure stream\n"
  604. "\t-s <command> send command\n"
  605. "\t-v <version> set version (0x0100, 0x0102, 0x0103\n");
  606. }
  607. static struct option main_options[] = {
  608. { "help", 0, 0, 'h' },
  609. { "device_role", 1, 0, 'd' },
  610. { "adapter", 1, 0, 'i' },
  611. { "connect", 1, 0, 'c' },
  612. { "listen", 0, 0, 'l' },
  613. { "reject", 0, 0, 'r' },
  614. { "fragment", 0, 0, 'f' },
  615. { "preconf", 0, 0, 'p' },
  616. { "send", 1, 0, 's' },
  617. { "version", 1, 0, 'v' },
  618. { 0, 0, 0, 0 }
  619. };
  620. static GIOChannel *do_listen(GError **err)
  621. {
  622. if (fragment)
  623. return bt_io_listen(connect_cb, NULL, NULL, NULL, err,
  624. BT_IO_OPT_SOURCE_BDADDR, &src,
  625. BT_IO_OPT_PSM, AVDTP_PSM,
  626. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
  627. BT_IO_OPT_MTU, 48,
  628. BT_IO_OPT_INVALID);
  629. return bt_io_listen(connect_cb, NULL, NULL, NULL, err,
  630. BT_IO_OPT_SOURCE_BDADDR, &src,
  631. BT_IO_OPT_PSM, AVDTP_PSM,
  632. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
  633. BT_IO_OPT_INVALID);
  634. }
  635. int main(int argc, char *argv[])
  636. {
  637. GError *err = NULL;
  638. int opt;
  639. bacpy(&src, BDADDR_ANY);
  640. bacpy(&dst, BDADDR_ANY);
  641. mainloop = g_main_loop_new(NULL, FALSE);
  642. if (!mainloop) {
  643. printf("Failed to create main loop\n");
  644. exit(1);
  645. }
  646. while ((opt = getopt_long(argc, argv, "d:hi:s:c:v:lrfp",
  647. main_options, NULL)) != EOF) {
  648. switch (opt) {
  649. case 'i':
  650. if (!strncmp(optarg, "hci", 3))
  651. hci_devba(atoi(optarg + 3), &src);
  652. else
  653. str2ba(optarg, &src);
  654. break;
  655. case 'd':
  656. if (!strncasecmp(optarg, "SRC", sizeof("SRC"))) {
  657. dev_role = AVDTP_SEP_TYPE_SOURCE;
  658. } else if (!strncasecmp(optarg, "SINK",
  659. sizeof("SINK"))) {
  660. dev_role = AVDTP_SEP_TYPE_SINK;
  661. } else {
  662. usage();
  663. exit(1);
  664. }
  665. break;
  666. case 'c':
  667. if (str2ba(optarg, &dst) < 0) {
  668. usage();
  669. exit(1);
  670. }
  671. break;
  672. case 'l':
  673. bacpy(&dst, BDADDR_ANY);
  674. break;
  675. case 'r':
  676. reject = true;
  677. break;
  678. case 'f':
  679. fragment = true;
  680. break;
  681. case 'p':
  682. preconf = true;
  683. break;
  684. case 's':
  685. parse_command(optarg);
  686. break;
  687. case 'v':
  688. version = strtol(optarg, NULL, 0);
  689. if (version != 0x0100 && version != 0x0102 &&
  690. version != 0x0103) {
  691. printf("invalid version\n");
  692. exit(1);
  693. }
  694. break;
  695. case 'h':
  696. usage();
  697. exit(0);
  698. default:
  699. usage();
  700. exit(1);
  701. }
  702. }
  703. lseps = queue_new();
  704. local_sep = avdtp_register_sep(lseps, dev_role, AVDTP_MEDIA_TYPE_AUDIO,
  705. 0x00, TRUE, &sep_ind, &sep_cfm, NULL);
  706. if (!local_sep) {
  707. printf("Failed to register sep\n");
  708. exit(1);
  709. }
  710. queue_push_tail(lseps, local_sep);
  711. if (!bacmp(&dst, BDADDR_ANY)) {
  712. printf("Listening...\n");
  713. io = do_listen(&err);
  714. } else {
  715. printf("Connecting...\n");
  716. io = do_connect(&err);
  717. }
  718. if (!io) {
  719. printf("Failed: %s\n", err->message);
  720. g_error_free(err);
  721. exit(1);
  722. }
  723. g_main_loop_run(mainloop);
  724. printf("Done\n");
  725. queue_destroy(lseps, NULL);
  726. avdtp_unref(avdtp);
  727. avdtp = NULL;
  728. g_main_loop_unref(mainloop);
  729. mainloop = NULL;
  730. return 0;
  731. }