~ubuntu-branches/ubuntu/trusty/bluez/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/12_check_device_before_removing_from_devices.patch/audio/unix.c

  • Committer: Package Import Robot
  • Author(s): Shih-Yuan Lee (FourDollars)
  • Date: 2014-04-02 23:53:58 UTC
  • Revision ID: package-import@ubuntu.com-20140402235358-4njirquez1y08ab9
Tags: 4.101-0ubuntu11
debian/patches/12_check_device_before_removing_from_devices.patch:
The power of some Bluetooth device will be cut and the device will be
removed from the devices list when suspending, so it has to check if
the device still exists in the devices list. (LP: #1300623)

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) 2006-2010  Nokia Corporation
 
6
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 
7
 *
 
8
 *
 
9
 *  This program is free software; you can redistribute it and/or modify
 
10
 *  it under the terms of the GNU General Public License as published by
 
11
 *  the Free Software Foundation; either version 2 of the License, or
 
12
 *  (at your option) any later version.
 
13
 *
 
14
 *  This program is distributed in the hope that it will be useful,
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 *  GNU General Public License for more details.
 
18
 *
 
19
 *  You should have received a copy of the GNU General Public License
 
20
 *  along with this program; if not, write to the Free Software
 
21
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
22
 *
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#include <config.h>
 
27
#endif
 
28
 
 
29
#include <stdio.h>
 
30
#include <fcntl.h>
 
31
#include <sys/socket.h>
 
32
#include <sys/un.h>
 
33
#include <stdlib.h>
 
34
#include <errno.h>
 
35
#include <unistd.h>
 
36
#include <stdint.h>
 
37
 
 
38
#include <bluetooth/bluetooth.h>
 
39
#include <bluetooth/sdp.h>
 
40
#include <dbus/dbus.h>
 
41
#include <glib.h>
 
42
 
 
43
#include "log.h"
 
44
#include "ipc.h"
 
45
#include "device.h"
 
46
#include "manager.h"
 
47
#include "avdtp.h"
 
48
#include "media.h"
 
49
#include "a2dp.h"
 
50
#include "headset.h"
 
51
#include "sink.h"
 
52
#include "source.h"
 
53
#include "gateway.h"
 
54
#include "unix.h"
 
55
 
 
56
#define check_nul(str) (str[sizeof(str) - 1] == '\0')
 
57
 
 
58
typedef enum {
 
59
        TYPE_NONE,
 
60
        TYPE_HEADSET,
 
61
        TYPE_GATEWAY,
 
62
        TYPE_SINK,
 
63
        TYPE_SOURCE
 
64
} service_type_t;
 
65
 
 
66
typedef void (*notify_cb_t) (struct audio_device *dev, void *data);
 
67
 
 
68
struct a2dp_data {
 
69
        struct avdtp *session;
 
70
        struct avdtp_stream *stream;
 
71
        struct a2dp_sep *sep;
 
72
};
 
73
 
 
74
struct headset_data {
 
75
        gboolean locked;
 
76
};
 
77
 
 
78
struct unix_client {
 
79
        struct audio_device *dev;
 
80
        GSList *caps;
 
81
        service_type_t type;
 
82
        char *interface;
 
83
        uint8_t seid;
 
84
        union {
 
85
                struct a2dp_data a2dp;
 
86
                struct headset_data hs;
 
87
        } d;
 
88
        int sock;
 
89
        int lock;
 
90
        int data_fd; /* To be deleted once two phase configuration is fully implemented */
 
91
        unsigned int req_id;
 
92
        unsigned int cb_id;
 
93
        gboolean (*cancel) (struct audio_device *dev, unsigned int id);
 
94
};
 
95
 
 
96
static GSList *clients = NULL;
 
97
 
 
98
static int unix_sock = -1;
 
99
 
 
100
static void client_free(void *data)
 
101
{
 
102
        struct unix_client *client = data;
 
103
 
 
104
        DBG("client_free(%p)", client);
 
105
 
 
106
        if (client->cancel && client->dev && client->req_id > 0)
 
107
                client->cancel(client->dev, client->req_id);
 
108
 
 
109
        if (client->sock >= 0)
 
110
                close(client->sock);
 
111
 
 
112
        g_slist_free_full(client->caps, g_free);
 
113
 
 
114
        g_free(client->interface);
 
115
        g_free(client);
 
116
}
 
117
 
 
118
static int set_nonblocking(int fd)
 
119
{
 
120
        long arg;
 
121
 
 
122
        arg = fcntl(fd, F_GETFL);
 
123
        if (arg < 0)
 
124
                return -errno;
 
125
 
 
126
        /* Return if already nonblocking */
 
127
        if (arg & O_NONBLOCK)
 
128
                return 0;
 
129
 
 
130
        arg |= O_NONBLOCK;
 
131
        if (fcntl(fd, F_SETFL, arg) < 0)
 
132
                return -errno;
 
133
 
 
134
        return 0;
 
135
}
 
136
 
 
137
/* Pass file descriptor through local domain sockets (AF_LOCAL, formerly
 
138
 * AF_UNIX) and the sendmsg() system call with the cmsg_type field of a "struct
 
139
 * cmsghdr" set to SCM_RIGHTS and the data being an integer value equal to the
 
140
 * handle of the file descriptor to be passed. */
 
141
static int unix_sendmsg_fd(int sock, int fd)
 
142
{
 
143
        char cmsg_b[CMSG_SPACE(sizeof(int))], m = 'm';
 
144
        struct cmsghdr *cmsg;
 
145
        struct iovec iov = { &m, sizeof(m) };
 
146
        struct msghdr msgh;
 
147
 
 
148
        memset(&msgh, 0, sizeof(msgh));
 
149
        msgh.msg_iov = &iov;
 
150
        msgh.msg_iovlen = 1;
 
151
        msgh.msg_control = &cmsg_b;
 
152
        msgh.msg_controllen = CMSG_LEN(sizeof(int));
 
153
 
 
154
        cmsg = CMSG_FIRSTHDR(&msgh);
 
155
        cmsg->cmsg_level = SOL_SOCKET;
 
156
        cmsg->cmsg_type = SCM_RIGHTS;
 
157
        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
 
158
        /* Initialize the payload */
 
159
        memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
 
160
 
 
161
        return sendmsg(sock, &msgh, MSG_NOSIGNAL);
 
162
}
 
163
 
 
164
static void unix_ipc_sendmsg(struct unix_client *client,
 
165
                                        const bt_audio_msg_header_t *msg)
 
166
{
 
167
        const char *type = bt_audio_strtype(msg->type);
 
168
        const char *name = bt_audio_strname(msg->name);
 
169
 
 
170
        DBG("Audio API: %s -> %s", type, name);
 
171
 
 
172
        if (send(client->sock, msg, msg->length, 0) < 0)
 
173
                error("Error %s(%d)", strerror(errno), errno);
 
174
}
 
175
 
 
176
static void unix_ipc_error(struct unix_client *client, uint8_t name, int err)
 
177
{
 
178
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
179
        bt_audio_error_t *rsp = (void *) buf;
 
180
 
 
181
        if (!g_slist_find(clients, client))
 
182
                return;
 
183
 
 
184
        memset(buf, 0, sizeof(buf));
 
185
        rsp->h.type = BT_ERROR;
 
186
        rsp->h.name = name;
 
187
        rsp->h.length = sizeof(*rsp);
 
188
 
 
189
        rsp->posix_errno = err;
 
190
 
 
191
        DBG("sending error %s(%d)", strerror(err), err);
 
192
        unix_ipc_sendmsg(client, &rsp->h);
 
193
}
 
194
 
 
195
static service_type_t select_service(struct audio_device *dev, const char *interface)
 
196
{
 
197
        if (!interface) {
 
198
                if (dev->sink && avdtp_is_connected(&dev->src, &dev->dst))
 
199
                        return TYPE_SINK;
 
200
                else if (dev->source && avdtp_is_connected(&dev->src,
 
201
                                                                &dev->dst))
 
202
                        return TYPE_SOURCE;
 
203
                else if (dev->headset && headset_is_active(dev))
 
204
                        return TYPE_HEADSET;
 
205
                else if (dev->sink)
 
206
                        return TYPE_SINK;
 
207
                else if (dev->source)
 
208
                        return TYPE_SOURCE;
 
209
                else if (dev->headset)
 
210
                        return TYPE_HEADSET;
 
211
        } else if (!strcmp(interface, AUDIO_SOURCE_INTERFACE) && dev->source)
 
212
                return TYPE_SOURCE;
 
213
        else if (!strcmp(interface, AUDIO_SINK_INTERFACE) && dev->sink)
 
214
                return TYPE_SINK;
 
215
        else if (!strcmp(interface, AUDIO_HEADSET_INTERFACE) && dev->headset)
 
216
                return TYPE_HEADSET;
 
217
        else if (!strcmp(interface, AUDIO_GATEWAY_INTERFACE) && dev->gateway)
 
218
                return TYPE_GATEWAY;
 
219
 
 
220
        return TYPE_NONE;
 
221
}
 
222
 
 
223
static void stream_state_changed(struct avdtp_stream *stream,
 
224
                                        avdtp_state_t old_state,
 
225
                                        avdtp_state_t new_state,
 
226
                                        struct avdtp_error *err,
 
227
                                        void *user_data)
 
228
{
 
229
        struct unix_client *client = user_data;
 
230
        struct a2dp_data *a2dp = &client->d.a2dp;
 
231
 
 
232
        switch (new_state) {
 
233
        case AVDTP_STATE_IDLE:
 
234
                if (a2dp->sep) {
 
235
                        a2dp_sep_unlock(a2dp->sep, a2dp->session);
 
236
                        a2dp->sep = NULL;
 
237
                }
 
238
                if (a2dp->session) {
 
239
                        avdtp_unref(a2dp->session);
 
240
                        a2dp->session = NULL;
 
241
                }
 
242
                a2dp->stream = NULL;
 
243
                client->cb_id = 0;
 
244
                break;
 
245
        default:
 
246
                break;
 
247
        }
 
248
}
 
