Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 8/8] btio: Remove libbluetooth dependence for obexd
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

Remove libbluetooth dependence for obex server daemon. obex-test and
obex-client still require libbluetooth because of sdp related
dependence.
---
 Makefile.am |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index f77fa27..05755a8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -75,7 +75,7 @@ src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) $(btio_sources) \
 
 src_obexd_LDADD = @DBUS_LIBS@ @GLIB_LIBS@ @GTHREAD_LIBS@ \
 					@EBOOK_LIBS@ @OPENOBEX_LIBS@ \
-					@BLUEZ_LIBS@ @LIBICAL_LIBS@ -ldl
+					@LIBICAL_LIBS@ -ldl
 
 src_obexd_LDFLAGS = -Wl,--export-dynamic
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 7/8] btio: include bluetooth.h to use devid2ba
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

---
 btio/btio.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index eaf61c1..62efcb3 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -32,6 +32,7 @@
 
 #include <glib.h>
 
+#include "bluetooth.h"
 #include "btio.h"
 
 #define ERROR_FAILED(gerr, str, err) \
@@ -576,7 +577,7 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 		case BT_IO_OPT_SOURCE:
 			str = va_arg(args, const char *);
 			if (strncasecmp(str, "hci", 3) == 0)
-				hci_devba(atoi(str + 3), &opts->src);
+				devid2ba(atoi(str + 3), &opts->src);
 			else
 				str2ba(str, &opts->src);
 			break;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 6/8] btio: Add bluetooth.[ch] helper functions
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

btio/bluetooth.[ch] is a subset of libbluetooth to provide helper APIs
for btio/btio.[ch].
---
 Makefile.am      |    2 +-
 btio/bluetooth.c |   80 ++++++++++++++++++++
 btio/bluetooth.h |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 292 insertions(+), 1 deletions(-)
 create mode 100644 btio/bluetooth.c
 create mode 100644 btio/bluetooth.h

diff --git a/Makefile.am b/Makefile.am
index a89e62b..f77fa27 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,7 +18,7 @@ gwobex_sources = gwobex/gw-obex.h gwobex/gw-obex.c \
 			gwobex/obex-xfer.h gwobex/obex-xfer.c \
 			gwobex/utils.h gwobex/utils.c gwobex/log.h
 
-btio_sources = btio/btio.h btio/btio.c
+btio_sources = btio/btio.h btio/btio.c btio/bluetooth.h btio/bluetooth.c
 
 libexec_PROGRAMS =
 
diff --git a/btio/bluetooth.c b/btio/bluetooth.c
new file mode 100644
index 0000000..f56be3b
--- /dev/null
+++ b/btio/bluetooth.c
@@ -0,0 +1,80 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <glib.h>
+
+#include "bluetooth.h"
+
+int devid2ba(int dev_id, bdaddr_t *bdaddr)
+{
+	struct hci_dev_info di;
+	int dd, err, ret;
+
+	memset(&di, 0, sizeof(di));
+
+	dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+	if (dd < 0)
+		return dd;
+
+	memset(&di, 0, sizeof(struct hci_dev_info));
+
+	di.dev_id = dev_id;
+	ret = ioctl(dd, HCIGETDEVINFO, (void *) &di);
+
+	err = errno;
+	close(dd);
+	errno = err;
+
+	if (ret)
+		return -1;
+
+	if (!di.flags & (1 << HCI_UP)) {
+		errno = ENETDOWN;
+		return -1;
+	}
+
+	bacpy(bdaddr, &di.bdaddr);
+
+	return 0;
+}
+
+void baswap(bdaddr_t *dst, const bdaddr_t *src)
+{
+	register unsigned char *d = (unsigned char *) dst;
+	register const unsigned char *s = (const unsigned char *) src;
+	register int i;
+
+	for (i = 0; i < 6; i++)
+		d[i] = s[5-i];
+}
+
+int ba2str(const bdaddr_t *ba, char *str)
+{
+	uint8_t b[6];
+
+	baswap((bdaddr_t *) b, ba);
+	return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+		b[0], b[1], b[2], b[3], b[4], b[5]);
+}
+
+int str2ba(const char *str, bdaddr_t *ba)
+{
+	uint8_t b[6];
+	const char *ptr = str;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		b[i] = (uint8_t) strtol(ptr, NULL, 16);
+		if (i != 5 && !(ptr = strchr(ptr, ':')))
+			ptr = ":00:00:00:00:00";
+		ptr++;
+	}
+
+	baswap(ba, (bdaddr_t *) b);
+
+	return 0;
+}
diff --git a/btio/bluetooth.h b/btio/bluetooth.h
new file mode 100644
index 0000000..4a0f357
--- /dev/null
+++ b/btio/bluetooth.h
@@ -0,0 +1,211 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2009-2010  Nokia Corporation
+ *  Copyright (C) 2010  Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifndef BLUETOOTH_H
+#define BLUETOOTH_H
+
+#include <stdint.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+
+#define BTPROTO_L2CAP		0
+#define BTPROTO_HCI		1
+#define BTPROTO_RFCOMM		3
+
+#define SOL_HCI		0
+#define SOL_L2CAP	6
+#define SOL_RFCOMM	18
+
+#ifndef SOL_BLUETOOTH
+#define SOL_BLUETOOTH	274
+#endif
+
+#define BT_SECURITY	4
+struct bt_security {
+	uint8_t level;
+};
+#define BT_SECURITY_SDP		0
+#define BT_SECURITY_LOW		1
+#define BT_SECURITY_MEDIUM	2
+#define BT_SECURITY_HIGH	3
+
+#define BT_DEFER_SETUP	7
+
+/* Byte order conversions */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define htobs(d)  (d)
+#define htobl(d)  (d)
+#define btohs(d)  (d)
+#define btohl(d)  (d)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define htobs(d)  bswap_16(d)
+#define htobl(d)  bswap_32(d)
+#define btohs(d)  bswap_16(d)
+#define btohl(d)  bswap_32(d)
+#else
+#error "Unknown byte order"
+#endif
+
+/* BD Address */
+typedef struct {
+	uint8_t b[6];
+} __attribute__((packed)) bdaddr_t;
+
+/* Copy, swap, convert BD Address */
+static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
+{
+	return memcmp(ba1, ba2, sizeof(bdaddr_t));
+}
+
+static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
+{
+	memcpy(dst, src, sizeof(bdaddr_t));
+}
+
+/* RFCOMM socket address */
+struct sockaddr_rc {
+	sa_family_t	rc_family;
+	bdaddr_t	rc_bdaddr;
+	uint8_t		rc_channel;
+};
+
+/* RFCOMM socket options */
+#define RFCOMM_CONNINFO	0x02
+struct rfcomm_conninfo {
+	uint16_t	hci_handle;
+	uint8_t		dev_class[3];
+};
+
+#define RFCOMM_LM	0x03
+#define RFCOMM_LM_MASTER	0x0001
+#define RFCOMM_LM_AUTH		0x0002
+#define RFCOMM_LM_ENCRYPT	0x0004
+#define RFCOMM_LM_TRUSTED	0x0008
+#define RFCOMM_LM_RELIABLE	0x0010
+#define RFCOMM_LM_SECURE	0x0020
+
+/* L2CAP socket address */
+struct sockaddr_l2 {
+	sa_family_t	l2_family;
+	unsigned short	l2_psm;
+	bdaddr_t	l2_bdaddr;
+	unsigned short	l2_cid;
+};
+
+/* L2CAP socket options */
+#define L2CAP_OPTIONS	0x01
+struct l2cap_options {
+	uint16_t	omtu;
+	uint16_t	imtu;
+	uint16_t	flush_to;
+	uint8_t		mode;
+	uint8_t		fcs;
+};
+
+#define L2CAP_CONNINFO	0x02
+struct l2cap_conninfo {
+	uint16_t	hci_handle;
+	uint8_t		dev_class[3];
+};
+
+#define L2CAP_LM	0x03
+#define L2CAP_LM_MASTER		0x0001
+#define L2CAP_LM_AUTH		0x0002
+#define L2CAP_LM_ENCRYPT	0x0004
+#define L2CAP_LM_TRUSTED	0x0008
+#define L2CAP_LM_RELIABLE	0x0010
+#define L2CAP_LM_SECURE		0x0020
+
+#define L2CAP_MODE_BASIC	0x00
+#define L2CAP_MODE_RETRANS	0x01
+#define L2CAP_MODE_FLOWCTL	0x02
+#define L2CAP_MODE_ERTM		0x03
+#define L2CAP_MODE_STREAMING	0x04
+
+/* hci.h */
+
+/* HCI device flags */
+enum {
+	HCI_UP,
+	HCI_INIT,
+	HCI_RUNNING,
+
+	HCI_PSCAN,
+	HCI_ISCAN,
+	HCI_AUTH,
+	HCI_ENCRYPT,
+	HCI_INQUIRY,
+
+	HCI_RAW,
+};
+
+#define HCIGETDEVINFO	_IOR('H', 211, int)
+
+/* Ioctl requests structures */
+struct hci_dev_stats {
+	uint32_t err_rx;
+	uint32_t err_tx;
+	uint32_t cmd_tx;
+	uint32_t evt_rx;
+	uint32_t acl_tx;
+	uint32_t acl_rx;
+	uint32_t sco_tx;
+	uint32_t sco_rx;
+	uint32_t byte_rx;
+	uint32_t byte_tx;
+};
+
+struct hci_dev_info {
+	uint16_t dev_id;
+	char     name[8];
+
+	bdaddr_t bdaddr;
+
+	uint32_t flags;
+	uint8_t  type;
+
+	uint8_t  features[8];
+
+	uint32_t pkt_type;
+	uint32_t link_policy;
+	uint32_t link_mode;
+
+	uint16_t acl_mtu;
+	uint16_t acl_pkts;
+	uint16_t sco_mtu;
+	uint16_t sco_pkts;
+
+	struct   hci_dev_stats stat;
+};
+
+int devid2ba(int dev_id, bdaddr_t *bdaddr);
+void baswap(bdaddr_t *dst, const bdaddr_t *src);
+int ba2str(const bdaddr_t *ba, char *str);
+int str2ba(const char *str, bdaddr_t *ba);
+
+#endif
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 5/8] btio: Remove unused bt_io_set function
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

It is not used by either obex or bluez.
---
 btio/btio.c |   33 ---------------------------------
 btio/btio.h |    3 ---
 2 files changed, 0 insertions(+), 36 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index c4bd527..eaf61c1 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -925,39 +925,6 @@ gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
 	return TRUE;
 }
 
-gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
-							BtIOOption opt1, ...)
-{
-	va_list args;
-	gboolean ret;
-	struct set_opts opts;
-	int sock;
-
-	va_start(args, opt1);
-	ret = parse_set_opts(&opts, err, opt1, args);
-	va_end(args);
-
-	if (!ret)
-		return ret;
-
-	sock = g_io_channel_unix_get_fd(io);
-
-	switch (type) {
-	case BT_IO_L2RAW:
-	case BT_IO_L2CAP:
-		return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu,
-						opts.mode, opts.master, err);
-	case BT_IO_RFCOMM:
-		return rfcomm_set(sock, opts.sec_level, opts.master, err);
-	case BT_IO_SCO:
-		return sco_set(sock, opts.mtu, err);
-	}
-
-	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-			"Unknown BtIO type %d", type);
-	return FALSE;
-}
-
 gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
 							BtIOOption opt1, ...)
 {
diff --git a/btio/btio.h b/btio/btio.h
index 591ceee..e4b751f 100644
--- a/btio/btio.h
+++ b/btio/btio.h
@@ -78,9 +78,6 @@ typedef void (*BtIOConnect)(GIOChannel *io, GError *err, void *user_data);
 gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
 					GDestroyNotify destroy, GError **err);
 
-gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
-						BtIOOption opt1, ...);
-
 gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
 						BtIOOption opt1, ...);
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/8] btio: Replace void * with gpointer
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

TO make it consistent with bluez btio.c.
---
 btio/btio.c |   24 ++++++++++++------------
 1 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index 92a5a41..c4bd527 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -56,20 +56,20 @@ struct set_opts {
 
 struct connect {
 	BtIOConnect connect;
-	void *user_data;
+	gpointer user_data;
 	GDestroyNotify destroy;
 };
 
 struct accept {
 	BtIOConnect connect;
-	void *user_data;
+	gpointer user_data;
 	GDestroyNotify destroy;
 };
 
 struct server {
 	BtIOConnect connect;
 	BtIOConfirm confirm;
-	void *user_data;
+	gpointer user_data;
 	GDestroyNotify destroy;
 };
 
@@ -109,7 +109,7 @@ static gboolean check_nval(GIOChannel *io)
 }
 
 static gboolean accept_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
+							gpointer user_data)
 {
 	struct accept *accept = user_data;
 	GError *err = NULL;
@@ -130,7 +130,7 @@ static gboolean accept_cb(GIOChannel *io, GIOCondition cond,
 }
 
 static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
+							gpointer user_data)
 {
 	struct connect *conn = user_data;
 	GError *gerr = NULL;
@@ -163,7 +163,7 @@ static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
 }
 
 static gboolean server_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
+							gpointer user_data)
 {
 	struct server *server = user_data;
 	int srv_sock, cli_sock;
@@ -195,7 +195,7 @@ static gboolean server_cb(GIOChannel *io, GIOCondition cond,
 }
 
 static void server_add(GIOChannel *io, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
+				BtIOConfirm confirm, gpointer user_data,
 				GDestroyNotify destroy)
 {
 	struct server *server;
@@ -213,7 +213,7 @@ static void server_add(GIOChannel *io, BtIOConnect connect,
 }
 
 static void connect_add(GIOChannel *io, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy)
+				gpointer user_data, GDestroyNotify destroy)
 {
 	struct connect *conn;
 	GIOCondition cond;
@@ -228,7 +228,7 @@ static void connect_add(GIOChannel *io, BtIOConnect connect,
 					(GDestroyNotify) connect_remove);
 }
 
-static void accept_add(GIOChannel *io, BtIOConnect connect, void *user_data,
+static void accept_add(GIOChannel *io, BtIOConnect connect, gpointer user_data,
 							GDestroyNotify destroy)
 {
 	struct accept *accept;
@@ -897,7 +897,7 @@ static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err,
 	return FALSE;
 }
 
-gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
+gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
 					GDestroyNotify destroy, GError **err)
 {
 	int sock;
@@ -1023,7 +1023,7 @@ failed:
 }
 
 GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy,
+				gpointer user_data, GDestroyNotify destroy,
 				GError **gerr, BtIOOption opt1, ...)
 {
 	GIOChannel *io;
@@ -1071,7 +1071,7 @@ GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
 }
 
 GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
+				BtIOConfirm confirm, gpointer user_data,
 				GDestroyNotify destroy, GError **err,
 				BtIOOption opt1, ...)
 {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 3/8] btio: Remove SCO/L2RAW related code
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

1. Remove SCO/L2RAW related code since Obex doesn't use at all.
2. Remove header dependence with libbluetooth.
---
 btio/btio.c |  186 +----------------------------------------------------------
 btio/btio.h |    3 +-
 2 files changed, 2 insertions(+), 187 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index 42a3bcd..92a5a41 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2009-2010  Nokia Corporation
+ *  Copyright (C) 2010  Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -29,13 +30,6 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sco.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-
 #include <glib.h>
 
 #include "btio.h"
@@ -563,63 +557,6 @@ static gboolean rfcomm_set(int sock, int sec_level, int master, GError **err)
 	return TRUE;
 }
 
-static int sco_bind(int sock, const bdaddr_t *src, GError **err)
-{
-	struct sockaddr_sco addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sco_family = AF_BLUETOOTH;
-	bacpy(&addr.sco_bdaddr, src);
-
-	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		ERROR_FAILED(err, "sco_bind", errno);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int sco_connect(int sock, const bdaddr_t *dst)
-{
-	struct sockaddr_sco addr;
-	int err;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sco_family = AF_BLUETOOTH;
-	bacpy(&addr.sco_bdaddr, dst);
-
-	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
-	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
-		return err;
-
-	return 0;
-}
-
-static gboolean sco_set(int sock, uint16_t mtu, GError **err)
-{
-	struct sco_options sco_opt;
-	socklen_t len;
-
-	if (!mtu)
-		return TRUE;
-
-	len = sizeof(sco_opt);
-	memset(&sco_opt, 0, len);
-	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
-		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
-		return FALSE;
-	}
-
-	sco_opt.mtu = mtu;
-	if (setsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt,
-						sizeof(sco_opt)) < 0) {
-		ERROR_FAILED(err, "setsockopt(SCO_OPTIONS)", errno);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
 static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 						BtIOOption opt1, va_list args)
 {
@@ -941,89 +878,6 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
 	return TRUE;
 }
 
