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

« back to all changes in this revision

Viewing changes to serial/port.c

ImportĀ upstreamĀ versionĀ 4.81

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *
3
3
 *  BlueZ - Bluetooth protocol stack for Linux
4
4
 *
5
 
 *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
 
5
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
6
6
 *
7
7
 *
8
8
 *  This program is free software; you can redistribute it and/or modify
47
47
 
48
48
#include "../src/dbus-common.h"
49
49
 
50
 
#include "logging.h"
 
50
#include "log.h"
51
51
#include "glib-helper.h"
52
52
#include "btio.h"
53
53
 
78
78
        char            *uuid;          /* service identification */
79
79
        char            *dev;           /* RFCOMM device name */
80
80
        int             fd;             /* Opened file descriptor */
 
81
        GIOChannel      *io;            /* BtIO channel */
81
82
        guint           listener_id;
82
83
        struct serial_device *device;
83
84
};
101
102
static struct serial_port *find_port(GSList *ports, const char *pattern)
102
103
{
103
104
        GSList *l;
 
105
        int channel;
 
106
        char *endptr = NULL;
 
107
 
 
108
        channel = strtol(pattern, &endptr, 10);
104
109
 
105
110
        for (l = ports; l != NULL; l = l->next) {
106
111
                struct serial_port *port = l->data;
107
112
                char *uuid_str;
108
113
                int ret;
109
114
 
110
 
                if (!strcasecmp(port->uuid, pattern))
 
115
                if (port->uuid && !strcasecmp(port->uuid, pattern))
 
116
                        return port;
 
117
 
 
118
                if (endptr && *endptr == '\0' && port->channel == channel)
111
119
                        return port;
112
120
 
113
121
                if (port->dev && !strcmp(port->dev, pattern))
114
122
                        return port;
115
123
 
 
124
                if (!port->uuid)
 
125
                        continue;
 
126
 
116
127
                uuid_str = bt_name2string(pattern);
117
128
                if (!uuid_str)
118
129
                        continue;
119
130
 
120
131
                ret = strcasecmp(port->uuid, uuid_str);
121
 
 
122
132
                g_free(uuid_str);
123
 
 
124
133
                if (ret == 0)
125
134
                        return port;
126
135
        }
134
143
        int rfcomm_ctl;
135
144
        int err = 0;
136
145
 
137
 
        debug("Serial port %s released", port->dev);
 
146
        if (port->id < 0) {
 
147
                if (port->io) {
 
148
                        g_io_channel_shutdown(port->io, TRUE, NULL);
 
149
                        g_io_channel_unref(port->io);
 
150
                        port->io = NULL;
 
151
                } else
 
152
                        bt_cancel_discovery(&port->device->src,
 
153
                                                &port->device->dst);
 
154
 
 
155
                return 0;
 
156
        }
 
157
 
 
158
        DBG("Serial port %s released", port->dev);
138
159
 
139
160
        rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
140
161
        if (rfcomm_ctl < 0)
175
196
        if (device && port->listener_id > 0)
176
197
                g_dbus_remove_watch(device->conn, port->listener_id);
177
198
 
178
 
        if (port->id >= 0)
179
 
                port_release(port);
 
199
        port_release(port);
180
200
 
181
201
        g_free(port->uuid);
182
202
        g_free(port);
194
214
{
195
215
        struct serial_port *port = user_data;
196
216
 
197
 
        if (port->id >= 0)
198
 
                port_release(port);
 
217
        port_release(port);
199
218
 
200
219
        port->listener_id = 0;
201
220
}
204
223
{
205
224
        struct serial_device *device = data;
206
225
 
207
 
        debug("Unregistered interface %s on path %s", SERIAL_PORT_INTERFACE,
 
226
        DBG("Unregistered interface %s on path %s", SERIAL_PORT_INTERFACE,
208
227
                device->path);
209
228
 
210
229
        devices = g_slist_remove(devices, device);
221
240
                                        const char *description)
222
241
{
223
242
        return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist",
224
 
                                description);
 
243
                                                        "%s", description);
225
244
}
226
245
 
227
246
static inline DBusMessage *invalid_arguments(DBusMessage *msg,
228
247
                                        const char *description)