249
 
 
250
static uint8_t headset_generate_capability(struct audio_device *dev,
 
251
                                                codec_capabilities_t *codec)
 
252
{
 
253
        pcm_capabilities_t *pcm;
 
254
 
 
255
        codec->seid = BT_A2DP_SEID_RANGE + 1;
 
256
        codec->transport = BT_CAPABILITIES_TRANSPORT_SCO;
 
257
        codec->type = BT_HFP_CODEC_PCM;
 
258
        codec->length = sizeof(*pcm);
 
259
 
 
260
        pcm = (void *) codec;
 
261
        pcm->sampling_rate = 8000;
 
262
        if (dev->headset) {
 
263
                if (headset_get_nrec(dev))
 
264
                        pcm->flags |= BT_PCM_FLAG_NREC;
 
265
                if (!headset_get_sco_hci(dev))
 
266
                        pcm->flags |= BT_PCM_FLAG_PCM_ROUTING;
 
267
                codec->configured = headset_is_active(dev);
 
268
                codec->lock = headset_get_lock(dev);
 
269
        } else {
 
270
                pcm->flags |= BT_PCM_FLAG_NREC;
 
271
                codec->configured = TRUE;
 
272
                codec->lock = 0;
 
273
        }
 
274
 
 
275
        return codec->length;
 
276
}
 
277
 
 
278
static void headset_discovery_complete(struct audio_device *dev, void *user_data)
 
279
{
 
280
        struct unix_client *client = user_data;
 
281
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
282
        struct bt_get_capabilities_rsp *rsp = (void *) buf;
 
283
        uint8_t length;
 
284
 
 
285
        client->req_id = 0;
 
286
 
 
287
        if (!dev)
 
288
                goto failed;
 
289
 
 
290
        memset(buf, 0, sizeof(buf));
 
291
 
 
292
        length = headset_generate_capability(dev, (void *) rsp->data);
 
293
 
 
294
        rsp->h.type = BT_RESPONSE;
 
295
        rsp->h.name = BT_GET_CAPABILITIES;
 
296
        rsp->h.length = sizeof(*rsp) + length;
 
297
 
 
298
        ba2str(&dev->src, rsp->source);
 
299
        ba2str(&dev->dst, rsp->destination);
 
300
        strncpy(rsp->object, dev->path, sizeof(rsp->object));
 
301
 
 
302
        unix_ipc_sendmsg(client, &rsp->h);
 
303
 
 
304
        return;
 
305
 
 
306
failed:
 
307
        error("discovery failed");
 
308
        unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
 
309
}
 
310
 
 
311
static void headset_setup_complete(struct audio_device *dev, void *user_data)
 
312
{
 
313
        struct unix_client *client = user_data;
 
314
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
315
        struct bt_set_configuration_rsp *rsp = (void *) buf;
 
316
 
 
317
        client->req_id = 0;
 
318
 
 
319
        if (!dev)
 
320
                goto failed;
 
321
 
 
322
        memset(buf, 0, sizeof(buf));
 
323
 
 
324
        rsp->h.type = BT_RESPONSE;
 
325
        rsp->h.name = BT_SET_CONFIGURATION;
 
326
        rsp->h.length = sizeof(*rsp);
 
327
 
 
328
        rsp->link_mtu = 48;
 
329
 
 
330
        client->data_fd = headset_get_sco_fd(dev);
 
331
 
 
332
        unix_ipc_sendmsg(client, &rsp->h);
 
333
 
 
334
        return;
 
335
 
 
336
failed:
 
337
        error("config failed");
 
338
        unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
 
339
}
 
340
 
 
341
static void gateway_setup_complete(struct audio_device *dev, GError *err, void *user_data)
 
342
{
 
343
        struct unix_client *client = user_data;
 
344
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
345
        struct bt_set_configuration_rsp *rsp = (void *) buf;
 
346
 
 
347
        if (err) {
 
348
                unix_ipc_error(client, BT_SET_CONFIGURATION, err->code);
 
349
                return;
 
350
        }
 
351
 
 
352
        client->req_id = 0;
 
353
 
 
354
        memset(buf, 0, sizeof(buf));
 
355
 
 
356
        rsp->h.type = BT_RESPONSE;
 
357
        rsp->h.name = BT_SET_CONFIGURATION;
 
358
        rsp->h.length = sizeof(*rsp);
 
359
 
 
360
        rsp->link_mtu = 48;
 
361
 
 
362
        client->data_fd = gateway_get_sco_fd(dev);
 
363
 
 
364
        unix_ipc_sendmsg(client, &rsp->h);
 
365
}
 
366
 
 
367
static void headset_resume_complete(struct audio_device *dev, void *user_data)
 
368
{
 
369
        struct unix_client *client = user_data;
 
370
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
371
        struct bt_start_stream_rsp *rsp = (void *) buf;
 
372
        struct bt_new_stream_ind *ind = (void *) buf;
 
373
 
 
374
        client->req_id = 0;
 
375
 
 
376
        if (!dev)
 
377
                goto failed;
 
378
 
 
379
        client->data_fd = headset_get_sco_fd(dev);
 
380
        if (client->data_fd < 0) {
 
381
                error("Unable to get a SCO fd");
 
382
                goto failed;
 
383
        }
 
384
 
 
385
        memset(buf, 0, sizeof(buf));
 
386
        rsp->h.type = BT_RESPONSE;
 
387
        rsp->h.name = BT_START_STREAM;
 
388
        rsp->h.length = sizeof(*rsp);
 
389
 
 
390
        unix_ipc_sendmsg(client, &rsp->h);
 
391
 
 
392
        memset(buf, 0, sizeof(buf));
 
393
        ind->h.type = BT_INDICATION;
 
394
        ind->h.name = BT_NEW_STREAM;
 
395
        ind->h.length = sizeof(*ind);
 
396
 
 
397
        unix_ipc_sendmsg(client, &ind->h);
 
398
 
 
399
        if (unix_sendmsg_fd(client->sock, client->data_fd) < 0) {
 
400
                error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno);
 
401
                goto failed;
 
402
        }
 
403
 
 
404
        return;
 
405
 
 
406
failed:
 
407
        error("headset_resume_complete: resume failed");
 
408
        unix_ipc_error(client, BT_START_STREAM, EIO);
 
409
}
 
410
 
 
411
static void gateway_resume_complete(struct audio_device *dev, GError *err, void *user_data)
 
412
{
 
413
        struct unix_client *client = user_data;
 
414
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
415
        struct bt_start_stream_rsp *rsp = (void *) buf;
 
416
        struct bt_new_stream_ind *ind = (void *) buf;
 
417
 
 
418
        if (err) {
 
419
                unix_ipc_error(client, BT_START_STREAM, err->code);
 
420
                return;
 
421
        }
 
422
 
 
423
        memset(buf, 0, sizeof(buf));
 
424
        rsp->h.type = BT_RESPONSE;
 
425
        rsp->h.name = BT_START_STREAM;
 
426
        rsp->h.length = sizeof(*rsp);
 
427
 
 
428
        unix_ipc_sendmsg(client, &rsp->h);
 
429
 
 
430
        memset(buf, 0, sizeof(buf));
 
431
        ind->h.type = BT_INDICATION;
 
432
        ind->h.name = BT_NEW_STREAM;
 
433
        ind->h.length = sizeof(*ind);
 
434
 
 
435
        unix_ipc_sendmsg(client, &ind->h);
 
436
 
 
437
        client->data_fd = gateway_get_sco_fd(dev);
 
438
        if (unix_sendmsg_fd(client->sock, client->data_fd) < 0) {
 
439
                error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno);
 
440
                unix_ipc_error(client, BT_START_STREAM, EIO);
 
441
        }
 
442
 
 
443
        client->req_id = 0;
 
444
}
 
445
 
 
446
static void headset_suspend_complete(struct audio_device *dev, void *user_data)
 
447
{
 
448
        struct unix_client *client = user_data;
 
449
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
450
        struct bt_stop_stream_rsp *rsp = (void *) buf;
 
451
 
 
452
        if (!dev)
 
453
                goto failed;
 
454
 
 
455
        memset(buf, 0, sizeof(buf));
 
456
        rsp->h.type = BT_RESPONSE;
 
457
        rsp->h.name = BT_STOP_STREAM;
 
458
        rsp->h.length = sizeof(*rsp);
 
459
 
 
460
        unix_ipc_sendmsg(client, &rsp->h);
 
461
 
 
462
        return;
 
463
 
 
464
failed:
 
465
        error("suspend failed");
 
466
        unix_ipc_error(client, BT_STOP_STREAM, EIO);
 
467
}
 
468
 
 
469
static void print_mpeg12(struct mpeg_codec_cap *mpeg)
 