-static int sco_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
-{
-	struct sco_conninfo info;
-	socklen_t len;
-
-	len = sizeof(info);
-	if (getsockopt(sock, SOL_SCO, SCO_CONNINFO, &info, &len) < 0)
-		return -errno;
-
-	if (handle)
-		*handle = info.hci_handle;
-
-	if (dev_class)
-		memcpy(dev_class, info.dev_class, 3);
-
-	return 0;
-}
-
-static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
-{
-	BtIOOption opt = opt1;
-	struct sockaddr_sco src, dst;
-	struct sco_options sco_opt;
-	socklen_t len;
-	uint8_t dev_class[3];
-	uint16_t handle;
-
-	len = sizeof(sco_opt);
-	memset(&sco_opt, 0, len);
-	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
-		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
-		return FALSE;
-	}
-
-	if (!get_peers(sock, (struct sockaddr *) &src,
-				(struct sockaddr *) &dst, sizeof(src), err))
-		return FALSE;
-
-	while (opt != BT_IO_OPT_INVALID) {
-		switch (opt) {
-		case BT_IO_OPT_SOURCE:
-			ba2str(&src.sco_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_SOURCE_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &src.sco_bdaddr);
-			break;
-		case BT_IO_OPT_DEST:
-			ba2str(&dst.sco_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_DEST_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &dst.sco_bdaddr);
-			break;
-		case BT_IO_OPT_MTU:
-		case BT_IO_OPT_IMTU:
-		case BT_IO_OPT_OMTU:
-			*(va_arg(args, uint16_t *)) = sco_opt.mtu;
-			break;
-		case BT_IO_OPT_HANDLE:
-			if (sco_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
-				return FALSE;
-			}
-			*(va_arg(args, uint16_t *)) = handle;
-			break;
-		case BT_IO_OPT_CLASS:
-			if (sco_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
-				return FALSE;
-			}
-			memcpy(va_arg(args, uint8_t *), dev_class, 3);
-			break;
-		default:
-			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-					"Unknown option %d", opt);
-			return FALSE;
-		}
-
-		opt = va_arg(args, int);
-	}
-
-	return TRUE;
-}
-
 static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err,
 						BtIOOption opt1, va_list args)
 {
@@ -1032,13 +886,10 @@ static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err,
 	sock = g_io_channel_unix_get_fd(io);
 
 	switch (type) {
-	case BT_IO_L2RAW:
 	case BT_IO_L2CAP:
 		return l2cap_get(sock, err, opt1, args);
 	case BT_IO_RFCOMM:
 		return rfcomm_get(sock, err, opt1, args);
-	case BT_IO_SCO:
-		return sco_get(sock, err, opt1, args);
 	}
 
 	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
@@ -1127,18 +978,6 @@ static GIOChannel *create_io(BtIOType type, gboolean server,
 	GIOChannel *io;
 
 	switch (type) {
-	case BT_IO_L2RAW:
-		sock = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
-		if (sock < 0) {
-			ERROR_FAILED(err, "socket(RAW, L2CAP)", errno);
-			return NULL;
-		}
-		if (l2cap_bind(sock, &opts->src,
-					server ? opts->psm : 0, err) < 0)
-			goto failed;
-		if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err))
-			goto failed;
-		break;
 	case BT_IO_L2CAP:
 		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
 		if (sock < 0) {
@@ -1164,17 +1003,6 @@ static GIOChannel *create_io(BtIOType type, gboolean server,
 		if (!rfcomm_set(sock, opts->sec_level, opts->master, err))
 			goto failed;
 		break;
-	case BT_IO_SCO:
-		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
-		if (sock < 0) {
-			ERROR_FAILED(err, "socket(SEQPACKET, SCO)", errno);
-			return NULL;
-		}
-		if (sco_bind(sock, &opts->src, err) < 0)
-			goto failed;
-		if (!sco_set(sock, opts->mtu, err))
-			goto failed;
-		break;
 	default:
 		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
 				"Unknown BtIO type %d", type);
@@ -1218,18 +1046,12 @@ GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
 	sock = g_io_channel_unix_get_fd(io);
 
 	switch (type) {
-	case BT_IO_L2RAW:
-		err = l2cap_connect(sock, &opts.dst, 0);
-		break;
 	case BT_IO_L2CAP:
 		err = l2cap_connect(sock, &opts.dst, opts.psm);
 		break;
 	case BT_IO_RFCOMM:
 		err = rfcomm_connect(sock, &opts.dst, opts.channel);
 		break;
-	case BT_IO_SCO:
-		err = sco_connect(sock, &opts.dst);
-		break;
 	default:
 		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
 						"Unknown BtIO type %d", type);
@@ -1259,12 +1081,6 @@ GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
 	int sock;
 	gboolean ret;
 
-	if (type == BT_IO_L2RAW) {
-		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-				"Server L2CAP RAW sockets not supported");
-		return NULL;
-	}
-
 	va_start(args, opt1);
 	ret = parse_set_opts(&opts, err, opt1, args);
 	va_end(args);
diff --git a/btio/btio.h b/btio/btio.h
index e9dcc9f..591ceee 100644
--- a/btio/btio.h
+++ b/btio/btio.h
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2009-2010  Nokia Corporation
+ *  Copyright (C) 2010  Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -38,10 +39,8 @@ typedef enum {
 GQuark bt_io_error_quark(void);
 
 typedef enum {
-	BT_IO_L2RAW,
 	BT_IO_L2CAP,
 	BT_IO_RFCOMM,
-	BT_IO_SCO,
 } BtIOType;
 
 typedef enum {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/8] btio: Seperate btio.[ch] into btio directory
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

Seperate btio.[ch] from src directory to btio sub-folder.
---
 Makefile.am |   19 +-
 btio/btio.c | 1299 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 btio/btio.h |   97 +++++
 src/btio.c  | 1299 -----------------------------------------------------------
 src/btio.h  |   97 -----
 5 files changed, 1406 insertions(+), 1405 deletions(-)
 create mode 100644 btio/btio.c
 create mode 100644 btio/btio.h
 delete mode 100644 src/btio.c
 delete mode 100644 src/btio.h

diff --git a/Makefile.am b/Makefile.am
index 73e2f28..a89e62b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,6 +18,8 @@ gwobex_sources = gwobex/gw-obex.h gwobex/gw-obex.c \
 			gwobex/obex-xfer.h gwobex/obex-xfer.c \
 			gwobex/utils.h gwobex/utils.c gwobex/log.h
 
+btio_sources = btio/btio.h btio/btio.c
+
 libexec_PROGRAMS =
 
 if SERVER
@@ -62,11 +64,10 @@ builtin_nodist += plugins/phonebook.c
 
 libexec_PROGRAMS += src/obexd
 
-src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) \
+src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) $(btio_sources) \
 			src/main.c src/obexd.h src/plugin.h src/plugin.c \
-			src/log.h src/log.c src/btio.h src/btio.c \
-			src/dbus.h src/manager.c src/obex.h src/obex.c \
-			src/obex-priv.h \
+			src/log.h src/log.c src/dbus.h src/manager.c \
+			src/obex.h src/obex.c src/obex-priv.h \
 			src/mimetype.h src/mimetype.c \
 			src/service.h src/service.c \
 			src/transport.h src/transport.c \
@@ -104,13 +105,12 @@ service_in_files += client/obex-client.service.in
 
 libexec_PROGRAMS += client/obex-client
 
-client_obex_client_SOURCES = $(gdbus_sources) $(gwobex_sources) client/main.c \
-				client/session.h client/session.c \
+client_obex_client_SOURCES = $(gdbus_sources) $(gwobex_sources) $(btio_sources) \
+				client/main.c client/session.h client/session.c \
 				src/log.h src/log.c \
 				client/pbap.h client/pbap.c \
 				client/sync.h client/sync.c \
-				client/transfer.h client/transfer.c \
-				src/btio.c src/btio.h
+				client/transfer.h client/transfer.c
 
 client_obex_client_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @OPENOBEX_LIBS@ @BLUEZ_LIBS@
 endif
@@ -123,7 +123,8 @@ AM_CFLAGS = @OPENOBEX_CFLAGS@ @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ \
 			-DOBEX_PLUGIN_BUILTIN -DPLUGINDIR=\""$(plugindir)"\"
 
 INCLUDES = -I$(builddir)/src -I$(srcdir)/src -I$(srcdir)/plugins \
-				-I$(srcdir)/gdbus -I$(srcdir)/gwobex
+				-I$(srcdir)/gdbus -I$(srcdir)/gwobex \
+				-I$(srcdir)/btio
 
 CLEANFILES = $(service_DATA) $(builtin_files)
 
