~ubuntu-branches/ubuntu/wily/bluez/wily

« back to all changes in this revision

Viewing changes to common/glib-helper.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello
  • Date: 2008-10-07 12:10:29 UTC
  • Revision ID: james.westby@ubuntu.com-20081007121029-4gup4fmmh2vfo5nh
Tags: upstream-4.12
ImportĀ upstreamĀ versionĀ 4.12

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) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
 
6
 *
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation; either version 2 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *
 
13
 *  This program is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *  GNU General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU General Public License
 
19
 *  along with this program; if not, write to the Free Software
 
20
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
21
 *
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <errno.h>
 
29
#include <fcntl.h>
 
30
#include <unistd.h>
 
31
#include <sys/ioctl.h>
 
32
#include <sys/socket.h>
 
33
 
 
34
#include <bluetooth/bluetooth.h>
 
35
#include <bluetooth/hci.h>
 
36
#include <bluetooth/hci_lib.h>
 
37
#include <bluetooth/rfcomm.h>
 
38
#include <bluetooth/l2cap.h>
 
39
#include <bluetooth/sco.h>
 
40
#include <bluetooth/sdp.h>
 
41
#include <bluetooth/sdp_lib.h>
 
42
 
 
43
#include <glib.h>
 
44
 
 
45
#include "glib-helper.h"
 
46
 
 
47
typedef int (*resolver_t) (int fd, char *src, char *dst);
 
48
typedef BtIOError (*connect_t) (BtIO *io, BtIOFunc func);
 
49
typedef BtIOError (*listen_t) (BtIO *io, BtIOFunc func);
 
50
 
 
51
struct hci_cmd_data {
 
52
        bt_hci_result_t         cb;
 
53
        uint16_t                handle;
 
54
        uint16_t                ocf;
 
55
        gpointer                caller_data;
 
56
};
 
57
 
 
58
int set_nonblocking(int fd)
 
59
{
 
60
        long arg;
 
61
 
 
62
        arg = fcntl(fd, F_GETFL);
 
63
        if (arg < 0)
 
64
                return -errno;
 
65
 
 
66
        /* Return if already nonblocking */
 
67
        if (arg & O_NONBLOCK)
 
68
                return 0;
 
69
 
 
70
        arg |= O_NONBLOCK;
 
71
        if (fcntl(fd, F_SETFL, arg) < 0)
 
72
                return -errno;
 
73
 
 
74
        return 0;
 
75
}
 
76
 
 
77
struct io_context {
 
78
        int                     fd;
 
79
        GIOChannel              *io;
 
80
        BtIOFunc                func;
 
81
        bt_io_callback_t        cb;
 
82
        resolver_t              resolver;
 
83
        gpointer                user_data;
 
84
};
 
85
 
 
86
struct bt_io {
 
87
        char                    src[18];
 
88
        char                    dst[18];
 
89
        guint32                 flags;
 
90
        guint8                  channel;
 
91
        guint16                 psm;
 
92
        guint16                 mtu;
 
93
        BtIOTransport           type;
 
94
        connect_t               connect;
 
95
        listen_t                listen;
 
96
        struct io_context       *io_ctxt;
 
97
        int                     refcount;
 
98
};
 
99
 
 
100
struct search_context {
 
101
        bdaddr_t                src;
 
102
        bdaddr_t                dst;
 
103
        sdp_session_t           *session;
 
104
        bt_callback_t           cb;
 
105
        bt_destroy_t            destroy;
 
106
        gpointer                user_data;
 
107
        uuid_t                  uuid;
 
108
};
 
109
 
 
110
static GSList *context_list = NULL;
 
111
 
 
112
static void search_context_cleanup(struct search_context *ctxt)
 
113
{
 
114
        context_list = g_slist_remove(context_list, ctxt);
 
115
 
 
116
        if (ctxt->destroy)
 
117
                ctxt->destroy(ctxt->user_data);
 
118
 
 
119
        g_free(ctxt);
 
120
}
 
121
 
 
122
static void search_completed_cb(uint8_t type, uint16_t status,
 
123
                        uint8_t *rsp, size_t size, void *user_data)
 
124
{
 
125
        struct search_context *ctxt = user_data;
 
126
        sdp_list_t *recs = NULL;
 
127
        int scanned, seqlen = 0, bytesleft = size;
 
128
        uint8_t dataType;
 
129
        int err = 0;
 
130
 
 
131
        if (status || type != SDP_SVC_SEARCH_ATTR_RSP) {
 
132
                err = -EPROTO;
 
133
                goto done;
 
134
        }
 
135
 
 
136
        scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen);
 
137
        if (!scanned || !seqlen)
 
138
                goto done;
 
139
 
 
140
        rsp += scanned;
 
141
        bytesleft -= scanned;
 
142
        do {
 
143
                sdp_record_t *rec;
 
144
                int recsize;
 
145
 
 
146
                recsize = 0;
 
147
                rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
 
148
                if (!rec)
 
149
                        break;
 
150
 
 
151
                if (!recsize) {
 
152
                        sdp_record_free(rec);
 
153
                        break;
 
154
                }
 
155
 
 
156
                scanned += recsize;
 
157
                rsp += recsize;
 
158
                bytesleft -= recsize;
 
159
 
 
160
                recs = sdp_list_append(recs, rec);
 
161
        } while (scanned < size && bytesleft > 0);
 
162
 
 
163
done:
 
164
        sdp_close(ctxt->session);
 
165
 
 
166
        if (ctxt->cb)
 
167
                ctxt->cb(recs, err, ctxt->user_data);
 
168
 
 
169
        if (recs)
 
170
                sdp_list_free(recs, (sdp_free_func_t) sdp_record_free);
 
171
 
 
172
        search_context_cleanup(ctxt);
 
173
}
 
174
 
 
175
static gboolean search_process_cb(GIOChannel *chan,
 
176
                        GIOCondition cond, void *user_data)
 
177
{
 
178
        struct search_context *ctxt = user_data;
 
179
        int err = 0;
 
180
 
 
181
        if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
 
182
                err = EIO;
 
183
                goto failed;
 
184
        }
 
185
 
 
186
        if (sdp_process(ctxt->session) < 0)
 
187
                goto failed;
 
188
 
 
189
        return TRUE;
 
190
 
 
191
failed:
 
192
        if (err) {
 
193
                sdp_close(ctxt->session);
 
194
 
 
195
                if (ctxt->cb)
 
196
                        ctxt->cb(NULL, err, ctxt->user_data);
 
197
 
 
198
                search_context_cleanup(ctxt);
 
199
        }
 
200
 
 
201
        return FALSE;
 
202
}
 
203
 
 
204
static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user_data)
 
205
{
 
206
        struct search_context *ctxt = user_data;
 
207
        sdp_list_t *search, *attrids;
 
208
        uint32_t range = 0x0000ffff;
 
209
        socklen_t len;
 
210
        int sk, err = 0;
 
211
 
 
212
        sk = g_io_channel_unix_get_fd(chan);
 
213
 
 
214
        len = sizeof(err);
 
215
        if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
 
216
                err = errno;
 
217
                goto failed;
 
218
        }
 
219
 
 
220
        if (err != 0)
 
221
                goto failed;
 