470
{
 
471
        DBG("Media Codec: MPEG12"
 
472
                " Channel Modes: %s%s%s%s"
 
473
                " Frequencies: %s%s%s%s%s%s"
 
474
                " Layers: %s%s%s"
 
475
                " CRC: %s",
 
476
                mpeg->channel_mode & MPEG_CHANNEL_MODE_MONO ? "Mono " : "",
 
477
                mpeg->channel_mode & MPEG_CHANNEL_MODE_DUAL_CHANNEL ?
 
478
                "DualChannel " : "",
 
479
                mpeg->channel_mode & MPEG_CHANNEL_MODE_STEREO ? "Stereo " : "",
 
480
                mpeg->channel_mode & MPEG_CHANNEL_MODE_JOINT_STEREO ?
 
481
                "JointStereo " : "",
 
482
                mpeg->frequency & MPEG_SAMPLING_FREQ_16000 ? "16Khz " : "",
 
483
                mpeg->frequency & MPEG_SAMPLING_FREQ_22050 ? "22.05Khz " : "",
 
484
                mpeg->frequency & MPEG_SAMPLING_FREQ_24000 ? "24Khz " : "",
 
485
                mpeg->frequency & MPEG_SAMPLING_FREQ_32000 ? "32Khz " : "",
 
486
                mpeg->frequency & MPEG_SAMPLING_FREQ_44100 ? "44.1Khz " : "",
 
487
                mpeg->frequency & MPEG_SAMPLING_FREQ_48000 ? "48Khz " : "",
 
488
                mpeg->layer & MPEG_LAYER_MP1 ? "1 " : "",
 
489
                mpeg->layer & MPEG_LAYER_MP2 ? "2 " : "",
 
490
                mpeg->layer & MPEG_LAYER_MP3 ? "3 " : "",
 
491
                mpeg->crc ? "Yes" : "No");
 
492
}
 
493
 
 
494
static void print_sbc(struct sbc_codec_cap *sbc)
 
495
{
 
496
        DBG("Media Codec: SBC"
 
497
                " Channel Modes: %s%s%s%s"
 
498
                " Frequencies: %s%s%s%s"
 
499
                " Subbands: %s%s"
 
500
                " Blocks: %s%s%s%s"
 
501
                " Bitpool: %d-%d",
 
502
                sbc->channel_mode & SBC_CHANNEL_MODE_MONO ? "Mono " : "",
 
503
                sbc->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL ?
 
504
                "DualChannel " : "",
 
505
                sbc->channel_mode & SBC_CHANNEL_MODE_STEREO ? "Stereo " : "",
 
506
                sbc->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO ? "JointStereo" : "",
 
507
                sbc->frequency & SBC_SAMPLING_FREQ_16000 ? "16Khz " : "",
 
508
                sbc->frequency & SBC_SAMPLING_FREQ_32000 ? "32Khz " : "",
 
509
                sbc->frequency & SBC_SAMPLING_FREQ_44100 ? "44.1Khz " : "",
 
510
                sbc->frequency & SBC_SAMPLING_FREQ_48000 ? "48Khz " : "",
 
511
                sbc->subbands & SBC_SUBBANDS_4 ? "4 " : "",
 
512
                sbc->subbands & SBC_SUBBANDS_8 ? "8 " : "",
 
513
                sbc->block_length & SBC_BLOCK_LENGTH_4 ? "4 " : "",
 
514
                sbc->block_length & SBC_BLOCK_LENGTH_8 ? "8 " : "",
 
515
                sbc->block_length & SBC_BLOCK_LENGTH_12 ? "12 " : "",
 
516
                sbc->block_length & SBC_BLOCK_LENGTH_16 ? "16 " : "",
 
517
                sbc->min_bitpool, sbc->max_bitpool);
 
518
}
 
519
 
 
520
static int a2dp_append_codec(struct bt_get_capabilities_rsp *rsp,
 
521
                                struct avdtp_service_capability *cap,
 
522
                                uint8_t seid,
 
523
                                uint8_t type,
 
524
                                uint8_t configured,
 
525
                                uint8_t lock)
 
526
{
 
527
        struct avdtp_media_codec_capability *codec_cap = (void *) cap->data;
 
528
        codec_capabilities_t *codec = (void *) rsp + rsp->h.length;
 
529
        size_t space_left;
 
530
 
 
531
        if (rsp->h.length > BT_SUGGESTED_BUFFER_SIZE)
 
532
                return -ENOMEM;
 
533
 
 
534
        space_left = BT_SUGGESTED_BUFFER_SIZE - rsp->h.length;
 
535
 
 
536
        /* endianness prevents direct cast */
 
537
        if (codec_cap->media_codec_type == A2DP_CODEC_SBC) {
 
538
                struct sbc_codec_cap *sbc_cap = (void *) codec_cap;
 
539
                sbc_capabilities_t *sbc = (void *) codec;
 
540
 
 
541
                if (space_left < sizeof(sbc_capabilities_t))
 
542
                        return -ENOMEM;
 
543
 
 
544
                if (type == AVDTP_SEP_TYPE_SINK)
 
545
                        codec->type = BT_A2DP_SBC_SINK;
 
546
                else if (type == AVDTP_SEP_TYPE_SOURCE)
 
547
                        codec->type = BT_A2DP_SBC_SOURCE;
 
548
                else
 
549
                        return -EINVAL;
 
550
 
 
551
                codec->length = sizeof(sbc_capabilities_t);
 
552
 
 
553
                sbc->channel_mode = sbc_cap->channel_mode;
 
554
                sbc->frequency = sbc_cap->frequency;
 
555
                sbc->allocation_method = sbc_cap->allocation_method;
 
556
                sbc->subbands = sbc_cap->subbands;
 
557
                sbc->block_length = sbc_cap->block_length;
 
558
                sbc->min_bitpool = sbc_cap->min_bitpool;
 
559
                sbc->max_bitpool = sbc_cap->max_bitpool;
 
560
 
 
561
                print_sbc(sbc_cap);
 
562
        } else if (codec_cap->media_codec_type == A2DP_CODEC_MPEG12) {
 
563
                struct mpeg_codec_cap *mpeg_cap = (void *) codec_cap;
 
564
                mpeg_capabilities_t *mpeg = (void *) codec;
 
565
 
 
566
                if (space_left < sizeof(mpeg_capabilities_t))
 
567
                        return -ENOMEM;
 
568
 
 
569
                if (type == AVDTP_SEP_TYPE_SINK)
 
570
                        codec->type = BT_A2DP_MPEG12_SINK;
 
571
                else if (type == AVDTP_SEP_TYPE_SOURCE)
 
572
                        codec->type = BT_A2DP_MPEG12_SOURCE;
 
573
                else
 
574
                        return -EINVAL;
 
575
 
 
576
                codec->length = sizeof(mpeg_capabilities_t);
 
577
 
 
578
                mpeg->channel_mode = mpeg_cap->channel_mode;
 
579
                mpeg->crc = mpeg_cap->crc;
 
580
                mpeg->layer = mpeg_cap->layer;
 
581
                mpeg->frequency = mpeg_cap->frequency;
 
582
                mpeg->mpf = mpeg_cap->mpf;
 
583
                mpeg->bitrate = mpeg_cap->bitrate;
 
584
 
 
585
                print_mpeg12(mpeg_cap);
 
586
        } else {
 
587
                size_t codec_length, type_length, total_length;
 
588
 
 
589
                codec_length = cap->length - (sizeof(struct avdtp_service_capability)
 
590
                                + sizeof(struct avdtp_media_codec_capability));
 
591
                type_length = sizeof(codec_cap->media_codec_type);
 
592
                total_length = type_length + codec_length +
 
593
                                sizeof(codec_capabilities_t);
 
594
 
 
595
                if (space_left < total_length)
 
596
                        return -ENOMEM;
 
597
 
 
598
                if (type == AVDTP_SEP_TYPE_SINK)
 
599
                        codec->type = BT_A2DP_UNKNOWN_SINK;
 
600
                else if (type == AVDTP_SEP_TYPE_SOURCE)
 
601
                        codec->type = BT_A2DP_UNKNOWN_SOURCE;
 
602
                else
 
603
                        return -EINVAL;
 
604
 
 
605
                codec->length = total_length;
 
606
                memcpy(codec->data, &codec_cap->media_codec_type, type_length);
 
607
                memcpy(codec->data + type_length, codec_cap->data,
 
608
                        codec_length);
 
609
        }
 
610
 
 
611
        codec->seid = seid;
 
612
        codec->configured = configured;
 
613
        codec->lock = lock;
 
614
        rsp->h.length += codec->length;
 
615
 
 
616
        DBG("Append %s seid %d - length %d - total %d",
 
617
                configured ? "configured" : "", seid, codec->length,
 
618
                rsp->h.length);
 
619
 
 
620
        return 0;
 
621
}
 
622
 
 
623
static void a2dp_discovery_complete(struct avdtp *session, GSList *seps,
 
624
                                        struct avdtp_error *err,
 
625
                                        void *user_data)
 
