Home | History | Annotate | Download | only in serial
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel (at) 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 <stdio.h>
     30 #include <stdint.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <termios.h>
     34 #include <unistd.h>
     35 #include <sys/ioctl.h>
     36 #include <sys/types.h>
     37 #include <sys/stat.h>
     38 #include <fcntl.h>
     39 
     40 #include <bluetooth/bluetooth.h>
     41 #include <bluetooth/rfcomm.h>
     42 #include <bluetooth/sdp.h>
     43 #include <bluetooth/sdp_lib.h>
     44 
     45 #include <glib.h>
     46 #include <gdbus.h>
     47 
     48 #include "../src/dbus-common.h"
     49 
     50 #include "log.h"
     51 #include "glib-helper.h"
     52 #include "btio.h"
     53 
     54 #include "error.h"
     55 #include "manager.h"
     56 #include "storage.h"
     57 #include "port.h"
     58 
     59 #define SERIAL_PORT_INTERFACE	"org.bluez.Serial"
     60 #define ERROR_INVALID_ARGS	"org.bluez.Error.InvalidArguments"
     61 #define ERROR_DOES_NOT_EXIST	"org.bluez.Error.DoesNotExist"
     62 
     63 #define MAX_OPEN_TRIES		5
     64 #define OPEN_WAIT		300	/* ms. udev node creation retry wait */
     65 
     66 struct serial_device {
     67 	DBusConnection	*conn;		/* for name listener handling */
     68 	bdaddr_t	src;		/* Source (local) address */
     69 	bdaddr_t	dst;		/* Destination address */
     70 	char		*path;		/* Device path */
     71 	GSList		*ports;		/* Available ports */
     72 };
     73 
     74 struct serial_port {
     75 	DBusMessage	*msg;		/* for name listener handling */
     76 	int16_t		id;		/* RFCOMM device id */
     77 	uint8_t		channel;	/* RFCOMM channel */
     78 	char		*uuid;		/* service identification */
     79 	char		*dev;		/* RFCOMM device name */
     80 	int		fd;		/* Opened file descriptor */
     81 	GIOChannel	*io;		/* BtIO channel */
     82 	guint		listener_id;
     83 	struct serial_device *device;
     84 };
     85 
     86 static GSList *devices = NULL;
     87 
     88 static struct serial_device *find_device(GSList *devices, const char *path)
     89 {
     90 	GSList *l;
     91 
     92 	for (l = devices; l != NULL; l = l->next) {
     93 		struct serial_device *device = l->data;
     94 
     95 		if (!strcmp(device->path, path))
     96 			return device;
     97 	}
     98 
     99 	return NULL;
    100 }
    101 
    102 static struct serial_port *find_port(GSList *ports, const char *pattern)
    103 {
    104 	GSList *l;
    105 	int channel;
    106 	char *endptr = NULL;
    107 
    108 	channel = strtol(pattern, &endptr, 10);
    109 
    110 	for (l = ports; l != NULL; l = l->next) {
    111 		struct serial_port *port = l->data;
    112 		char *uuid_str;
    113 		int ret;
    114 
    115 		if (port->uuid && !strcasecmp(port->uuid, pattern))
    116 			return port;
    117 
    118 		if (endptr && *endptr == '\0' && port->channel == channel)
    119 			return port;
    120 
    121 		if (port->dev && !strcmp(port->dev, pattern))
    122 			return port;
    123 
    124 		if (!port->uuid)
    125 			continue;
    126 
    127 		uuid_str = bt_name2string(pattern);
    128 		if (!uuid_str)
    129 			continue;
    130 
    131 		ret = strcasecmp(port->uuid, uuid_str);
    132 		g_free(uuid_str);
    133 		if (ret == 0)
    134 			return port;
    135 	}
    136 
    137 	return NULL;
    138 }
    139 
    140 static int port_release(struct serial_port *port)
    141 {
    142 	struct rfcomm_dev_req req;
    143 	int rfcomm_ctl;
    144 	int err = 0;
    145 
    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);
    159 
    160 	rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
    161 	if (rfcomm_ctl < 0)
    162 		return -errno;
    163 
    164 	if (port->fd >= 0) {
    165 		close(port->fd);
    166 		port->fd = -1;
    167 	}
    168 
    169 	memset(&req, 0, sizeof(req));
    170 	req.dev_id = port->id;
    171 
    172 	/*
    173 	 * We are hitting a kernel bug inside RFCOMM code when
    174 	 * RFCOMM_HANGUP_NOW bit is set on request's flags passed to
    175 	 * ioctl(RFCOMMRELEASEDEV)!
    176 	 */
    177 	req.flags = (1 << RFCOMM_HANGUP_NOW);
    178 
    179 	if (ioctl(rfcomm_ctl, RFCOMMRELEASEDEV, &req) < 0) {
    180 		err = errno;
    181 		error("Can't release device %s: %s (%d)",
    182 				port->dev, strerror(err), err);
    183 	}
    184 
    185 	g_free(port->dev);
    186 	port->dev = NULL;
    187 	port->id = -1;
    188 	close(rfcomm_ctl);
    189 	return -err;
    190 }
    191 
    192 static void serial_port_free(struct serial_port *port)
    193 {
    194 	struct serial_device *device = port->device;
    195 
    196 	if (device && port->listener_id > 0)
    197 		g_dbus_remove_watch(device->conn, port->listener_id);
    198 
    199 	port_release(port);
    200 
    201 	g_free(port->uuid);
    202 	g_free(port);
    203 }
    204 
    205 static void serial_device_free(struct serial_device *device)
    206 {
    207 	g_free(device->path);
    208 	if (device->conn)
    209 		dbus_connection_unref(device->conn);
    210 	g_free(device);
    211 }
    212 
    213 static void port_owner_exited(DBusConnection *conn, void *user_data)
    214 {
    215 	struct serial_port *port = user_data;
    216 
    217 	port_release(port);
    218 
    219 	port->listener_id = 0;
    220 }
    221 
    222 static void path_unregister(void *data)
    223 {
    224 	struct serial_device *device = data;
    225 
    226 	DBG("Unregistered interface %s on path %s", SERIAL_PORT_INTERFACE,
    227 		device->path);
    228 
    229 	devices = g_slist_remove(devices, device);
    230 	serial_device_free(device);
    231 }
    232 
    233 void port_release_all(void)
    234 {
    235 	g_slist_foreach(devices, (GFunc) serial_device_free, NULL);
    236 	g_slist_free(devices);
    237 }
    238 
    239 static inline DBusMessage *does_not_exist(DBusMessage *msg,
    240 					const char *description)
    241 {
    242 	return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist",
    243 				description);
    244 }
    245 
    246 static inline DBusMessage *invalid_arguments(DBusMessage *msg,
    247 					const char *description)
    248 {
    249 	return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments",
    250 				description);
    251 }
    252 
    253 static inline DBusMessage *failed(DBusMessage *msg, const char *description)
    254 {
    255 	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
    256 				description);
    257 }
    258 
    259 static void open_notify(int fd, int err, struct serial_port *port)
    260 {
    261 	struct serial_device *device = port->device;
    262 	DBusMessage *reply;
    263 
    264 	if (err) {
    265 		/* Max tries exceeded */
    266 		port_release(port);
    267 		reply = failed(port->msg, strerror(err));
    268 	} else {
    269 		port->fd = fd;
    270 		reply = g_dbus_create_reply(port->msg,
    271 				DBUS_TYPE_STRING, &port->dev,
    272 				DBUS_TYPE_INVALID);
    273 	}
    274 
    275 	/* Reply to the requestor */
    276 	g_dbus_send_message(device->conn, reply);
    277 }
    278 
    279 static gboolean open_continue(gpointer user_data)
    280 {
    281 	struct serial_port *port = user_data;
    282 	int fd;
    283 	static int ntries = MAX_OPEN_TRIES;
    284 
    285 	if (!port->listener_id)
    286 		return FALSE; /* Owner exited */
    287 
    288 	fd = open(port->dev, O_RDONLY | O_NOCTTY);
    289 	if (fd < 0) {
    290 		int err = errno;
    291 		error("Could not open %s: %s (%d)",
    292 				port->dev, strerror(err), err);
    293 		if (!--ntries) {
    294 			/* Reporting error */
    295 			open_notify(fd, err, port);
    296 			ntries = MAX_OPEN_TRIES;
    297 			return FALSE;
    298 		}
    299 		return TRUE;
    300 	}
    301 
    302 	/* Connection succeeded */
    303 	open_notify(fd, 0, port);
    304 	return FALSE;
    305 }
    306 
    307 static int port_open(struct serial_port *port)
    308 {
    309 	int fd;
    310 
    311 	fd = open(port->dev, O_RDONLY | O_NOCTTY);
    312 	if (fd < 0) {
    313 		g_timeout_add(OPEN_WAIT, open_continue, port);
    314 		return -EINPROGRESS;
    315 	}
    316 
    317 	return fd;
    318 }
    319 
    320 static void rfcomm_connect_cb(GIOChannel *chan, GError *conn_err,
    321 							gpointer user_data)
    322 {
    323 	struct serial_port *port = user_data;
    324 	struct serial_device *device = port->device;
    325 	struct rfcomm_dev_req req;
    326 	int sk, fd;
    327 	DBusMessage *reply;
    328 
    329 	/* Owner exited? */
    330 	if (!port->listener_id)
    331 		return;
    332 
    333 	if (conn_err) {
    334 		error("%s", conn_err->message);
    335 		reply = failed(port->msg, conn_err->message);
    336 		goto fail;
    337 	}
    338 
    339 	memset(&req, 0, sizeof(req));
    340 	req.dev_id = -1;
    341 	req.flags = (1 << RFCOMM_REUSE_DLC);
    342 	bacpy(&req.src, &device->src);
    343 	bacpy(&req.dst, &device->dst);
    344 	req.channel = port->channel;
    345 
    346 	g_io_channel_unref(port->io);
    347 	port->io = NULL;
    348 
    349 	sk = g_io_channel_unix_get_fd(chan);
    350 	port->id = ioctl(sk, RFCOMMCREATEDEV, &req);
    351 	if (port->id < 0) {
    352 		int err = errno;
    353 		error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(err), err);
    354 		reply = failed(port->msg, strerror(err));
    355 		g_io_channel_shutdown(chan, TRUE, NULL);
    356 		goto fail;
    357 	}
    358 
    359 	port->dev = g_strdup_printf("/dev/rfcomm%d", port->id);
    360 
    361 	DBG("Serial port %s created", port->dev);
    362 
    363 	g_io_channel_shutdown(chan, TRUE, NULL);
    364 
    365 	/* Addressing connect port */
    366 	fd = port_open(port);
    367 	if (fd < 0)
    368 		/* Open in progress: Wait the callback */
    369 		return;
    370 
    371 	open_notify(fd, 0, port);
    372 	return;
    373 
    374 fail:
    375 	g_dbus_send_message(device->conn, reply);
    376 	g_dbus_remove_watch(device->conn, port->listener_id);
    377 	port->listener_id = 0;
    378 }
    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 
    489 static DBusMessage *port_connect(DBusConnection *conn,
    490 					DBusMessage *msg, void *user_data)
    491 {
    492 	struct serial_device *device = user_data;
    493 	struct serial_port *port;
    494 	const char *pattern;
    495 	int err;
    496 
    497 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
    498 						DBUS_TYPE_INVALID) == FALSE)
    499 		return NULL;
    500 
    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 	}
    512 
    513 	if (port->listener_id)
    514 		return failed(msg, "Port already in use");
    515 
    516 	port->listener_id = g_dbus_add_disconnect_watch(conn,
    517 						dbus_message_get_sender(msg),
    518 						port_owner_exited, port,
    519 						NULL);
    520 	port->msg = dbus_message_ref(msg);
    521 
    522 	err = connect_port(port);
    523 	if (err < 0) {
    524 		DBusMessage *reply;
    525 
    526 		error("%s", strerror(-err));
    527 		g_dbus_remove_watch(conn, port->listener_id);
    528 		port->listener_id = 0;
    529 		reply = failed(msg, strerror(-err));
    530 		return reply;
    531 	}
    532 
    533 	return NULL;
    534 }
    535 
    536 static DBusMessage *port_disconnect(DBusConnection *conn,
    537 					DBusMessage *msg, void *user_data)
    538 {
    539 	struct serial_device *device = user_data;
    540 	struct serial_port *port;
    541 	const char *dev, *owner, *caller;
    542 
    543 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &dev,
    544 						DBUS_TYPE_INVALID) == FALSE)
    545 		return NULL;
    546 
    547 	port = find_port(device->ports, dev);
    548 	if (!port)
    549 		return does_not_exist(msg, "Port does not exist");
    550 
    551 	if (!port->listener_id)
    552 		return failed(msg, "Not connected");
    553 
    554 	owner = dbus_message_get_sender(port->msg);
    555 	caller = dbus_message_get_sender(msg);
    556 	if (!g_str_equal(owner, caller))
    557 		return failed(msg, "Operation not permited");
    558 
    559 	port_release(port);
    560 
    561 	g_dbus_remove_watch(conn, port->listener_id);
    562 	port->listener_id = 0;
    563 
    564 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
    565 }
    566 
    567 static GDBusMethodTable port_methods[] = {
    568 	{ "Connect",    "s", "s", port_connect, G_DBUS_METHOD_FLAG_ASYNC },
    569 	{ "Disconnect", "s", "",  port_disconnect },
    570 	{ }
    571 };
    572 
    573 static struct serial_device *create_serial_device(DBusConnection *conn,
    574 					const char *path, bdaddr_t *src,
    575 					bdaddr_t *dst)
    576 {
    577 	struct serial_device *device;
    578 
    579 	device = g_new0(struct serial_device, 1);
    580 	device->conn = dbus_connection_ref(conn);
    581 	bacpy(&device->dst, dst);
    582 	bacpy(&device->src, src);
    583 	device->path = g_strdup(path);
    584 
    585 	if (!g_dbus_register_interface(conn, path,
    586 				SERIAL_PORT_INTERFACE,
    587 				port_methods, NULL, NULL,
    588 				device, path_unregister)) {
    589 		error("D-Bus failed to register %s interface",
    590 				SERIAL_PORT_INTERFACE);
    591 		serial_device_free(device);
    592 		return NULL;
    593 	}
    594 
    595 	DBG("Registered interface %s on path %s",
    596 		SERIAL_PORT_INTERFACE, path);
    597 
    598 	return device;
    599 }
    600 
    601 int port_register(DBusConnection *conn, const char *path, bdaddr_t *src,
    602 			bdaddr_t *dst, const char *uuid, uint8_t channel)
    603 {
    604 	struct serial_device *device;
    605 	struct serial_port *port;
    606 
    607 	device = find_device(devices, path);
    608 	if (!device) {
    609 		device = create_serial_device(conn, path, src, dst);
    610 		if (!device)
    611 			return -1;
    612 		devices = g_slist_append(devices, device);
    613 	}
    614 
    615 	if (find_port(device->ports, uuid))
    616 		return 0;
    617 
    618 	port = g_new0(struct serial_port, 1);
    619 	port->uuid = g_strdup(uuid);
    620 	port->channel = channel;
    621 	port->device = device;
    622 	port->id = -1;
    623 	port->fd = -1;
    624 
    625 	device->ports = g_slist_append(device->ports, port);
    626 
    627 	return 0;
    628 }
    629 
    630 int port_unregister(const char *path)
    631 {
    632 	struct serial_device *device;
    633 
    634 	device = find_device(devices, path);
    635 	if (!device)
    636 		return -ENOENT;
    637 
    638 	g_slist_foreach(device->ports, (GFunc) serial_port_free, NULL);
    639 	g_slist_free(device->ports);
    640 
    641 	g_dbus_unregister_interface(device->conn, path, SERIAL_PORT_INTERFACE);
    642 
    643 	return 0;
    644 }
    645