222
 
 
223
        if (sdp_set_notify(ctxt->session, search_completed_cb, ctxt) < 0) {
 
224
                err = EIO;
 
225
                goto failed;
 
226
        }
 
227
 
 
228
        search = sdp_list_append(NULL, &ctxt->uuid);
 
229
        attrids = sdp_list_append(NULL, &range);
 
230
        if (sdp_service_search_attr_async(ctxt->session,
 
231
                                search, SDP_ATTR_REQ_RANGE, attrids) < 0) {
 
232
                sdp_list_free(attrids, NULL);
 
233
                sdp_list_free(search, NULL);
 
234
                err = EIO;
 
235
                goto failed;
 
236
        }
 
237
 
 
238
        sdp_list_free(attrids, NULL);
 
239
        sdp_list_free(search, NULL);
 
240
 
 
241
        /* Set callback responsible for update the internal SDP transaction */
 
242
        g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 
243
                        search_process_cb, ctxt);
 
244
        return FALSE;
 
245
 
 
246
failed:
 
247
        sdp_close(ctxt->session);
 
248
 
 
249
        if (ctxt->cb)
 
250
                ctxt->cb(NULL, -err, ctxt->user_data);
 
251
 
 
252
        search_context_cleanup(ctxt);
 
253
 
 
254
        return FALSE;
 
255
}
 
256
 
 
257
static int create_search_context(struct search_context **ctxt,
 
258
                                const bdaddr_t *src, const bdaddr_t *dst,
 
259
                                uuid_t *uuid)
 
260
{
 
261
        sdp_session_t *s;
 
262
        GIOChannel *chan;
 
263
 
 
264
        if (!ctxt)
 
265
                return -EINVAL;
 
266
 
 
267
        s = sdp_connect(src, dst, SDP_NON_BLOCKING);
 
268
        if (!s)
 
269
                return -errno;
 
270
 
 
271
        *ctxt = g_try_malloc0(sizeof(struct search_context));
 
272
        if (!*ctxt) {
 
273
                sdp_close(s);
 
274
                return -ENOMEM;
 
275
        }
 
276
 
 
277
        bacpy(&(*ctxt)->src, src);
 
278
        bacpy(&(*ctxt)->dst, dst);
 
279
        (*ctxt)->session = s;
 
280
        (*ctxt)->uuid = *uuid;
 
281
 
 
282
        chan = g_io_channel_unix_new(sdp_get_socket(s));
 
283
        g_io_add_watch(chan, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 
284
                        connect_watch, *ctxt);
 
285
        g_io_channel_unref(chan);
 
286
 
 
287
        return 0;
 
288
}
 
289
 
 
290
int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
 
291
                        uuid_t *uuid, bt_callback_t cb, void *user_data,
 
292
                        bt_destroy_t destroy)
 
293
{
 
294
        struct search_context *ctxt = NULL;
 
295
        int err;
 
296
 
 
297
        if (!cb)
 
298
                return -EINVAL;
 
299
 
 
300
        err = create_search_context(&ctxt, src, dst, uuid);
 
301
        if (err < 0)
 
302
                return err;
 
303
 
 
304
        ctxt->cb        = cb;
 
305
        ctxt->destroy   = destroy;
 
306
        ctxt->user_data = user_data;
 
307
 
 
308
        context_list = g_slist_append(context_list, ctxt);
 
309
 
 
310
        return 0;
 
311
}
 
312
 
 
313
int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst,
 
314
                bt_callback_t cb, void *user_data, bt_destroy_t destroy)
 
315
{
 
316
        uuid_t uuid;
 
317
 
 
318
        sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP);
 
319
 
 
320
        return bt_search_service(src, dst, &uuid, cb, user_data, destroy);
 
321
}
 
322
 
 
323
static int find_by_bdaddr(const void *data, const void *user_data)
 
324
{
 
325
        const struct search_context *ctxt = data, *search = user_data;
 
326
 
 
327
        return (bacmp(&ctxt->dst, &search->dst) &&
 
328
                                        bacmp(&ctxt->src, &search->src));
 
329
}
 
330
 
 
331
int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst)
 
332
{
 
333
        struct search_context search, *ctxt;
 
334
        GSList *match;
 
335
 
 
336
        memset(&search, 0, sizeof(search));
 
337
        bacpy(&search.src, src);
 
338
        bacpy(&search.dst, dst);
 
339
 
 
340
        /* Ongoing SDP Discovery */
 
341
        match = g_slist_find_custom(context_list, &search, find_by_bdaddr);
 
342
        if (!match)
 
343
                return -ENODATA;
 
344
 
 
345
        ctxt = match->data;
 
346
        if (!ctxt->session)
 
347
                return -ENOTCONN;
 
348
 
 
349
        close(ctxt->session->sock);
 
350
        return 0;
 
351
}
 
352
 
 
353
char *bt_uuid2string(uuid_t *uuid)
 
354
{
 
355
        gchar *str;
 
356
        uuid_t uuid128;
 
357
        unsigned int data0;
 
358
        unsigned short data1;
 
359
        unsigned short data2;
 
360
        unsigned short data3;
 
361
        unsigned int data4;
 
362
        unsigned short data5;
 
363
 
 
364
        if (!uuid)
 
365
                return NULL;
 
366
 
 
367
        switch (uuid->type) {
 
368
        case SDP_UUID16:
 
369
                sdp_uuid16_to_uuid128(&uuid128, uuid);
 
370
                break;
 
371
        case SDP_UUID32:
 
372
                sdp_uuid32_to_uuid128(&uuid128, uuid);
 
373
                break;
 
374
        case SDP_UUID128:
 
375
                memcpy(&uuid128, uuid, sizeof(uuid_t));
 
376
                break;
 
377
        default:
 
378
                /* Type of UUID unknown */
 
379
                return NULL;
 
380
        }
 
381
 
 
382
        memcpy(&data0, &uuid128.value.uuid128.data[0], 4);
 
383
        memcpy(&data1, &uuid128.value.uuid128.data[4], 2);
 
384
        memcpy(&data2, &uuid128.value.uuid128.data[6], 2);
 
385
        memcpy(&data3, &uuid128.value.uuid128.data[8], 2);
 
386
        memcpy(&data4, &uuid128.value.uuid128.data[10], 4);
 
387
        memcpy(&data5, &uuid128.value.uuid128.data[14], 2);
 
388
 
 
389
        str = g_try_malloc0(MAX_LEN_UUID_STR);
 
390
        if (!str)
 
391
                return NULL;
 
392
 
 
393
        sprintf(str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
 
394
                        g_ntohl(data0), g_ntohs(data1),
 
395
                        g_ntohs(data2), g_ntohs(data3),
 
396
                        g_ntohl(data4), g_ntohs(data5));
 
397
 
 
398
        return str;
 
399
}
 