626
{
 
627
        struct unix_client *client = user_data;
 
628
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
629
        struct bt_get_capabilities_rsp *rsp = (void *) buf;
 
630
        struct a2dp_data *a2dp = &client->d.a2dp;
 
631
 
 
632
        if (!g_slist_find(clients, client)) {
 
633
                DBG("Client disconnected during discovery");
 
634
                return;
 
635
        }
 
636
 
 
637
        if (err)
 
638
                goto failed;
 
639
 
 
640
        memset(buf, 0, sizeof(buf));
 
641
        client->req_id = 0;
 
642
 
 
643
        rsp->h.type = BT_RESPONSE;
 
644
        rsp->h.name = BT_GET_CAPABILITIES;
 
645
        rsp->h.length = sizeof(*rsp);
 
646
        ba2str(&client->dev->src, rsp->source);
 
647
        ba2str(&client->dev->dst, rsp->destination);
 
648
        strncpy(rsp->object, client->dev->path, sizeof(rsp->object));
 
649
 
 
650
        for (; seps; seps = g_slist_next(seps)) {
 
651
                struct avdtp_remote_sep *rsep = seps->data;
 
652
                struct a2dp_sep *sep;
 
653
                struct avdtp_service_capability *cap;
 
654
                struct avdtp_stream *stream;
 
655
                uint8_t type, seid, configured = 0, lock = 0;
 
656
                GSList *cl;
 
657
 
 
658
                type = avdtp_get_type(rsep);
 
659
 
 
660
                if (type != AVDTP_SEP_TYPE_SINK &&
 
661
                                                type != AVDTP_SEP_TYPE_SOURCE)
 
662
                        continue;
 
663
 
 
664
                cap = avdtp_get_codec(rsep);
 
665
 
 
666
                if (cap->category != AVDTP_MEDIA_CODEC)
 
667
                        continue;
 
668
 
 
669
                seid = avdtp_get_seid(rsep);
 
670
 
 
671
                if (client->seid != 0 && client->seid != seid)
 
672
                        continue;
 
673
 
 
674
                stream = avdtp_get_stream(rsep);
 
675
                if (stream) {
 
676
                        configured = 1;
 
677
                        if (client->seid == seid)
 
678
                                cap = avdtp_stream_get_codec(stream);
 
679
                }
 
680
 
 
681
                for (cl = clients; cl; cl = cl->next) {
 
682
                        struct unix_client *c = cl->data;
 
683
                        struct a2dp_data *ca2dp = &c->d.a2dp;
 
684
 
 
685
                        if (ca2dp->session == session && c->seid == seid) {
 
686
                                lock = c->lock;
 
687
                                break;
 
688
                        }
 
689
                }
 
690
 
 
691
                sep = a2dp_get_sep(session, stream);
 
692
                if (sep && a2dp_sep_get_lock(sep))
 
693
                        lock = BT_WRITE_LOCK;
 
694
 
 
695
                a2dp_append_codec(rsp, cap, seid, type, configured, lock);
 
696
        }
 
697
 
 
698
        unix_ipc_sendmsg(client, &rsp->h);
 
699
 
 
700
        return;
 
701
 
 
702
failed:
 
703
        error("discovery failed");
 
704
        unix_ipc_error(client, BT_GET_CAPABILITIES, EIO);
 
705
 
 
706
        if (a2dp->sep) {
 
707
                a2dp_sep_unlock(a2dp->sep, a2dp->session);
 
708
                a2dp->sep = NULL;
 
709
        }
 
710
 
 
711
        avdtp_unref(a2dp->session);
 
712
        a2dp->session = NULL;
 
713
        a2dp->stream = NULL;
 
714
}
 
715
 
 
716
static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep,
 
717
                                        struct avdtp_stream *stream,
 
718
                                        struct avdtp_error *err,
 
719
                                        void *user_data)
 
720
{
 
721
        struct unix_client *client = user_data;
 
722
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
723
        struct bt_set_configuration_rsp *rsp = (void *) buf;
 
724
        struct a2dp_data *a2dp = &client->d.a2dp;
 
725
        uint16_t imtu, omtu;
 
726
        GSList *caps;
 
727
 
 
728
        client->req_id = 0;
 
729
 
 
730
        if (err)
 
731
                goto failed;
 
732
 
 
733
        memset(buf, 0, sizeof(buf));
 
734
 
 
735
        if (!stream)
 
736
                goto failed;
 
737
 
 
738
        if (client->cb_id > 0)
 
739
                avdtp_stream_remove_cb(a2dp->session, a2dp->stream,
 
740
                                                                client->cb_id);
 
741
 
 
742
        a2dp->sep = sep;
 
743
        a2dp->stream = stream;
 
744
 
 
745
        if (!avdtp_stream_get_transport(stream, &client->data_fd, &imtu, &omtu,
 
746
                                        &caps)) {
 
747
                error("Unable to get stream transport");
 
748
                goto failed;
 
749
        }
 
750
 
 
751
        rsp->h.type = BT_RESPONSE;
 
752
        rsp->h.name = BT_SET_CONFIGURATION;
 
753
        rsp->h.length = sizeof(*rsp);
 
754
 
 
755
        /* FIXME: Use imtu when fd_opt is CFG_FD_OPT_READ */
 
756
        rsp->link_mtu = omtu;
 
757
 
 
758
        unix_ipc_sendmsg(client, &rsp->h);
 
759
 
 
760
        client->cb_id = avdtp_stream_add_cb(session, stream,
 
761
                                                stream_state_changed, client);
 
762
 
 
763
        return;
 
764
 
 
765
failed:
 
766
        error("config failed");
 
767
 
 
768
        unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
 
769
 
 
770
        avdtp_unref(a2dp->session);
 
771
 
 
772
        a2dp->session = NULL;
 
773
        a2dp->stream = NULL;
 
774
        a2dp->sep = NULL;
 
775
}
 
776
 
 
777
static void a2dp_resume_complete(struct avdtp *session,
 
778
                                struct avdtp_error *err, void *user_data)
 
779
{
 
780
        struct unix_client *client = user_data;
 
781
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
782
        struct bt_start_stream_rsp *rsp = (void *) buf;
 
783
        struct bt_new_stream_ind *ind = (void *) buf;
 
784
        struct a2dp_data *a2dp = &client->d.a2dp;
 
785
 
 
786
        if (err)
 
787
                goto failed;
 
788
 
 
789
        memset(buf, 0, sizeof(buf));
 
790
        rsp->h.type = BT_RESPONSE;
 
791
        rsp->h.name = BT_START_STREAM;
 
792
        rsp->h.length = sizeof(*rsp);
 
793
 
 
794
        unix_ipc_sendmsg(client, &rsp->h);
 
795
 
 
796
        memset(buf, 0, sizeof(buf));
 
797
        ind->h.type = BT_RESPONSE;
 
798
        ind->h.name = BT_NEW_STREAM;
 
799
        rsp->h.length = sizeof(*ind);
 
800
 
 
801
        unix_ipc_sendmsg(client, &ind->h);
 
802
 
 
803
        if (unix_sendmsg_fd(client->sock, client->data_fd) < 0) {
 
804
                error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno);
 
805
                goto failed;
 
806
        }
 
807
 
 
808
        return;
 
809
 
 
810
failed:
 
811
        error("resume failed");
 
812
 
 
813
        unix_ipc_error(client, BT_START_STREAM, EIO);
 
814
 
 
815
        if (client->cb_id > 0) {
 
816
                avdtp_stream_remove_cb(a2dp->session, a2dp->stream,
 
817
                                        client->cb_id);
 
818
                client->cb_id = 0;
 
819
        }
 
820
 
 
821
        if (a2dp->sep) {
 
822
                a2dp_sep_unlock(a2dp->sep, a2dp->session);
 
823
                a2dp->sep = NULL;
 
824
        }
 
825
 
 
826
        avdtp_unref(a2dp->session);
 
827
        a2dp->session = NULL;
 
828
        a2dp->stream = NULL;
 
829
}
 
830
 
 
831
static void a2dp_suspend_complete(struct avdtp *session,
 
832
                                struct avdtp_error *err, void *user_data)
 
833
{
 
834
        struct unix_client *client = user_data;
 
835
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
836
        struct bt_stop_stream_rsp *rsp = (void *) buf;
 
837
 
 
838
        if (err)
 
839
                goto failed;
 
840
 
 
841
        memset(buf, 0, sizeof(buf));
 
842
        rsp->h.type = BT_RESPONSE;
 
843
        rsp->h.name = BT_STOP_STREAM;
 
844
        rsp->h.length = sizeof(*rsp);
 
845
 
 
846
        unix_ipc_sendmsg(client, &rsp->h);
 
847
 
 
848
        return;
 
849
 
 
850
failed:
 
851
        error("suspend failed");
 
852
 
 
853
        unix_ipc_error(client, BT_STOP_STREAM, EIO);
 
854
}
 
855
 
 
856
static void start_discovery(struct audio_device *dev, struct unix_client *client)
 
857
{
 
858
        struct a2dp_data *a2dp;
 
859
        int err = 0;
 
860
 
 
861
        switch (client->type) {
 
862
        case TYPE_SINK:
 
863
        case TYPE_SOURCE:
 
864
                a2dp = &client->d.a2dp;
 
865
 
 
866
                if (!a2dp->session)
 
867
                        a2dp->session = avdtp_get(&dev->src, &dev->dst);
 
868
 
 
869
                if (!a2dp->session) {
 
870
                        error("Unable to get a session");
 
871
                        goto failed;
 
872
                }
 
873
 
 
874
                err = avdtp_discover(a2dp->session, a2dp_discovery_complete,
 
875
                                        client);
 
876
                if (err) {
 
877
                        if (a2dp->session) {
 
878
                                avdtp_unref(a2dp->session);
 
879
                                a2dp->session = NULL;
 
880
                        }
 
881
                        goto failed;
 
882
                }
 
883
                break;
 
884
 
 
885
        case TYPE_HEADSET:
 
886
        case TYPE_GATEWAY:
 
887
                headset_discovery_complete(dev, client);
 
888
                break;
 
889
 
 
890
        default:
 
891
                error("No known services for device");
 
892
                goto failed;
 
893
        }
 
894
 
 
895
        client->dev = dev;
 
896
 
 
897
        return;
 
898
 
 
899
failed:
 
900
        unix_ipc_error(client, BT_GET_CAPABILITIES, err ? : EIO);
 
901
}
 
902
 
 
903
static void open_complete(struct audio_device *dev, void *user_data)
 
904
{
 
905
        struct unix_client *client = user_data;
 
906
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
907
        struct bt_open_rsp *rsp = (void *) buf;
 
908
 
 
909
        memset(buf, 0, sizeof(buf));
 
910
 
 
911
        rsp->h.type = BT_RESPONSE;
 
912
        rsp->h.name = BT_OPEN;
 
913
        rsp->h.length = sizeof(*rsp);
 
914
 
 
915
        ba2str(&dev->src, rsp->source);
 
916
        ba2str(&dev->dst, rsp->destination);
 
917
        strncpy(rsp->object, dev->path, sizeof(rsp->object));
 
918
 
 
919
        unix_ipc_sendmsg(client, &rsp->h);
 
920
}
 