diff --git a/btio/btio.c b/btio/btio.c
new file mode 100644
index 0000000..42a3bcd
--- /dev/null
+++ b/btio/btio.c
@@ -0,0 +1,1299 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2009-2010  Nokia Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sco.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include <glib.h>
+
+#include "btio.h"
+
+#define ERROR_FAILED(gerr, str, err) \
+		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED, \
+				str ": %s (%d)", strerror(err), err)
+
+#define DEFAULT_DEFER_TIMEOUT 30
+
+struct set_opts {
+	bdaddr_t src;
+	bdaddr_t dst;
+	int defer;
+	int sec_level;
+	uint8_t channel;
+	uint16_t psm;
+	uint16_t mtu;
+	uint16_t imtu;
+	uint16_t omtu;
+	int master;
+	uint8_t mode;
+};
+
+struct connect {
+	BtIOConnect connect;
+	void *user_data;
+	GDestroyNotify destroy;
+};
+
+struct accept {
+	BtIOConnect connect;
+	void *user_data;
+	GDestroyNotify destroy;
+};
+
+struct server {
+	BtIOConnect connect;
+	BtIOConfirm confirm;
+	void *user_data;
+	GDestroyNotify destroy;
+};
+
+static void server_remove(struct server *server)
+{
+	if (server->destroy)
+		server->destroy(server->user_data);
+	g_free(server);
+}
+
+static void connect_remove(struct connect *conn)
+{
+	if (conn->destroy)
+		conn->destroy(conn->user_data);
+	g_free(conn);
+}
+
+static void accept_remove(struct accept *accept)
+{
+	if (accept->destroy)
+		accept->destroy(accept->user_data);
+	g_free(accept);
+}
+
+static gboolean check_nval(GIOChannel *io)
+{
+	struct pollfd fds;
+
+	memset(&fds, 0, sizeof(fds));
+	fds.fd = g_io_channel_unix_get_fd(io);
+	fds.events = POLLNVAL;
+
+	if (poll(&fds, 1, 0) > 0 && (fds.revents & POLLNVAL))
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean accept_cb(GIOChannel *io, GIOCondition cond,
+							void *user_data)
+{
+	struct accept *accept = user_data;
+	GError *err = NULL;
+
+	/* If the user aborted this accept attempt */
+	if ((cond & G_IO_NVAL) || check_nval(io))
+		return FALSE;
+
+	if (cond & (G_IO_HUP | G_IO_ERR))
+		g_set_error(&err, BT_IO_ERROR, BT_IO_ERROR_DISCONNECTED,
+				"HUP or ERR on socket");
+
+	accept->connect(io, err, accept->user_data);
+
+	g_clear_error(&err);
+
+	return FALSE;
+}
+
+static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
+							void *user_data)
+{
+	struct connect *conn = user_data;
+	GError *gerr = NULL;
+
+	/* If the user aborted this connect attempt */
+	if ((cond & G_IO_NVAL) || check_nval(io))
+		return FALSE;
+
+	if (cond & G_IO_OUT) {
+		int err = 0, sock = g_io_channel_unix_get_fd(io);
+		socklen_t len = sizeof(err);
+
+		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
+			err = errno;
+
+		if (err)
+			g_set_error(&gerr, BT_IO_ERROR,
+					BT_IO_ERROR_CONNECT_FAILED, "%s (%d)",
+					strerror(err), err);
+	} else if (cond & (G_IO_HUP | G_IO_ERR))
+		g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED,
+				"HUP or ERR on socket");
+
+	conn->connect(io, gerr, conn->user_data);
+
+	if (gerr)
+		g_error_free(gerr);
+
+	return FALSE;
+}
+
+static gboolean server_cb(GIOChannel *io, GIOCondition cond,
+							void *user_data)
+{
+	struct server *server = user_data;
+	int srv_sock, cli_sock;
+	GIOChannel *cli_io;
+
+	/* If the user closed the server */
+	if ((cond & G_IO_NVAL) || check_nval(io))
+		return FALSE;
+
+	srv_sock = g_io_channel_unix_get_fd(io);
+
+	cli_sock = accept(srv_sock, NULL, NULL);
+	if (cli_sock < 0)
+		return TRUE;
+
+	cli_io = g_io_channel_unix_new(cli_sock);
+
+	g_io_channel_set_close_on_unref(cli_io, TRUE);
+	g_io_channel_set_flags(cli_io, G_IO_FLAG_NONBLOCK, NULL);
+
+	if (server->confirm)
+		server->confirm(cli_io, server->user_data);
+	else
+		server->connect(cli_io, NULL, server->user_data);
+
+	g_io_channel_unref(cli_io);
+
+	return TRUE;
+}
+
+static void server_add(GIOChannel *io, BtIOConnect connect,
+				BtIOConfirm confirm, void *user_data,
+				GDestroyNotify destroy)
+{
+	struct server *server;
+	GIOCondition cond;
+
+	server = g_new0(struct server, 1);
+	server->connect = connect;
+	server->confirm = confirm;
+	server->user_data = user_data;
+	server->destroy = destroy;
+
+	cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, server_cb, server,
+					(GDestroyNotify) server_remove);
+}
+
+static void connect_add(GIOChannel *io, BtIOConnect connect,
+				void *user_data, GDestroyNotify destroy)
+{
+	struct connect *conn;
+	GIOCondition cond;
+
+	conn = g_new0(struct connect, 1);
+	conn->connect = connect;
+	conn->user_data = user_data;
+	conn->destroy = destroy;
+
+	cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, connect_cb, conn,
+					(GDestroyNotify) connect_remove);
+}
+
+static void accept_add(GIOChannel *io, BtIOConnect connect, void *user_data,
+							GDestroyNotify destroy)
+{
+	struct accept *accept;
+	GIOCondition cond;
+
+	accept = g_new0(struct accept, 1);
+	accept->connect = connect;
+	accept->user_data = user_data;
+	accept->destroy = destroy;
+
+	cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, accept_cb, accept,
+					(GDestroyNotify) accept_remove);
+}
+
+static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm, GError **err)
+{
+	struct sockaddr_l2 addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, src);
+	addr.l2_psm = htobs(psm);
+
+	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		ERROR_FAILED(err, "l2cap_bind", errno);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int l2cap_connect(int sock, const bdaddr_t *dst, uint16_t psm)
+{
+	int err;
+	struct sockaddr_l2 addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, dst);
+	addr.l2_psm = htobs(psm);
+
+	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
+		return err;
+
+	return 0;
+}
+
+static int l2cap_set_master(int sock, int master)
+{
+	int flags;
+	socklen_t len;
+
+	len = sizeof(flags);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, &len) < 0)
+		return -errno;
+
+	if (master) {
+		if (flags & L2CAP_LM_MASTER)
+			return 0;
+		flags |= L2CAP_LM_MASTER;
+	} else {
+		if (!(flags & L2CAP_LM_MASTER))
+			return 0;
+		flags &= ~L2CAP_LM_MASTER;
+	}
+
+	if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, sizeof(flags)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+static int rfcomm_set_master(int sock, int master)
+{
+	int flags;
+	socklen_t len;
+
+	len = sizeof(flags);
+	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, &len) < 0)
+		return -errno;
+
+	if (master) {
+		if (flags & RFCOMM_LM_MASTER)
+			return 0;
+		flags |= RFCOMM_LM_MASTER;
+	} else {
+		if (!(flags & RFCOMM_LM_MASTER))
+			return 0;
+		flags &= ~RFCOMM_LM_MASTER;
+	}
+
+	if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, sizeof(flags)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+static int l2cap_set_lm(int sock, int level)
+{
+	int lm_map[] = {
+		0,
+		L2CAP_LM_AUTH,
+		L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT,
+		L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE,
+	}, opt = lm_map[level];
+
+	if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+static int rfcomm_set_lm(int sock, int level)
+{
+	int lm_map[] = {
+		0,
+		RFCOMM_LM_AUTH,
+		RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT,
+		RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE,
+	}, opt = lm_map[level];
+
+	if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+static gboolean set_sec_level(int sock, BtIOType type, int level, GError **err)
+{
+	struct bt_security sec;
+	int ret;
+
+	if (level < BT_SECURITY_LOW || level > BT_SECURITY_HIGH) {
+		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+				"Valid security level range is %d-%d",
+				BT_SECURITY_LOW, BT_SECURITY_HIGH);
+		return FALSE;
+	}
+
+	memset(&sec, 0, sizeof(sec));
+	sec.level = level;
+
+	if (setsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec,
+							sizeof(sec)) == 0)
+		return TRUE;
+
+	if (errno != ENOPROTOOPT) {
+		ERROR_FAILED(err, "setsockopt(BT_SECURITY)", errno);
+		return FALSE;
+	}
+
+	if (type == BT_IO_L2CAP)
+		ret = l2cap_set_lm(sock, level);
+	else
+		ret = rfcomm_set_lm(sock, level);
+
+	if (ret < 0) {
+		ERROR_FAILED(err, "setsockopt(LM)", -ret);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int l2cap_get_lm(int sock, int *sec_level)
+{
+	int opt;
+	socklen_t len;
+
+	len = sizeof(opt);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, &len) < 0)
+		return -errno;
+
+	*sec_level = 0;
+
+	if (opt & L2CAP_LM_AUTH)
+		*sec_level = BT_SECURITY_LOW;
+	if (opt & L2CAP_LM_ENCRYPT)
+		*sec_level = BT_SECURITY_MEDIUM;
+	if (opt & L2CAP_LM_SECURE)
+		*sec_level = BT_SECURITY_HIGH;
+
+	return 0;
+}
+
+static int rfcomm_get_lm(int sock, int *sec_level)
+{
+	int opt;
+	socklen_t len;
+
+	len = sizeof(opt);
+	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, &len) < 0)
+		return -errno;
+
+	*sec_level = 0;
+
+	if (opt & RFCOMM_LM_AUTH)
+		*sec_level = BT_SECURITY_LOW;
+	if (opt & RFCOMM_LM_ENCRYPT)
+		*sec_level = BT_SECURITY_MEDIUM;
+	if (opt & RFCOMM_LM_SECURE)
+		*sec_level = BT_SECURITY_HIGH;
+
+	return 0;
+}
+
+static gboolean get_sec_level(int sock, BtIOType type, int *level,
+								GError **err)
+{
+	struct bt_security sec;
+	socklen_t len;
+	int ret;
+
+	memset(&sec, 0, sizeof(sec));
+	len = sizeof(sec);
+	if (getsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) == 0) {
+		*level = sec.level;
+		return TRUE;
+	}
+
+	if (errno != ENOPROTOOPT) {
+		ERROR_FAILED(err, "getsockopt(BT_SECURITY)", errno);
+		return FALSE;
+	}
+
+	if (type == BT_IO_L2CAP)
+		ret = l2cap_get_lm(sock, level);
+	else
+		ret = rfcomm_get_lm(sock, level);
+
+	if (ret < 0) {
+		ERROR_FAILED(err, "getsockopt(LM)", -ret);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu, uint16_t omtu,
+					uint8_t mode, int master, GError **err)
+{
+	if (imtu || omtu || mode) {
+		struct l2cap_options l2o;
+		socklen_t len;
+
+		memset(&l2o, 0, sizeof(l2o));
+		len = sizeof(l2o);
+		if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
+								&len) < 0) {
+			ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno);
+			return FALSE;
+		}
+
+		if (imtu)
+			l2o.imtu = imtu;
+		if (omtu)
+			l2o.omtu = omtu;
+		if (mode)
+			l2o.mode = mode;
+
+		if (setsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
+							sizeof(l2o)) < 0) {
+			ERROR_FAILED(err, "setsockopt(L2CAP_OPTIONS)", errno);
+			return FALSE;
+		}
+	}
+
+	if (master >= 0 && l2cap_set_master(sock, master) < 0) {
+		ERROR_FAILED(err, "l2cap_set_master", errno);
+		return FALSE;
+	}
+
+	if (sec_level && !set_sec_level(sock, BT_IO_L2CAP, sec_level, err))
+		return FALSE;
+
+	return TRUE;
+}
+
+static int rfcomm_bind(int sock,
+		const bdaddr_t *src, uint8_t channel, GError **err)
+{
+	struct sockaddr_rc addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, src);
+	addr.rc_channel = channel;
+
+	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		ERROR_FAILED(err, "rfcomm_bind", errno);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int rfcomm_connect(int sock, const bdaddr_t *dst, uint8_t channel)
+{
+	int err;
+	struct sockaddr_rc addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, dst);
+	addr.rc_channel = channel;
+
+	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
+		return err;
+
+	return 0;
+}
+
+static gboolean rfcomm_set(int sock, int sec_level, int master, GError **err)
+{
+	if (sec_level && !set_sec_level(sock, BT_IO_RFCOMM, sec_level, err))
+		return FALSE;
+
+	if (master >= 0 && rfcomm_set_master(sock, master) < 0) {
+		ERROR_FAILED(err, "rfcomm_set_master", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int sco_bind(int sock, const bdaddr_t *src, GError **err)
+{
+	struct sockaddr_sco addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sco_family = AF_BLUETOOTH;
+	bacpy(&addr.sco_bdaddr, src);
+
+	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		ERROR_FAILED(err, "sco_bind", errno);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int sco_connect(int sock, const bdaddr_t *dst)
+{
+	struct sockaddr_sco addr;
+	int err;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sco_family = AF_BLUETOOTH;
+	bacpy(&addr.sco_bdaddr, dst);
+
+	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
+		return err;
+
+	return 0;
+}
+
+static gboolean sco_set(int sock, uint16_t mtu, GError **err)
+{
+	struct sco_options sco_opt;
+	socklen_t len;
+
+	if (!mtu)
+		return TRUE;
+
+	len = sizeof(sco_opt);
+	memset(&sco_opt, 0, len);
+	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
+		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	sco_opt.mtu = mtu;
+	if (setsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt,
+						sizeof(sco_opt)) < 0) {
+		ERROR_FAILED(err, "setsockopt(SCO_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean parse_set_opts(struct set_opts *opts, GError **err,
+						BtIOOption opt1, va_list args)
+{
+	BtIOOption opt = opt1;
+	const char *str;
+
+	memset(opts, 0, sizeof(*opts));
+
+	/* Set defaults */
+	opts->defer = DEFAULT_DEFER_TIMEOUT;
+	opts->master = -1;
+	opts->sec_level = BT_IO_SEC_MEDIUM;
+	opts->mode = L2CAP_MODE_BASIC;
+
+	while (opt != BT_IO_OPT_INVALID) {
+		switch (opt) {
+		case BT_IO_OPT_SOURCE:
+			str = va_arg(args, const char *);
+			if (strncasecmp(str, "hci", 3) == 0)
+				hci_devba(atoi(str + 3), &opts->src);
+			else
+				str2ba(str, &opts->src);
+			break;
+		case BT_IO_OPT_SOURCE_BDADDR:
+			bacpy(&opts->src, va_arg(args, const bdaddr_t *));
+			break;
+		case BT_IO_OPT_DEST:
+			str2ba(va_arg(args, const char *), &opts->dst);
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(&opts->dst, va_arg(args, const bdaddr_t *));
+			break;
+		case BT_IO_OPT_DEFER_TIMEOUT:
+			opts->defer = va_arg(args, int);
+			break;
+		case BT_IO_OPT_SEC_LEVEL:
+			opts->sec_level = va_arg(args, int);
+			break;
+		case BT_IO_OPT_CHANNEL:
+			opts->channel = va_arg(args, int);
+			break;
+		case BT_IO_OPT_PSM:
+			opts->psm = va_arg(args, int);
+			break;
+		case BT_IO_OPT_MTU:
+			opts->mtu = va_arg(args, int);
+			opts->imtu = opts->mtu;
+			opts->omtu = opts->mtu;
+			break;
+		case BT_IO_OPT_OMTU:
+			opts->omtu = va_arg(args, int);
+			if (!opts->mtu)
+				opts->mtu = opts->omtu;
+			break;
+		case BT_IO_OPT_IMTU:
+			opts->imtu = va_arg(args, int);
+			if (!opts->mtu)
+				opts->mtu = opts->imtu;
+			break;
+		case BT_IO_OPT_MASTER:
+			opts->master = va_arg(args, gboolean);
+			break;
+		case BT_IO_OPT_MODE:
+			opts->mode = va_arg(args, int);
+			break;
+		default:
+			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+					"Unknown option %d", opt);
+			return FALSE;
+		}
+
+		opt = va_arg(args, int);
+	}
+
+	return TRUE;
+}
+
+static gboolean get_peers(int sock, struct sockaddr *src, struct sockaddr *dst,
+				socklen_t len, GError **err)
+{
+	socklen_t olen;
+
+	memset(src, 0, len);
+	olen = len;
+	if (getsockname(sock, src, &olen) < 0) {
+		ERROR_FAILED(err, "getsockname", errno);
+		return FALSE;
+	}
+
+	memset(dst, 0, len);
+	olen = len;
+	if (getpeername(sock, dst, &olen) < 0) {
+		ERROR_FAILED(err, "getpeername", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int l2cap_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+	struct l2cap_conninfo info;
+	socklen_t len;
+
+	len = sizeof(info);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_CONNINFO, &info, &len) < 0)
+		return -errno;
+
+	if (handle)
+		*handle = info.hci_handle;
+
+	if (dev_class)
+		memcpy(dev_class, info.dev_class, 3);
+
+	return 0;
+}
+
+static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
+								va_list args)
+{
+	BtIOOption opt = opt1;
+	struct sockaddr_l2 src, dst;
+	struct l2cap_options l2o;
+	int flags;
+	uint8_t dev_class[3];
+	uint16_t handle;
+	socklen_t len;
+
+	len = sizeof(l2o);
+	memset(&l2o, 0, len);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) {
+		ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	if (!get_peers(sock, (struct sockaddr *) &src,
+				(struct sockaddr *) &dst, sizeof(src), err))
+		return FALSE;
+
+	while (opt != BT_IO_OPT_INVALID) {
+		switch (opt) {
+		case BT_IO_OPT_SOURCE:
+			ba2str(&src.l2_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_SOURCE_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &src.l2_bdaddr);
+			break;
+		case BT_IO_OPT_DEST:
+			ba2str(&dst.l2_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &dst.l2_bdaddr);
+			break;
+		case BT_IO_OPT_DEFER_TIMEOUT:
+			len = sizeof(int);
+			if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP,
+					va_arg(args, int *), &len) < 0) {
+				ERROR_FAILED(err, "getsockopt(DEFER_SETUP)",
+									errno);
+				return FALSE;
+			}
+			break;
+		case BT_IO_OPT_SEC_LEVEL:
+			if (!get_sec_level(sock, BT_IO_L2CAP,
+						va_arg(args, int *), err))
+				return FALSE;
+			break;
+		case BT_IO_OPT_PSM:
+			*(va_arg(args, uint16_t *)) = src.l2_psm ?
+						src.l2_psm : dst.l2_psm;
+			break;
+		case BT_IO_OPT_OMTU:
+			*(va_arg(args, uint16_t *)) = l2o.omtu;
+			break;
+		case BT_IO_OPT_IMTU:
+			*(va_arg(args, uint16_t *)) = l2o.imtu;
+			break;
+		case BT_IO_OPT_MASTER:
+			len = sizeof(flags);
+			if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags,
+								&len) < 0) {
+				ERROR_FAILED(err, "getsockopt(L2CAP_LM)",
+									errno);
+				return FALSE;
+			}
+			*(va_arg(args, gboolean *)) =
+				(flags & L2CAP_LM_MASTER) ? TRUE : FALSE;
+			break;
+		case BT_IO_OPT_HANDLE:
+			if (l2cap_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "L2CAP_CONNINFO", errno);
+				return FALSE;
+			}
+			*(va_arg(args, uint16_t *)) = handle;
+			break;
+		case BT_IO_OPT_CLASS:
+			if (l2cap_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "L2CAP_CONNINFO", errno);
+				return FALSE;
+			}
+			memcpy(va_arg(args, uint8_t *), dev_class, 3);
+			break;
+		default:
+			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+					"Unknown option %d", opt);
+			return FALSE;
+		}
+
+		opt = va_arg(args, int);
+	}
+
+	return TRUE;
+}
+
+static int rfcomm_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+	struct rfcomm_conninfo info;
+	socklen_t len;
+
+	len = sizeof(info);
+	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_CONNINFO, &info, &len) < 0)
+		return -errno;
+
+	if (handle)
+		*handle = info.hci_handle;
+
+	if (dev_class)
+		memcpy(dev_class, info.dev_class, 3);
+
+	return 0;
+}
+
+static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
+								va_list args)
+{
+	BtIOOption opt = opt1;
+	struct sockaddr_rc src, dst;
+	int flags;
+	socklen_t len;
+	uint8_t dev_class[3];
+	uint16_t handle;
+
+	if (!get_peers(sock, (struct sockaddr *) &src,
+				(struct sockaddr *) &dst, sizeof(src), err))
+		return FALSE;
+
+	while (opt != BT_IO_OPT_INVALID) {
+		switch (opt) {
+		case BT_IO_OPT_SOURCE:
+			ba2str(&src.rc_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_SOURCE_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &src.rc_bdaddr);
+			break;
+		case BT_IO_OPT_DEST:
+			ba2str(&dst.rc_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &dst.rc_bdaddr);
+			break;
+		case BT_IO_OPT_DEFER_TIMEOUT:
+			len = sizeof(int);
+			if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP,
+					va_arg(args, int *), &len) < 0) {
+				ERROR_FAILED(err, "getsockopt(DEFER_SETUP)",
+									errno);
+				return FALSE;
+			}
+			break;
+		case BT_IO_OPT_SEC_LEVEL:
+			if (!get_sec_level(sock, BT_IO_RFCOMM,
+						va_arg(args, int *), err))
+				return FALSE;
+			break;
+		case BT_IO_OPT_CHANNEL:
+			*(va_arg(args, uint8_t *)) = src.rc_channel ?
+					src.rc_channel : dst.rc_channel;
+			break;
+		case BT_IO_OPT_SOURCE_CHANNEL:
+			*(va_arg(args, uint8_t *)) = src.rc_channel;
+			break;
+		case BT_IO_OPT_DEST_CHANNEL:
+			*(va_arg(args, uint8_t *)) = dst.rc_channel;
+			break;
+		case BT_IO_OPT_MASTER:
+			len = sizeof(flags);
+			if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags,
+								&len) < 0) {
+				ERROR_FAILED(err, "getsockopt(RFCOMM_LM)",
+									errno);
+				return FALSE;
+			}
+			*(va_arg(args, gboolean *)) =
+				(flags & RFCOMM_LM_MASTER) ? TRUE : FALSE;
+			break;
+		case BT_IO_OPT_HANDLE:
+			if (rfcomm_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			*(va_arg(args, uint16_t *)) = handle;
+			break;
+		case BT_IO_OPT_CLASS:
+			if (rfcomm_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			memcpy(va_arg(args, uint8_t *), dev_class, 3);
+			break;
+		default:
+			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+					"Unknown option %d", opt);
+			return FALSE;
+		}
+
+		opt = va_arg(args, int);
+	}
+
+	return TRUE;
+}
+
+static int sco_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+	struct sco_conninfo info;
+	socklen_t len;
+
+	len = sizeof(info);
+	if (getsockopt(sock, SOL_SCO, SCO_CONNINFO, &info, &len) < 0)
+		return -errno;
+
+	if (handle)
+		*handle = info.hci_handle;
+
+	if (dev_class)
+		memcpy(dev_class, info.dev_class, 3);
+
+	return 0;
+}
+
+static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
+{
+	BtIOOption opt = opt1;
+	struct sockaddr_sco src, dst;
+	struct sco_options sco_opt;
+	socklen_t len;
+	uint8_t dev_class[3];
+	uint16_t handle;
+
+	len = sizeof(sco_opt);
+	memset(&sco_opt, 0, len);
+	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
+		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	if (!get_peers(sock, (struct sockaddr *) &src,
+				(struct sockaddr *) &dst, sizeof(src), err))
+		return FALSE;
+
+	while (opt != BT_IO_OPT_INVALID) {
+		switch (opt) {
+		case BT_IO_OPT_SOURCE:
+			ba2str(&src.sco_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_SOURCE_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &src.sco_bdaddr);
+			break;
+		case BT_IO_OPT_DEST:
+			ba2str(&dst.sco_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &dst.sco_bdaddr);
+			break;
+		case BT_IO_OPT_MTU:
+		case BT_IO_OPT_IMTU:
+		case BT_IO_OPT_OMTU:
+			*(va_arg(args, uint16_t *)) = sco_opt.mtu;
+			break;
+		case BT_IO_OPT_HANDLE:
+			if (sco_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			*(va_arg(args, uint16_t *)) = handle;
+			break;
+		case BT_IO_OPT_CLASS:
+			if (sco_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			memcpy(va_arg(args, uint8_t *), dev_class, 3);
+			break;
+		default:
+			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+					"Unknown option %d", opt);
+			return FALSE;
+		}
+
+		opt = va_arg(args, int);
+	}
+
+	return TRUE;
+}
+
+static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err,
+						BtIOOption opt1, va_list args)
+{
+	int sock;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	switch (type) {
+	case BT_IO_L2RAW:
+	case BT_IO_L2CAP:
+		return l2cap_get(sock, err, opt1, args);
+	case BT_IO_RFCOMM:
+		return rfcomm_get(sock, err, opt1, args);
+	case BT_IO_SCO:
+		return sco_get(sock, err, opt1, args);
+	}
+
+	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+			"Unknown BtIO type %d", type);
+	return FALSE;
+}
+
+gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
+					GDestroyNotify destroy, GError **err)
+{
+	int sock;
+	char c;
+	struct pollfd pfd;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	memset(&pfd, 0, sizeof(pfd));
+	pfd.fd = sock;
+	pfd.events = POLLOUT;
+
+	if (poll(&pfd, 1, 0) < 0) {
+		ERROR_FAILED(err, "poll", errno);
+		return FALSE;
+	}
+
+	if (!(pfd.revents & POLLOUT)) {
+		int ret;
+		ret = read(sock, &c, 1);
+	}
+
+	accept_add(io, connect, user_data, destroy);
+
+	return TRUE;
+}
+
+gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
+							BtIOOption opt1, ...)
+{
+	va_list args;
+	gboolean ret;
+	struct set_opts opts;
+	int sock;
+
+	va_start(args, opt1);
+	ret = parse_set_opts(&opts, err, opt1, args);
+	va_end(args);
+
+	if (!ret)
+		return ret;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	switch (type) {
+	case BT_IO_L2RAW:
+	case BT_IO_L2CAP:
+		return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu,
+						opts.mode, opts.master, err);
+	case BT_IO_RFCOMM:
+		return rfcomm_set(sock, opts.sec_level, opts.master, err);
+	case BT_IO_SCO:
+		return sco_set(sock, opts.mtu, err);
+	}
+
+	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+			"Unknown BtIO type %d", type);
+	return FALSE;
+}
+
+gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
+							BtIOOption opt1, ...)
+{
+	va_list args;
+	gboolean ret;
+
+	va_start(args, opt1);
+	ret = get_valist(io, type, err, opt1, args);
+	va_end(args);
+
+	return ret;
+}
+
+static GIOChannel *create_io(BtIOType type, gboolean server,
+					struct set_opts *opts, GError **err)
+{
+	int sock;
+	GIOChannel *io;
+
+	switch (type) {
+	case BT_IO_L2RAW:
+		sock = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
+		if (sock < 0) {
+			ERROR_FAILED(err, "socket(RAW, L2CAP)", errno);
+			return NULL;
+		}
+		if (l2cap_bind(sock, &opts->src,
+					server ? opts->psm : 0, err) < 0)
+			goto failed;
+		if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err))
+			goto failed;
+		break;
+	case BT_IO_L2CAP:
+		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+		if (sock < 0) {
+			ERROR_FAILED(err, "socket(SEQPACKET, L2CAP)", errno);
+			return NULL;
+		}
+		if (l2cap_bind(sock, &opts->src,
+					server ? opts->psm : 0, err) < 0)
+			goto failed;
+		if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu,
+						opts->mode, opts->master, err))
+			goto failed;
+		break;
+	case BT_IO_RFCOMM:
+		sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+		if (sock < 0) {
+			ERROR_FAILED(err, "socket(STREAM, RFCOMM)", errno);
+			return NULL;
+		}
+		if (rfcomm_bind(sock, &opts->src,
+					server ? opts->channel : 0, err) < 0)
+			goto failed;
+		if (!rfcomm_set(sock, opts->sec_level, opts->master, err))
+			goto failed;
+		break;
+	case BT_IO_SCO:
+		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
+		if (sock < 0) {
+			ERROR_FAILED(err, "socket(SEQPACKET, SCO)", errno);
+			return NULL;
+		}
+		if (sco_bind(sock, &opts->src, err) < 0)
+			goto failed;
+		if (!sco_set(sock, opts->mtu, err))
+			goto failed;
+		break;
+	default:
+		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+				"Unknown BtIO type %d", type);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(sock);
+
+	g_io_channel_set_close_on_unref(io, TRUE);
+	g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
+
+	return io;
+
+failed:
+	close(sock);
+
+	return NULL;
+}
+
+GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
+				void *user_data, GDestroyNotify destroy,
+				GError **gerr, BtIOOption opt1, ...)
+{
+	GIOChannel *io;
+	va_list args;
+	struct set_opts opts;
+	int err, sock;
+	gboolean ret;
+
+	va_start(args, opt1);
+	ret = parse_set_opts(&opts, gerr, opt1, args);
+	va_end(args);
+
+	if (ret == FALSE)
+		return NULL;
+
+	io = create_io(type, FALSE, &opts, gerr);
+	if (io == NULL)
+		return NULL;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	switch (type) {
+	case BT_IO_L2RAW:
+		err = l2cap_connect(sock, &opts.dst, 0);
+		break;
+	case BT_IO_L2CAP:
+		err = l2cap_connect(sock, &opts.dst, opts.psm);
+		break;
+	case BT_IO_RFCOMM:
+		err = rfcomm_connect(sock, &opts.dst, opts.channel);
+		break;
+	case BT_IO_SCO:
+		err = sco_connect(sock, &opts.dst);
+		break;
+	default:
+		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+						"Unknown BtIO type %d", type);
+		return NULL;
+	}
+
+	if (err < 0) {
+		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED,
+				"connect: %s (%d)", strerror(-err), -err);
+		g_io_channel_unref(io);
+		return NULL;
+	}
+
+	connect_add(io, connect, user_data, destroy);
+
+	return io;
+}
+
+GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
+				BtIOConfirm confirm, void *user_data,
+				GDestroyNotify destroy, GError **err,
+				BtIOOption opt1, ...)
+{
+	GIOChannel *io;
+	va_list args;
+	struct set_opts opts;
+	int sock;
+	gboolean ret;
+
+	if (type == BT_IO_L2RAW) {
+		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+				"Server L2CAP RAW sockets not supported");
+		return NULL;
+	}
+
+	va_start(args, opt1);
+	ret = parse_set_opts(&opts, err, opt1, args);
+	va_end(args);
+
+	if (ret == FALSE)
+		return NULL;
+
+	io = create_io(type, TRUE, &opts, err);
+	if (io == NULL)
+		return NULL;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	if (confirm)
+		setsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, &opts.defer,
+							sizeof(opts.defer));
+
+	if (listen(sock, 5) < 0) {
+		ERROR_FAILED(err, "listen", errno);
+		g_io_channel_unref(io);
+		return NULL;
+	}
+
+	server_add(io, connect, confirm, user_data, destroy);
+
+	return io;
+}
+
+GQuark bt_io_error_quark(void)
+{
+	return g_quark_from_static_string("bt-io-error-quark");
+}
diff --git a/btio/btio.h b/btio/btio.h
new file mode 100644
index 0000000..e9dcc9f
--- /dev/null
+++ b/btio/btio.h
@@ -0,0 +1,97 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2009-2010  Nokia Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifndef BT_IO_H
+#define BT_IO_H
+
+#include <glib.h>
+
+typedef enum {
+	BT_IO_ERROR_DISCONNECTED,
+	BT_IO_ERROR_CONNECT_FAILED,
+	BT_IO_ERROR_FAILED,
+	BT_IO_ERROR_INVALID_ARGS,
+} BtIOError;
+
+#define BT_IO_ERROR bt_io_error_quark()
+
+GQuark bt_io_error_quark(void);
+
+typedef enum {
+	BT_IO_L2RAW,
+	BT_IO_L2CAP,
+	BT_IO_RFCOMM,
+	BT_IO_SCO,
+} BtIOType;
+
+typedef enum {
+	BT_IO_OPT_INVALID = 0,
+	BT_IO_OPT_SOURCE,
+	BT_IO_OPT_SOURCE_BDADDR,
+	BT_IO_OPT_DEST,
+	BT_IO_OPT_DEST_BDADDR,
+	BT_IO_OPT_DEFER_TIMEOUT,
+	BT_IO_OPT_SEC_LEVEL,
+	BT_IO_OPT_CHANNEL,
+	BT_IO_OPT_SOURCE_CHANNEL,
+	BT_IO_OPT_DEST_CHANNEL,
+	BT_IO_OPT_PSM,
+	BT_IO_OPT_MTU,
+	BT_IO_OPT_OMTU,
+	BT_IO_OPT_IMTU,
+	BT_IO_OPT_MASTER,
+	BT_IO_OPT_HANDLE,
+	BT_IO_OPT_CLASS,
+	BT_IO_OPT_MODE,
+} BtIOOption;
+
+typedef enum {
+	BT_IO_SEC_SDP = 0,
+	BT_IO_SEC_LOW,
+	BT_IO_SEC_MEDIUM,
+	BT_IO_SEC_HIGH,
+} BtIOSecLevel;
+
+typedef void (*BtIOConfirm)(GIOChannel *io, void *user_data);
+
+typedef void (*BtIOConnect)(GIOChannel *io, GError *err, void *user_data);
+
+gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
+					GDestroyNotify destroy, GError **err);
+
+gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
+						BtIOOption opt1, ...);
+
+gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
+						BtIOOption opt1, ...);
+
+GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
+				void *user_data, GDestroyNotify destroy,
+				GError **err, BtIOOption opt1, ...);
+
+GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
+				BtIOConfirm confirm, void *user_data,
+				GDestroyNotify destroy, GError **err,
+				BtIOOption opt1, ...);
+
+#endif
diff --git a/src/btio.c b/src/btio.c
deleted file mode 100644
index 42a3bcd..0000000
--- a/src/btio.c
+++ /dev/null
@@ -1,1299 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (C) 2009-2010  Nokia Corporation
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <poll.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sco.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-
-#include <glib.h>
-
-#include "btio.h"
-
-#define ERROR_FAILED(gerr, str, err) \
-		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED, \
-				str ": %s (%d)", strerror(err), err)
-
-#define DEFAULT_DEFER_TIMEOUT 30
-
-struct set_opts {
-	bdaddr_t src;
-	bdaddr_t dst;
-	int defer;
-	int sec_level;
-	uint8_t channel;
-	uint16_t psm;
-	uint16_t mtu;
-	uint16_t imtu;
-	uint16_t omtu;
-	int master;
-	uint8_t mode;
-};
-
-struct connect {
-	BtIOConnect connect;
-	void *user_data;
-	GDestroyNotify destroy;
-};
-
-struct accept {
-	BtIOConnect connect;
-	void *user_data;
-	GDestroyNotify destroy;
-};
-
-struct server {
-	BtIOConnect connect;
-	BtIOConfirm confirm;
-	void *user_data;
-	GDestroyNotify destroy;
-};
-
-static void server_remove(struct server *server)
-{
-	if (server->destroy)
-		server->destroy(server->user_data);
-	g_free(server);
-}
-
-static void connect_remove(struct connect *conn)
-{
-	if (conn->destroy)
-		conn->destroy(conn->user_data);
-	g_free(conn);
-}
-
-static void accept_remove(struct accept *accept)
-{
-	if (accept->destroy)
-		accept->destroy(accept->user_data);
-	g_free(accept);
-}
-
-static gboolean check_nval(GIOChannel *io)
-{
-	struct pollfd fds;
-
-	memset(&fds, 0, sizeof(fds));
-	fds.fd = g_io_channel_unix_get_fd(io);
-	fds.events = POLLNVAL;
-
-	if (poll(&fds, 1, 0) > 0 && (fds.revents & POLLNVAL))
-		return TRUE;
-
-	return FALSE;
-}
-
-static gboolean accept_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
-{
-	struct accept *accept = user_data;
-	GError *err = NULL;
-
-	/* If the user aborted this accept attempt */
-	if ((cond & G_IO_NVAL) || check_nval(io))
-		return FALSE;
-
-	if (cond & (G_IO_HUP | G_IO_ERR))
-		g_set_error(&err, BT_IO_ERROR, BT_IO_ERROR_DISCONNECTED,
-				"HUP or ERR on socket");
-
-	accept->connect(io, err, accept->user_data);
-
-	g_clear_error(&err);
-
-	return FALSE;
-}
-
-static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
-{
-	struct connect *conn = user_data;
-	GError *gerr = NULL;
-
-	/* If the user aborted this connect attempt */
-	if ((cond & G_IO_NVAL) || check_nval(io))
-		return FALSE;
-
-	if (cond & G_IO_OUT) {
-		int err = 0, sock = g_io_channel_unix_get_fd(io);
-		socklen_t len = sizeof(err);
-
-		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
-			err = errno;
-
-		if (err)
-			g_set_error(&gerr, BT_IO_ERROR,
-					BT_IO_ERROR_CONNECT_FAILED, "%s (%d)",
-					strerror(err), err);
-	} else if (cond & (G_IO_HUP | G_IO_ERR))
-		g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED,
-				"HUP or ERR on socket");
-
-	conn->connect(io, gerr, conn->user_data);
-
-	if (gerr)
-		g_error_free(gerr);
-
-	return FALSE;
-}
-
-static gboolean server_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
-{
-	struct server *server = user_data;
-	int srv_sock, cli_sock;
-	GIOChannel *cli_io;
-
-	/* If the user closed the server */
-	if ((cond & G_IO_NVAL) || check_nval(io))
-		return FALSE;
-
-	srv_sock = g_io_channel_unix_get_fd(io);
-
-	cli_sock = accept(srv_sock, NULL, NULL);
-	if (cli_sock < 0)
-		return TRUE;
-
-	cli_io = g_io_channel_unix_new(cli_sock);
-
-	g_io_channel_set_close_on_unref(cli_io, TRUE);
-	g_io_channel_set_flags(cli_io, G_IO_FLAG_NONBLOCK, NULL);
-
-	if (server->confirm)
-		server->confirm(cli_io, server->user_data);
-	else
-		server->connect(cli_io, NULL, server->user_data);
-
-	g_io_channel_unref(cli_io);
-
-	return TRUE;
-}
-
-static void server_add(GIOChannel *io, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
-				GDestroyNotify destroy)
-{
-	struct server *server;
-	GIOCondition cond;
-
-	server = g_new0(struct server, 1);
-	server->connect = connect;
-	server->confirm = confirm;
-	server->user_data = user_data;
-	server->destroy = destroy;
-
-	cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
-	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, server_cb, server,
-					(GDestroyNotify) server_remove);
-}
-
-static void connect_add(GIOChannel *io, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy)
-{
-	struct connect *conn;
-	GIOCondition cond;
-
-	conn = g_new0(struct connect, 1);
-	conn->connect = connect;
-	conn->user_data = user_data;
-	conn->destroy = destroy;
-
-	cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
-	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, connect_cb, conn,
-					(GDestroyNotify) connect_remove);
-}
-
-static void accept_add(GIOChannel *io, BtIOConnect connect, void *user_data,
-							GDestroyNotify destroy)
-{
-	struct accept *accept;
-	GIOCondition cond;
-
-	accept = g_new0(struct accept, 1);
-	accept->connect = connect;
-	accept->user_data = user_data;
-	accept->destroy = destroy;
-
-	cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
-	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, accept_cb, accept,
-					(GDestroyNotify) accept_remove);
-}
-
-static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm, GError **err)
-{
-	struct sockaddr_l2 addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.l2_family = AF_BLUETOOTH;
-	bacpy(&addr.l2_bdaddr, src);
-	addr.l2_psm = htobs(psm);
-
-	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		ERROR_FAILED(err, "l2cap_bind", errno);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int l2cap_connect(int sock, const bdaddr_t *dst, uint16_t psm)
-{
-	int err;
-	struct sockaddr_l2 addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.l2_family = AF_BLUETOOTH;
-	bacpy(&addr.l2_bdaddr, dst);
-	addr.l2_psm = htobs(psm);
-
-	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
-	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
-		return err;
-
-	return 0;
-}
-
-static int l2cap_set_master(int sock, int master)
-{
-	int flags;
-	socklen_t len;
-
-	len = sizeof(flags);
-	if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, &len) < 0)
-		return -errno;
-
-	if (master) {
-		if (flags & L2CAP_LM_MASTER)
-			return 0;
-		flags |= L2CAP_LM_MASTER;
-	} else {
-		if (!(flags & L2CAP_LM_MASTER))
-			return 0;
-		flags &= ~L2CAP_LM_MASTER;
-	}
-
-	if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, sizeof(flags)) < 0)
-		return -errno;
-
-	return 0;
-}
-
-static int rfcomm_set_master(int sock, int master)
-{
-	int flags;
-	socklen_t len;
-
-	len = sizeof(flags);
-	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, &len) < 0)
-		return -errno;
-
-	if (master) {
-		if (flags & RFCOMM_LM_MASTER)
-			return 0;
-		flags |= RFCOMM_LM_MASTER;
-	} else {
-		if (!(flags & RFCOMM_LM_MASTER))
-			return 0;
-		flags &= ~RFCOMM_LM_MASTER;
-	}
-
-	if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, sizeof(flags)) < 0)
-		return -errno;
-
-	return 0;
-}
-
-static int l2cap_set_lm(int sock, int level)
-{
-	int lm_map[] = {
-		0,
-		L2CAP_LM_AUTH,
-		L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT,
-		L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE,
-	}, opt = lm_map[level];
-
-	if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0)
-		return -errno;
-
-	return 0;
-}
-
-static int rfcomm_set_lm(int sock, int level)
-{
-	int lm_map[] = {
-		0,
-		RFCOMM_LM_AUTH,
-		RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT,
-		RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE,
-	}, opt = lm_map[level];
-
-	if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)) < 0)
-		return -errno;
-
-	return 0;
-}
-
-static gboolean set_sec_level(int sock, BtIOType type, int level, GError **err)
-{
-	struct bt_security sec;
-	int ret;
-
-	if (level < BT_SECURITY_LOW || level > BT_SECURITY_HIGH) {
-		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-				"Valid security level range is %d-%d",
-				BT_SECURITY_LOW, BT_SECURITY_HIGH);
-		return FALSE;
-	}
-
-	memset(&sec, 0, sizeof(sec));
-	sec.level = level;
-
-	if (setsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec,
-							sizeof(sec)) == 0)
-		return TRUE;
-
-	if (errno != ENOPROTOOPT) {
-		ERROR_FAILED(err, "setsockopt(BT_SECURITY)", errno);
-		return FALSE;
-	}
-
-	if (type == BT_IO_L2CAP)
-		ret = l2cap_set_lm(sock, level);
-	else
-		ret = rfcomm_set_lm(sock, level);
-
-	if (ret < 0) {
-		ERROR_FAILED(err, "setsockopt(LM)", -ret);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static int l2cap_get_lm(int sock, int *sec_level)
-{
-	int opt;
-	socklen_t len;
-
-	len = sizeof(opt);
-	if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, &len) < 0)
-		return -errno;
-
-	*sec_level = 0;
-
-	if (opt & L2CAP_LM_AUTH)
-		*sec_level = BT_SECURITY_LOW;
-	if (opt & L2CAP_LM_ENCRYPT)
-		*sec_level = BT_SECURITY_MEDIUM;
-	if (opt & L2CAP_LM_SECURE)
-		*sec_level = BT_SECURITY_HIGH;
-
-	return 0;
-}
-
-static int rfcomm_get_lm(int sock, int *sec_level)
-{
-	int opt;
-	socklen_t len;
-
-	len = sizeof(opt);
-	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, &len) < 0)
-		return -errno;
-
-	*sec_level = 0;
-
-	if (opt & RFCOMM_LM_AUTH)
-		*sec_level = BT_SECURITY_LOW;
-	if (opt & RFCOMM_LM_ENCRYPT)
-		*sec_level = BT_SECURITY_MEDIUM;
-	if (opt & RFCOMM_LM_SECURE)
-		*sec_level = BT_SECURITY_HIGH;
-
-	return 0;
-}
-
-static gboolean get_sec_level(int sock, BtIOType type, int *level,
-								GError **err)
-{
-	struct bt_security sec;
-	socklen_t len;
-	int ret;
-
-	memset(&sec, 0, sizeof(sec));
-	len = sizeof(sec);
-	if (getsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) == 0) {
-		*level = sec.level;
-		return TRUE;
-	}
-
-	if (errno != ENOPROTOOPT) {
-		ERROR_FAILED(err, "getsockopt(BT_SECURITY)", errno);
-		return FALSE;
-	}
-
-	if (type == BT_IO_L2CAP)
-		ret = l2cap_get_lm(sock, level);
-	else
-		ret = rfcomm_get_lm(sock, level);
-
-	if (ret < 0) {
-		ERROR_FAILED(err, "getsockopt(LM)", -ret);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu, uint16_t omtu,
-					uint8_t mode, int master, GError **err)
-{
-	if (imtu || omtu || mode) {
-		struct l2cap_options l2o;
-		socklen_t len;
-
-		memset(&l2o, 0, sizeof(l2o));
-		len = sizeof(l2o);
-		if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
-								&len) < 0) {
-			ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno);
-			return FALSE;
-		}
-
-		if (imtu)
-			l2o.imtu = imtu;
-		if (omtu)
-			l2o.omtu = omtu;
-		if (mode)
-			l2o.mode = mode;
-
-		if (setsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
-							sizeof(l2o)) < 0) {
-			ERROR_FAILED(err, "setsockopt(L2CAP_OPTIONS)", errno);
-			return FALSE;
-		}
-	}
-
-	if (master >= 0 && l2cap_set_master(sock, master) < 0) {
-		ERROR_FAILED(err, "l2cap_set_master", errno);
-		return FALSE;
-	}
-
-	if (sec_level && !set_sec_level(sock, BT_IO_L2CAP, sec_level, err))
-		return FALSE;
-
-	return TRUE;
-}
-
-static int rfcomm_bind(int sock,
-		const bdaddr_t *src, uint8_t channel, GError **err)
-{
-	struct sockaddr_rc addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.rc_family = AF_BLUETOOTH;
-	bacpy(&addr.rc_bdaddr, src);
-	addr.rc_channel = channel;
-
-	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		ERROR_FAILED(err, "rfcomm_bind", errno);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int rfcomm_connect(int sock, const bdaddr_t *dst, uint8_t channel)
-{
-	int err;
-	struct sockaddr_rc addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.rc_family = AF_BLUETOOTH;
-	bacpy(&addr.rc_bdaddr, dst);
-	addr.rc_channel = channel;
-
-	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
-	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
-		return err;
-
-	return 0;
-}
-
-static gboolean rfcomm_set(int sock, int sec_level, int master, GError **err)
-{
-	if (sec_level && !set_sec_level(sock, BT_IO_RFCOMM, sec_level, err))
-		return FALSE;
-
-	if (master >= 0 && rfcomm_set_master(sock, master) < 0) {
-		ERROR_FAILED(err, "rfcomm_set_master", errno);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static int sco_bind(int sock, const bdaddr_t *src, GError **err)
-{
-	struct sockaddr_sco addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sco_family = AF_BLUETOOTH;
-	bacpy(&addr.sco_bdaddr, src);
-
-	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		ERROR_FAILED(err, "sco_bind", errno);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int sco_connect(int sock, const bdaddr_t *dst)
-{
-	struct sockaddr_sco addr;
-	int err;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sco_family = AF_BLUETOOTH;
-	bacpy(&addr.sco_bdaddr, dst);
-
-	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
-	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
-		return err;
-
-	return 0;
-}
-
-static gboolean sco_set(int sock, uint16_t mtu, GError **err)
-{
-	struct sco_options sco_opt;
-	socklen_t len;
-
-	if (!mtu)
-		return TRUE;
-
-	len = sizeof(sco_opt);
-	memset(&sco_opt, 0, len);
-	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
-		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
-		return FALSE;
-	}
-
-	sco_opt.mtu = mtu;
-	if (setsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt,
-						sizeof(sco_opt)) < 0) {
-		ERROR_FAILED(err, "setsockopt(SCO_OPTIONS)", errno);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static gboolean parse_set_opts(struct set_opts *opts, GError **err,
-						BtIOOption opt1, va_list args)
-{
-	BtIOOption opt = opt1;
-	const char *str;
-
-	memset(opts, 0, sizeof(*opts));
-
-	/* Set defaults */
-	opts->defer = DEFAULT_DEFER_TIMEOUT;
-	opts->master = -1;
-	opts->sec_level = BT_IO_SEC_MEDIUM;
-	opts->mode = L2CAP_MODE_BASIC;
-
-	while (opt != BT_IO_OPT_INVALID) {
-		switch (opt) {
-		case BT_IO_OPT_SOURCE:
-			str = va_arg(args, const char *);
-			if (strncasecmp(str, "hci", 3) == 0)
-				hci_devba(atoi(str + 3), &opts->src);
-			else
-				str2ba(str, &opts->src);
-			break;
-		case BT_IO_OPT_SOURCE_BDADDR:
-			bacpy(&opts->src, va_arg(args, const bdaddr_t *));
-			break;
-		case BT_IO_OPT_DEST:
-			str2ba(va_arg(args, const char *), &opts->dst);
-			break;
-		case BT_IO_OPT_DEST_BDADDR:
-			bacpy(&opts->dst, va_arg(args, const bdaddr_t *));
-			break;
-		case BT_IO_OPT_DEFER_TIMEOUT:
-			opts->defer = va_arg(args, int);
-			break;
-		case BT_IO_OPT_SEC_LEVEL:
-			opts->sec_level = va_arg(args, int);
-			break;
-		case BT_IO_OPT_CHANNEL:
-			opts->channel = va_arg(args, int);
-			break;
-		case BT_IO_OPT_PSM:
-			opts->psm = va_arg(args, int);
-			break;
-		case BT_IO_OPT_MTU:
-			opts->mtu = va_arg(args, int);
-			opts->imtu = opts->mtu;
-			opts->omtu = opts->mtu;
-			break;
-		case BT_IO_OPT_OMTU:
-			opts->omtu = va_arg(args, int);
-			if (!opts->mtu)
-				opts->mtu = opts->omtu;
-			break;
-		case BT_IO_OPT_IMTU:
-			opts->imtu = va_arg(args, int);
-			if (!opts->mtu)
-				opts->mtu = opts->imtu;
-			break;
-		case BT_IO_OPT_MASTER:
-			opts->master = va_arg(args, gboolean);
-			break;
-		case BT_IO_OPT_MODE:
-			opts->mode = va_arg(args, int);
-			break;
-		default:
-			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-					"Unknown option %d", opt);
-			return FALSE;
-		}
-
-		opt = va_arg(args, int);
-	}
-
-	return TRUE;
-}
-
-static gboolean get_peers(int sock, struct sockaddr *src, struct sockaddr *dst,
-				socklen_t len, GError **err)
-{
-	socklen_t olen;
-
-	memset(src, 0, len);
-	olen = len;
-	if (getsockname(sock, src, &olen) < 0) {
-		ERROR_FAILED(err, "getsockname", errno);
-		return FALSE;
-	}
-
-	memset(dst, 0, len);
-	olen = len;
-	if (getpeername(sock, dst, &olen) < 0) {
-		ERROR_FAILED(err, "getpeername", errno);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static int l2cap_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
-{
-	struct l2cap_conninfo info;
-	socklen_t len;
-
-	len = sizeof(info);
-	if (getsockopt(sock, SOL_L2CAP, L2CAP_CONNINFO, &info, &len) < 0)
-		return -errno;
-
-	if (handle)
-		*handle = info.hci_handle;
-
-	if (dev_class)
-		memcpy(dev_class, info.dev_class, 3);
-
-	return 0;
-}
-
-static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
-								va_list args)
-{
-	BtIOOption opt = opt1;
-	struct sockaddr_l2 src, dst;
-	struct l2cap_options l2o;
-	int flags;
-	uint8_t dev_class[3];
-	uint16_t handle;
-	socklen_t len;
-
-	len = sizeof(l2o);
-	memset(&l2o, 0, len);
-	if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) {
-		ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno);
-		return FALSE;
-	}
-
-	if (!get_peers(sock, (struct sockaddr *) &src,
-				(struct sockaddr *) &dst, sizeof(src), err))
-		return FALSE;
-
-	while (opt != BT_IO_OPT_INVALID) {
-		switch (opt) {
-		case BT_IO_OPT_SOURCE:
-			ba2str(&src.l2_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_SOURCE_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &src.l2_bdaddr);
-			break;
-		case BT_IO_OPT_DEST:
-			ba2str(&dst.l2_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_DEST_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &dst.l2_bdaddr);
-			break;
-		case BT_IO_OPT_DEFER_TIMEOUT:
-			len = sizeof(int);
-			if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP,
-					va_arg(args, int *), &len) < 0) {
-				ERROR_FAILED(err, "getsockopt(DEFER_SETUP)",
-									errno);
-				return FALSE;
-			}
-			break;
-		case BT_IO_OPT_SEC_LEVEL:
-			if (!get_sec_level(sock, BT_IO_L2CAP,
-						va_arg(args, int *), err))
-				return FALSE;
-			break;
-		case BT_IO_OPT_PSM:
-			*(va_arg(args, uint16_t *)) = src.l2_psm ?
-						src.l2_psm : dst.l2_psm;
-			break;
-		case BT_IO_OPT_OMTU:
-			*(va_arg(args, uint16_t *)) = l2o.omtu;
-			break;
-		case BT_IO_OPT_IMTU:
-			*(va_arg(args, uint16_t *)) = l2o.imtu;
-			break;
-		case BT_IO_OPT_MASTER:
-			len = sizeof(flags);
-			if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags,
-								&len) < 0) {
-				ERROR_FAILED(err, "getsockopt(L2CAP_LM)",
-									errno);
-				return FALSE;
-			}
-			*(va_arg(args, gboolean *)) =
-				(flags & L2CAP_LM_MASTER) ? TRUE : FALSE;
-			break;
-		case BT_IO_OPT_HANDLE:
-			if (l2cap_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "L2CAP_CONNINFO", errno);
-				return FALSE;
-			}
-			*(va_arg(args, uint16_t *)) = handle;
-			break;
-		case BT_IO_OPT_CLASS:
-			if (l2cap_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "L2CAP_CONNINFO", errno);
-				return FALSE;
-			}
-			memcpy(va_arg(args, uint8_t *), dev_class, 3);
-			break;
-		default:
-			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-					"Unknown option %d", opt);
-			return FALSE;
-		}
-
-		opt = va_arg(args, int);
-	}
-
-	return TRUE;
-}
-
-static int rfcomm_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
-{
-	struct rfcomm_conninfo info;
-	socklen_t len;
-
-	len = sizeof(info);
-	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_CONNINFO, &info, &len) < 0)
-		return -errno;
-
-	if (handle)
-		*handle = info.hci_handle;
-
-	if (dev_class)
-		memcpy(dev_class, info.dev_class, 3);
-
-	return 0;
-}
-
-static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
-								va_list args)
-{
-	BtIOOption opt = opt1;
-	struct sockaddr_rc src, dst;
-	int flags;
-	socklen_t len;
-	uint8_t dev_class[3];
-	uint16_t handle;
-
-	if (!get_peers(sock, (struct sockaddr *) &src,
-				(struct sockaddr *) &dst, sizeof(src), err))
-		return FALSE;
-
-	while (opt != BT_IO_OPT_INVALID) {
-		switch (opt) {
-		case BT_IO_OPT_SOURCE:
-			ba2str(&src.rc_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_SOURCE_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &src.rc_bdaddr);
-			break;
-		case BT_IO_OPT_DEST:
-			ba2str(&dst.rc_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_DEST_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &dst.rc_bdaddr);
-			break;
-		case BT_IO_OPT_DEFER_TIMEOUT:
-			len = sizeof(int);
-			if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP,
-					va_arg(args, int *), &len) < 0) {
-				ERROR_FAILED(err, "getsockopt(DEFER_SETUP)",
-									errno);
-				return FALSE;
-			}
-			break;
-		case BT_IO_OPT_SEC_LEVEL:
-			if (!get_sec_level(sock, BT_IO_RFCOMM,
-						va_arg(args, int *), err))
-				return FALSE;
-			break;
-		case BT_IO_OPT_CHANNEL:
-			*(va_arg(args, uint8_t *)) = src.rc_channel ?
-					src.rc_channel : dst.rc_channel;
-			break;
-		case BT_IO_OPT_SOURCE_CHANNEL:
-			*(va_arg(args, uint8_t *)) = src.rc_channel;
-			break;
-		case BT_IO_OPT_DEST_CHANNEL:
-			*(va_arg(args, uint8_t *)) = dst.rc_channel;
-			break;
-		case BT_IO_OPT_MASTER:
-			len = sizeof(flags);
-			if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags,
-								&len) < 0) {
-				ERROR_FAILED(err, "getsockopt(RFCOMM_LM)",
-									errno);
-				return FALSE;
-			}
-			*(va_arg(args, gboolean *)) =
-				(flags & RFCOMM_LM_MASTER) ? TRUE : FALSE;
-			break;
-		case BT_IO_OPT_HANDLE:
-			if (rfcomm_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
-				return FALSE;
-			}
-			*(va_arg(args, uint16_t *)) = handle;
-			break;
-		case BT_IO_OPT_CLASS:
-			if (rfcomm_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
-				return FALSE;
-			}
-			memcpy(va_arg(args, uint8_t *), dev_class, 3);
-			break;
-		default:
-			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-					"Unknown option %d", opt);
-			return FALSE;
-		}
-
-		opt = va_arg(args, int);
-	}
-
-	return TRUE;
-}
-
-static int sco_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
-{
-	struct sco_conninfo info;
-	socklen_t len;
-
-	len = sizeof(info);
-	if (getsockopt(sock, SOL_SCO, SCO_CONNINFO, &info, &len) < 0)
-		return -errno;
-
-	if (handle)
-		*handle = info.hci_handle;
-
-	if (dev_class)
-		memcpy(dev_class, info.dev_class, 3);
-
-	return 0;
-}
-
-static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
-{
-	BtIOOption opt = opt1;
-	struct sockaddr_sco src, dst;
-	struct sco_options sco_opt;
-	socklen_t len;
-	uint8_t dev_class[3];
-	uint16_t handle;
-
-	len = sizeof(sco_opt);
-	memset(&sco_opt, 0, len);
-	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
-		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
-		return FALSE;
-	}
-
-	if (!get_peers(sock, (struct sockaddr *) &src,
-				(struct sockaddr *) &dst, sizeof(src), err))
-		return FALSE;
-
-	while (opt != BT_IO_OPT_INVALID) {
-		switch (opt) {
-		case BT_IO_OPT_SOURCE:
-			ba2str(&src.sco_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_SOURCE_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &src.sco_bdaddr);
-			break;
-		case BT_IO_OPT_DEST:
-			ba2str(&dst.sco_bdaddr, va_arg(args, char *));
-			break;
-		case BT_IO_OPT_DEST_BDADDR:
-			bacpy(va_arg(args, bdaddr_t *), &dst.sco_bdaddr);
-			break;
-		case BT_IO_OPT_MTU:
-		case BT_IO_OPT_IMTU:
-		case BT_IO_OPT_OMTU:
-			*(va_arg(args, uint16_t *)) = sco_opt.mtu;
-			break;
-		case BT_IO_OPT_HANDLE:
-			if (sco_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
-				return FALSE;
-			}
-			*(va_arg(args, uint16_t *)) = handle;
-			break;
-		case BT_IO_OPT_CLASS:
-			if (sco_get_info(sock, &handle, dev_class) < 0) {
-				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
-				return FALSE;
-			}
-			memcpy(va_arg(args, uint8_t *), dev_class, 3);
-			break;
-		default:
-			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-					"Unknown option %d", opt);
-			return FALSE;
-		}
-
-		opt = va_arg(args, int);
-	}
-
-	return TRUE;
-}
-
-static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err,
-						BtIOOption opt1, va_list args)
-{
-	int sock;
-
-	sock = g_io_channel_unix_get_fd(io);
-
-	switch (type) {
-	case BT_IO_L2RAW:
-	case BT_IO_L2CAP:
-		return l2cap_get(sock, err, opt1, args);
-	case BT_IO_RFCOMM:
-		return rfcomm_get(sock, err, opt1, args);
-	case BT_IO_SCO:
-		return sco_get(sock, err, opt1, args);
-	}
-
-	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-			"Unknown BtIO type %d", type);
-	return FALSE;
-}
-
-gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
-					GDestroyNotify destroy, GError **err)
-{
-	int sock;
-	char c;
-	struct pollfd pfd;
-
-	sock = g_io_channel_unix_get_fd(io);
-
-	memset(&pfd, 0, sizeof(pfd));
-	pfd.fd = sock;
-	pfd.events = POLLOUT;
-
-	if (poll(&pfd, 1, 0) < 0) {
-		ERROR_FAILED(err, "poll", errno);
-		return FALSE;
-	}
-
-	if (!(pfd.revents & POLLOUT)) {
-		int ret;
-		ret = read(sock, &c, 1);
-	}
-
-	accept_add(io, connect, user_data, destroy);
-
-	return TRUE;
-}
-
-gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
-							BtIOOption opt1, ...)
-{
-	va_list args;
-	gboolean ret;
-	struct set_opts opts;
-	int sock;
-
-	va_start(args, opt1);
-	ret = parse_set_opts(&opts, err, opt1, args);
-	va_end(args);
-
-	if (!ret)
-		return ret;
-
-	sock = g_io_channel_unix_get_fd(io);
-
-	switch (type) {
-	case BT_IO_L2RAW:
-	case BT_IO_L2CAP:
-		return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu,
-						opts.mode, opts.master, err);
-	case BT_IO_RFCOMM:
-		return rfcomm_set(sock, opts.sec_level, opts.master, err);
-	case BT_IO_SCO:
-		return sco_set(sock, opts.mtu, err);
-	}
-
-	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-			"Unknown BtIO type %d", type);
-	return FALSE;
-}
-
-gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
-							BtIOOption opt1, ...)
-{
-	va_list args;
-	gboolean ret;
-
-	va_start(args, opt1);
-	ret = get_valist(io, type, err, opt1, args);
-	va_end(args);
-
-	return ret;
-}
-
-static GIOChannel *create_io(BtIOType type, gboolean server,
-					struct set_opts *opts, GError **err)
-{
-	int sock;
-	GIOChannel *io;
-
-	switch (type) {
-	case BT_IO_L2RAW:
-		sock = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
-		if (sock < 0) {
-			ERROR_FAILED(err, "socket(RAW, L2CAP)", errno);
-			return NULL;
-		}
-		if (l2cap_bind(sock, &opts->src,
-					server ? opts->psm : 0, err) < 0)
-			goto failed;
-		if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err))
-			goto failed;
-		break;
-	case BT_IO_L2CAP:
-		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
-		if (sock < 0) {
-			ERROR_FAILED(err, "socket(SEQPACKET, L2CAP)", errno);
-			return NULL;
-		}
-		if (l2cap_bind(sock, &opts->src,
-					server ? opts->psm : 0, err) < 0)
-			goto failed;
-		if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu,
-						opts->mode, opts->master, err))
-			goto failed;
-		break;
-	case BT_IO_RFCOMM:
-		sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-		if (sock < 0) {
-			ERROR_FAILED(err, "socket(STREAM, RFCOMM)", errno);
-			return NULL;
-		}
-		if (rfcomm_bind(sock, &opts->src,
-					server ? opts->channel : 0, err) < 0)
-			goto failed;
-		if (!rfcomm_set(sock, opts->sec_level, opts->master, err))
-			goto failed;
-		break;
-	case BT_IO_SCO:
-		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
-		if (sock < 0) {
-			ERROR_FAILED(err, "socket(SEQPACKET, SCO)", errno);
-			return NULL;
-		}
-		if (sco_bind(sock, &opts->src, err) < 0)
-			goto failed;
-		if (!sco_set(sock, opts->mtu, err))
-			goto failed;
-		break;
-	default:
-		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-				"Unknown BtIO type %d", type);
-		return NULL;
-	}
-
-	io = g_io_channel_unix_new(sock);
-
-	g_io_channel_set_close_on_unref(io, TRUE);
-	g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
-
-	return io;
-
-failed:
-	close(sock);
-
-	return NULL;
-}
-
-GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy,
-				GError **gerr, BtIOOption opt1, ...)
-{
-	GIOChannel *io;
-	va_list args;
-	struct set_opts opts;
-	int err, sock;
-	gboolean ret;
-
-	va_start(args, opt1);
-	ret = parse_set_opts(&opts, gerr, opt1, args);
-	va_end(args);
-
-	if (ret == FALSE)
-		return NULL;
-
-	io = create_io(type, FALSE, &opts, gerr);
-	if (io == NULL)
-		return NULL;
-
-	sock = g_io_channel_unix_get_fd(io);
-
-	switch (type) {
-	case BT_IO_L2RAW:
-		err = l2cap_connect(sock, &opts.dst, 0);
-		break;
-	case BT_IO_L2CAP:
-		err = l2cap_connect(sock, &opts.dst, opts.psm);
-		break;
-	case BT_IO_RFCOMM:
-		err = rfcomm_connect(sock, &opts.dst, opts.channel);
-		break;
-	case BT_IO_SCO:
-		err = sco_connect(sock, &opts.dst);
-		break;
-	default:
-		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-						"Unknown BtIO type %d", type);
-		return NULL;
-	}
-
-	if (err < 0) {
-		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED,
-				"connect: %s (%d)", strerror(-err), -err);
-		g_io_channel_unref(io);
-		return NULL;
-	}
-
-	connect_add(io, connect, user_data, destroy);
-
-	return io;
-}
-
-GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
-				GDestroyNotify destroy, GError **err,
-				BtIOOption opt1, ...)
-{
-	GIOChannel *io;
-	va_list args;
-	struct set_opts opts;
-	int sock;
-	gboolean ret;
-
-	if (type == BT_IO_L2RAW) {
-		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
-				"Server L2CAP RAW sockets not supported");
-		return NULL;
-	}
-
-	va_start(args, opt1);
-	ret = parse_set_opts(&opts, err, opt1, args);
-	va_end(args);
-
-	if (ret == FALSE)
-		return NULL;
-
-	io = create_io(type, TRUE, &opts, err);
-	if (io == NULL)
-		return NULL;
-
-	sock = g_io_channel_unix_get_fd(io);
-
-	if (confirm)
-		setsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, &opts.defer,
-							sizeof(opts.defer));
-
-	if (listen(sock, 5) < 0) {
-		ERROR_FAILED(err, "listen", errno);
-		g_io_channel_unref(io);
-		return NULL;
-	}
-
-	server_add(io, connect, confirm, user_data, destroy);
-
-	return io;
-}
-
-GQuark bt_io_error_quark(void)
-{
-	return g_quark_from_static_string("bt-io-error-quark");
-}
diff --git a/src/btio.h b/src/btio.h
deleted file mode 100644
index e9dcc9f..0000000
--- a/src/btio.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (C) 2009-2010  Nokia Corporation
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-#ifndef BT_IO_H
-#define BT_IO_H
-
-#include <glib.h>
-
-typedef enum {
-	BT_IO_ERROR_DISCONNECTED,
-	BT_IO_ERROR_CONNECT_FAILED,
-	BT_IO_ERROR_FAILED,
-	BT_IO_ERROR_INVALID_ARGS,
-} BtIOError;
-
-#define BT_IO_ERROR bt_io_error_quark()
-
-GQuark bt_io_error_quark(void);
-
-typedef enum {
-	BT_IO_L2RAW,
-	BT_IO_L2CAP,
-	BT_IO_RFCOMM,
-	BT_IO_SCO,
-} BtIOType;
-
-typedef enum {
-	BT_IO_OPT_INVALID = 0,
-	BT_IO_OPT_SOURCE,
-	BT_IO_OPT_SOURCE_BDADDR,
-	BT_IO_OPT_DEST,
-	BT_IO_OPT_DEST_BDADDR,
-	BT_IO_OPT_DEFER_TIMEOUT,
-	BT_IO_OPT_SEC_LEVEL,
-	BT_IO_OPT_CHANNEL,
-	BT_IO_OPT_SOURCE_CHANNEL,
-	BT_IO_OPT_DEST_CHANNEL,
-	BT_IO_OPT_PSM,
-	BT_IO_OPT_MTU,
-	BT_IO_OPT_OMTU,
-	BT_IO_OPT_IMTU,
-	BT_IO_OPT_MASTER,
-	BT_IO_OPT_HANDLE,
-	BT_IO_OPT_CLASS,
-	BT_IO_OPT_MODE,
-} BtIOOption;
-
-typedef enum {
-	BT_IO_SEC_SDP = 0,
-	BT_IO_SEC_LOW,
-	BT_IO_SEC_MEDIUM,
-	BT_IO_SEC_HIGH,
-} BtIOSecLevel;
-
-typedef void (*BtIOConfirm)(GIOChannel *io, void *user_data);
-
-typedef void (*BtIOConnect)(GIOChannel *io, GError *err, void *user_data);
-
-gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
-					GDestroyNotify destroy, GError **err);
-
-gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
-						BtIOOption opt1, ...);
-
-gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
-						BtIOOption opt1, ...);
-
-GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy,
-				GError **err, BtIOOption opt1, ...);
-
-GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
-				GDestroyNotify destroy, GError **err,
-				BtIOOption opt1, ...);
-
-#endif
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/8] btio: Remove blank line at EOF
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1282227676-15381-1-git-send-email-zhenhua.zhang@intel.com>