400
 
 
401
static struct {
 
402
        const char      *name;
 
403
        uint16_t        class;
 
404
} bt_services[] = {
 
405
        { "vcp",        VIDEO_CONF_SVCLASS_ID           },
 
406
        { "pbap",       PBAP_SVCLASS_ID                 },
 
407
        { "sap",        SAP_SVCLASS_ID                  },
 
408
        { "ftp",        OBEX_FILETRANS_SVCLASS_ID       },
 
409
        { "bpp",        BASIC_PRINTING_SVCLASS_ID       },
 
410
        { "bip",        IMAGING_SVCLASS_ID              },
 
411
        { "synch",      IRMC_SYNC_SVCLASS_ID            },
 
412
        { "dun",        DIALUP_NET_SVCLASS_ID           },
 
413
        { "opp",        OBEX_OBJPUSH_SVCLASS_ID         },
 
414
        { "fax",        FAX_SVCLASS_ID                  },
 
415
        { "spp",        SERIAL_PORT_SVCLASS_ID          },
 
416
        { "hsp",        HEADSET_SVCLASS_ID              },
 
417
        { "hfp",        HANDSFREE_SVCLASS_ID            },
 
418
        { }
 
419
};
 
420
 
 
421
uint16_t bt_string2class(const char *pattern)
 
422
{
 
423
        int i;
 
424
 
 
425
        for (i = 0; bt_services[i].name; i++) {
 
426
                if (strcasecmp(bt_services[i].name, pattern) == 0)
 
427
                        return bt_services[i].class;
 
428
        }
 
429
 
 
430
        return 0;
 
431
}
 
432
 
 
433
int bt_string2uuid(uuid_t *uuid, const char *string)
 
434
{
 
435
        uint32_t data0, data4;
 
436
        uint16_t data1, data2, data3, data5;
 
437
 
 
438
        if (strlen(string) == 36 &&
 
439
                        string[8] == '-' &&
 
440
                        string[13] == '-' &&
 
441
                        string[18] == '-' &&
 
442
                        string[23] == '-' &&
 
443
                        sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
 
444
                                &data0, &data1, &data2, &data3, &data4, &data5) == 6) {
 
445
                uint8_t val[16];
 
446
 
 
447
                data0 = g_htonl(data0);
 
448
                data1 = g_htons(data1);
 
449
                data2 = g_htons(data2);
 
450
                data3 = g_htons(data3);
 
451
                data4 = g_htonl(data4);
 
452
                data5 = g_htons(data5);
 
453
 
 
454
                memcpy(&val[0], &data0, 4);
 
455
                memcpy(&val[4], &data1, 2);
 
456
                memcpy(&val[6], &data2, 2);
 
457
                memcpy(&val[8], &data3, 2);
 
458
                memcpy(&val[10], &data4, 4);
 
459
                memcpy(&val[14], &data5, 2);
 
460
 
 
461
                sdp_uuid128_create(uuid, val);
 
462
 
 
463
                return 0;
 
464
        } else {
 
465
                uint16_t class = bt_string2class(string);
 
466
                if (class) {
 
467
                        sdp_uuid16_create(uuid, class);
 
468
                        return 0;
 
469
                }
 
470
        }
 
471
 
 
472
        return -1;
 
473
}
 
474
 
 
475
gchar *bt_list2string(GSList *list)
 
476
{
 
477
        GSList *l;
 
478
        gchar *str, *tmp;
 
479
 
 
480
        if (!list)
 
481
                return NULL;
 
482
 
 
483
        str = g_strdup((const gchar *) list->data);
 
484
 
 
485
        for (l = list->next; l; l = l->next) {
 
486
                tmp = g_strconcat(str, " " , (const gchar *) l->data, NULL);
 
487
                g_free(str);
 
488
                str = tmp;
 
489
        }
 
490
 
 
491
        return str;
 
492
}
 
493
 
 
494
GSList *bt_string2list(const gchar *str)
 
495
{
 
496
        GSList *l = NULL;
 
497
        gchar **uuids;
 
498
        int i = 0;
 
499
 
 
500
        if (!str)
 
501
                return NULL;
 
502
 
 
503
        /* FIXME: eglib doesn't support g_strsplit */
 
504
        uuids = g_strsplit(str, " ", 0);
 
505
        if (!uuids)
 
506
                return NULL;
 
507
 
 
508
        while (uuids[i]) {
 
509
                l = g_slist_append(l, uuids[i]);
 
510
                i++;
 
511
        }
 
512
 
 
513
        g_free(uuids);
 
514
 
 
515
        return l;
 
516
}
 
517
 
 
518
static inline int resolve_names(int fd, struct sockaddr *host,
 
519
                        struct sockaddr *peer, socklen_t len)
 
520
{
 
521
        int err;
 
522
        socklen_t namelen;
 
523
 
 
524
        namelen = len;
 
525
        memset(host, 0, len);
 
526
        err = getsockname(fd, host, &namelen);
 
527
        if (err < 0)
 
528
                return err;
 
529
 
 
530
        namelen = len;
 
531
        memset(peer, 0, len);
 
532
        err = getpeername(fd, peer, &namelen);
 
533
        if (err < 0)
 
534
                return err;
 
535
 
 
536
        return 0;
 
537
}
 
538
 
 
539
static int rfcomm_resolver(int fd, char *src, char *dst)
 
540
{
 
541
        struct sockaddr_rc host, peer;
 
542
        socklen_t len;
 
543
        int err;
 
544
 
 
545
        len = sizeof(host);
 
546
        err = resolve_names(fd, (struct sockaddr *) &host,
 
547
                        (struct sockaddr *) &peer, len);
 
548
        if (err < 0)
 
549
                return err;
 
550
 
 
551
        ba2str(&host.rc_bdaddr, src);
 
552
        ba2str(&peer.rc_bdaddr, dst);
 
553
 
 
554
        return 0;
 
555
}
 
556
 
 
557
static int l2cap_resolver(int fd, char *src, char *dst)
 
558
{
 
559
        struct sockaddr_l2 host, peer;
 
560
        socklen_t len;
 
561
        int err;
 
562
 
 
563
        len = sizeof(host);
 
564
        err = resolve_names(fd, (struct sockaddr *) &host,
 
565
                        (struct sockaddr *) &peer, len);
 
566
        if (err < 0)
 
567
                return err;
 
568
 
 
569
        ba2str(&host.l2_bdaddr, src);
 
570
        ba2str(&peer.l2_bdaddr, dst);
 
571
 
 
572
        return 0;
 
573
}
 
574
 
 
575
static int sco_resolver(int fd, char *src, char *dst)
 
576
{
 
577
        struct sockaddr_sco host, peer;
 
578
        socklen_t len;
 
579
        int err;
 
580
 
 
581
        len = sizeof(host);
 
582
        err = resolve_names(fd, (struct sockaddr *) &host,
 
583
                        (struct sockaddr *) &peer, len);
 
584
        if (err < 0)
 
585
                return err;
 
586
 
 
587
        ba2str(&host.sco_bdaddr, src);
 
588
        ba2str(&peer.sco_bdaddr, dst);
 
589
 
 
590
        return 0;
 
591
}
 
592
 
 
593
static gboolean listen_cb(GIOChannel *chan, GIOCondition cond,
 
594
                gpointer user_data)
 