921
 
 
922
static void start_open(struct audio_device *dev, struct unix_client *client)
 
923
{
 
924
        struct a2dp_data *a2dp;
 
925
        struct headset_data *hs;
 
926
        struct avdtp_remote_sep *rsep;
 
927
        gboolean unref_avdtp_on_fail = FALSE;
 
928
 
 
929
        switch (client->type) {
 
930
        case TYPE_SINK:
 
931
        case TYPE_SOURCE:
 
932
                a2dp = &client->d.a2dp;
 
933
 
 
934
                if (!a2dp->session) {
 
935
                        a2dp->session = avdtp_get(&dev->src, &dev->dst);
 
936
                        unref_avdtp_on_fail = TRUE;
 
937
                }
 
938
 
 
939
                if (!a2dp->session) {
 
940
                        error("Unable to get a session");
 
941
                        goto failed;
 
942
                }
 
943
 
 
944
                if (a2dp->sep) {
 
945
                        error("Client already has an opened session");
 
946
                        goto failed;
 
947
                }
 
948
 
 
949
                rsep = avdtp_get_remote_sep(a2dp->session, client->seid);
 
950
                if (!rsep) {
 
951
                        error("Invalid seid %d", client->seid);
 
952
                        goto failed;
 
953
                }
 
954
 
 
955
                a2dp->sep = a2dp_get(a2dp->session, rsep);
 
956
                if (!a2dp->sep) {
 
957
                        error("seid %d not available or locked", client->seid);
 
958
                        goto failed;
 
959
                }
 
960
 
 
961
                if (!a2dp_sep_lock(a2dp->sep, a2dp->session)) {
 
962
                        error("Unable to open seid %d", client->seid);
 
963
                        a2dp->sep = NULL;
 
964
                        goto failed;
 
965
                }
 
966
 
 
967
                break;
 
968
 
 
969
        case TYPE_HEADSET:
 
970
                hs = &client->d.hs;
 
971
 
 
972
                if (hs->locked) {
 
973
                        error("Client already has an opened session");
 
974
                        goto failed;
 
975
                }
 
976
 
 
977
                hs->locked = headset_lock(dev, client->lock);
 
978
                if (!hs->locked) {
 
979
                        error("Unable to open seid %d", client->seid);
 
980
                        goto failed;
 
981
                }
 
982
                break;
 
983
 
 
984
        case TYPE_GATEWAY:
 
985
                break;
 
986
        default:
 
987
                error("No known services for device");
 
988
                goto failed;
 
989
        }
 
990
 
 
991
        client->dev = dev;
 
992
 
 
993
        open_complete(dev, client);
 
994
 
 
995
        return;
 
996
 
 
997
failed:
 
998
        if (unref_avdtp_on_fail && a2dp->session) {
 
999
                avdtp_unref(a2dp->session);
 
1000
                a2dp->session = NULL;
 
1001
        }
 
1002
        unix_ipc_error(client, BT_OPEN, EINVAL);
 
1003
}
 
1004
 
 
1005
static void start_config(struct audio_device *dev, struct unix_client *client)
 
1006
{
 
1007
        struct a2dp_data *a2dp;
 
1008
        struct headset_data *hs;
 
1009
        unsigned int id;
 
1010
 
 
1011
        switch (client->type) {
 
1012
        case TYPE_SINK:
 
1013
        case TYPE_SOURCE:
 
1014
                a2dp = &client->d.a2dp;
 
1015
 
 
1016
                if (!a2dp->session)
 
1017
                        a2dp->session = avdtp_get(&dev->src, &dev->dst);
 
1018
 
 
1019
                if (!a2dp->session) {
 
1020
                        error("Unable to get a session");
 
1021
                        goto failed;
 
1022
                }
 
1023
 
 
1024
                if (!a2dp->sep) {
 
1025
                        error("seid %d not opened", client->seid);
 
1026
                        goto failed;
 
1027
                }
 
1028
 
 
1029
                id = a2dp_config(a2dp->session, a2dp->sep, a2dp_config_complete,
 
1030
                                        client->caps, client);
 
1031
                client->cancel = a2dp_cancel;
 
1032
                break;
 
1033
 
 
1034
        case TYPE_HEADSET:
 
1035
                hs = &client->d.hs;
 
1036
 
 
1037
                if (!hs->locked) {
 
1038
                        error("seid %d not opened", client->seid);
 
1039
                        goto failed;
 
1040
                }
 
1041
 
 
1042
                id = headset_config_stream(dev, TRUE, headset_setup_complete,
 
1043
                                                client);
 
1044
                client->cancel = headset_cancel_stream;
 
1045
                break;
 
1046
        case TYPE_GATEWAY:
 
1047
                id = gateway_config_stream(dev, gateway_setup_complete, client);
 
1048
                client->cancel = gateway_cancel_stream;
 
1049
                break;
 
1050
 
 
1051
        default:
 
1052
                error("No known services for device");
 
1053
                goto failed;
 
1054
        }
 
1055
 
 
1056
        if (id == 0) {
 
1057
                error("config failed");
 
1058
                goto failed;
 
1059
        }
 
1060
 
 
1061
        client->req_id = id;
 
1062
        g_slist_free(client->caps);
 
1063
        client->caps = NULL;
 
1064
 
 
1065
        return;
 
1066
 
 
1067
failed:
 
1068
        unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
 
1069
}
 
1070
 
 
1071
static void start_resume(struct audio_device *dev, struct unix_client *client)
 
1072
{
 
1073
        struct a2dp_data *a2dp = NULL;
 
1074
        struct headset_data *hs;
 
1075
        unsigned int id;
 
1076
        struct avdtp *session = NULL;
 
1077
 
 
1078
        switch (client->type) {
 
1079
        case TYPE_SINK:
 
1080
        case TYPE_SOURCE:
 
1081
                a2dp = &client->d.a2dp;
 
1082
 
 
1083
                if (!a2dp->sep) {
 
1084
                        error("seid not opened");
 
1085
                        goto failed;
 
1086
                }
 
1087
 
 
1088
                if (!a2dp->session) {
 
1089
                        session = avdtp_get(&dev->src, &dev->dst);
 
1090
                        if (!session) {
 
1091
                                error("Unable to get a session");
 
1092
                                goto failed;
 
1093
                        }
 
1094
                        a2dp->session = session;
 
1095
                }
 
1096
 
 
1097
                id = a2dp_resume(a2dp->session, a2dp->sep, a2dp_resume_complete,
 
1098
                                        client);
 
1099
                client->cancel = a2dp_cancel;
 
1100
 
 
1101
                break;
 
1102
 
 
1103
        case TYPE_HEADSET:
 
1104
                hs = &client->d.hs;
 
1105
 
 
1106
                if (!hs->locked) {
 
1107
                        error("seid not opened");
 
1108
                        goto failed;
 
1109
                }
 
1110
 
 
1111
                id = headset_request_stream(dev, headset_resume_complete,
 
1112
                                                client);
 
1113
                client->cancel = headset_cancel_stream;
 
1114
                break;
 
1115
 
 
1116
        case TYPE_GATEWAY:
 
1117
                id = gateway_request_stream(dev, gateway_resume_complete,
 
1118
                                                client);
 
1119
                client->cancel = gateway_cancel_stream;
 
1120
                break;
 
1121
 
 
1122
        default:
 
1123
                error("No known services for device");
 
1124
                goto failed;
 
1125
        }
 
1126
 
 
1127
        if (id == 0) {
 
1128
                error("start_resume: resume failed");
 
1129
                goto failed;
 
1130
        }
 
1131
 
 
1132
        client->req_id = id;
 
1133
 
 
1134
        return;
 
1135
 
 
1136
failed:
 
1137
        if (session) {
 
1138
                avdtp_unref(session);
 
1139
                a2dp->session = NULL;
 
1140
        }
 
1141
 
 
1142
        unix_ipc_error(client, BT_START_STREAM, EIO);
 
1143
}
 
1144
 
 
1145
static void start_suspend(struct audio_device *dev, struct unix_client *client)
 
1146
{
 
1147
        struct a2dp_data *a2dp = NULL;
 
1148
        struct headset_data *hs;
 
1149
        unsigned int id;
 
1150
        struct avdtp *session = NULL;
 
1151
 
 
1152
        switch (client->type) {
 
1153
        case TYPE_SINK:
 
1154
        case TYPE_SOURCE:
 
1155
                a2dp = &client->d.a2dp;
 
1156
 
 
1157
                if (!a2dp->sep) {
 
1158
                        error("seid not opened");
 
1159
                        goto failed;
 
1160
                }
 
1161
 
 
1162
                if (!a2dp->session) {
 
1163
                        session = avdtp_get(&dev->src, &dev->dst);
 
1164
                        if (!session) {
 
1165
                                error("Unable to get a session");
 
1166
                                goto failed;
 
1167
                        }
 
1168
                        a2dp->session = session;
 
1169
                }
 
1170
 
 
1171
                if (!a2dp->sep) {
 
1172
                        error("Unable to get a sep");
 
1173
                        goto failed;
 
1174
                }
 
1175
 
 
1176
                id = a2dp_suspend(a2dp->session, a2dp->sep,
 
1177
                                        a2dp_suspend_complete, client);
 
1178
                client->cancel = a2dp_cancel;
 
1179
                break;
 
1180
 
 
1181
        case TYPE_HEADSET:
 
1182
                hs = &client->d.hs;
 
1183
 
 
1184
                if (!hs->locked) {
 
1185
                        error("seid not opened");
 
1186
                        goto failed;
 
1187
                }
 
1188
 
 
1189
                id = headset_suspend_stream(dev, headset_suspend_complete,
 
1190
                                                client);
 
1191
                client->cancel = headset_cancel_stream;
 
1192
                break;
 
1193
 
 
1194
        case TYPE_GATEWAY:
 
1195
                gateway_suspend_stream(dev);
 
1196
                client->cancel = gateway_cancel_stream;
 
1197
                headset_suspend_complete(dev, client);
 
1198
                id = 1;
 
1199
                break;
 
1200
 
 
1201
        default:
 
1202
                error("No known services for device");
 
1203
                goto failed;
 
1204
        }
 
1205
 
 
1206
        if (id == 0) {
 
1207
                error("suspend failed");
 
1208
                goto failed;
 
1209
        }
 
1210
 
 
1211
        return;
 
1212
 
 
1213
failed:
 
1214
        if (session) {
 
1215
                avdtp_unref(session);
 
1216
                a2dp->session = NULL;
 
1217
        }
 
1218
 
 
1219
        unix_ipc_error(client, BT_STOP_STREAM, EIO);
 
1220
}
 