---
 src/btio.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/src/btio.c b/src/btio.c
index 485eec6..42a3bcd 100644
--- a/src/btio.c
+++ b/src/btio.c
@@ -1297,4 +1297,3 @@ GQuark bt_io_error_quark(void)
 {
 	return g_quark_from_static_string("bt-io-error-quark");
 }
-
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 0/8] Clean up Obex btio.[ch] and make it self contained
From: Zhenhua Zhang @ 2010-08-19 14:21 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

This series of patches is to seperate btio.[ch] from src to btio directory. To make btio.[ch] self contained for obexd, there're some cleanup work:

1. remove unused bt_io_set(). It is neither used by bluez or obexd.
2. remove unused SCO/L2RAW related code for Obexd. Note: BlueZ code requires SCO/L2RAW related functions. We may consider to add them back later.
3. replace void *userdata with gpointer userdata. To make it consistent with bluez btio.c
4. refactor hci_devba into devid2ba. Remove dependence with hci*.h
5. Remove libbluetooth dependence for obexd.

Regards,
Zhenhua

^ permalink raw reply

* Re: [PATCH 1/2] Add handling of single contact's fields handled in VCARD structure
From: Johan Hedberg @ 2010-08-19 13:36 UTC (permalink / raw)
  To: Rafal Michalski; +Cc: linux-bluetooth
