~vanvugt/ubuntu/xenial/bluez/trunk

« back to all changes in this revision

Viewing changes to android/avdtptest.c

  • Committer: Daniel van Vugt
  • Date: 2017-05-24 07:16:52 UTC
  • Revision ID: daniel.van.vugt@canonical.com-20170524071652-8fnev589l3n104m1
Initial import from xenial

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}