1221
 
 
1222
static void close_complete(struct audio_device *dev, void *user_data)
 
1223
{
 
1224
        struct unix_client *client = user_data;
 
1225
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
1226
        struct bt_close_rsp *rsp = (void *) buf;
 
1227
 
 
1228
        memset(buf, 0, sizeof(buf));
 
1229
 
 
1230
        rsp->h.type = BT_RESPONSE;
 
1231
        rsp->h.name = BT_CLOSE;
 
1232
        rsp->h.length = sizeof(*rsp);
 
1233
 
 
1234
        unix_ipc_sendmsg(client, &rsp->h);
 
1235
 
 
1236
        return;
 
1237
}
 
1238
 
 
1239
static void start_close(struct audio_device *dev, struct unix_client *client,
 
1240
                        gboolean reply)
 
1241
{
 
1242
        struct a2dp_data *a2dp;
 
1243
        struct headset_data *hs;
 
1244
 
 
1245
        if (!client->dev)
 
1246
                goto failed;
 
1247
 
 
1248
        switch (client->type) {
 
1249
        case TYPE_HEADSET:
 
1250
                hs = &client->d.hs;
 
1251
 
 
1252
                if (client->dev && hs->locked) {
 
1253
                        headset_unlock(client->dev, client->lock);
 
1254
                        hs->locked = FALSE;
 
1255
                }
 
1256
                break;
 
1257
        case TYPE_GATEWAY:
 
1258
                break;
 
1259
        case TYPE_SOURCE:
 
1260
        case TYPE_SINK:
 
1261
                a2dp = &client->d.a2dp;
 
1262
 
 
1263
                if (client->cb_id > 0) {
 
1264
                        avdtp_stream_remove_cb(a2dp->session, a2dp->stream,
 
1265
                                                                client->cb_id);
 
1266
                        client->cb_id = 0;
 
1267
                }
 
1268
                if (a2dp->sep) {
 
1269
                        a2dp_sep_unlock(a2dp->sep, a2dp->session);
 
1270
                        a2dp->sep = NULL;
 
1271
                }
 
1272
                if (a2dp->session) {
 
1273
                        avdtp_unref(a2dp->session);
 
1274
                        a2dp->session = NULL;
 
1275
                }
 
1276
                a2dp->stream = NULL;
 
1277
                break;
 
1278
        default:
 
1279
                error("No known services for device");
 
1280
                goto failed;
 
1281
        }
 
1282
 
 
1283
        if (!reply)
 
1284
                return;
 
1285
 
 
1286
        close_complete(dev, client);
 
1287
        client->dev = NULL;
 
1288
 
 
1289
        return;
 
1290
 
 
1291
failed:
 
1292
        if (reply)
 
1293
                unix_ipc_error(client, BT_STOP_STREAM, EINVAL);
 
1294
}
 
1295
 
 
1296
static void handle_getcapabilities_req(struct unix_client *client,
 
1297
                                        struct bt_get_capabilities_req *req)
 
1298
{
 
1299
        struct audio_device *dev;
 
1300
        bdaddr_t src, dst;
 
1301
        int err = EIO;
 
1302
        const char *interface;
 
1303
 
 
1304
        if (!check_nul(req->source) || !check_nul(req->destination) ||
 
1305
                        !check_nul(req->object)) {
 
1306
                err = EINVAL;
 
1307
                goto failed;
 
1308
        }
 
1309
 
 
1310
        str2ba(req->source, &src);
 
1311
        str2ba(req->destination, &dst);
 
1312
 
 
1313
        if (!manager_find_device(req->object, &src, &dst, NULL, FALSE))
 
1314
                goto failed;
 
1315
 
 
1316
        if (req->transport == BT_CAPABILITIES_TRANSPORT_SCO)
 
1317
                interface = AUDIO_HEADSET_INTERFACE;
 
1318
        else if (req->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
 
1319
                interface = AUDIO_SINK_INTERFACE;
 
1320
        else
 
1321
                interface = client->interface;
 
1322
 
 
1323
        dev = manager_find_device(req->object, &src, &dst, interface, TRUE);
 
1324
        if (!dev && (req->flags & BT_FLAG_AUTOCONNECT))
 
1325
                dev = manager_find_device(req->object, &src, &dst,
 
1326
                                                        interface, FALSE);
 
1327
 
 
1328
        if (!dev) {
 
1329
                if (req->transport == BT_CAPABILITIES_TRANSPORT_SCO)
 
1330
                        interface = AUDIO_GATEWAY_INTERFACE;
 
1331
                else if (req->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
 
1332
                        interface = AUDIO_SOURCE_INTERFACE;
 
1333
                else
 
1334
                        interface = NULL;
 
1335
                dev = manager_find_device(req->object, &src, &dst,
 
1336
                                                        interface, TRUE);
 
1337
                if (!dev && (req->flags & BT_FLAG_AUTOCONNECT))
 
1338
                        dev = manager_find_device(req->object, &src, &dst,
 
1339
                                                        interface, FALSE);
 
1340
        }
 
1341
 
 
1342
        if (!dev) {
 
1343
                error("Unable to find a matching device");
 
1344
                goto failed;
 
1345
        }
 
1346
 
 
1347
        client->type = select_service(dev, interface);
 
1348
        if (client->type == TYPE_NONE) {
 
1349
                error("No matching service found");
 
1350
                goto failed;
 
1351
        }
 
1352
 
 
1353
        if (g_strcmp0(interface, client->interface) != 0) {
 
1354
                g_free(client->interface);
 
1355
                client->interface = g_strdup(interface);
 
1356
        }
 
1357
 
 
1358
        client->seid = req->seid;
 
1359
 
 
1360
        start_discovery(dev, client);
 
1361
 
 
1362
        return;
 
1363
 
 
1364
failed:
 
1365
        unix_ipc_error(client, BT_GET_CAPABILITIES, err);
 
1366
}
 
1367
 
 
1368
static int handle_sco_open(struct unix_client *client, struct bt_open_req *req)
 
1369
{
 
1370
        if (!client->interface)
 
1371
                client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);
 
1372
        else if (!g_str_equal(client->interface, AUDIO_HEADSET_INTERFACE) &&
 
1373
                !g_str_equal(client->interface, AUDIO_GATEWAY_INTERFACE))
 
1374
                return -EIO;
 
1375
 
 
1376
        DBG("open sco - object=%s source=%s destination=%s lock=%s%s",
 
1377
                        strcmp(req->object, "") ? req->object : "ANY",
 
1378
                        strcmp(req->source, "") ? req->source : "ANY",
 
1379
                        strcmp(req->destination, "") ? req->destination : "ANY",
 
1380
                        req->lock & BT_READ_LOCK ? "read" : "",
 
1381
                        req->lock & BT_WRITE_LOCK ? "write" : "");
 
1382
 
 
1383
        return 0;
 
1384
}
 
1385
 
 
1386
static int handle_a2dp_open(struct unix_client *client, struct bt_open_req *req)
 
1387
{
 
1388
        if (!client->interface)
 
1389
                /* FIXME: are we treating a sink or a source? */
 
1390
                client->interface = g_strdup(AUDIO_SINK_INTERFACE);
 
1391
        else if (!g_str_equal(client->interface, AUDIO_SINK_INTERFACE) &&
 
1392
                        !g_str_equal(client->interface, AUDIO_SOURCE_INTERFACE))
 
1393
                return -EIO;
 
1394
 
 
1395
        DBG("open a2dp - object=%s source=%s destination=%s lock=%s%s",
 
1396
                        strcmp(req->object, "") ? req->object : "ANY",
 
1397
                        strcmp(req->source, "") ? req->source : "ANY",
 
1398
                        strcmp(req->destination, "") ? req->destination : "ANY",
 
1399
                        req->lock & BT_READ_LOCK ? "read" : "",
 
1400
                        req->lock & BT_WRITE_LOCK ? "write" : "");
 
1401
 
 
1402
        return 0;
 
1403
}
 
1404
 
 
1405
static void handle_open_req(struct unix_client *client, struct bt_open_req *req)
 
1406
{
 
1407
        struct audio_device *dev;
 
1408
        bdaddr_t src, dst;
 
1409
        int err = 0;
 
1410
 
 
1411
        if (!check_nul(req->source) || !check_nul(req->destination) ||
 
1412
                        !check_nul(req->object)) {
 
1413
                err = EINVAL;
 
1414
                goto failed;
 
1415
        }
 
1416
 
 
1417
        str2ba(req->source, &src);
 
1418
        str2ba(req->destination, &dst);
 
1419
 
 
1420
        if (req->seid > BT_A2DP_SEID_RANGE) {
 
1421
                err = handle_sco_open(client, req);
 
1422
                if (err < 0) {
 
1423
                        err = -err;
 
1424
                        goto failed;
 
1425
                }
 
1426
        } else {
 
1427
                err = handle_a2dp_open(client, req);
 
1428
                if (err < 0) {
 
1429
                        err = -err;
 
1430
                        goto failed;
 
1431
                }
 
1432
        }
 
1433
 
 
1434
        if (!manager_find_device(req->object, &src, &dst, NULL, FALSE))
 
1435
                goto failed;
 
1436
 
 
1437
        dev = manager_find_device(req->object, &src, &dst, client->interface,
 
1438
                                TRUE);
 
1439
        if (!dev)
 
1440
                dev = manager_find_device(req->object, &src, &dst,
 
1441
                                        client->interface, FALSE);
 
1442
 
 
1443
        if (!dev)
 
1444
                goto failed;
 
1445
 
 
1446
        client->seid = req->seid;
 
1447
        client->lock = req->lock;
 
1448
 
 
1449
        start_open(dev, client);
 
1450
 
 
1451
        return;
 
1452
 
 
1453
failed:
 
1454
        unix_ipc_error(client, BT_OPEN, err ? : EIO);
 
1455
}
 
1456
 
 
1457
static int handle_sco_transport(struct unix_client *client,
 
1458
                                struct bt_set_configuration_req *req)
 
1459
{
 
1460
        struct audio_device *dev = client->dev;
 
1461
 
 
1462
        if (!client->interface) {
 
1463
                if (dev->headset)
 
1464
                        client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);
 
1465
                else if (dev->gateway)
 
1466
                        client->interface = g_strdup(AUDIO_GATEWAY_INTERFACE);
 
1467
                else
 
1468
                        return -EIO;
 
1469
        } else if (!g_str_equal(client->interface, AUDIO_HEADSET_INTERFACE) &&
 
1470
                        !g_str_equal(client->interface, AUDIO_GATEWAY_INTERFACE))
 
1471
                return -EIO;
 
1472
 
 
1473
        return 0;
 
1474
}
 