229
248
{
230
249
        return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments",
231
 
                                description);
 
250
                                                        "%s", description);
232
251
}
233
252
 
234
253
static inline DBusMessage *failed(DBusMessage *msg, const char *description)
235
254
{
236
255
        return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
237
 
                                description);
 
256
                                                        "%s", description);
238
257
}
239
258
 
240
259
static void open_notify(int fd, int err, struct serial_port *port)
324
343
        bacpy(&req.dst, &device->dst);
325
344
        req.channel = port->channel;
326
345
 
 
346
        g_io_channel_unref(port->io);
 
347
        port->io = NULL;
 
348
 
327
349
        sk = g_io_channel_unix_get_fd(chan);
328
350
        port->id = ioctl(sk, RFCOMMCREATEDEV, &req);
329
351
        if (port->id < 0) {
336
358
 
337
359
        port->dev = g_strdup_printf("/dev/rfcomm%d", port->id);
338
360
 
339
 
        debug("Serial port %s created", port->dev);
 
361
        DBG("Serial port %s created", port->dev);
340
362
 
341
363
        g_io_channel_shutdown(chan, TRUE, NULL);
342
364
 
355
377
        port->listener_id = 0;
356
378
}
357
379
 
 
380
static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
 
381
{
 
382
        struct serial_port *port = user_data;
 
383
        struct serial_device *device = port->device;
 
384
        sdp_record_t *record = NULL;
 
385
        sdp_list_t *protos;
 
386
        DBusMessage *reply;
 
387
        GError *gerr = NULL;
 
388
 
 
389
        if (!port->listener_id) {
 
390
                reply = NULL;
 
391
                goto failed;
 
392
        }
 
393
 
 
394
        if (err < 0) {
 
395
                error("Unable to get service record: %s (%d)", strerror(-err),
 
396
                        -err);
 
397
                reply = failed(port->msg, strerror(-err));
 
398
                goto failed;
 
399
        }
 
400
 
 
401
        if (!recs || !recs->data) {
 
402
                error("No record found");
 
403
                reply = failed(port->msg, "No record found");
 
404
                goto failed;
 
405
        }
 
406
 
 
407
        record = recs->data;
 
408
 
 
409
        if (sdp_get_access_protos(record, &protos) < 0) {
 
410
                error("Unable to get access protos from port record");
 
411
                reply = failed(port->msg, "Invalid channel");
 
412
                goto failed;
 
413
        }
 
414
 
 
415
        port->channel = sdp_get_proto_port(protos, RFCOMM_UUID);
 
416
 
 
417
        sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
 
418
        sdp_list_free(protos, NULL);
 
419
 
 
420
        port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port,
 
421
                                NULL, &gerr,
 
422
                                BT_IO_OPT_SOURCE_BDADDR, &device->src,
 
423
                                BT_IO_OPT_DEST_BDADDR, &device->dst,
 
424
                                BT_IO_OPT_CHANNEL, port->channel,
 
425
                                BT_IO_OPT_INVALID);
 
426
        if (!port->io) {
 
427
                error("%s", gerr->message);
 
428
                reply = failed(port->msg, gerr->message);
 
429
                g_error_free(gerr);
 
430
                goto failed;
 
431
        }
 
432
 
 
433
        return;
 
434
 
 
435
failed:
 
436
        g_dbus_remove_watch(device->conn, port->listener_id);
 
437
        port->listener_id = 0;
 
438
        g_dbus_send_message(device->conn, reply);
 
439
}
 
440
 
 
441
static int connect_port(struct serial_port *port)
 
442
{
 
443
        struct serial_device *device = port->device;
 
444
        uuid_t uuid;
 
445
        int err;
 
446
 
 
447
        if (!port->uuid)
 
448
                goto connect;
 
449
 
 
450
        err = bt_string2uuid(&uuid, port->uuid);
 
451
        if (err < 0)
 
452
                return err;
 
453
 
 
454
        sdp_uuid128_to_uuid(&uuid);
 
455
 
 
456
        return bt_search_service(&device->src, &device->dst, &uuid,
 
457
                                get_record_cb, port, NULL);
 
458
 
 
459
connect:
 
460
        port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port,
 
461
                                NULL, NULL,
 
462
                                BT_IO_OPT_SOURCE_BDADDR, &device->src,
 
463
                                BT_IO_OPT_DEST_BDADDR, &device->dst,
 
464
                                BT_IO_OPT_CHANNEL, port->channel,
 
465
                                BT_IO_OPT_INVALID);
 