595
{
 
596
        BtIO *io = user_data;
 
597
        struct io_context *io_ctxt = io->io_ctxt;
 
598
        int fd, err = 0;
 
599
        GIOChannel *gio;
 
600
        struct sockaddr addr;
 
601
        socklen_t len;
 
602
        bdaddr_t src, dst;
 
603
 
 
604
        if (cond & G_IO_NVAL)
 
605
                return FALSE;
 
606
 
 
607
        if (cond & (G_IO_HUP | G_IO_ERR)) {
 
608
                g_io_channel_close(chan);
 
609
                g_io_channel_unref(chan);
 
610
                g_free(io_ctxt);
 
611
                return FALSE;
 
612
        }
 
613
 
 
614
        len = sizeof(addr);
 
615
        memset(&addr, 0, len);
 
616
        fd = accept(io_ctxt->fd, &addr, &len);
 
617
        if (fd < 0)
 
618
                goto drop;
 
619
 
 
620
        if (io_ctxt->resolver) {
 
621
                err = io_ctxt->resolver(fd, io->src, io->dst);
 
622
                if (err < 0) {
 
623
                        close(fd);
 
624
                        goto drop;
 
625
                }
 
626
        }
 
627
 
 
628
        gio = g_io_channel_unix_new(fd);
 
629
        if (!gio)
 
630
                err = -ENOMEM;
 
631
 
 
632
        if (io_ctxt->func)
 
633
                io_ctxt->func(io, err, gio, io_ctxt->user_data);
 
634
        if (io_ctxt->cb) {
 
635
                str2ba(io->src, &src);
 
636
                str2ba(io->dst, &dst);
 
637
                io_ctxt->cb(gio, err, &src, &dst, io_ctxt->user_data);
 
638
        }
 
639
 
 
640
        return TRUE;
 
641
 
 
642
drop:
 
643
        if (io_ctxt->func)
 
644
                io_ctxt->func(io, -errno, NULL, io_ctxt->user_data);
 
645
        if (io_ctxt->cb)
 
646
                io_ctxt->cb(NULL, err, NULL, NULL, io_ctxt->user_data);
 
647
 
 
648
        return TRUE;
 
649
}
 
650
 
 
651
static int transport_listen(BtIO *io)
 
652
{
 
653
        struct io_context *io_ctxt = io->io_ctxt;
 
654
        int err;
 
655
 
 
656
        err = listen(io_ctxt->fd, 5);
 
657
        if (err < 0)
 
658
                return -errno;
 
659
 
 
660
        io_ctxt->io = g_io_channel_unix_new(io_ctxt->fd);
 
661
        if (!io_ctxt->io)
 
662
                return -ENOMEM;
 
663
 
 
664
        g_io_add_watch(io_ctxt->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 
665
                        (GIOFunc) listen_cb, io);
 
666
 
 
667
        return 0;
 
668
}
 
669
 
 
670
static gboolean connect_cb(GIOChannel *gio, GIOCondition cond,
 
671
                                gpointer user_data)
 
672
{
 
673
        BtIO *io = user_data;
 
674
        struct io_context *io_ctxt = io->io_ctxt;
 
675
        int err = 0, ret;
 
676
        socklen_t len;
 
677
        bdaddr_t src, dst;
 
678
 
 
679
        if (cond & G_IO_NVAL)
 
680
                return FALSE;
 
681
 
 
682
        len = sizeof(ret);
 
683
        if (getsockopt(io_ctxt->fd, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
 
684
                err = -errno;
 
685
                goto done;
 
686
        }
 
687
 
 
688
        if (ret != 0) {
 
689
                err = -ret;
 
690
                goto done;
 
691
        }
 
692
 
 
693
        if (io_ctxt->resolver) {
 
694
                err = io_ctxt->resolver(io_ctxt->fd, io->src, io->dst);
 
695
                if (err < 0)
 
696
                        goto done;
 
697
        }
 
698
 
 
699
        io_ctxt->io = NULL;
 
700
 
 
701
done:
 
702
        if (io_ctxt->func)
 
703
                io_ctxt->func(io, err, gio, io_ctxt->user_data);
 
704
        if (io_ctxt->cb) {
 
705
                str2ba(io->src, &src);
 
706
                str2ba(io->dst, &dst);
 
707
                io_ctxt->cb(gio, err, &src, &dst, io_ctxt->user_data);
 
708
        }
 
709
        if (io_ctxt->io) {
 
710
                g_io_channel_close(io_ctxt->io);
 
711
                g_io_channel_unref(io_ctxt->io);
 
712
        }
 
713
        g_free(io_ctxt);
 
714
 
 
715
        return FALSE;
 
716
}
 
717
 
 
718
static int transport_connect(BtIO *io, struct sockaddr *addr,
 
719
                socklen_t addrlen)
 
720
{
 
721
        struct io_context *io_ctxt = io->io_ctxt;
 
722
        int err;
 
723
 
 
724
        io_ctxt->io = g_io_channel_unix_new(io_ctxt->fd);
 
725
        if (!io_ctxt->io)
 
726
                return -ENOMEM;
 
727
 
 
728
        err = g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL);
 
729
        if (err != G_IO_STATUS_NORMAL)
 
730
                return -EPERM;
 
731
 
 
732
        err = connect(io_ctxt->fd, addr, addrlen);
 
733
        if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
 
734
                return -errno;
 
735
 
 
736
        g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 
737
                        (GIOFunc) connect_cb, io);
 
738
 
 
739
        return 0;
 
740
}
 
741
 
 
742
static int sco_bind(struct io_context *io_ctxt, const char *address,
 
743
                        uint16_t mtu, struct sockaddr_sco *addr)
 
744
{
 
745
        int err;
 
746
        struct sco_options sco_opt;
 
747
 
 
748
        io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
 
749
        if (io_ctxt->fd < 0)
 
750
                return -errno;
 
751
 
 
752
        memset(addr, 0, sizeof(*addr));
 
753
        addr->sco_family = AF_BLUETOOTH;
 
754
        str2ba(address, &addr->sco_bdaddr);
 
755
 
 
756
        err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr));
 
757
        if (err < 0) {
 
758
                close(io_ctxt->fd);
 
759
                return -errno;
 
760
        }
 
761
 
 
762
        if (mtu) {
 
763
                socklen_t olen = sizeof(sco_opt);
 
764
                memset(&sco_opt, 0, olen);
 
765
                getsockopt(io_ctxt->fd, SOL_SCO, SCO_OPTIONS, &sco_opt, &olen);
 
766
                sco_opt.mtu = mtu;
 
767
                setsockopt(io_ctxt->fd, SOL_SCO, SCO_OPTIONS, &sco_opt,
 
768
                                sizeof(sco_opt));
 
769
        }
 
770
 
 
771
        return 0;
 
772
}
 
773
 
 
774
static BtIOError sco_connect(BtIO *io, BtIOFunc func)
 
775
{
 
776
        struct io_context *io_ctxt = io->io_ctxt;
 
777
        struct sockaddr_sco addr;
 
778
        int sk, err;
 
779
 
 
780
        io_ctxt->func = func;
 
781
 
 
782
        err = sco_bind(io_ctxt, io->src, 0, &addr);
 
783
        if (err < 0)
 
784
                return BT_IO_FAILED;
 
785
 
 
786
        memset(&addr, 0, sizeof(addr));
 
787
        addr.sco_family = AF_BLUETOOTH;
 
788
        str2ba(io->dst, &addr.sco_bdaddr);
 
789
 
 
790
        err = transport_connect(io, (struct sockaddr *) &addr,
 
791
                                sizeof(addr));
 
792
        if (err < 0) {
 
793
                close(sk);
 
794
                return BT_IO_FAILED;
 
795
        }
 
796
 
 
797
        return BT_IO_SUCCESS;
 
798
}
 