1475
 
 
1476
static int handle_a2dp_transport(struct unix_client *client,
 
1477
                                struct bt_set_configuration_req *req)
 
1478
{
 
1479
        struct avdtp_service_capability *media_transport, *media_codec;
 
1480
        struct sbc_codec_cap sbc_cap;
 
1481
        struct mpeg_codec_cap mpeg_cap;
 
1482
 
 
1483
        if (!client->interface)
 
1484
                /* FIXME: are we treating a sink or a source? */
 
1485
                client->interface = g_strdup(AUDIO_SINK_INTERFACE);
 
1486
        else if (!g_str_equal(client->interface, AUDIO_SINK_INTERFACE) &&
 
1487
                        !g_str_equal(client->interface, AUDIO_SOURCE_INTERFACE))
 
1488
                return -EIO;
 
1489
 
 
1490
        g_slist_free_full(client->caps, g_free);
 
1491
        client->caps = NULL;
 
1492
 
 
1493
        media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
 
1494
                                                NULL, 0);
 
1495
 
 
1496
        client->caps = g_slist_append(client->caps, media_transport);
 
1497
 
 
1498
        if (req->codec.type == BT_A2DP_MPEG12_SINK ||
 
1499
                req->codec.type == BT_A2DP_MPEG12_SOURCE) {
 
1500
                mpeg_capabilities_t *mpeg = (void *) &req->codec;
 
1501
 
 
1502
                memset(&mpeg_cap, 0, sizeof(mpeg_cap));
 
1503
 
 
1504
                mpeg_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
 
1505
                mpeg_cap.cap.media_codec_type = A2DP_CODEC_MPEG12;
 
1506
                mpeg_cap.channel_mode = mpeg->channel_mode;
 
1507
                mpeg_cap.crc = mpeg->crc;
 
1508
                mpeg_cap.layer = mpeg->layer;
 
1509
                mpeg_cap.frequency = mpeg->frequency;
 
1510
                mpeg_cap.mpf = mpeg->mpf;
 
1511
                mpeg_cap.bitrate = mpeg->bitrate;
 
1512
 
 
1513
                media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &mpeg_cap,
 
1514
                                                        sizeof(mpeg_cap));
 
1515
 
 
1516
                print_mpeg12(&mpeg_cap);
 
1517
        } else if (req->codec.type == BT_A2DP_SBC_SINK ||
 
1518
                        req->codec.type == BT_A2DP_SBC_SOURCE) {
 
1519
                sbc_capabilities_t *sbc = (void *) &req->codec;
 
1520
 
 
1521
                memset(&sbc_cap, 0, sizeof(sbc_cap));
 
1522
 
 
1523
                sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
 
1524
                sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC;
 
1525
                sbc_cap.channel_mode = sbc->channel_mode;
 
1526
                sbc_cap.frequency = sbc->frequency;
 
1527
                sbc_cap.allocation_method = sbc->allocation_method;
 
1528
                sbc_cap.subbands = sbc->subbands;
 
1529
                sbc_cap.block_length = sbc->block_length;
 
1530
                sbc_cap.min_bitpool = sbc->min_bitpool;
 
1531
                sbc_cap.max_bitpool = sbc->max_bitpool;
 
1532
 
 
1533
                media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
 
1534
                                                        sizeof(sbc_cap));
 
1535
 
 
1536
                print_sbc(&sbc_cap);
 
1537
        } else
 
1538
                return -EINVAL;
 
1539
 
 
1540
        client->caps = g_slist_append(client->caps, media_codec);
 
1541
 
 
1542
        return 0;
 
1543
}
 
1544
 
 
1545
static void handle_setconfiguration_req(struct unix_client *client,
 
1546
                                        struct bt_set_configuration_req *req)
 
1547
{
 
1548
        int err = 0;
 
1549
 
 
1550
        if (req->codec.seid != client->seid) {
 
1551
                error("Unable to set configuration: seid %d not opened",
 
1552
                                req->codec.seid);
 
1553
                goto failed;
 
1554
        }
 
1555
 
 
1556
        if (!client->dev)
 
1557
                goto failed;
 
1558
 
 
1559
        if (req->codec.transport == BT_CAPABILITIES_TRANSPORT_SCO) {
 
1560
                err = handle_sco_transport(client, req);
 
1561
                if (err < 0) {
 
1562
                        err = -err;
 
1563
                        goto failed;
 
1564
                }
 
1565
        } else if (req->codec.transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
 
1566
                err = handle_a2dp_transport(client, req);
 
1567
                if (err < 0) {
 
1568
                        err = -err;
 
1569
                        goto failed;
 
1570
                }
 
1571
        }
 
1572
 
 
1573
        start_config(client->dev, client);
 
1574
 
 
1575
        return;
 
1576
 
 
1577
failed:
 
1578
        unix_ipc_error(client, BT_SET_CONFIGURATION, err ? : EIO);
 
1579
}
 
1580
 
 
1581
static void handle_streamstart_req(struct unix_client *client,
 
1582
                                        struct bt_start_stream_req *req)
 
1583
{
 
1584
        if (!client->dev)
 
1585
                goto failed;
 
1586
 
 
1587
        start_resume(client->dev, client);
 
1588
 
 
1589
        return;
 
1590
 
 
1591
failed:
 
1592
        unix_ipc_error(client, BT_START_STREAM, EIO);
 
1593
}
 
1594
 
 
1595
static void handle_streamstop_req(struct unix_client *client,
 
1596
                                        struct bt_stop_stream_req *req)
 
1597
{
 
1598
        if (!client->dev)
 
1599
                goto failed;
 
1600
 
 
1601
        start_suspend(client->dev, client);
 
1602
 
 
1603
        return;
 
1604
 
 
1605
failed:
 
1606
        unix_ipc_error(client, BT_STOP_STREAM, EIO);
 
1607
}
 
1608
 
 
1609
static void handle_close_req(struct unix_client *client,
 
1610
                                struct bt_close_req *req)
 
1611
{
 
1612
        if (!client->dev)
 
1613
                goto failed;
 
1614
 
 
1615
        start_close(client->dev, client, TRUE);
 
1616
 
 
1617
        return;
 
1618
 
 
1619
failed:
 
1620
        unix_ipc_error(client, BT_CLOSE, EIO);
 
1621
}
 
1622
 
 
1623
static void handle_control_req(struct unix_client *client,
 
1624
                                        struct bt_control_req *req)
 
1625
{
 
1626
        /* FIXME: really implement that */
 
1627
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
1628
        struct bt_set_configuration_rsp *rsp = (void *) buf;
 
1629
 
 
1630
        memset(buf, 0, sizeof(buf));
 
1631
        rsp->h.type = BT_RESPONSE;
 
1632
        rsp->h.name = BT_CONTROL;
 
1633
        rsp->h.length = sizeof(*rsp);
 
1634
 
 
1635
        unix_ipc_sendmsg(client, &rsp->h);
 
1636
}
 
1637
 
 
1638
static void handle_delay_report_req(struct unix_client *client,
 
1639
                                        struct bt_delay_report_req *req)
 