In-Reply-To: <1282218500-18458-1-git-send-email-michalski.raf@gmail.com>

Hi Rafal,

On Thu, Aug 19, 2010, Rafal Michalski wrote:
> After pulling contacts these fields weren't present in downloaded
> VCARD structure in spite of that these fields existed (not empty).
> 
> This patch adds handling of fields: BDAY, NICKNAME, URL, PHOTO
> To solve this problem extending number of columns and queries of database
> was needed especially. Displaying these fields is done by genaral
> functions: vcard_printf_slash_tag, vcard_printf_slash_slash_tag.
> Of course fields mentioned above were added to phonebook_contact structure
> as char * type to save gained data.
> ---
>  plugins/phonebook-tracker.c |   29 +++++++++++++++----
>  plugins/vcard.c             |   66 +++++++++++++++++++++++++++++++++++++++++++
>  plugins/vcard.h             |    4 ++
>  3 files changed, 93 insertions(+), 6 deletions(-)

Please always check that your patches compile cleanly with
./bootstrap-configure before submitting upstream. I get this when
compiling your patch:

plugins/vcard.c: In function ‘vcard_printf_tag’:
plugins/vcard.c:268: error: ISO C90 forbids mixed declarations and code
plugins/vcard.c: In function ‘vcard_printf_slash_tag’:
plugins/vcard.c:292: error: ISO C90 forbids mixed declarations and code
plugins/vcard.c:302: error: ISO C90 forbids mixed declarations and code
make[1]: *** [plugins/vcard.o] Error 1