799
 
 
800
static int l2cap_bind(struct io_context *io_ctxt, const char *address,
 
801
                        uint16_t psm, uint16_t mtu, uint32_t flags,
 
802
                        struct sockaddr_l2 *addr)
 
803
{
 
804
        int err;
 
805
        struct l2cap_options l2o;
 
806
 
 
807
        io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
 
808
        if (io_ctxt->fd < 0)
 
809
                return -errno;
 
810
 
 
811
        memset(addr, 0, sizeof(*addr));
 
812
        addr->l2_family = AF_BLUETOOTH;
 
813
        str2ba(address, &addr->l2_bdaddr);
 
814
        addr->l2_psm = htobs(psm);
 
815
 
 
816
        err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr));
 
817
        if (err < 0) {
 
818
                close(io_ctxt->fd);
 
819
                return -errno;
 
820
        }
 
821
 
 
822
        if (mtu) {
 
823
                socklen_t olen = sizeof(l2o);
 
824
                memset(&l2o, 0, olen);
 
825
                getsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen);
 
826
                l2o.imtu = l2o.omtu = mtu;
 
827
                setsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o));
 
828
        }
 
829
 
 
830
        if (flags) {
 
831
                int opt = flags;
 
832
                err = setsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_LM, &opt,
 
833
                                sizeof(opt));
 
834
                if (err < 0) {
 
835
                        close(io_ctxt->fd);
 
836
                        return -errno;
 
837
                }
 
838
        }
 
839
 
 
840
        return 0;
 
841
}
 
842
 
 
843
static BtIOError l2cap_listen(BtIO *io, BtIOFunc func)
 
844
{
 
845
        struct io_context *io_ctxt = io->io_ctxt;
 
846
        struct sockaddr_l2 addr;
 
847
        BtIOError err;
 
848
 
 
849
        io_ctxt->func = func;
 
850
 
 
851
        err = l2cap_bind(io_ctxt, io->src, io->psm, io->mtu, io->flags, &addr);
 
852
        if (err < 0)
 
853
                return err;
 
854
 
 
855
        err = transport_listen(io);
 
856
        if (err < 0) {
 
857
                close(io_ctxt->fd);
 
858
                return err;
 
859
        }
 
860
 
 
861
        return BT_IO_SUCCESS;
 
862
}
 
863
 
 
864
static BtIOError l2cap_connect(BtIO *io, BtIOFunc func)
 
865
{
 
866
        struct io_context *io_ctxt = io->io_ctxt;
 
867
        struct sockaddr_l2 l2a;
 
868
        BtIOError err;
 
869
 
 
870
        io_ctxt->func = func;
 
871
 
 
872
        err = l2cap_bind(io_ctxt, io->src, 0, io->mtu, 0, &l2a);
 
873
        if (err < 0)
 
874
                return err;
 
875
 
 
876
        memset(&l2a, 0, sizeof(l2a));
 
877
        l2a.l2_family = AF_BLUETOOTH;
 
878
        str2ba(io->dst, &l2a.l2_bdaddr);
 
879
        l2a.l2_psm = htobs(io->psm);
 
880
 
 
881
        err = transport_connect(io, (struct sockaddr *) &l2a,
 
882
                                sizeof(l2a));
 
883
        if (err < 0) {
 
884
                close(io_ctxt->fd);
 
885
                return err;
 
886
        }
 
887
 
 
888
        return BT_IO_SUCCESS;
 
889
}
 
890
 
 
891
static BtIOError rfcomm_bind(struct io_context *io_ctxt, const char *address,
 
892
                                uint8_t channel, uint32_t flags,
 
893
                                struct sockaddr_rc *addr)
 
894
{
 
895
        BtIOError err;
 
896
 
 
897
        io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
 
898
        if (io_ctxt->fd < 0)
 
899
                return BT_IO_FAILED;
 
900
 
 
901
 
 
902
        memset(addr, 0, sizeof(*addr));
 
903
        addr->rc_family = AF_BLUETOOTH;
 
904
        str2ba(address, &addr->rc_bdaddr);
 
905
        addr->rc_channel = channel;
 
906
 
 
907
        err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr));
 
908
        if (err < 0) {
 
909
                close(io_ctxt->fd);
 
910
                return BT_IO_FAILED;
 
911
        }
 
912
 
 
913
        if (flags) {
 
914
                int opt = flags;
 
915
                err = setsockopt(io_ctxt->fd, SOL_RFCOMM, RFCOMM_LM, &opt,
 
916
                                sizeof(opt));
 
917
                if (err < 0) {
 
918
                        close(io_ctxt->fd);
 
919
                        return BT_IO_FAILED;
 
920
                }
 
921
        }
 
922
 
 
923
        return BT_IO_SUCCESS;
 
924
}
 
925
 
 
926
static BtIOError rfcomm_listen(BtIO *io, BtIOFunc func)
 
927
{
 
928
        struct io_context *io_ctxt = io->io_ctxt;
 
929
        struct sockaddr_rc addr;
 
930
        socklen_t sa_len;
 
931
        BtIOError err;
 
932
 
 
933
        io_ctxt->func = func;
 
934
 
 
935
        err = rfcomm_bind(io_ctxt, io->src, io->channel, io->flags, &addr);
 
936
        if (err < 0)
 
937
                return err;
 
938
 
 
939
        err = transport_listen(io);
 
940
        if (err < 0) {
 
941
                close(io_ctxt->fd);
 
942
                return err;
 
943
        }
 
944
 
 
945
        sa_len = sizeof(struct sockaddr_rc);
 
946
        memset(&addr, 0, sizeof(addr));
 
947
        if (getsockname(io_ctxt->fd, (struct sockaddr *) &addr, &sa_len) < 0) {
 
948
                err = -errno;
 
949
                close(io_ctxt->fd);
 
950
                return err;
 
951
        }
 
952
 
 
953
        io->channel = addr.rc_channel;
 
954
 
 
955
        return BT_IO_SUCCESS;
 
956
}
 
957
 
 
958
static BtIOError rfcomm_connect(BtIO *io, BtIOFunc func)
 
959
{
 
960
        struct io_context *io_ctxt = io->io_ctxt;
 
961
        struct sockaddr_rc addr;
 
962
        BtIOError err;
 
963
 
 
964
        io_ctxt->func = func;
 
965
 
 
966
        err = rfcomm_bind(io_ctxt, io->src, 0, 0, &addr);
 
967
        if (err < 0)
 
968
                return err;
 
969
 
 
970
        memset(&addr, 0, sizeof(addr));
 
971
        addr.rc_family = AF_BLUETOOTH;
 
972
        str2ba(io->dst, &addr.rc_bdaddr);
 
973
        addr.rc_channel = io->channel;
 
974
 
 
975
        err = transport_connect(io, (struct sockaddr *) &addr,
 
976
                                sizeof(addr));
 
977
        if (err < 0) {
 
978
                close(io_ctxt->fd);
 
979
                return err;
 
980
        }
 
981
 
 
982
        return BT_IO_SUCCESS;
 
983
}
 