466
        if (port->io)
 
467
                return 0;
 
468
 
 
469
        return -errno;
 
470
}
 
471
 
 
472
static struct serial_port *create_port(struct serial_device *device,
 
473
                                        const char *uuid, uint8_t channel)
 
474
{
 
475
        struct serial_port *port;
 
476
 
 
477
        port = g_new0(struct serial_port, 1);
 
478
        port->uuid = g_strdup(uuid);
 
479
        port->channel = channel;
 
480
        port->device = device;
 
481
        port->id = -1;
 
482
        port->fd = -1;
 
483
 
 
484
        device->ports = g_slist_append(device->ports, port);
 
485
 
 
486
        return port;
 
487
}
 
488
 
358
489
static DBusMessage *port_connect(DBusConnection *conn,
359
490
                                        DBusMessage *msg, void *user_data)
360
491
{
361
492
        struct serial_device *device = user_data;
362
493
        struct serial_port *port;
363
 
        const char *uuid;
364
 
        GIOChannel *io;
365
 
        GError *err = NULL;
 
494
        const char *pattern;
 
495
        int err;
366
496
 
367
 
        if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
 
497
        if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
368
498
                                                DBUS_TYPE_INVALID) == FALSE)
369
499
                return NULL;
370
500
 
371
 
        port = find_port(device->ports, uuid);
372
 
        if (!port)
373
 
                return does_not_exist(msg, "Does not match");
 
501
        port = find_port(device->ports, pattern);
 
502
        if (!port) {
 
503
                char *endptr = NULL;
 
504
                int channel;
 
505
 
 
506
                channel = strtol(pattern, &endptr, 10);
 
507
                if ((endptr && *endptr != '\0') || channel < 1 || channel > 30)
 
508
                        return does_not_exist(msg, "Does not match");
 
509
 
 
510
                port = create_port(device, NULL, channel);
 
511
        }
374
512
 
375
513
        if (port->listener_id)
376
514
                return failed(msg, "Port already in use");
381
519
                                                NULL);
382
520
        port->msg = dbus_message_ref(msg);
383
521
 
384
 
        io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port,
385
 
                                NULL, &err,
386
 
                                BT_IO_OPT_SOURCE_BDADDR, &device->src,
387
 
                                BT_IO_OPT_DEST_BDADDR, &device->dst,
388
 
                                BT_IO_OPT_CHANNEL, port->channel,
389
 
                                BT_IO_OPT_INVALID);
390
 
        if (!io) {
 
522
        err = connect_port(port);
 
523
        if (err < 0) {
391
524
                DBusMessage *reply;
392
525
 
393
 
                error("%s", err->message);
 
526
                error("%s", strerror(-err));
394
527
                g_dbus_remove_watch(conn, port->listener_id);
395
528
                port->listener_id = 0;
396
 
                reply = failed(msg, err->message);
397
 
                g_error_free(err);
 
529
                reply = failed(msg, strerror(-err));
398
530
                return reply;
399
531
        }
400
532
 
401
 
        g_io_channel_unref(io);
402
 
 
403
533
        return NULL;
404
534
}
405
535
 
426
556
        if (!g_str_equal(owner, caller))
427
557
                return failed(msg, "Operation not permited");
428
558
 
429
 
        if (port->id >= 0)
430
 
                port_release(port);
 
559
        port_release(port);
431
560
 
432
561
        g_dbus_remove_watch(conn, port->listener_id);
433
562
        port->listener_id = 0;
463
592
                return NULL;
464
593
        }
465
594
 
466
 
        debug("Registered interface %s on path %s",
 
595
        DBG("Registered interface %s on path %s",
467
596
                SERIAL_PORT_INTERFACE, path);
468
597
 
469
598
        return device;