Furthermore, there were the following issues I spotted:

> +static void vcard_printf_tag(GString *vcards, const char *tag,
> +					const char* category, const char *fld)

That should be "char *category" and not "char* category"

> +	char separator = '\0', *type = "";
> +	char buf[LEN_MAX];
> +
> +	if (category && strlen(category)) {
> +		separator = ';';
> +		type = "TYPE=";
> +	}
> +
> +	snprintf(buf, sizeof(buf), "%s%c%s%s", tag, separator, type, category);

sprintf("...%c...", '\0'); will embed a null-byte into the string which
I'm sure is something that you don't want. Just use a normal string and
%s instead, i.e. "".

> +static void vcard_printf_slash_tag(GString *vcards, const char *tag,
> +					const char* category, const char *fld)

Again, char *foo instead of char* foo.

> +	char separator = '\0', *type = "";
> +	char buf[LEN_MAX];
> +
> +	if (category && strlen(category)) {
> +		separator = ';';
> +		type = "TYPE=";
> +	}
> +
> +	snprintf(buf, sizeof(buf), "%s%c%s%s", tag, separator, type, category);

And the same problem with the null-byte.

Johan

^ permalink raw reply

* [PATCH 1/2] Add handling of single contact's fields handled in VCARD structure
From: Rafal Michalski @ 2010-08-19 11:56 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Michalski