984
 
 
985
static BtIOError sco_listen(BtIO *io, BtIOFunc func)
 
986
{
 
987
        struct io_context *io_ctxt = io->io_ctxt;
 
988
        struct sockaddr_sco addr;
 
989
        BtIOError err;
 
990
 
 
991
        io_ctxt->func = func;
 
992
 
 
993
        err = sco_bind(io_ctxt, io->src, io->mtu, &addr);
 
994
        if (err < 0)
 
995
                return err;
 
996
 
 
997
        err = transport_listen(io);
 
998
        if (err < 0) {
 
999
                close(io_ctxt->fd);
 
1000
                return err;
 
1001
        }
 
1002
 
 
1003
        return BT_IO_SUCCESS;
 
1004
}
 
1005
 
 
1006
static gboolean hci_event_watch(GIOChannel *io,
 
1007
                        GIOCondition cond, gpointer user_data)
 
1008
{
 
1009
        unsigned char buf[HCI_MAX_EVENT_SIZE], *body;
 
1010
        struct hci_cmd_data *cmd = user_data;
 
1011
        evt_cmd_status *evt_status;
 
1012
        evt_auth_complete *evt_auth;
 
1013
        evt_encrypt_change *evt_enc;
 
1014
        hci_event_hdr *hdr;
 
1015
        set_conn_encrypt_cp cp;
 
1016
        int dd;
 
1017
        uint16_t ocf;
 
1018
        uint8_t status = HCI_OE_POWER_OFF;
 
1019
 
 
1020
        if (cond & G_IO_NVAL) {
 
1021
                cmd->cb(status, cmd->caller_data);
 
1022
                return FALSE;
 
1023
        }
 
1024
 
 
1025
        if (cond & (G_IO_ERR | G_IO_HUP))
 
1026
                goto failed;
 
1027
 
 
1028
        dd = g_io_channel_unix_get_fd(io);
 
1029
 
 
1030
        if (read(dd, buf, sizeof(buf)) < 0)
 
1031
                goto failed;
 
1032
 
 
1033
        hdr = (hci_event_hdr *) (buf + 1);
 
1034
        body = buf + (1 + HCI_EVENT_HDR_SIZE);
 
1035
 
 
1036
        switch (hdr->evt) {
 
1037
        case EVT_CMD_STATUS:
 
1038
                evt_status = (evt_cmd_status *) body;
 
1039
                ocf = cmd_opcode_ocf(evt_status->opcode);
 
1040
                if (ocf != cmd->ocf)
 
1041
                        return TRUE;
 
1042
                switch (ocf) {
 
1043
                case OCF_AUTH_REQUESTED:
 
1044
                case OCF_SET_CONN_ENCRYPT:
 
1045
                        if (evt_status->status != 0) {
 
1046
                                /* Baseband rejected command */
 
1047
                                status = evt_status->status;
 
1048
                                goto failed;
 
1049
                        }
 
1050
                        break;
 
1051
                default:
 
1052
                        return TRUE;
 
1053
                }
 
1054
                /* Wait for the next event */
 
1055
                return TRUE;
 
1056
        case EVT_AUTH_COMPLETE:
 
1057
                evt_auth = (evt_auth_complete *) body;
 
1058
                if (evt_auth->handle != cmd->handle) {
 
1059
                        /* Skipping */
 
1060
                        return TRUE;
 
1061
                }
 
1062
 
 
1063
                if (evt_auth->status != 0x00) {
 
1064
                        status = evt_auth->status;
 
1065
                        /* Abort encryption */
 
1066
                        goto failed;
 
1067
                }
 
1068
 
 
1069
                memset(&cp, 0, sizeof(cp));
 
1070
                cp.handle  = cmd->handle;
 
1071
                cp.encrypt = 1;
 
1072
 
 
1073
                cmd->ocf = OCF_SET_CONN_ENCRYPT;
 
1074
 
 
1075
                if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT,
 
1076
                                        SET_CONN_ENCRYPT_CP_SIZE, &cp) < 0) {
 
1077
                        status = HCI_COMMAND_DISALLOWED;
 
1078
                        goto failed;
 
1079
                }
 
1080
                /* Wait for encrypt change event */
 
1081
                return TRUE;
 
1082
        case EVT_ENCRYPT_CHANGE:
 
1083
                evt_enc = (evt_encrypt_change *) body;
 
1084
                if (evt_enc->handle != cmd->handle)
 
1085
                        return TRUE;
 
1086
 
 
1087
                /* Procedure finished: reporting status */
 
1088
                status = evt_enc->status;
 
1089
                break;
 
1090
        default:
 
1091
                /* Skipping */
 
1092
                return TRUE;
 
1093
        }
 
1094
 
 
1095
failed:
 
1096
        cmd->cb(status, cmd->caller_data);
 
1097
        g_io_channel_close(io);
 
1098
 
 
1099
        return FALSE;
 
1100
}
 
1101
 
 
1102
int bt_acl_encrypt(const bdaddr_t *src, const bdaddr_t *dst,
 
1103
                        bt_hci_result_t cb, gpointer user_data)
 
1104
{
 
1105
        GIOChannel *io;
 
1106
        struct hci_cmd_data *cmd;
 
1107
        struct hci_conn_info_req *cr;
 
1108
        auth_requested_cp cp;
 
1109
        struct hci_filter nf;
 
1110
        int dd, dev_id, err;
 
1111
        char src_addr[18];
 
1112
        uint32_t link_mode;
 
1113
        uint16_t handle;
 
1114
 
 
1115
        ba2str(src, src_addr);
 
1116
        dev_id = hci_devid(src_addr);
 
1117
        if (dev_id < 0)
 
1118
                return -errno;
 
1119
 
 
1120
        dd = hci_open_dev(dev_id);
 
1121
        if (dd < 0)
 
1122
                return -errno;
 
1123
 
 
1124
        cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info));
 
1125
        cr->type = ACL_LINK;
 
1126
        bacpy(&cr->bdaddr, dst);
 
1127
 
 
1128
        err = ioctl(dd, HCIGETCONNINFO, cr);
 
1129
        link_mode = cr->conn_info->link_mode;
 
1130
        handle = cr->conn_info->handle;
 
1131
        g_free(cr);
 
1132
 
 
1133
        if (err < 0) {
 
1134
                err = errno;
 
1135
                goto failed;
 
1136
        }
 
1137
 
 
1138
        if (link_mode & HCI_LM_ENCRYPT) {
 
1139
                /* Already encrypted */
 
1140
                err = EALREADY;
 
1141
                goto failed;
 
1142
        }
 
1143
 
 
1144
        memset(&cp, 0, sizeof(cp));
 
1145
        cp.handle = htobs(handle);
 
1146
 
 
1147
        if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_AUTH_REQUESTED,
 
1148
                                AUTH_REQUESTED_CP_SIZE, &cp) < 0) {
 
1149
                err = errno;
 
1150
                goto failed;
 
1151
        }
 
1152
 
 
1153
        cmd = g_new0(struct hci_cmd_data, 1);
 
1154
        cmd->handle = handle;
 