1640
{
 
1641
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
1642
        struct bt_set_configuration_rsp *rsp = (void *) buf;
 
1643
        struct a2dp_data *a2dp;
 
1644
        int err;
 
1645
 
 
1646
        if (!client->dev) {
 
1647
                err = -ENODEV;
 
1648
                goto failed;
 
1649
        }
 
1650
 
 
1651
        switch (client->type) {
 
1652
        case TYPE_HEADSET:
 
1653
        case TYPE_GATEWAY:
 
1654
                err = -EINVAL;
 
1655
                goto failed;
 
1656
        case TYPE_SOURCE:
 
1657
        case TYPE_SINK:
 
1658
                a2dp = &client->d.a2dp;
 
1659
                if (a2dp->session && a2dp->stream) {
 
1660
                        err = avdtp_delay_report(a2dp->session, a2dp->stream,
 
1661
                                                                req->delay);
 
1662
                        if (err < 0)
 
1663
                                goto failed;
 
1664
                } else {
 
1665
                        err = -EINVAL;
 
1666
                        goto failed;
 
1667
                }
 
1668
                break;
 
1669
        default:
 
1670
                error("No known services for device");
 
1671
                err = -EINVAL;
 
1672
                goto failed;
 
1673
        }
 
1674
 
 
1675
        memset(buf, 0, sizeof(buf));
 
1676
        rsp->h.type = BT_RESPONSE;
 
1677
        rsp->h.name = BT_DELAY_REPORT;
 
1678
        rsp->h.length = sizeof(*rsp);
 
1679
 
 
1680
        unix_ipc_sendmsg(client, &rsp->h);
 
1681
 
 
1682
        return;
 
1683
 
 
1684
failed:
 
1685
        unix_ipc_error(client, BT_DELAY_REPORT, -err);
 
1686
}
 
1687
 
 
1688
static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 
1689
{
 
1690
        char buf[BT_SUGGESTED_BUFFER_SIZE];
 
1691
        bt_audio_msg_header_t *msghdr = (void *) buf;
 
1692
        struct unix_client *client = data;
 
1693
        int len;
 
1694
        const char *type, *name;
 
1695
 
 
1696
        if (cond & G_IO_NVAL)
 
1697
                return FALSE;
 
1698
 
 
1699
        if (cond & (G_IO_HUP | G_IO_ERR)) {
 
1700
                DBG("Unix client disconnected (fd=%d)", client->sock);
 
1701
 
 
1702
                goto failed;
 
1703
        }
 
1704
 
 
1705
        memset(buf, 0, sizeof(buf));
 
1706
 
 
1707
        len = recv(client->sock, buf, sizeof(buf), 0);
 
1708
        if (len < 0) {
 
1709
                error("recv: %s (%d)", strerror(errno), errno);
 
1710
                goto failed;
 
1711
        }
 
1712
 
 
1713
        type = bt_audio_strtype(msghdr->type);
 
1714
        name = bt_audio_strname(msghdr->name);
 
1715
 
 
1716
        DBG("Audio API: %s <- %s", type, name);
 
1717
 
 
1718
        if (msghdr->length != len) {
 
1719
                error("Invalid message: length mismatch");
 
1720
                goto failed;
 
1721
        }
 
1722
 
 
1723
        switch (msghdr->name) {
 
1724
        case BT_GET_CAPABILITIES:
 
1725
                handle_getcapabilities_req(client,
 
1726
                                (struct bt_get_capabilities_req *) msghdr);
 
1727
                break;
 
1728
        case BT_OPEN:
 
1729
                handle_open_req(client,
 
1730
                                (struct bt_open_req *) msghdr);
 
1731
                break;
 
1732
        case BT_SET_CONFIGURATION:
 
1733
                handle_setconfiguration_req(client,
 
1734
                                (struct bt_set_configuration_req *) msghdr);
 
1735
                break;
 
1736
        case BT_START_STREAM:
 
1737
                handle_streamstart_req(client,
 
1738
                                (struct bt_start_stream_req *) msghdr);
 
1739
                break;
 
1740
        case BT_STOP_STREAM:
 
1741
                handle_streamstop_req(client,
 
1742
                                (struct bt_stop_stream_req *) msghdr);
 
1743
                break;
 
1744
        case BT_CLOSE:
 
1745
                handle_close_req(client,
 
1746
                                (struct bt_close_req *) msghdr);
 
1747
                break;
 
1748
        case BT_CONTROL:
 
1749
                handle_control_req(client,
 
1750
                                (struct bt_control_req *) msghdr);
 
1751
                break;
 
1752
        case BT_DELAY_REPORT:
 
1753
                handle_delay_report_req(client,
 
1754
                                (struct bt_delay_report_req *) msghdr);
 
1755
                break;
 
1756
        default:
 
1757
                error("Audio API: received unexpected message name %d",
 
1758
                                msghdr->name);
 
1759
        }
 
1760
 
 
1761
        return TRUE;
 
1762
 
 
1763
failed:
 
1764
        clients = g_slist_remove(clients, client);
 
1765
        start_close(client->dev, client, FALSE);
 
1766
        client_free(client);
 
1767
        return FALSE;
 
1768
}
 
1769
 
 
1770
static gboolean server_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 
1771
{
 
1772
        struct sockaddr_un addr;
 
1773
        socklen_t addrlen;
 
1774
        int sk, cli_sk;
 
1775
        struct unix_client *client;
 
1776
        GIOChannel *io;
 
1777
 
 
1778
        if (cond & G_IO_NVAL)
 
1779
                return FALSE;
 
1780
 
 
1781
        if (cond & (G_IO_HUP | G_IO_ERR)) {
 
1782
                g_io_channel_shutdown(chan, TRUE, NULL);
 
1783
                return FALSE;
 
1784
        }
 
1785
 
 
1786
        sk = g_io_channel_unix_get_fd(chan);
 
1787
 
 
1788
        memset(&addr, 0, sizeof(addr));
 
1789
        addrlen = sizeof(addr);
 
1790
 
 
1791
        cli_sk = accept(sk, (struct sockaddr *) &addr, &addrlen);
 
1792
        if (cli_sk < 0) {
 
1793
                error("accept: %s (%d)", strerror(errno), errno);
 
1794
                return TRUE;
 
1795
        }
 
1796
 
 
1797
        DBG("Accepted new client connection on unix socket (fd=%d)", cli_sk);
 
1798
        set_nonblocking(cli_sk);
 
1799
 
 
1800
        client = g_new0(struct unix_client, 1);
 
1801
        client->sock = cli_sk;
 
1802
        clients = g_slist_append(clients, client);
 
1803
 
 
1804
        io = g_io_channel_unix_new(cli_sk);
 
1805
        g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 
1806
                                                        client_cb, client);
 
1807
        g_io_channel_unref(io);
 
1808
 
 
1809
        return TRUE;
 
1810
}
 
1811
 
 
1812
void unix_device_removed(struct audio_device *dev)
 
1813
{
 
1814
        GSList *l;
 
1815
 
 
1816
        DBG("unix_device_removed(%p)", dev);
 
1817
 
 
1818
        l = clients;
 
1819
        while (l) {
 
1820
                struct unix_client *client = l->data;
 
1821
 
 
1822
                l = l->next;
 
1823
 
 
1824
                if (client->dev == dev) {
 
1825
                        clients = g_slist_remove(clients, client);
 
1826
                        start_close(client->dev, client, FALSE);
 
1827
                        client_free(client);
 
1828
                }
 
1829
        }
 
1830
}
 
1831
 
 
1832
void unix_delay_report(struct audio_device *dev, uint8_t seid, uint16_t delay)
 
1833
{
 
1834
        GSList *l;
 
1835
        struct bt_delay_report_ind ind;
 
1836
 
 
1837
        DBG("unix_delay_report(%p): %u.%ums", dev, delay / 10, delay % 10);
 
1838
 
 
1839
        memset(&ind, 0, sizeof(ind));
 
1840
        ind.h.type = BT_INDICATION;
 
1841
        ind.h.name = BT_DELAY_REPORT;
 
1842
        ind.h.length = sizeof(ind);
 
1843
        ind.delay = delay;
 
1844
 
 
1845
        for (l = clients; l != NULL; l = g_slist_next(l)) {
 
1846
                struct unix_client *client = l->data;
 
1847
 
 
1848
                if (client->dev != dev || client->seid != seid)
 
1849
                        continue;
 
1850
 
 
1851
                unix_ipc_sendmsg(client, (void *) &ind);
 
1852
        }
 
1853
}
 
1854
 
 
1855
int unix_init(void)
 
1856
{
 
1857
        GIOChannel *io;
 
1858
        struct sockaddr_un addr = {
 
1859
                AF_UNIX, BT_IPC_SOCKET_NAME
 
1860
        };
 
1861
 
 
1862
        int sk, err;
 
1863
 
 
1864
        sk = socket(PF_LOCAL, SOCK_STREAM, 0);
 
1865
        if (sk < 0) {
 
1866
                err = -errno;
 
1867
                error("Can't create unix socket: %s (%d)", strerror(-err),
 
1868
                                                                        -err);
 
1869
                return err;
 
1870
        }
 
1871
 
 
1872
        if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
 
1873
                err = -errno;
 
1874
                error("Can't bind unix socket: %s (%d)", strerror(-err),
 
1875
                                                                        -err);
 
1876
                close(sk);
 
1877
                return err;
 
1878
        }
 
1879
 
 
1880
        set_nonblocking(sk);
 
1881
 
 
1882
        if (listen(sk, 1) < 0) {
 
1883
                err = -errno;
 
1884
                error("Can't listen on unix socket: %s (%d)", strerror(-err),
 
1885
                                                                        -err);
 
1886
                close(sk);
 
1887
                return err;
 
1888
        }
 
1889
 
 
1890
        unix_sock = sk;
 
1891
 
 
1892
        io = g_io_channel_unix_new(sk);
 
1893
        g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 
1894
                                                        server_cb, NULL);
 
1895
        g_io_channel_unref(io);
 
1896
 
 
1897
        DBG("Unix socket created: %d", sk);
 
1898
 
 
1899
        return 0;
 
1900
}
 
1901
 
 
1902
void unix_exit(void)
 
1903
{
 
1904
        g_slist_free_full(clients, client_free);
 
1905
        if (unix_sock >= 0) {
 
1906
                close(unix_sock);
 
1907
                unix_sock = -1;
 
1908
        }
 
1909
}