After pulling contacts these fields weren't present in downloaded
VCARD structure in spite of that these fields existed (not empty).

This patch adds handling of fields: BDAY, NICKNAME, URL, PHOTO
To solve this problem extending number of columns and queries of database
was needed especially. Displaying these fields is done by genaral
functions: vcard_printf_slash_tag, vcard_printf_tag.
---
 plugins/phonebook-tracker.c |   29 +++++++++++++++----
 plugins/vcard.c             |   66 +++++++++++++++++++++++++++++++++++++++++++
 plugins/vcard.h             |    4 ++
 3 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 1109968..fd92125 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -43,16 +43,16 @@
 #define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
 
 #define TRACKER_DEFAULT_CONTACT_ME "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#default-contact-me"
-#define CONTACTS_ID_COL 21
-#define PULL_QUERY_COL_AMOUNT 22
+#define CONTACTS_ID_COL 25
+#define PULL_QUERY_COL_AMOUNT 26
 #define COL_HOME_NUMBER 0
 #define COL_HOME_EMAIL 7
 #define COL_WORK_NUMBER 8
 #define COL_FAX_NUMBER 16
 #define COL_WORK_EMAIL 17
-#define COL_DATE 18
-#define COL_SENT 19
-#define COL_ANSWERED 20
+#define COL_DATE 22
+#define COL_SENT 23
+#define COL_ANSWERED 24
 
 #define CONTACTS_QUERY_ALL						\
 	"SELECT ?v nco:fullname(?c) "					\
@@ -62,6 +62,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"\"NOTACALL\" \"false\" \"false\" ?c "				\
 	"WHERE { "							\
 		"?c a nco:PersonContact . "				\
@@ -106,6 +108,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -151,6 +155,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -196,6 +202,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew)"	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -239,6 +247,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -306,6 +316,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f  nco:emailAddress(?ew)"	\
+	"nco:birthDate(<%s>) nco:nickname(<%s>) nco:websiteUrl(<%s>) "	\
+	"nco:photo(<%s>) "						\
 	"\"NOTACALL\" \"false\" \"false\" <%s> "			\
 	"WHERE { "							\
 		"<%s> a nco:Contact . "					\
@@ -774,6 +786,10 @@ add_entry:
 	contact->region = g_strdup(reply[13]);
 	contact->postal = g_strdup(reply[14]);
 	contact->country = g_strdup(reply[15]);
+	contact->birthday = g_strdup(reply[18]);
+	contact->nickname = g_strdup(reply[19]);
+	contact->website = g_strdup(reply[20]);
+	contact->photo = g_strdup(reply[21]);
 
 	set_call_type(contact, reply[COL_DATE], reply[COL_SENT],
 			reply[COL_ANSWERED]);
@@ -978,7 +994,8 @@ int phonebook_get_entry(const char *folder, const char *id,
 	data->vcardentry = TRUE;
 
 	query = g_strdup_printf(CONTACTS_QUERY_FROM_URI, id, id, id, id, id,
-						id, id, id, id, id, id, id);
+						id, id, id, id, id, id, id,
+						id, id, id, id);
 
 	ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data);
 
diff --git a/plugins/vcard.c b/plugins/vcard.c
index 18b5952..c45bfcd 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -256,6 +256,54 @@ static void vcard_printf_number(GString *vcards, uint8_t format,
 	vcard_printf(vcards, buf, number);
 }
 
+static void vcard_printf_tag(GString *vcards, const char *tag,
+					const char* category, const char *fld)
+{
+	if (tag == NULL || strlen(tag) == 0)
+		return;
+
+	if (fld == NULL || strlen(fld) == 0)
+		return;
+
+	char separator = '\0', *type = "";
+	char buf[LEN_MAX];
+
+	if (category && strlen(category)) {
+		separator = ';';
+		type = "TYPE=";
+	}
+
+	snprintf(buf, sizeof(buf), "%s%c%s%s", tag, separator, type, category);
+
+	vcard_printf(vcards, "%s:%s", buf, fld);
+}
+
+static void vcard_printf_slash_tag(GString *vcards, const char *tag,
+					const char* category, const char *fld)
+{
+	int len;
+
+	if (tag == NULL || strlen(tag) == 0)
+		return;
+
+	if (fld == NULL || (len = strlen(fld)) == 0)
+		return;
+
+	char separator = '\0', *type = "";
+	char buf[LEN_MAX];
+
+	if (category && strlen(category)) {
+		separator = ';';
+		type = "TYPE=";
+	}
+
+	snprintf(buf, sizeof(buf), "%s%c%s%s", tag, separator, type, category);
+
+	char field[LEN_MAX];
+	add_slash(field, fld, LEN_MAX, len);
+	vcard_printf(vcards, "%s:%s", buf, field);
+}
+
 static void vcard_printf_email(GString *vcards, const char *email)
 {
 	int len = 0;
@@ -354,6 +402,20 @@ void phonebook_add_contact(GString *vcards, struct phonebook_contact *contact,
 	if (filter & FILTER_ADR)
 		vcard_printf_adr(vcards, contact);
 
+	if (filter & FILTER_BDAY)
+		vcard_printf_tag(vcards, "BDAY", NULL, contact->birthday);
+
+	if (filter & FILTER_NICKNAME)
+		vcard_printf_slash_tag(vcards, "NICKNAME", NULL,
+							contact->nickname);
+
+	if (filter & FILTER_URL)
+		vcard_printf_slash_tag(vcards, "URL", "INTERNET",
+							contact->website);
+
+	if (filter & FILTER_PHOTO)
+		vcard_printf_tag(vcards, "PHOTO", NULL, contact->photo);
+
 	if (filter & FILTER_X_IRMC_CALL_DATETIME)
 		vcard_printf_datetime(vcards, contact);
 
@@ -392,6 +454,10 @@ void phonebook_contact_free(struct phonebook_contact *contact)
 	g_free(contact->region);
 	g_free(contact->postal);
 	g_free(contact->country);
+	g_free(contact->birthday);
+	g_free(contact->nickname);
+	g_free(contact->website);
+	g_free(contact->photo);
 	g_free(contact->datetime);
 	g_free(contact);
 }
diff --git a/plugins/vcard.h b/plugins/vcard.h
index fa571e4..a9809ea 100644
--- a/plugins/vcard.h
+++ b/plugins/vcard.h
@@ -55,6 +55,10 @@ struct phonebook_contact {
 	char *region;
 	char *postal;
 	char *country;
+	char *birthday;
+	char *nickname;
+	char *website;
+	char *photo;
 	char *datetime;
 	int calltype;
 };
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 2/2] Add handling of ORG contact's fields handled in VCARD structure
From: Rafal Michalski @ 2010-08-19 11:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Michalski

After pulling contacts these fields weren't present in downloaded
VCARD structure in spite of that these fields existed (not empty).

This patch adds handling of fields grouped under ORG tag.
To solve this problem extending number of columns and queries of database
was needed especially. Of course fields mentioned above were added to
phonebook_contact structure as char * type to save gained data.
---
 plugins/phonebook-tracker.c |   38 +++++++++++++++++++++++++++-----------
 plugins/vcard.c             |   30 ++++++++++++++++++++++++++++++
 plugins/vcard.h             |    3 +++
 3 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index fd92125..3f63dcb 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -43,16 +43,16 @@
 #define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
 
 #define TRACKER_DEFAULT_CONTACT_ME "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#default-contact-me"
-#define CONTACTS_ID_COL 25
-#define PULL_QUERY_COL_AMOUNT 26
+#define CONTACTS_ID_COL 28
+#define PULL_QUERY_COL_AMOUNT 29
 #define COL_HOME_NUMBER 0
 #define COL_HOME_EMAIL 7
 #define COL_WORK_NUMBER 8
 #define COL_FAX_NUMBER 16
 #define COL_WORK_EMAIL 17
-#define COL_DATE 22
-#define COL_SENT 23
-#define COL_ANSWERED 24
+#define COL_DATE 25
+#define COL_SENT 26
+#define COL_ANSWERED 27
 
 #define CONTACTS_QUERY_ALL						\
 	"SELECT ?v nco:fullname(?c) "					\
@@ -63,7 +63,8 @@
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
-	"nco:photo(?c) "						\
+	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
+	"nco:role(?a) "							\
 	"\"NOTACALL\" \"false\" \"false\" ?c "				\
 	"WHERE { "							\
 		"?c a nco:PersonContact . "				\
@@ -83,6 +84,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"}"
 
@@ -109,7 +111,8 @@
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
-	"nco:photo(?c) "						\
+	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
+	"nco:role(?a) "							\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -130,6 +133,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} ORDER BY DESC(nmo:receivedDate(?call))"
 
@@ -156,7 +160,8 @@
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
-	"nco:photo(?c) "						\
+	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
+	"nco:role(?a) "							\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -177,6 +182,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} ORDER BY DESC(nmo:receivedDate(?call))"
 
@@ -203,7 +209,8 @@
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew)"	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
-	"nco:photo(?c) "						\
+	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
+	"nco:role(?a) "							\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -223,6 +230,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} ORDER BY DESC(nmo:sentDate(?call))"
 
@@ -248,7 +256,8 @@
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
-	"nco:photo(?c) "						\
+	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
+	"nco:role(?a) "							\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -268,6 +277,7 @@
 	"OPTIONAL { ?c nco:hasAffiliation ?a . "			\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} UNION { "							\
 		"?call a nmo:Call ; "					\
@@ -285,6 +295,7 @@
 	"OPTIONAL { ?c nco:hasAffiliation ?a . "			\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} } ORDER BY DESC(nmo:receivedDate(?call))"
 
@@ -317,7 +328,8 @@
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f  nco:emailAddress(?ew)"	\
 	"nco:birthDate(<%s>) nco:nickname(<%s>) nco:websiteUrl(<%s>) "	\
-	"nco:photo(<%s>) "						\
+	"nco:photo(<%s>) nco:fullname(?o) nco:department(?a) "		\
+	"nco:role(?a) "							\
 	"\"NOTACALL\" \"false\" \"false\" <%s> "			\
 	"WHERE { "							\
 		"<%s> a nco:Contact . "					\
@@ -337,6 +349,7 @@
 		"<%s> nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . }" 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . }"		\
+		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"}"
 
@@ -790,6 +803,9 @@ add_entry:
 	contact->nickname = g_strdup(reply[19]);
 	contact->website = g_strdup(reply[20]);
 	contact->photo = g_strdup(reply[21]);
+	contact->company = g_strdup(reply[22]);
+	contact->department = g_strdup(reply[23]);
+	contact->title = g_strdup(reply[24]);
 
 	set_call_type(contact, reply[COL_DATE], reply[COL_SENT],
 			reply[COL_ANSWERED]);
diff --git a/plugins/vcard.c b/plugins/vcard.c
index c45bfcd..b33c8e3 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -319,6 +319,30 @@ static void vcard_printf_email(GString *vcards, const char *email)
 	}
 }
 
+static gboolean org_fields_present(struct phonebook_contact *contact)
+{
+	if (contact->company && strlen(contact->company))
+		return TRUE;
+
+	if (contact->department && strlen(contact->department))
+		return TRUE;
+
+	if (contact->title && strlen(contact->title))
+		return TRUE;
+
+	return FALSE;
+}
+
+static void vcard_printf_org(GString *vcards,
+					struct phonebook_contact *contact)
+{
+	if (org_fields_present(contact) == FALSE)
+		return;
+
+	vcard_printf(vcards, "ORG:%s;%s;%s", contact->company,
+				contact->department, contact->title);
+}
+
 static void vcard_printf_adr(GString *vcards, struct phonebook_contact *contact)
 {
 	if (address_fields_present(contact) == FALSE) {
@@ -416,6 +440,9 @@ void phonebook_add_contact(GString *vcards, struct phonebook_contact *contact,
 	if (filter & FILTER_PHOTO)
 		vcard_printf_tag(vcards, "PHOTO", NULL, contact->photo);
 
+	if (filter & FILTER_ORG)
+		vcard_printf_org(vcards, contact);
+
 	if (filter & FILTER_X_IRMC_CALL_DATETIME)
 		vcard_printf_datetime(vcards, contact);
 
@@ -458,6 +485,9 @@ void phonebook_contact_free(struct phonebook_contact *contact)
 	g_free(contact->nickname);
 	g_free(contact->website);
 	g_free(contact->photo);
+	g_free(contact->company);
+	g_free(contact->department);
+	g_free(contact->title);
 	g_free(contact->datetime);
 	g_free(contact);
 }
diff --git a/plugins/vcard.h b/plugins/vcard.h
index a9809ea..0f52425 100644
--- a/plugins/vcard.h
+++ b/plugins/vcard.h
@@ -59,6 +59,9 @@ struct phonebook_contact {
 	char *nickname;
 	char *website;
 	char *photo;
+	char *company;
+	char *department;
+	char *title;
 	char *datetime;
 	int calltype;
 };
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 1/2] Add handling of single contact's fields handled in VCARD structure
From: Rafal Michalski @ 2010-08-19 11:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Michalski

After pulling contacts these fields weren't present in downloaded
VCARD structure in spite of that these fields existed (not empty).

This patch adds handling of fields: BDAY, NICKNAME, URL, PHOTO
To solve this problem extending number of columns and queries of database
was needed especially. Displaying these fields is done by genaral
functions: vcard_printf_slash_tag, vcard_printf_slash_slash_tag.
Of course fields mentioned above were added to phonebook_contact structure
as char * type to save gained data.
---
 plugins/phonebook-tracker.c |   29 +++++++++++++++----
 plugins/vcard.c             |   66 +++++++++++++++++++++++++++++++++++++++++++
 plugins/vcard.h             |    4 ++
 3 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 1109968..fd92125 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -43,16 +43,16 @@
 #define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
 
 #define TRACKER_DEFAULT_CONTACT_ME "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#default-contact-me"
-#define CONTACTS_ID_COL 21
-#define PULL_QUERY_COL_AMOUNT 22
+#define CONTACTS_ID_COL 25
+#define PULL_QUERY_COL_AMOUNT 26
 #define COL_HOME_NUMBER 0
 #define COL_HOME_EMAIL 7
 #define COL_WORK_NUMBER 8
 #define COL_FAX_NUMBER 16
 #define COL_WORK_EMAIL 17
-#define COL_DATE 18
-#define COL_SENT 19
-#define COL_ANSWERED 20
+#define COL_DATE 22
+#define COL_SENT 23
+#define COL_ANSWERED 24
 
 #define CONTACTS_QUERY_ALL						\
 	"SELECT ?v nco:fullname(?c) "					\
@@ -62,6 +62,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"\"NOTACALL\" \"false\" \"false\" ?c "				\
 	"WHERE { "							\
 		"?c a nco:PersonContact . "				\
@@ -106,6 +108,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -151,6 +155,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -196,6 +202,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew)"	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -239,6 +247,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
+	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
+	"nco:photo(?c) "						\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -306,6 +316,8 @@
 	"nco:phoneNumber(?w) nco:pobox(?p) nco:extendedAddress(?p) "	\
 	"nco:streetAddress(?p) nco:locality(?p) nco:region(?p) "	\
 	"nco:postalcode(?p) nco:country(?p) ?f  nco:emailAddress(?ew)"	\