1155
        cmd->ocf = OCF_AUTH_REQUESTED;
 
1156
        cmd->cb = cb;
 
1157
        cmd->caller_data = user_data;
 
1158
 
 
1159
        hci_filter_clear(&nf);
 
1160
        hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
 
1161
        hci_filter_set_event(EVT_CMD_STATUS, &nf);
 
1162
        hci_filter_set_event(EVT_AUTH_COMPLETE, &nf);
 
1163
        hci_filter_set_event(EVT_ENCRYPT_CHANGE, &nf);
 
1164
 
 
1165
        if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) {
 
1166
                err = errno;
 
1167
                goto failed;
 
1168
        }
 
1169
 
 
1170
        io = g_io_channel_unix_new(dd);
 
1171
        g_io_channel_set_close_on_unref(io, FALSE);
 
1172
        g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
 
1173
                        G_IO_HUP | G_IO_ERR | G_IO_NVAL | G_IO_IN,
 
1174
                        hci_event_watch, cmd, g_free);
 
1175
        g_io_channel_unref(io);
 
1176
 
 
1177
        return 0;
 
1178
 
 
1179
failed:
 
1180
        close(dd);
 
1181
 
 
1182
        return -err;
 
1183
}
 
1184
 
 
1185
static int create_io_context(struct io_context **io_ctxt, BtIOFunc func,
 
1186
                        gpointer cb, gpointer resolver, gpointer user_data)
 
1187
{
 
1188
        *io_ctxt = g_try_malloc0(sizeof(struct search_context));
 
1189
        if (!*io_ctxt)
 
1190
                return -ENOMEM;
 
1191
 
 
1192
        (*io_ctxt)->cb = cb;
 
1193
        (*io_ctxt)->func = func;
 
1194
        (*io_ctxt)->resolver = resolver;
 
1195
        (*io_ctxt)->user_data = user_data;
 
1196
 
 
1197
        return 0;
 
1198
}
 
1199
 
 
1200
static void io_context_cleanup(struct io_context *io_ctxt)
 
1201
{
 
1202
        if (io_ctxt->io) {
 
1203
                g_io_channel_close(io_ctxt->io);
 
1204
                g_io_channel_unref(io_ctxt->io);
 
1205
        }
 
1206
        g_free(io_ctxt);
 
1207
}
 
1208
 
 
1209
GIOChannel *rfcomm_listen_internal(const bdaddr_t *src, uint8_t *channel,
 
1210
                        uint32_t flags, bt_io_callback_t cb, void *user_data)
 
1211
{
 
1212
        BtIO *io;
 
1213
        BtIOError err;
 
1214
 
 
1215
        io = bt_io_create(BT_IO_RFCOMM, user_data, NULL);
 
1216
        if (!io)
 
1217
                return NULL;
 
1218
 
 
1219
        ba2str(src, io->src);
 
1220
        io->channel = *channel;
 
1221
        io->flags = flags;
 
1222
        io->io_ctxt->cb = cb;
 
1223
        err = bt_io_listen(io, NULL, NULL);
 
1224
        if (err != BT_IO_SUCCESS) {
 
1225
                bt_io_unref(io);
 
1226
                return NULL;
 
1227
        }
 
1228
 
 
1229
        *channel = io->channel;
 
1230
 
 
1231
        return io->io_ctxt->io;
 
1232
}
 
1233
 
 
1234
GIOChannel *bt_rfcomm_listen_allocate(const bdaddr_t *src, uint8_t *channel,
 
1235
                        uint32_t flags, bt_io_callback_t cb, void *user_data)
 
1236
{
 
1237
        if (!channel)
 
1238
                return NULL;
 
1239
 
 
1240
        *channel = 0;
 
1241
 
 
1242
        return rfcomm_listen_internal(src, channel, flags, cb, user_data);
 
1243
}
 
1244
 
 
1245
GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel,
 
1246
                        uint32_t flags, bt_io_callback_t cb, void *user_data)
 
1247
{
 
1248
        if (channel < 1 || channel > 30)
 
1249
                return NULL;
 
1250
 
 
1251
        return rfcomm_listen_internal(src, &channel, flags, cb, user_data);
 
1252
 
 
1253
}
 
1254
 
 
1255
int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst,
 
1256
                        uint8_t channel, bt_io_callback_t cb, void *user_data)
 
1257
{
 
1258
        BtIO *io;
 
1259
        BtIOError err;
 
1260
 
 
1261
        io = bt_io_create(BT_IO_RFCOMM, user_data, NULL);
 
1262
        if (!io)
 
1263
                return -1;
 
1264
 
 
1265
        ba2str(src, io->src);
 
1266
        ba2str(dst, io->dst);
 
1267
        io->channel = channel;
 
1268
        io->io_ctxt->cb = cb;
 
1269
        err = bt_io_connect(io, NULL, NULL);
 
1270
        if (err != BT_IO_SUCCESS) {
 
1271
                bt_io_unref(io);
 
1272
                return -1;
 
1273
        }
 
1274
 
 
1275
        return 0;
 
1276
}
 
1277
 
 
1278
GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu,
 
1279
                        uint32_t flags, bt_io_callback_t cb, void *user_data)
 
1280
{
 
1281
        BtIO *io;
 
1282
        BtIOError err;
 
1283
 
 
1284
        io = bt_io_create(BT_IO_L2CAP, user_data, NULL);
 
1285
        if (!io)
 
1286
                return NULL;
 
1287
 
 
1288
        ba2str(src, io->src);
 
1289
        io->psm = psm;
 
1290
        io->mtu = mtu;
 
1291
        io->flags = flags;
 
1292
        io->io_ctxt->cb = cb;
 
1293
        err = bt_io_listen(io, NULL, NULL);
 
1294
        if (err != BT_IO_SUCCESS) {
 
1295
                bt_io_unref(io);
 
1296
                return NULL;
 
1297
        }
 
1298
 
 
1299
        return io->io_ctxt->io;
 
1300
}
 
1301
 
 
1302
int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst,
 
1303
                        uint16_t psm, uint16_t mtu, bt_io_callback_t cb,
 
1304
                        void *user_data)
 
1305
{
 
1306
        BtIO *io;
 
1307
        BtIOError err;
 
1308
 
 
1309
        io = bt_io_create(BT_IO_L2CAP, user_data, NULL);
 
1310
        if (!io)
 
1311
                return -1;
 
1312
 
 
1313
        ba2str(src, io->src);
 
1314
        ba2str(dst, io->dst);
 
1315
        io->psm = psm;
 
1316
        io->mtu = mtu;
 
1317
        io->io_ctxt->cb = cb;
 
1318
        err = bt_io_connect(io, NULL, NULL);
 
1319
        if (err != BT_IO_SUCCESS) {
 
1320
                bt_io_unref(io);
 
1321
                return -1;
 
1322
        }
 
1323
 
 
1324
        return 0;
 
1325
}
 
1326
 
 
1327
GIOChannel *bt_sco_listen(const bdaddr_t *src, uint16_t mtu,
 
1328
                                bt_io_callback_t cb, void *user_data)
 
