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