3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2006-2010 Nokia Corporation
6
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
7
* Copyright (C) 2009 Lennart Poettering
8
* Copyright (C) 2008 Joao Paulo Rechi Vita
11
* This library is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU Lesser General Public
13
* License as published by the Free Software Foundation; either
14
* version 2.1 of the License, or (at your option) any later version.
16
* This library is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
* Lesser General Public License for more details.
21
* You should have received a copy of the GNU Lesser General Public
22
* License along with this library; if not, write to the Free Software
23
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
46
#define DBG(fmt, arg...) \
47
printf("debug %s: " fmt "\n" , __FUNCTION__ , ## arg)
48
#define ERR(fmt, arg...) \
49
fprintf(stderr, "ERROR %s: " fmt "\n" , __FUNCTION__ , ## arg)
51
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
54
# define MIN(x, y) ((x) < (y) ? (x) : (y))
58
# define MAX(x, y) ((x) > (y) ? (x) : (y))
69
#define YES_NO(t) ((t) ? "yes" : "no")
71
#define BUFFER_SIZE 2048
72
#define MAX_BITPOOL 64
76
sbc_capabilities_t sbc_capabilities;
77
sbc_t sbc; /* Codec data */
78
int sbc_initialized; /* Keep track if the encoder is initialized */
79
size_t codesize; /* SBC codesize */
81
void* buffer; /* Codec transfer buffer */
82
size_t buffer_size; /* Size of the buffer */
84
uint16_t seq_num; /* Cumulative packet sequence */
88
pcm_capabilities_t pcm_capabilities;
94
GIOChannel *stream_channel;
96
GIOChannel *gin; /* dude, I am thirsty now */
102
struct a2dp_info a2dp;
106
gboolean debug_stream_read : 1;
107
gboolean debug_stream_write : 1;
110
static struct userdata data = {
113
.transport = BT_CAPABILITIES_TRANSPORT_A2DP,
119
static int start_stream(struct userdata *u);
120
static int stop_stream(struct userdata *u);
121
static gboolean input_cb(GIOChannel *gin, GIOCondition condition, gpointer data);
123
static GMainLoop *main_loop;
125
static int service_send(struct userdata *u, const bt_audio_msg_header_t *msg)
132
length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
134
DBG("sending %s:%s", bt_audio_strtype(msg->type),
135
bt_audio_strname(msg->name));
137
if (send(u->service_fd, msg, length, 0) > 0)
141
ERR("Error sending data to audio service: %s(%d)",
142
strerror(errno), errno);
148
static int service_recv(struct userdata *u, bt_audio_msg_header_t *rsp)
151
const char *type, *name;
156
length = rsp->length ? : BT_SUGGESTED_BUFFER_SIZE;
158
DBG("trying to receive msg from audio service...");
159
if (recv(u->service_fd, rsp, length, 0) > 0) {
160
type = bt_audio_strtype(rsp->type);
161
name = bt_audio_strname(rsp->name);
163
DBG("Received %s - %s", type, name);
167
ERR("Bogus message type %d - name %d"
168
"received from audio service",
169
rsp->type, rsp->name);
173
ERR("Error receiving data from audio service: %s(%d)",
174
strerror(errno), errno);
180
static ssize_t service_expect(struct userdata *u, bt_audio_msg_header_t *rsp,
181
uint8_t expected_name)
186
assert(u->service_fd >= 0);
189
if ((r = service_recv(u, rsp)) < 0)
192
if ((rsp->type != BT_INDICATION && rsp->type != BT_RESPONSE) ||
193
(rsp->name != expected_name)) {
194
if (rsp->type == BT_ERROR && rsp->length == sizeof(bt_audio_error_t))
195
ERR("Received error condition: %s",
196
strerror(((bt_audio_error_t*) rsp)->posix_errno));
198
ERR("Bogus message %s received while %s was expected",
199
bt_audio_strname(rsp->name),
200
bt_audio_strname(expected_name));
207
static int init_bt(struct userdata *u)
211
if (u->service_fd != -1)
214
DBG("bt_audio_service_open");
216
u->service_fd = bt_audio_service_open();
217
if (u->service_fd <= 0) {
218
perror(strerror(errno));
225
static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *rsp)
229
codec_capabilities_t codec;
234
bytes_left = rsp->h.length - sizeof(*rsp);
236
if (bytes_left < sizeof(codec_capabilities_t)) {
237
ERR("Packet too small to store codec information.");
241
ptr = ((void *) rsp) + sizeof(*rsp);
243
memcpy(&codec, ptr, sizeof(codec)); /** ALIGNMENT? **/
245
DBG("Payload size is %lu %lu",
246
(unsigned long) bytes_left, (unsigned long) sizeof(codec));
248
if (u->transport != codec.transport) {
249
ERR("Got capabilities for wrong codec.");
253
if (u->transport == BT_CAPABILITIES_TRANSPORT_SCO) {
255
if (bytes_left <= 0 ||
256
codec.length != sizeof(u->hsp.pcm_capabilities))
259
assert(codec.type == BT_HFP_CODEC_PCM);
261
memcpy(&u->hsp.pcm_capabilities,
262
&codec, sizeof(u->hsp.pcm_capabilities));
265
YES_NO(u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC));
267
} else if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
269
while (bytes_left > 0) {
270
if (codec.type == BT_A2DP_SBC_SINK &&
271
!(codec.lock & BT_WRITE_LOCK))
274
bytes_left -= codec.length;
276
memcpy(&codec, ptr, sizeof(codec));
279
DBG("bytes_left = %d, codec.length = %d",
280
bytes_left, codec.length);
282
if (bytes_left <= 0 ||
283
codec.length != sizeof(u->a2dp.sbc_capabilities))
286
assert(codec.type == BT_A2DP_SBC_SINK);
288
memcpy(&u->a2dp.sbc_capabilities, &codec,
289
sizeof(u->a2dp.sbc_capabilities));
297
static int get_caps(struct userdata *u)
300
struct bt_get_capabilities_req getcaps_req;
301
struct bt_get_capabilities_rsp getcaps_rsp;
302
bt_audio_error_t error;
303
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
308
memset(&msg, 0, sizeof(msg));
309
msg.getcaps_req.h.type = BT_REQUEST;
310
msg.getcaps_req.h.name = BT_GET_CAPABILITIES;
311
msg.getcaps_req.h.length = sizeof(msg.getcaps_req);
313
strncpy(msg.getcaps_req.destination, u->address,
314
sizeof(msg.getcaps_req.destination));
315
msg.getcaps_req.transport = u->transport;
316
msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT;
318
if (service_send(u, &msg.getcaps_req.h) < 0)
321
msg.getcaps_rsp.h.length = 0;
322
if (service_expect(u, &msg.getcaps_rsp.h, BT_GET_CAPABILITIES) < 0)
325
return parse_caps(u, &msg.getcaps_rsp);
328
static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode)
331
case BT_SBC_SAMPLING_FREQ_16000:
332
case BT_SBC_SAMPLING_FREQ_32000:
335
case BT_SBC_SAMPLING_FREQ_44100:
338
case BT_A2DP_CHANNEL_MODE_MONO:
339
case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
342
case BT_A2DP_CHANNEL_MODE_STEREO:
343
case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
347
DBG("Invalid channel mode %u", mode);
351
case BT_SBC_SAMPLING_FREQ_48000:
354
case BT_A2DP_CHANNEL_MODE_MONO:
355
case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
358
case BT_A2DP_CHANNEL_MODE_STEREO:
359
case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
363
DBG("Invalid channel mode %u", mode);
368
DBG("Invalid sampling freq %u", freq);
373
static int setup_a2dp(struct userdata *u)
375
sbc_capabilities_t *cap;
378
static const struct {
382
{ 16000U, BT_SBC_SAMPLING_FREQ_16000 },
383
{ 32000U, BT_SBC_SAMPLING_FREQ_32000 },
384
{ 44100U, BT_SBC_SAMPLING_FREQ_44100 },
385
{ 48000U, BT_SBC_SAMPLING_FREQ_48000 }
389
assert(u->transport == BT_CAPABILITIES_TRANSPORT_A2DP);
391
cap = &u->a2dp.sbc_capabilities;
393
/* Find the lowest freq that is at least as high as the requested
395
for (i = 0; (unsigned) i < ARRAY_SIZE(freq_table); i++)
396
if (freq_table[i].rate >= u->rate &&
397
(cap->frequency & freq_table[i].cap)) {
398
u->rate = freq_table[i].rate;
399
cap->frequency = freq_table[i].cap;
403
if ((unsigned) i >= ARRAY_SIZE(freq_table)) {
404
for (; i >= 0; i--) {
405
if (cap->frequency & freq_table[i].cap) {
406
u->rate = freq_table[i].rate;
407
cap->frequency = freq_table[i].cap;
413
DBG("Not suitable sample rate");
418
if (u->channels <= 1) {
419
if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
420
cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
426
if (u->channels >= 2) {
429
if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
430
cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
431
else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
432
cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
433
else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
434
cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
435
else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
436
cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
439
DBG("No supported channel modes");
444
if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
445
cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
446
else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
447
cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
448
else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
449
cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
450
else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
451
cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
453
DBG("No supported block lengths");
457
if (cap->subbands & BT_A2DP_SUBBANDS_8)
458
cap->subbands = BT_A2DP_SUBBANDS_8;
459
else if (cap->subbands & BT_A2DP_SUBBANDS_4)
460
cap->subbands = BT_A2DP_SUBBANDS_4;
462
DBG("No supported subbands");
466
if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
467
cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
468
else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
469
cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
471
cap->min_bitpool = (uint8_t) MAX(MIN_BITPOOL, cap->min_bitpool);
472
cap->max_bitpool = (uint8_t) MIN(
473
a2dp_default_bitpool(cap->frequency, cap->channel_mode),
479
static void setup_sbc(struct a2dp_info *a2dp)
481
sbc_capabilities_t *active_capabilities;
485
active_capabilities = &a2dp->sbc_capabilities;
487
if (a2dp->sbc_initialized)
488
sbc_reinit(&a2dp->sbc, 0);
490
sbc_init(&a2dp->sbc, 0);
491
a2dp->sbc_initialized = TRUE;
493
switch (active_capabilities->frequency) {
494
case BT_SBC_SAMPLING_FREQ_16000:
495
a2dp->sbc.frequency = SBC_FREQ_16000;
497
case BT_SBC_SAMPLING_FREQ_32000:
498
a2dp->sbc.frequency = SBC_FREQ_32000;
500
case BT_SBC_SAMPLING_FREQ_44100:
501
a2dp->sbc.frequency = SBC_FREQ_44100;
503
case BT_SBC_SAMPLING_FREQ_48000:
504
a2dp->sbc.frequency = SBC_FREQ_48000;
510
switch (active_capabilities->channel_mode) {
511
case BT_A2DP_CHANNEL_MODE_MONO:
512
a2dp->sbc.mode = SBC_MODE_MONO;
514
case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
515
a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL;
517
case BT_A2DP_CHANNEL_MODE_STEREO:
518
a2dp->sbc.mode = SBC_MODE_STEREO;
520
case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
521
a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
527
switch (active_capabilities->allocation_method) {
528
case BT_A2DP_ALLOCATION_SNR:
529
a2dp->sbc.allocation = SBC_AM_SNR;
531
case BT_A2DP_ALLOCATION_LOUDNESS:
532
a2dp->sbc.allocation = SBC_AM_LOUDNESS;
538
switch (active_capabilities->subbands) {
539
case BT_A2DP_SUBBANDS_4:
540
a2dp->sbc.subbands = SBC_SB_4;
542
case BT_A2DP_SUBBANDS_8:
543
a2dp->sbc.subbands = SBC_SB_8;
549
switch (active_capabilities->block_length) {
550
case BT_A2DP_BLOCK_LENGTH_4:
551
a2dp->sbc.blocks = SBC_BLK_4;
553
case BT_A2DP_BLOCK_LENGTH_8:
554
a2dp->sbc.blocks = SBC_BLK_8;
556
case BT_A2DP_BLOCK_LENGTH_12:
557
a2dp->sbc.blocks = SBC_BLK_12;
559
case BT_A2DP_BLOCK_LENGTH_16:
560
a2dp->sbc.blocks = SBC_BLK_16;
566
a2dp->sbc.bitpool = active_capabilities->max_bitpool;
567
a2dp->codesize = (uint16_t) sbc_get_codesize(&a2dp->sbc);
570
static int bt_open(struct userdata *u)
573
struct bt_open_req open_req;
574
struct bt_open_rsp open_rsp;
575
bt_audio_error_t error;
576
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
579
memset(&msg, 0, sizeof(msg));
580
msg.open_req.h.type = BT_REQUEST;
581
msg.open_req.h.name = BT_OPEN;
582
msg.open_req.h.length = sizeof(msg.open_req);
584
strncpy(msg.open_req.destination, u->address,
585
sizeof(msg.open_req.destination));
586
msg.open_req.seid = u->transport == BT_CAPABILITIES_TRANSPORT_A2DP ?
587
u->a2dp.sbc_capabilities.capability.seid :
588
BT_A2DP_SEID_RANGE + 1;
589
msg.open_req.lock = u->transport == BT_CAPABILITIES_TRANSPORT_A2DP ?
590
BT_WRITE_LOCK : BT_READ_LOCK | BT_WRITE_LOCK;
592
if (service_send(u, &msg.open_req.h) < 0)
595
msg.open_rsp.h.length = sizeof(msg.open_rsp);
596
if (service_expect(u, &msg.open_rsp.h, BT_OPEN) < 0)
602
static int set_conf(struct userdata *u)
605
struct bt_set_configuration_req setconf_req;
606
struct bt_set_configuration_rsp setconf_rsp;
607
bt_audio_error_t error;
608
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
611
if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
612
if (setup_a2dp(u) < 0)
616
memset(&msg, 0, sizeof(msg));
617
msg.setconf_req.h.type = BT_REQUEST;
618
msg.setconf_req.h.name = BT_SET_CONFIGURATION;
619
msg.setconf_req.h.length = sizeof(msg.setconf_req);
621
if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
622
memcpy(&msg.setconf_req.codec, &u->a2dp.sbc_capabilities,
623
sizeof(u->a2dp.sbc_capabilities));
624
msg.setconf_req.h.length += msg.setconf_req.codec.length -
625
sizeof(msg.setconf_req.codec);
627
msg.setconf_req.codec.transport = BT_CAPABILITIES_TRANSPORT_SCO;
628
msg.setconf_req.codec.seid = BT_A2DP_SEID_RANGE + 1;
629
msg.setconf_req.codec.length = sizeof(pcm_capabilities_t);
632
if (service_send(u, &msg.setconf_req.h) < 0)
635
msg.setconf_rsp.h.length = sizeof(msg.setconf_rsp);
636
if (service_expect(u, &msg.setconf_rsp.h, BT_SET_CONFIGURATION) < 0)
639
u->link_mtu = msg.setconf_rsp.link_mtu;
641
/* setup SBC encoder now we agree on parameters */
642
if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
644
u->block_size = u->a2dp.codesize;
645
DBG("SBC parameters:\n\tallocation=%u\n"
646
"\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
647
u->a2dp.sbc.allocation, u->a2dp.sbc.subbands,
648
u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool);
650
u->block_size = u->link_mtu;
655
static int setup_bt(struct userdata *u)
662
DBG("Got device caps");
673
static int init_profile(struct userdata *u)
680
static void shutdown_bt(struct userdata *u)
684
if (u->stream_fd != -1) {
686
DBG("close(stream_fd)");
691
if (u->service_fd != -1) {
692
DBG("bt_audio_service_close");
693
bt_audio_service_close(u->service_fd);
698
static void make_fd_nonblock(int fd)
703
assert((v = fcntl(fd, F_GETFL)) >= 0);
705
if (!(v & O_NONBLOCK))
706
assert(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
709
static void make_socket_low_delay(int fd)
711
/* FIXME: is this widely supported? */
717
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority,
718
sizeof(priority)) < 0)
719
ERR("SO_PRIORITY failed: %s", strerror(errno));
723
static int read_stream(struct userdata *u)
730
assert(u->stream_fd >= 0);
732
buf = alloca(u->link_mtu);
735
l = read(u->stream_fd, buf, u->link_mtu);
736
if (u->debug_stream_read)
737
DBG("read from socket: %lli bytes", (long long) l);
739
if (l < 0 && errno == EINTR)
742
ERR("Failed to read date from stream_fd: %s",
743
ret < 0 ? strerror(errno) : "EOF");
754
/* It's what PulseAudio is doing, not sure it's necessary for this
756
static ssize_t pa_write(int fd, const void *buf, size_t count)
760
if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0)
763
if (errno != ENOTSOCK)
766
return write(fd, buf, count);
769
static int write_stream(struct userdata *u)
776
assert(u->stream_fd >= 0);
777
buf = alloca(u->link_mtu);
780
l = pa_write(u->stream_fd, buf, u->link_mtu);
781
if (u->debug_stream_write)
782
DBG("written to socket: %lli bytes", (long long) l);
788
ERR("Failed to write data: %s", strerror(errno));
793
assert((size_t)l <= u->link_mtu);
801
static gboolean stream_cb(GIOChannel *gin, GIOCondition condition, gpointer data)
807
if (condition & G_IO_IN) {
808
if (read_stream(u) < 0)
810
} else if (condition & G_IO_OUT) {
811
if (write_stream(u) < 0)
814
DBG("Got %d", condition);
815
g_main_loop_quit(main_loop);
826
static int start_stream(struct userdata *u)
829
bt_audio_msg_header_t rsp;
830
struct bt_start_stream_req start_req;
831
struct bt_start_stream_rsp start_rsp;
832
struct bt_new_stream_ind streamfd_ind;
833
bt_audio_error_t error;
834
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
839
if (u->stream_fd >= 0)
841
if (u->stream_watch != 0) {
842
g_source_remove(u->stream_watch);
845
if (u->stream_channel != 0) {
846
g_io_channel_unref(u->stream_channel);
847
u->stream_channel = NULL;
850
memset(msg.buf, 0, BT_SUGGESTED_BUFFER_SIZE);
851
msg.start_req.h.type = BT_REQUEST;
852
msg.start_req.h.name = BT_START_STREAM;
853
msg.start_req.h.length = sizeof(msg.start_req);
855
if (service_send(u, &msg.start_req.h) < 0)
858
msg.rsp.length = sizeof(msg.start_rsp);
859
if (service_expect(u, &msg.rsp, BT_START_STREAM) < 0)
862
msg.rsp.length = sizeof(msg.streamfd_ind);
863
if (service_expect(u, &msg.rsp, BT_NEW_STREAM) < 0)
866
if ((u->stream_fd = bt_audio_service_get_data_fd(u->service_fd)) < 0) {
867
DBG("Failed to get stream fd from audio service.");
871
make_fd_nonblock(u->stream_fd);
872
make_socket_low_delay(u->stream_fd);
874
assert(u->stream_channel = g_io_channel_unix_new(u->stream_fd));
876
u->stream_watch = g_io_add_watch(u->stream_channel,
877
G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
883
static int stop_stream(struct userdata *u)
886
bt_audio_msg_header_t rsp;
887
struct bt_stop_stream_req stop_req;
888
struct bt_stop_stream_rsp stop_rsp;
889
bt_audio_error_t error;
890
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
894
if (u->stream_fd < 0)
898
assert(u->stream_channel);
900
g_source_remove(u->stream_watch);
902
g_io_channel_unref(u->stream_channel);
903
u->stream_channel = NULL;
905
memset(msg.buf, 0, BT_SUGGESTED_BUFFER_SIZE);
906
msg.stop_req.h.type = BT_REQUEST;
907
msg.stop_req.h.name = BT_STOP_STREAM;
908
msg.stop_req.h.length = sizeof(msg.stop_req);
910
if (service_send(u, &msg.stop_req.h) < 0) {
915
msg.rsp.length = sizeof(msg.stop_rsp);
916
if (service_expect(u, &msg.rsp, BT_STOP_STREAM) < 0)
926
static gboolean sleep_cb(gpointer data)
932
u->gin_watch = g_io_add_watch(u->gin,
933
G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, input_cb, data);
941
static gboolean input_cb(GIOChannel *gin, GIOCondition condition, gpointer data)
945
GError *error = NULL;
950
if (!(condition & G_IO_IN)) {
951
DBG("Got %d", condition);
952
g_main_loop_quit(main_loop);
956
if (g_io_channel_read_line(gin, &line, NULL, &term_pos, &error) !=
960
line[term_pos] = '\0';
962
if ((tmp = strchr(line, '#')))
966
#define IF_CMD(cmd) \
967
if (!success && (success = (strncmp(line, #cmd, strlen(#cmd)) == 0)))
970
g_main_loop_quit(main_loop);
975
unsigned int seconds;
976
if (sscanf(line, "%*s %d", &seconds) != 1)
977
DBG("sleep SECONDS");
979
g_source_remove(u->gin_watch);
980
g_timeout_add_seconds(seconds, sleep_cb, u);
989
if (sscanf(line, "%*s %as %d", &what, &enable) != 1)
990
DBG("debug [stream_read|stream_write] [0|1]");
991
if (strncmp(what, "stream_read", 12) == 0) {
992
u->debug_stream_read = enable;
993
} else if (strncmp(what, "stream_write", 13) == 0) {
994
u->debug_stream_write = enable;
996
DBG("debug [stream_read|stream_write] [0|1]");
1001
DBG("%d", init_bt(u));
1004
IF_CMD(init_profile) {
1005
DBG("%d", init_profile(u));
1008
IF_CMD(start_stream) {
1009
DBG("%d", start_stream(u));
1012
IF_CMD(stop_stream) {
1013
DBG("%d", stop_stream(u));
1016
IF_CMD(shutdown_bt) {
1021
if (sscanf(line, "%*s %d", &u->rate) != 1)
1022
DBG("set with rate RATE");
1023
DBG("rate %d", u->rate);
1029
if (sscanf(line, "%*s %as", &address) != 1)
1030
DBG("set with bdaddr BDADDR");
1034
u->address = address;
1035
DBG("bdaddr %s", u->address);
1039
char *profile = NULL;
1041
if (sscanf(line, "%*s %as", &profile) != 1)
1042
DBG("set with profile [hsp|a2dp]");
1043
if (strncmp(profile, "hsp", 4) == 0) {
1044
u->transport = BT_CAPABILITIES_TRANSPORT_SCO;
1045
} else if (strncmp(profile, "a2dp", 5) == 0) {
1046
u->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
1048
DBG("set with profile [hsp|a2dp]");
1052
DBG("profile %s", u->transport == BT_CAPABILITIES_TRANSPORT_SCO ?
1056
if (!success && strlen(line) != 0) {
1057
DBG("%s, unknown command", line);
1066
static void show_usage(char* prgname)
1068
printf("%s: ipctest [--interactive] BDADDR\n", basename(prgname));
1071
static void sig_term(int sig)
1073
g_main_loop_quit(main_loop);
1076
int main(int argc, char *argv[])
1079
show_usage(argv[0]);
1083
assert(main_loop = g_main_loop_new(NULL, FALSE));
1085
if (strncmp("--interactive", argv[1], 14) == 0) {
1087
show_usage(argv[0]);
1091
data.address = strdup(argv[2]);
1093
signal(SIGTERM, sig_term);
1094
signal(SIGINT, sig_term);
1096
assert(data.gin = g_io_channel_unix_new(fileno(stdin)));
1098
data.gin_watch = g_io_add_watch(data.gin,
1099
G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, input_cb, &data);
1104
g_main_loop_run(main_loop);
1107
data.address = strdup(argv[1]);
1109
assert(init_bt(&data) == 0);
1111
assert(init_profile(&data) == 0);
1113
assert(start_stream(&data) == 0);
1115
g_main_loop_run(main_loop);
1117
assert(stop_stream(&data) == 0);
1122
g_main_loop_unref(main_loop);
1124
printf("\nExiting\n");