1329
{
 
1330
        BtIO *io;
 
1331
        BtIOError err;
 
1332
 
 
1333
        io = bt_io_create(BT_IO_SCO, user_data, NULL);
 
1334
        if (!io)
 
1335
                return NULL;
 
1336
 
 
1337
        ba2str(src, io->src);
 
1338
        io->io_ctxt->cb = cb;
 
1339
        err = bt_io_listen(io, NULL, NULL);
 
1340
        if (err != BT_IO_SUCCESS) {
 
1341
                bt_io_unref(io);
 
1342
                return NULL;
 
1343
        }
 
1344
 
 
1345
        return io->io_ctxt->io;
 
1346
}
 
1347
 
 
1348
 
 
1349
int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst,
 
1350
                        bt_io_callback_t cb, void *user_data)
 
1351
{
 
1352
        BtIO *io;
 
1353
        BtIOError err;
 
1354
 
 
1355
        io = bt_io_create(BT_IO_SCO, user_data, NULL);
 
1356
        if (!io)
 
1357
                return -1;
 
1358
 
 
1359
        ba2str(src, io->src);
 
1360
        ba2str(dst, io->dst);
 
1361
        io->io_ctxt->cb = cb;
 
1362
        err = bt_io_connect(io, NULL, NULL);
 
1363
        if (err != BT_IO_SUCCESS) {
 
1364
                bt_io_unref(io);
 
1365
                return -1;
 
1366
        }
 
1367
 
 
1368
        return 0;
 
1369
}
 
1370
 
 
1371
/* Experiemental bt_io API */
 
1372
 
 
1373
BtIO *bt_io_create(BtIOTransport type, gpointer user_data, GDestroyNotify notify)
 
1374
{
 
1375
        BtIO *io;
 
1376
        int err;
 
1377
 
 
1378
        io = g_new0(BtIO, 1);
 
1379
        if (!io)
 
1380
                return NULL;
 
1381
 
 
1382
        io->refcount = 1;
 
1383
 
 
1384
        switch (type) {
 
1385
        case BT_IO_L2CAP:
 
1386
                err = create_io_context(&io->io_ctxt, NULL, NULL,
 
1387
                                l2cap_resolver, user_data);
 
1388
                io->connect = l2cap_connect;
 
1389
                io->listen = l2cap_listen;
 
1390
                break;
 
1391
        case BT_IO_RFCOMM:
 
1392
                err = create_io_context(&io->io_ctxt, NULL, NULL,
 
1393
                                rfcomm_resolver, user_data);
 
1394
                io->connect = rfcomm_connect;
 
1395
                io->listen = rfcomm_listen;
 
1396
                break;
 
1397
        case BT_IO_SCO:
 
1398
                err = create_io_context(&io->io_ctxt, NULL, NULL,
 
1399
                                sco_resolver, user_data);
 
1400
                io->connect = sco_connect;
 
1401
                io->listen = sco_listen;
 
1402
                break;
 
1403
        default:
 
1404
                return NULL;
 
1405
        }
 
1406
 
 
1407
        if (err < 0) {
 
1408
                bt_io_unref(io);
 
1409
                return NULL;
 
1410
        }
 
1411
 
 
1412
        return io;
 
1413
}
 
1414
 
 
1415
BtIO *bt_io_ref(BtIO *io)
 
1416
{
 
1417
        io->refcount++;
 
1418
 
 
1419
        return io;
 
1420
}
 
1421
 
 
1422
void bt_io_unref(BtIO *io)
 
1423
{
 
1424
        io->refcount--;
 
1425
 
 
1426
        if (io->refcount)
 
1427
                return;
 
1428
 
 
1429
        io_context_cleanup(io->io_ctxt);
 
1430
        g_free(io);
 
1431
}
 
1432
 
 
1433
gboolean bt_io_set_source(BtIO *io, const char *address)
 
1434
{
 
1435
        if (strlen(address) != sizeof(io->src))
 
1436
                return FALSE;
 
1437
 
 
1438
        memcpy(io->src, address, sizeof(io->src));
 
1439
 
 
1440
        return TRUE;
 
1441
}
 
1442
 
 
1443
const char *bt_io_get_source(BtIO *io)
 
1444
{
 
1445
        return io->src;
 
1446
}
 
1447
 
 
1448
gboolean bt_io_set_destination(BtIO *io, const char *address)
 
1449
{
 
1450
        if (strlen(address) != sizeof(io->dst))
 
1451
                return FALSE;
 
1452
 
 
1453
        memcpy(io->dst, address, sizeof(io->dst));
 
1454
 
 
1455
        return TRUE;
 
1456
}
 
1457
 
 
1458
const char *bt_io_get_destination(BtIO *io)
 
1459
{
 
1460
        return io->dst;
 
1461
}
 
1462
 
 
1463
gboolean bt_io_set_flags(BtIO *io, guint32 flags)
 
1464
{
 
1465
        io->flags = flags;
 
1466
 
 
1467
        return TRUE;
 
1468
}
 
1469
 
 
1470
guint32 bt_io_get_flags(BtIO *io)
 
1471
{
 
1472
        return io->flags;
 
1473
}
 
1474
 
 
1475
gboolean bt_io_set_channel(BtIO *io, guint8 channel)
 
1476
{
 
1477
        if (io->type != BT_IO_RFCOMM)
 
1478
                return FALSE;
 
1479
 
 
1480
        io->channel = channel;
 
1481
 
 
1482
        return TRUE;
 
1483
}
 
1484
 
 
1485
guint8 bt_io_get_channel(BtIO *io)
 
1486
{
 
1487
        return io->channel;
 
1488
}
 
1489
 
 
1490
gboolean bt_io_set_psm(BtIO *io, guint16 psm)
 
1491
{
 
1492
        if (io->type != BT_IO_L2CAP)
 
1493
                return FALSE;
 
1494
 
 
1495
        io->psm = psm;
 
1496
 
 
1497
        return TRUE;
 
1498
}
 
1499
 
 
1500
guint16 bt_io_get_psm(BtIO *io)
 
1501
{
 
1502
        return io->psm;
 
1503
}
 
1504
 
 
1505
gboolean bt_io_set_mtu(BtIO *io, guint16 mtu)
 
1506
{
 
1507
        io->mtu = mtu;
 
1508
 
 
1509
        return TRUE;
 
1510
}
 
1511
 
 
1512
guint16 bt_io_get_mtu(BtIO *io)
 
1513
{
 
1514
        return io->mtu;
 
1515
}
 
1516
 
 
1517
BtIOError bt_io_connect(BtIO *io, const char *uuid, BtIOFunc func)
 
1518
{
 
1519
        if (!io->connect)
 
1520
                return BT_IO_FAILED;
 
1521
 
 
1522
        return io->connect(io, func);
 
1523
}
 
1524
 
 
1525
BtIOError bt_io_listen(BtIO *io, const char *uuid, BtIOFunc func)
 
1526
{
 
1527
        if (!io->listen)
 
1528
                return BT_IO_FAILED;
 
1529
 
 
1530
        return io->listen(io, func);
 
1531
}
 
1532
 
 
1533
BtIOError bt_io_shutdown(BtIO *io)
 
1534
{
 
1535
        io_context_cleanup(io->io_ctxt);
 
1536
 
 
1537
        return BT_IO_SUCCESS;
 
1538
}