+	"nco:birthDate(<%s>) nco:nickname(<%s>) nco:websiteUrl(<%s>) "	\
+	"nco:photo(<%s>) "						\
 	"\"NOTACALL\" \"false\" \"false\" <%s> "			\
 	"WHERE { "							\
 		"<%s> a nco:Contact . "					\
@@ -774,6 +786,10 @@ add_entry:
 	contact->region = g_strdup(reply[13]);
 	contact->postal = g_strdup(reply[14]);
 	contact->country = g_strdup(reply[15]);
+	contact->birthday = g_strdup(reply[18]);
+	contact->nickname = g_strdup(reply[19]);
+	contact->website = g_strdup(reply[20]);
+	contact->photo = g_strdup(reply[21]);
 
 	set_call_type(contact, reply[COL_DATE], reply[COL_SENT],
 			reply[COL_ANSWERED]);
@@ -978,7 +994,8 @@ int phonebook_get_entry(const char *folder, const char *id,
 	data->vcardentry = TRUE;
 
 	query = g_strdup_printf(CONTACTS_QUERY_FROM_URI, id, id, id, id, id,
-						id, id, id, id, id, id, id);
+						id, id, id, id, id, id, id,
+						id, id, id, id);
 
 	ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data);
 
diff --git a/plugins/vcard.c b/plugins/vcard.c
index 18b5952..c45bfcd 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -256,6 +256,54 @@ static void vcard_printf_number(GString *vcards, uint8_t format,
 	vcard_printf(vcards, buf, number);
 }
 
+static void vcard_printf_tag(GString *vcards, const char *tag,
+					const char* category, const char *fld)
+{
+	if (tag == NULL || strlen(tag) == 0)
+		return;
+
+	if (fld == NULL || strlen(fld) == 0)
+		return;
+
+	char separator = '\0', *type = "";
+	char buf[LEN_MAX];
+
+	if (category && strlen(category)) {
+		separator = ';';
+		type = "TYPE=";
+	}
+
+	snprintf(buf, sizeof(buf), "%s%c%s%s", tag, separator, type, category);
+
+	vcard_printf(vcards, "%s:%s", buf, fld);
+}
+
+static void vcard_printf_slash_tag(GString *vcards, const char *tag,
+					const char* category, const char *fld)
+{
+	int len;
+
+	if (tag == NULL || strlen(tag) == 0)
+		return;
+
+	if (fld == NULL || (len = strlen(fld)) == 0)
+		return;
+
+	char separator = '\0', *type = "";
+	char buf[LEN_MAX];
+
+	if (category && strlen(category)) {
+		separator = ';';
+		type = "TYPE=";
+	}
+
+	snprintf(buf, sizeof(buf), "%s%c%s%s", tag, separator, type, category);
+
+	char field[LEN_MAX];
+	add_slash(field, fld, LEN_MAX, len);
+	vcard_printf(vcards, "%s:%s", buf, field);
+}
+
 static void vcard_printf_email(GString *vcards, const char *email)
 {
 	int len = 0;
@@ -354,6 +402,20 @@ void phonebook_add_contact(GString *vcards, struct phonebook_contact *contact,
 	if (filter & FILTER_ADR)
 		vcard_printf_adr(vcards, contact);
 
+	if (filter & FILTER_BDAY)
+		vcard_printf_tag(vcards, "BDAY", NULL, contact->birthday);
+
+	if (filter & FILTER_NICKNAME)
+		vcard_printf_slash_tag(vcards, "NICKNAME", NULL,
+							contact->nickname);
+
+	if (filter & FILTER_URL)
+		vcard_printf_slash_tag(vcards, "URL", "INTERNET",
+							contact->website);
+
+	if (filter & FILTER_PHOTO)
+		vcard_printf_tag(vcards, "PHOTO", NULL, contact->photo);
+
 	if (filter & FILTER_X_IRMC_CALL_DATETIME)
 		vcard_printf_datetime(vcards, contact);
 
@@ -392,6 +454,10 @@ void phonebook_contact_free(struct phonebook_contact *contact)
 	g_free(contact->region);
 	g_free(contact->postal);
 	g_free(contact->country);
+	g_free(contact->birthday);
+	g_free(contact->nickname);
+	g_free(contact->website);
+	g_free(contact->photo);
 	g_free(contact->datetime);
 	g_free(contact);
 }
diff --git a/plugins/vcard.h b/plugins/vcard.h
index fa571e4..a9809ea 100644
--- a/plugins/vcard.h
+++ b/plugins/vcard.h
@@ -55,6 +55,10 @@ struct phonebook_contact {
 	char *region;
 	char *postal;
 	char *country;
+	char *birthday;
+	char *nickname;
+	char *website;
+	char *photo;
 	char *datetime;
 	int calltype;
 };
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH] Fix crash when there is no enough space to fragment avdtp packet
From: Johan Hedberg @ 2010-08-19 11:08 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1282215669-24429-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Thu, Aug 19, 2010, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
> 
> This was catch when running codenomicon tests when the output mtu is not
> big enough to stuff fragmented packets.
> ---
>  audio/avdtp.c |    6 ++++++
>  1 files changed, 6 insertions(+), 0 deletions(-)

Thanks. The patch has been pushed upstream.

Johan

^ permalink raw reply

* [PATCH] bluetooth: fix not setting security level when creating a rfcomm session
From: Luiz Augusto von Dentz @ 2010-08-19 11:06 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: ville.tervo

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

This cause 'No Bonding' to be used if userspace has not yet been paired
with remote device since the l2cap socket used to create the rfcomm
session does not have any security level set.

Signed-off-by: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
---
 net/bluetooth/rfcomm/core.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 7dca91b..08f5757 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -79,7 +79,10 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr);
 
 static void rfcomm_process_connect(struct rfcomm_session *s);
 
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
+							bdaddr_t *dst,
+							u8 sec_level,
+							int *err);
 static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
 static void rfcomm_session_del(struct rfcomm_session *s);
 
@@ -402,7 +405,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
 
 	s = rfcomm_session_get(src, dst);
 	if (!s) {
-		s = rfcomm_session_create(src, dst, &err);
+		s = rfcomm_session_create(src, dst, d->sec_level, &err);
 		if (!s)
 			return err;
 	}
@@ -680,7 +683,10 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
 	rfcomm_session_put(s);
 }
 
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
+							bdaddr_t *dst,
+							u8 sec_level,
+							int *err)
 {
 	struct rfcomm_session *s = NULL;
 	struct sockaddr_l2 addr;
@@ -705,6 +711,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
 	sk = sock->sk;
 	lock_sock(sk);
 	l2cap_pi(sk)->imtu = l2cap_mtu;
+	l2cap_pi(sk)->sec_level = sec_level;
 	if (l2cap_ertm)
 		l2cap_pi(sk)->mode = L2CAP_MODE_ERTM;
 	release_sock(sk);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH] Fix crash when there is no enough space to fragment avdtp packet
From: Luiz Augusto von Dentz @ 2010-08-19 11:01 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

This was catch when running codenomicon tests when the output mtu is not
big enough to stuff fragmented packets.
---
 audio/avdtp.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/audio/avdtp.c b/audio/avdtp.c
index cf07f6c..cc7066f 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -537,6 +537,12 @@ static gboolean avdtp_send(struct avdtp *session, uint8_t transaction,
 		return try_send(sock, session->buf, sizeof(single) + len);
 	}
 
+	/* Check if there is enough space to start packet */
+	if (session->omtu < sizeof(start)) {
+		error("No enough space to fragment packet");
+		return FALSE;
+	}
+
 	/* Count the number of needed fragments */
 	cont_fragments = (len - (session->omtu - sizeof(start))) /
 					(session->omtu - sizeof(cont)) + 1;
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] IrMC sync server support
From: Luiz Augusto von Dentz @ 2010-08-19 10:53 UTC (permalink / raw)
  To: Marcel J.E. Mol; +Cc: Marcel Holtmann, linux-bluetooth
In-Reply-To: <20100817084850.GA16821@joshua.mesa.nl>

Hi Marcel,

On Tue, Aug 17, 2010 at 11:48 AM, Marcel J.E. Mol <marcel@mesa.nl> wrote:
> Ok, then 17 is just fine for IrMC then. I posted a 3th version at the end=
 of
> last week. Are there any new comments I have to take care of? Or can it =
=A0be
> considere for inclusion in the main tree now?
>
>
> On the other hand, if the channel 'varies' it might be better to let the
> plugin manager select a channel number for each service instead of alloca=
ting
> a fixed one in the specific plugin code.
>
> What did you found about channel 11 then? On my nokia 7710 channel 11 is =
used for
> "OBEX File Transfer" (serivce 0x1106).

We decided to use 14, also Johan pushed a complete list of bluez
assigned number to:

http://git.kernel.org/?p=3Dbluetooth/bluez.git;a=3Dcommitdiff;h=3Dfbeff4fd3=
03b43fa7f6c27e95fb6f023e80720a9;hp=3D0627552640140e1d986d36bb4770ccc4b3206b=
03

Could you please update your changes to use 14? Also there seems to be
some white spaces that doesn't follow our code styling, could you
please fix those?

--=20
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* Re: its possible to make a streaming video whith bluez?
From: Johan Hedberg @ 2010-08-19  8:50 UTC (permalink / raw)
  To: Alexander Orlenko, Lorenzo Brito Morales, linux-bluetooth
In-Reply-To: <20100819083323.GA7327@jh-x301>

On Thu, Aug 19, 2010, Johan Hedberg wrote:
> On Thu, Aug 19, 2010, Alexander Orlenko wrote:
> > > Do you have plans to implement this for BlueZ?
> > It's a GSoC'10 project. http://hostisdown.org/gsoc/projects/vdp
> 
> Ha. Seems I've missed that one completely (though not really a surprise
> since there doesn't seem to have been any communication about it here on
> the mailing list).

I just just took a peek at the projects git tree. There's essentially
nothing there besides some very simple stub files. Also, there doesn't
seem to be anything AVDTP related in the tree but just raw data (video)
sending over an L2CAP connection. So if that's all that there is then
the statement "nothing exists for VDP in BlueZ right now" is actually
quite close to the truth.

Johan

^ permalink raw reply

* Re: BlueZ's A2DP sink role
From: Luiz Augusto von Dentz @ 2010-08-19  8:49 UTC (permalink / raw)
  To: Pavan Savoy; +Cc: linux-bluetooth
In-Reply-To: <AANLkTimXDqAej=LAVDvDgspKuH_SAKivp9eL8R9tXPJc@mail.gmail.com>

Hi Pavan,

On Wed, Aug 18, 2010 at 11:22 PM, Pavan Savoy <pavan_savoy@sify.com> wrote:
> As I understand, the A2DP sink role is @ audio/source.c and A2DP
> source role is at sink.c ? (or what is called as the interfaces?..)
> Also How do I test out a2dp sink role in BlueZ, any test audio-server
> I can run ?

You can use PA as explained in Joao Paulo's blog:

http://jprvita.wordpress.com/2009/12/15/1-2-3-4-a2dp-stream/


-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* Re: its possible to make a streaming video whith bluez?
From: Johan Hedberg @ 2010-08-19  8:33 UTC (permalink / raw)
  To: Alexander Orlenko; +Cc: Lorenzo Brito Morales, linux-bluetooth
In-Reply-To: <AANLkTindRBGJtWuE8OX+fAEAQOSQHzEgLdGdUUHfOKKT@mail.gmail.com>

On Thu, Aug 19, 2010, Alexander Orlenko wrote:
> > Do you have plans to implement this for BlueZ?
> It's a GSoC'10 project. http://hostisdown.org/gsoc/projects/vdp

Ha. Seems I've missed that one completely (though not really a surprise
since there doesn't seem to have been any communication about it here on
the mailing list).

Johan

^ permalink raw reply

* Re: its possible to make a streaming video whith bluez?
From: Alexander Orlenko @ 2010-08-19  8:25 UTC (permalink / raw)
  To: Lorenzo Brito Morales, linux-bluetooth
In-Reply-To: <20100819074920.GA5401@jh-x301>

> Do you have plans to implement this for BlueZ?
It's a GSoC'10 project. http://hostisdown.org/gsoc/projects/vdp

On 19 August 2010 18:49, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi,
>
> On Thu, Aug 19, 2010, Lorenzo Brito Morales wrote:
>> its possible to make a streaming video whith bluez?
>
> Not right now.
>
>> if not, are there plans to implementing?
>
> Nothing concrete, but at least the first requirement would be for there
> to exist some devices on the market that support VDP. Do you know any?
> Do you have plans to implement this for BlueZ?
>
> Johan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: [PATCH 1/2] bluetooth: Add support Bluetooth controller of MacbookPro 6,2
From: Marcel Holtmann @ 2010-08-19  8:11 UTC (permalink / raw)
  To: Nobuhiro Iwamatsu; +Cc: linux-bluetooth, stable
In-Reply-To: <1282197259-16609-1-git-send-email-iwamatsu@nigauri.org>

Hi Nobuhiro.

> Bluetooth controller of MacbookPro 6,2 does not work.
> Because Device Class of these controllers was set 255 (Vendor Sepecific Class).
> 
> Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>

it would be nice if you include the output from /proc/bus/usb/devices or
usb-devices.sh script to proof the different device class.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] Fix problem with multiple emails in vcard
From: Johan Hedberg @ 2010-08-19  8:03 UTC (permalink / raw)
  To: Radoslaw Jablonski; +Cc: linux-bluetooth
In-Reply-To: <1282200587-5475-1-git-send-email-ext-jablonski.radoslaw@nokia.com>

Hi Radek,

On Thu, Aug 19, 2010, Radoslaw Jablonski wrote:
> Previously only one email appeared in generated vcard, even if contact
> had defined multiple email addresses in contact data.
> Changed vcard struct and phonebook-tracker pull_contacts func to support
> multiple emails.
> ---
>  plugins/phonebook-tracker.c |   99 +++++++++++++++++++++++++++++-------------
>  plugins/vcard.c             |   12 ++++-
>  plugins/vcard.h             |    2 +-
>  3 files changed, 78 insertions(+), 35 deletions(-)

Thanks. The patch is now upstream.

Johan

^ permalink raw reply

* Re: its possible to make a streaming video whith bluez?
From: Johan Hedberg @ 2010-08-19  7:49 UTC (permalink / raw)
  To: Lorenzo Brito Morales; +Cc: linux-bluetooth
In-Reply-To: <AANLkTikEHVwEXQg=0ahqwDOANa-VPLjd11xC2ri2N8d5@mail.gmail.com>

Hi,

On Thu, Aug 19, 2010, Lorenzo Brito Morales wrote:
> its possible to make a streaming video whith bluez?

Not right now.

> if not, are there plans to implementing?

Nothing concrete, but at least the first requirement would be for there
to exist some devices on the market that support VDP. Do you know any?
Do you have plans to implement this for BlueZ?

Johan

^ permalink raw reply

* its possible to make a streaming video whith bluez?
From: Lorenzo Brito Morales @ 2010-08-19  6:57 UTC (permalink / raw)
  To: linux-bluetooth

its possible to make a streaming video whith bluez? if not, are there
plans to implementing?

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox