linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/14] input: remove unneeded header inclusions
@ 2012-07-09 21:10 Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 02/14] serial: remove the whole serial code Gustavo Padovan
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 input/device.c  |    5 -----
 input/fakehid.c |    4 ----
 input/manager.c |    3 ---
 3 files changed, 12 deletions(-)

diff --git a/input/device.c b/input/device.c
index 7eac71e..829ca03 100644
--- a/input/device.c
+++ b/input/device.c
@@ -29,9 +29,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hidp.h>
@@ -39,8 +36,6 @@
 #include <bluetooth/sdp_lib.h>
 #include <bluetooth/uuid.h>
 
-#include <glib.h>
-#include <dbus/dbus.h>
 #include <gdbus.h>
 
 #include "log.h"
diff --git a/input/fakehid.c b/input/fakehid.c
index 3181538..3be1489 100644
--- a/input/fakehid.c
+++ b/input/fakehid.c
@@ -25,12 +25,8 @@
 #include <config.h>
 #endif
 
-#include <stdio.h>
-#include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
 
 #include <bluetooth/bluetooth.h>
 
diff --git a/input/manager.c b/input/manager.c
index 01f83ce..928a2f5 100644
--- a/input/manager.c
+++ b/input/manager.c
@@ -28,13 +28,10 @@
 #include <errno.h>
 
 #include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
 #include <bluetooth/sdp.h>
 #include <bluetooth/sdp_lib.h>
 #include <bluetooth/uuid.h>
 
-#include <gdbus.h>
-
 #include "log.h"
 #include "../src/adapter.h"
 #include "../src/device.h"
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 02/14] serial: remove the whole serial code
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 03/14] btmgmt: move to tools folder Gustavo Padovan
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 Makefile.am        |   20 +-
 acinclude.m4       |    6 -
 doc/serial-api.txt |  138 +-----
 serial/main.c      |   59 ---
 serial/manager.c   |  174 -------
 serial/manager.h   |   25 --
 serial/port.c      |  646 --------------------------
 serial/port.h      |   29 --
 serial/proxy.c     | 1269 ----------------------------------------------------
 serial/proxy.h     |   25 --
 serial/serial.conf |   10 -
 11 files changed, 6 insertions(+), 2395 deletions(-)
 delete mode 100644 serial/main.c
 delete mode 100644 serial/manager.c
 delete mode 100644 serial/manager.h
 delete mode 100644 serial/port.c
 delete mode 100644 serial/port.h
 delete mode 100644 serial/proxy.c
 delete mode 100644 serial/proxy.h
 delete mode 100644 serial/serial.conf

diff --git a/Makefile.am b/Makefile.am
index 97146c9..a2c85e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -191,14 +191,6 @@ builtin_modules += hog
 builtin_sources += input/hog_device.h input/hog_device.c
 endif
 
-if SERIALPLUGIN
-builtin_modules += serial
-builtin_sources += serial/main.c \
-			serial/manager.h serial/manager.c \
-			serial/proxy.h serial/proxy.c \
-			serial/port.h serial/port.c
-endif
-
 if NETWORKPLUGIN
 builtin_modules += network
 builtin_sources += network/main.c \
@@ -334,11 +326,10 @@ endif
 
 EXTRA_DIST += src/genbuiltin src/bluetooth.conf src/org.bluez.service \
 			src/main.conf network/network.conf \
-			input/input.conf serial/serial.conf \
+			input/input.conf proximity/proximity.conf \
 			audio/audio.conf audio/telephony-dummy.c \
 			audio/telephony-maemo5.c audio/telephony-ofono.c \
-			audio/telephony-maemo6.c sap/sap-dummy.c sap/sap-u8500.c \
-			proximity/proximity.conf
+			audio/telephony-maemo6.c sap/sap-dummy.c sap/sap-u8500.c
 
 if AUDIOPLUGIN
 if GSTREAMER
@@ -392,10 +383,9 @@ EXTRA_DIST += scripts/bluetooth-hid2hci.rules scripts/bluetooth-serial.rules
 EXTRA_DIST += doc/manager-api.txt \
 		doc/adapter-api.txt doc/device-api.txt \
 		doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
-		doc/serial-api.txt doc/network-api.txt \
-		doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
-		doc/hfp-api.txt doc/health-api.txt doc/sap-api.txt \
-		doc/media-api.txt doc/assigned-numbers.txt
+		doc/network-api.txt doc/input-api.txt doc/audio-api.txt \
+		doc/control-api.txt doc/hfp-api.txt doc/health-api.txt \
+		doc/sap-api.txt doc/media-api.txt doc/assigned-numbers.txt
 
 AM_YFLAGS = -d
 
diff --git a/acinclude.m4 b/acinclude.m4
index 3a2a50a..842eea3 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -172,7 +172,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	gstreamer_enable=${gstreamer_found}
 	audio_enable=yes
 	input_enable=yes
-	serial_enable=yes
 	network_enable=yes
 	sap_enable=no
 	service_enable=yes
@@ -218,10 +217,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	])
 	AC_SUBST([SAP_DRIVER], [sap-${sap_driver}.c])
 
-	AC_ARG_ENABLE(serial, AC_HELP_STRING([--disable-serial], [disable serial plugin]), [
-		serial_enable=${enableval}
-	])
-
 	AC_ARG_ENABLE(input, AC_HELP_STRING([--disable-input], [disable input plugin]), [
 		input_enable=${enableval}
 	])
@@ -345,7 +340,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(GSTREAMER, test "${gstreamer_enable}" = "yes" && test "${gstreamer_found}" = "yes")
 	AM_CONDITIONAL(AUDIOPLUGIN, test "${audio_enable}" = "yes")
 	AM_CONDITIONAL(INPUTPLUGIN, test "${input_enable}" = "yes")
-	AM_CONDITIONAL(SERIALPLUGIN, test "${serial_enable}" = "yes")
 	AM_CONDITIONAL(NETWORKPLUGIN, test "${network_enable}" = "yes")
 	AM_CONDITIONAL(SAPPLUGIN, test "${sap_enable}" = "yes")
 	AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes")
diff --git a/doc/serial-api.txt b/doc/serial-api.txt
index 0bdbdcd..9bb0054 100644
--- a/doc/serial-api.txt
+++ b/doc/serial-api.txt
@@ -11,22 +11,7 @@ Service		org.bluez
 Interface	org.bluez.Serial
 Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
 
-Methods		string Connect(string pattern)
-
-			Connects to a specific RFCOMM based service on a
-			remote device and then creates a RFCOMM TTY
-			device for it. The RFCOMM TTY device is returned.
-
-			Possible patterns: UUID 128 bit as string
-					   Profile short names, e.g: spp, dun
-					   RFCOMM channel as string, 1-30
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.InProgress
-					 org.bluez.Error.ConnectionAttemptFailed
-					 org.bluez.Error.NotSupported
-
-Methods		fd ConnectFD(string pattern) [experimental]
+Methods		fd Connect(string pattern)
 
 			Connects to a specific RFCOMM based service on a
 			remote device and returns a file descriptor to talk
@@ -40,124 +25,3 @@ Methods		fd ConnectFD(string pattern) [experimental]
 					 org.bluez.Error.InProgress
 					 org.bluez.Error.ConnectionAttemptFailed
 					 org.bluez.Error.NotSupported
-
-
-		void Disconnect(string device)
-
-			Disconnect a RFCOMM TTY device that has been
-			created by Connect method.
-
-			To abort a connection attempt in case of errors or
-			timeouts in the client it is fine to call this method.
-
-			In that case one of patterns of the Connect method should
-			be supplied instead of the TTY device.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.DoesNotExist
-
-Serial Proxy Manager hierarchy [experimental]
-=============================================
-
-Service		org.bluez
-Interface	org.bluez.SerialProxyManager
-Object path	[variable prefix]/{hci0,hci1,...}
-
-Methods		array{string} ListProxies()
-
-			Returns an array of the object path strings of
-			all the proxies created for the adapter.
-
-		string CreateProxy(string pattern, string address)
-
-			Possible patterns: UUID 128 bit as string
-					   Profile short names, e.g: spp, dun
-					   RFCOMM channel as string, 1-30
-
-			Address is the path to the TTY or Unix socket to be used.
-			Only one proxy per address (TTY or Unix socket)
-			is allowed.
-
-			The object path of created proxy is returned.
-			On success this will emit a ProxyCreated signal.
-
-			Possible Errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.AlreadyExists
-					 org.bluez.Error.Failed
-
-		void RemoveProxy(string path)
-
-			This removes the proxy object at the given path.
-			On success this will emit a ProxyRemoved signal.
-
-			Possible Errors: org.bluez.Error.DoesNotExist
-					 org.bluez.Error.NotAuthorized
-
-Signals		ProxyCreated(string path)
-
-			This signal indicates a proxy was created.
-			Parameter is object path of created proxy.
-
-		ProxyRemoved(string path)
-
-			This signal indicates a proxy was removed.
-			Parameter is object path of removed proxy.
-
-Serial Proxy hierarchy [experimental]
-=====================================
-
-Service		org.bluez
-Interface	org.bluez.SerialProxy
-Object path	[variable prefix]/{hci0,hci1,...}/{proxy0,proxy1,...}
-
-Methods		void Enable()
-
-			Starts to listen to the TTY or Unix socket, allocates
-			a RFCOMM channel and add record to the server.
-
-			Possible errors: org.bluez.Error.Failed
-
-		void Disable()
-
-			Stops to listen to the TTY or Unix socket, shutdown
-			the RFCOMM channel allocated for the proxy, and remove
-			record from the server.
-
-			Possible errors: org.bluez.Error.Failed
-
-		dict GetInfo()
-
-			Returns all properties for the proxy. See the
-			properties section for available properties.
-
-		void SetSerialParameters(string rate, uint8 data, uint8 stop,
-			string parity)
-
-			Configures serial communication setting baud rate,
-			data bits, stop bits and parity.
-
-			Doesn't allow change TTY settings if it is open.
-
-			Possible errors: org.bluez.Error.InvalidArguments
-					 org.bluez.Error.NotAuthorized
-
-Properties	string uuid [readonly]
-
-			128-bit UUID that represents the available remote service.
-
-		string address [readonly]
-
-			Address is the path to the TTY or Unix socket name used,
-			set when the proxy was created.
-
-		uint8 channel [readonly]
-
-			RFCOMM channel.
-
-		boolean enabled [readonly]
-
-			Indicates if the proxy is currently enabled.
-
-		boolean connected [readonly]
-
-			Indicates if the proxy is currently connected.
diff --git a/serial/main.c b/serial/main.c
deleted file mode 100644
index 38ded03..0000000
--- a/serial/main.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-
-#include <gdbus.h>
-
-#include "plugin.h"
-#include "manager.h"
-
-static DBusConnection *connection;
-
-static int serial_init(void)
-{
-	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
-	if (connection == NULL)
-		return -EIO;
-
-	if (serial_manager_init(connection) < 0) {
-		dbus_connection_unref(connection);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void serial_exit(void)
-{
-	serial_manager_exit();
-
-	dbus_connection_unref(connection);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(serial, VERSION,
-			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, serial_init, serial_exit)
diff --git a/serial/manager.c b/serial/manager.c
deleted file mode 100644
index 438ba6c..0000000
--- a/serial/manager.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/uuid.h>
-
-#include <glib.h>
-#include <gdbus.h>
-
-#include "../src/dbus-common.h"
-#include "adapter.h"
-#include "device.h"
-
-#include "log.h"
-
-#include "error.h"
-#include "port.h"
-#include "proxy.h"
-#include "storage.h"
-#include "manager.h"
-#include "sdpd.h"
-#include "glib-helper.h"
-
-static DBusConnection *connection = NULL;
-
-static int serial_probe(struct btd_device *device, const char *uuid)
-{
-	struct btd_adapter *adapter = device_get_adapter(device);
-	const gchar *path = device_get_path(device);
-	sdp_list_t *protos;
-	int ch;
-	bdaddr_t src, dst;
-	const sdp_record_t *rec;
-
-	DBG("path %s: %s", path, uuid);
-
-	rec = btd_device_get_record(device, uuid);
-	if (!rec)
-		return -EINVAL;
-
-	if (sdp_get_access_protos(rec, &protos) < 0)
-		return -EINVAL;
-
-	ch = sdp_get_proto_port(protos, RFCOMM_UUID);
-	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
-	sdp_list_free(protos, NULL);
-
-	if (ch < 1 || ch > 30) {
-		error("Channel out of range: %d", ch);
-		return -EINVAL;
-	}
-
-	adapter_get_address(adapter, &src);
-	device_get_address(device, &dst, NULL);
-
-	return port_register(connection, path, &src, &dst, uuid, ch);
-}
-
-static void serial_remove(struct btd_device *device)
-{
-	const gchar *path = device_get_path(device);
-
-	DBG("path %s", path);
-
-	port_unregister(path);
-}
-
-
-static int port_probe(struct btd_device *device, GSList *uuids)
-{
-	while (uuids) {
-		serial_probe(device, uuids->data);
-		uuids = uuids->next;
-	}
-
-	return 0;
-}
-
-static void port_remove(struct btd_device *device)
-{
-	return serial_remove(device);
-}
-
-static struct btd_device_driver serial_port_driver = {
-	.name	= "serial-port",
-	.uuids	= BTD_UUIDS(RFCOMM_UUID_STR),
-	.probe	= port_probe,
-	.remove	= port_remove,
-};
-
-static int proxy_probe(struct btd_adapter *adapter)
-{
-	const char *path = adapter_get_path(adapter);
-
-	DBG("path %s", path);
-
-	return proxy_register(connection, adapter);
-}
-
-static void proxy_remove(struct btd_adapter *adapter)
-{
-	const char *path = adapter_get_path(adapter);
-
-	DBG("path %s", path);
-
-	proxy_unregister(adapter);
-}
-
-static struct btd_adapter_driver serial_proxy_driver = {
-	.name	= "serial-proxy",
-	.probe	= proxy_probe,
-	.remove	= proxy_remove,
-};
-
-int serial_manager_init(DBusConnection *conn)
-{
-	connection = dbus_connection_ref(conn);
-
-	btd_register_adapter_driver(&serial_proxy_driver);
-	btd_register_device_driver(&serial_port_driver);
-
-	return 0;
-}
-
-void serial_manager_exit(void)
-{
-	btd_unregister_device_driver(&serial_port_driver);
-
-	dbus_connection_unref(connection);
-	connection = NULL;
-}
diff --git a/serial/manager.h b/serial/manager.h
deleted file mode 100644
index c8b96e8..0000000
--- a/serial/manager.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-int serial_manager_init(DBusConnection *conn);
-void serial_manager_exit(void);
diff --git a/serial/port.c b/serial/port.c
deleted file mode 100644
index f90bb6a..0000000
--- a/serial/port.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include <glib.h>
-#include <gdbus.h>
-
-#include "../src/dbus-common.h"
-
-#include "log.h"
-#include "glib-helper.h"
-#include "sdp-client.h"
-#include "btio.h"
-
-#include "error.h"
-#include "manager.h"
-#include "adapter.h"
-#include "device.h"
-#include "storage.h"
-#include "port.h"
-
-#define SERIAL_PORT_INTERFACE	"org.bluez.Serial"
-
-#define MAX_OPEN_TRIES		5
-#define OPEN_WAIT		300	/* ms. udev node creation retry wait */
-
-struct serial_device {
-	DBusConnection	*conn;		/* for name listener handling */
-	bdaddr_t	src;		/* Source (local) address */
-	bdaddr_t	dst;		/* Destination address */
-	char		*path;		/* Device path */
-	GSList		*ports;		/* Available ports */
-};
-
-struct serial_port {
-	DBusMessage	*msg;		/* for name listener handling */
-	int16_t		id;		/* RFCOMM device id */
-	uint8_t		channel;	/* RFCOMM channel */
-	char		*uuid;		/* service identification */
-	char		*dev;		/* RFCOMM device name */
-	int		fd;		/* Opened file descriptor */
-	GIOChannel	*io;		/* BtIO channel */
-	guint		listener_id;
-	struct serial_device *device;
-};
-
-static GSList *devices = NULL;
-
-static struct serial_device *find_device(GSList *devices, const char *path)
-{
-	GSList *l;
-
-	for (l = devices; l != NULL; l = l->next) {
-		struct serial_device *device = l->data;
-
-		if (!strcmp(device->path, path))
-			return device;
-	}
-
-	return NULL;
-}
-
-static struct serial_port *find_port(GSList *ports, const char *pattern)
-{
-	GSList *l;
-	int channel;
-	char *endptr = NULL;
-
-	channel = strtol(pattern, &endptr, 10);
-
-	for (l = ports; l != NULL; l = l->next) {
-		struct serial_port *port = l->data;
-		char *uuid_str;
-		int ret;
-
-		if (port->uuid && !strcasecmp(port->uuid, pattern))
-			return port;
-
-		if (endptr && *endptr == '\0' && port->channel == channel)
-			return port;
-
-		if (port->dev && !strcmp(port->dev, pattern))
-			return port;
-
-		if (!port->uuid)
-			continue;
-
-		uuid_str = bt_name2string(pattern);
-		if (!uuid_str)
-			continue;
-
-		ret = strcasecmp(port->uuid, uuid_str);
-		g_free(uuid_str);
-		if (ret == 0)
-			return port;
-	}
-
-	return NULL;
-}
-
-static int port_release(struct serial_port *port)
-{
-	struct rfcomm_dev_req req;
-	int rfcomm_ctl;
-	int err = 0;
-
-	if (port->id < 0) {
-		if (port->io) {
-			g_io_channel_shutdown(port->io, TRUE, NULL);
-			g_io_channel_unref(port->io);
-			port->io = NULL;
-		} else
-			bt_cancel_discovery(&port->device->src,
-						&port->device->dst);
-
-		return 0;
-	}
-
-	DBG("Serial port %s released", port->dev);
-
-	rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
-	if (rfcomm_ctl < 0)
-		return -errno;
-
-	if (port->fd >= 0) {
-		close(port->fd);
-		port->fd = -1;
-	}
-
-	memset(&req, 0, sizeof(req));
-	req.dev_id = port->id;
-
-	/*
-	 * We are hitting a kernel bug inside RFCOMM code when
-	 * RFCOMM_HANGUP_NOW bit is set on request's flags passed to
-	 * ioctl(RFCOMMRELEASEDEV)!
-	 */
-	req.flags = (1 << RFCOMM_HANGUP_NOW);
-
-	if (ioctl(rfcomm_ctl, RFCOMMRELEASEDEV, &req) < 0) {
-		err = -errno;
-		error("Can't release device %s: %s (%d)",
-				port->dev, strerror(-err), -err);
-	}
-
-	g_free(port->dev);
-	port->dev = NULL;
-	port->id = -1;
-	close(rfcomm_ctl);
-	return err;
-}
-
-static void serial_port_free(void *data)
-{
-	struct serial_port *port = data;
-	struct serial_device *device = port->device;
-
-	if (device && port->listener_id > 0)
-		g_dbus_remove_watch(device->conn, port->listener_id);
-
-	port_release(port);
-
-	g_free(port->uuid);
-	g_free(port);
-}
-
-static void serial_device_free(void *data)
-{
-	struct serial_device *device = data;
-
-	g_free(device->path);
-	if (device->conn)
-		dbus_connection_unref(device->conn);
-	g_free(device);
-}
-
-static void port_owner_exited(DBusConnection *conn, void *user_data)
-{
-	struct serial_port *port = user_data;
-
-	port_release(port);
-
-	port->listener_id = 0;
-}
-
-static void path_unregister(void *data)
-{
-	struct serial_device *device = data;
-
-	DBG("Unregistered interface %s on path %s", SERIAL_PORT_INTERFACE,
-		device->path);
-
-	devices = g_slist_remove(devices, device);
-	serial_device_free(device);
-}
-
-void port_release_all(void)
-{
-	g_slist_free_full(devices, serial_device_free);
-}
-
-static void open_notify(int fd, int err, struct serial_port *port)
-{
-	struct serial_device *device = port->device;
-	DBusMessage *reply;
-
-	if (err < 0) {
-		/* Max tries exceeded */
-		port_release(port);
-		reply = btd_error_failed(port->msg, strerror(-err));
-	} else {
-		port->fd = fd;
-		reply = g_dbus_create_reply(port->msg,
-				DBUS_TYPE_STRING, &port->dev,
-				DBUS_TYPE_INVALID);
-	}
-
-	/* Reply to the requestor */
-	g_dbus_send_message(device->conn, reply);
-}
-
-static gboolean open_continue(gpointer user_data)
-{
-	struct serial_port *port = user_data;
-	int fd;
-	static int ntries = MAX_OPEN_TRIES;
-
-	if (!port->listener_id)
-		return FALSE; /* Owner exited */
-
-	fd = open(port->dev, O_RDONLY | O_NOCTTY);
-	if (fd < 0) {
-		int err = -errno;
-		error("Could not open %s: %s (%d)",
-				port->dev, strerror(-err), -err);
-		if (!--ntries) {
-			/* Reporting error */
-			open_notify(fd, err, port);
-			ntries = MAX_OPEN_TRIES;
-			return FALSE;
-		}
-		return TRUE;
-	}
-
-	/* Connection succeeded */
-	open_notify(fd, 0, port);
-	return FALSE;
-}
-
-static int port_open(struct serial_port *port)
-{
-	int fd;
-
-	fd = open(port->dev, O_RDONLY | O_NOCTTY);
-	if (fd < 0) {
-		g_timeout_add(OPEN_WAIT, open_continue, port);
-		return -EINPROGRESS;
-	}
-
-	return fd;
-}
-
-static void rfcomm_connect_cb(GIOChannel *chan, GError *conn_err,
-							gpointer user_data)
-{
-	struct serial_port *port = user_data;
-	struct serial_device *device = port->device;
-	struct rfcomm_dev_req req;
-	int sk, fd;
-	DBusMessage *reply;
-
-	/* Owner exited? */
-	if (!port->listener_id)
-		return;
-
-	if (conn_err) {
-		error("%s", conn_err->message);
-		reply = btd_error_failed(port->msg, conn_err->message);
-		goto fail;
-	}
-
-	sk = g_io_channel_unix_get_fd(chan);
-
-	if (dbus_message_has_member(port->msg, "ConnectFD")) {
-		reply = g_dbus_create_reply(port->msg, DBUS_TYPE_UNIX_FD, &sk,
-							DBUS_TYPE_INVALID);
-		g_dbus_send_message(device->conn, reply);
-
-		close(sk);
-
-		g_dbus_remove_watch(device->conn, port->listener_id);
-		port->listener_id = 0;
-
-		return;
-	}
-
-	memset(&req, 0, sizeof(req));
-	req.dev_id = -1;
-	req.flags = (1 << RFCOMM_REUSE_DLC);
-	bacpy(&req.src, &device->src);
-	bacpy(&req.dst, &device->dst);
-	req.channel = port->channel;
-
-	g_io_channel_unref(port->io);
-	port->io = NULL;
-
-	port->id = ioctl(sk, RFCOMMCREATEDEV, &req);
-	if (port->id < 0) {
-		int err = -errno;
-		error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(-err), -err);
-		reply = btd_error_failed(port->msg, strerror(-err));
-		g_io_channel_shutdown(chan, TRUE, NULL);
-		goto fail;
-	}
-
-	port->dev = g_strdup_printf("/dev/rfcomm%d", port->id);
-
-	DBG("Serial port %s created", port->dev);
-
-	g_io_channel_shutdown(chan, TRUE, NULL);
-
-	/* Addressing connect port */
-	fd = port_open(port);
-	if (fd < 0)
-		/* Open in progress: Wait the callback */
-		return;
-
-	open_notify(fd, 0, port);
-	return;
-
-fail:
-	g_dbus_send_message(device->conn, reply);
-	g_dbus_remove_watch(device->conn, port->listener_id);
-	port->listener_id = 0;
-}
-
-static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
-{
-	struct serial_port *port = user_data;
-	struct serial_device *device = port->device;
-	sdp_record_t *record = NULL;
-	sdp_list_t *protos;
-	DBusMessage *reply;
-	GError *gerr = NULL;
-
-	if (!port->listener_id)
-		return;
-
-	if (err < 0) {
-		error("Unable to get service record: %s (%d)", strerror(-err),
-			-err);
-		reply = btd_error_failed(port->msg, strerror(-err));
-		goto failed;
-	}
-
-	if (!recs || !recs->data) {
-		error("No record found");
-		reply = btd_error_failed(port->msg, "No record found");
-		goto failed;
-	}
-
-	record = recs->data;
-
-	if (sdp_get_access_protos(record, &protos) < 0) {
-		error("Unable to get access protos from port record");
-		reply = btd_error_failed(port->msg, "Invalid channel");
-		goto failed;
-	}
-
-	port->channel = sdp_get_proto_port(protos, RFCOMM_UUID);
-
-	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
-	sdp_list_free(protos, NULL);
-
-	port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port,
-				NULL, &gerr,
-				BT_IO_OPT_SOURCE_BDADDR, &device->src,
-				BT_IO_OPT_DEST_BDADDR, &device->dst,
-				BT_IO_OPT_CHANNEL, port->channel,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-				BT_IO_OPT_INVALID);
-	if (!port->io) {
-		error("%s", gerr->message);
-		reply = btd_error_failed(port->msg, gerr->message);
-		g_error_free(gerr);
-		goto failed;
-	}
-
-	return;
-
-failed:
-	g_dbus_remove_watch(device->conn, port->listener_id);
-	port->listener_id = 0;
-	g_dbus_send_message(device->conn, reply);
-}
-
-static int connect_port(struct serial_port *port)
-{
-	struct serial_device *device = port->device;
-	uuid_t uuid;
-	int err;
-
-	if (!port->uuid)
-		goto connect;
-
-	err = bt_string2uuid(&uuid, port->uuid);
-	if (err < 0)
-		return err;
-
-	sdp_uuid128_to_uuid(&uuid);
-
-	return bt_search_service(&device->src, &device->dst, &uuid,
-				get_record_cb, port, NULL);
-
-connect:
-	port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port,
-				NULL, NULL,
-				BT_IO_OPT_SOURCE_BDADDR, &device->src,
-				BT_IO_OPT_DEST_BDADDR, &device->dst,
-				BT_IO_OPT_CHANNEL, port->channel,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-				BT_IO_OPT_INVALID);
-	if (port->io == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-static struct serial_port *create_port(struct serial_device *device,
-					const char *uuid, uint8_t channel)
-{
-	struct serial_port *port;
-
-	port = g_new0(struct serial_port, 1);
-	port->uuid = g_strdup(uuid);
-	port->channel = channel;
-	port->device = device;
-	port->id = -1;
-	port->fd = -1;
-
-	device->ports = g_slist_append(device->ports, port);
-
-	return port;
-}
-
-static DBusMessage *port_connect(DBusConnection *conn,
-					DBusMessage *msg, void *user_data)
-{
-	struct serial_device *device = user_data;
-	struct serial_port *port;
-	const char *pattern;
-	int err;
-
-	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
-						DBUS_TYPE_INVALID) == FALSE)
-		return NULL;
-
-	port = find_port(device->ports, pattern);
-	if (!port) {
-		char *endptr = NULL;
-		int channel;
-
-		channel = strtol(pattern, &endptr, 10);
-		if ((endptr && *endptr != '\0') || channel < 1 || channel > 30)
-			return btd_error_does_not_exist(msg);
-
-		port = create_port(device, NULL, channel);
-	}
-
-	if (port->listener_id)
-		return btd_error_failed(msg, "Port already in use");
-
-	port->listener_id = g_dbus_add_disconnect_watch(conn,
-						dbus_message_get_sender(msg),
-						port_owner_exited, port,
-						NULL);
-
-	port->msg = dbus_message_ref(msg);
-
-	err = connect_port(port);
-	if (err < 0) {
-		error("%s", strerror(-err));
-		g_dbus_remove_watch(conn, port->listener_id);
-		port->listener_id = 0;
-
-		return btd_error_failed(msg, strerror(-err));
-	}
-
-	return NULL;
-}
-
-static DBusMessage *port_disconnect(DBusConnection *conn,
-					DBusMessage *msg, void *user_data)
-{
-	struct serial_device *device = user_data;
-	struct serial_port *port;
-	const char *dev, *owner, *caller;
-
-	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &dev,
-						DBUS_TYPE_INVALID) == FALSE)
-		return NULL;
-
-	port = find_port(device->ports, dev);
-	if (!port)
-		return btd_error_does_not_exist(msg);
-
-	if (!port->listener_id)
-		return btd_error_not_connected(msg);
-
-	owner = dbus_message_get_sender(port->msg);
-	caller = dbus_message_get_sender(msg);
-	if (!g_str_equal(owner, caller))
-		return btd_error_not_authorized(msg);
-
-	port_release(port);
-
-	g_dbus_remove_watch(conn, port->listener_id);
-	port->listener_id = 0;
-
-	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
-}
-
-static const GDBusMethodTable port_methods[] = {
-	{ GDBUS_ASYNC_METHOD("Connect",
-		GDBUS_ARGS({ "pattern", "s" }),	GDBUS_ARGS({ "tty", "s" }),
-		port_connect) },
-	{ GDBUS_ASYNC_METHOD("ConnectFD",
-		GDBUS_ARGS({ "pattern", "s" }), GDBUS_ARGS({ "fd", "s" }),
-		port_connect) },
-	{ GDBUS_METHOD("Disconnect",
-		GDBUS_ARGS({ "device", "s" }), NULL,
-		port_disconnect) },
-	{ }
-};
-
-static struct serial_device *create_serial_device(DBusConnection *conn,
-					const char *path, bdaddr_t *src,
-					bdaddr_t *dst)
-{
-	struct serial_device *device;
-
-	device = g_new0(struct serial_device, 1);
-	device->conn = dbus_connection_ref(conn);
-	bacpy(&device->dst, dst);
-	bacpy(&device->src, src);
-	device->path = g_strdup(path);
-
-	if (!g_dbus_register_interface(conn, path,
-				SERIAL_PORT_INTERFACE,
-				port_methods, NULL, NULL,
-				device, path_unregister)) {
-		error("D-Bus failed to register %s interface",
-				SERIAL_PORT_INTERFACE);
-		serial_device_free(device);
-		return NULL;
-	}
-
-	DBG("Registered interface %s on path %s",
-		SERIAL_PORT_INTERFACE, path);
-
-	return device;
-}
-
-int port_register(DBusConnection *conn, const char *path, bdaddr_t *src,
-			bdaddr_t *dst, const char *uuid, uint8_t channel)
-{
-	struct serial_device *device;
-	struct serial_port *port;
-
-	device = find_device(devices, path);
-	if (!device) {
-		device = create_serial_device(conn, path, src, dst);
-		if (!device)
-			return -1;
-		devices = g_slist_append(devices, device);
-	}
-
-	if (find_port(device->ports, uuid))
-		return 0;
-
-	port = g_new0(struct serial_port, 1);
-	port->uuid = g_strdup(uuid);
-	port->channel = channel;
-	port->device = device;
-	port->id = -1;
-	port->fd = -1;
-
-	device->ports = g_slist_append(device->ports, port);
-
-	return 0;
-}
-
-int port_unregister(const char *path)
-{
-	struct serial_device *device;
-
-	device = find_device(devices, path);
-	if (!device)
-		return -ENOENT;
-
-	g_slist_free_full(device->ports, serial_port_free);
-
-	g_dbus_unregister_interface(device->conn, path, SERIAL_PORT_INTERFACE);
-
-	return 0;
-}
diff --git a/serial/port.h b/serial/port.h
deleted file mode 100644
index 74ac9f0..0000000
--- a/serial/port.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-void port_release_all(void);
-
-int port_register(DBusConnection *conn, const char *path, bdaddr_t *src,
-		  bdaddr_t *dst, const char *name, uint8_t channel);
-
-int port_unregister(const char *path);
diff --git a/serial/proxy.c b/serial/proxy.c
deleted file mode 100644
index dd38317..0000000
--- a/serial/proxy.c
+++ /dev/null
@@ -1,1269 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/rfcomm.h>
-
-#include <glib.h>
-#include <gdbus.h>
-
-#include "../src/dbus-common.h"
-#include "../src/adapter.h"
-
-#include "log.h"
-
-#include "error.h"
-#include "sdpd.h"
-#include "glib-helper.h"
-#include "btio.h"
-#include "proxy.h"
-
-#define SERIAL_PROXY_INTERFACE	"org.bluez.SerialProxy"
-#define SERIAL_MANAGER_INTERFACE "org.bluez.SerialProxyManager"
-#define BUF_SIZE		1024
-
-typedef enum {
-	TTY_PROXY,
-	UNIX_SOCKET_PROXY,
-	TCP_SOCKET_PROXY,
-	UNKNOWN_PROXY_TYPE = 0xFF
-} proxy_type_t;
-
-struct serial_adapter {
-	struct btd_adapter	*btd_adapter;	/* Adapter pointer */
-	DBusConnection		*conn;		/* Adapter connection */
-	GSList			*proxies;	/* Proxies list */
-};
-
-struct serial_proxy {
-	bdaddr_t	src;		/* Local address */
-	bdaddr_t	dst;		/* Remote address */
-	char		*path;		/* Proxy path */
-	char		*uuid128;	/* UUID 128 */
-	char		*address;	/* TTY or Unix socket name */
-	char		*owner;		/* Application bus name */
-	guint		watch;		/* Application watch */
-	short int	port;		/* TCP port */
-	proxy_type_t	type;		/* TTY or Unix socket */
-	struct termios  sys_ti;		/* Default TTY setting */
-	struct termios  proxy_ti;	/* Proxy TTY settings */
-	uint8_t		channel;	/* RFCOMM channel */
-	uint32_t	record_id;	/* Service record id */
-	GIOChannel	*io;		/* Server listen */
-	GIOChannel	*rfcomm;	/* Remote RFCOMM channel*/
-	GIOChannel	*local;		/* Local channel: TTY or Unix socket */
-	struct serial_adapter *adapter;	/* Adapter pointer */
-};
-
-static GSList *adapters = NULL;
-static int sk_counter = 0;
-
-static void disable_proxy(struct serial_proxy *prx)
-{
-	if (prx->rfcomm) {
-		g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
-		g_io_channel_unref(prx->rfcomm);
-		prx->rfcomm = NULL;
-	}
-
-	if (prx->local) {
-		g_io_channel_shutdown(prx->local, TRUE, NULL);
-		g_io_channel_unref(prx->local);
-		prx->local = NULL;
-	}
-
-	remove_record_from_server(prx->record_id);
-	prx->record_id = 0;
-
-	g_io_channel_unref(prx->io);
-	prx->io = NULL;
-}
-
-static void proxy_free(struct serial_proxy *prx)
-{
-	g_free(prx->owner);
-	g_free(prx->path);
-	g_free(prx->address);
-	g_free(prx->uuid128);
-	g_free(prx);
-}
-
-static sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel)
-{
-	sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id;
-	uuid_t uuid, root_uuid, l2cap, rfcomm;
-	sdp_profile_desc_t profile;
-	sdp_record_t *record;
-	sdp_data_t *ch;
-
-	record = sdp_record_alloc();
-	if (!record)
-		return NULL;
-
-	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
-	root = sdp_list_append(NULL, &root_uuid);
-	sdp_set_browse_groups(record, root);
-	sdp_list_free(root, NULL);
-
-	bt_string2uuid(&uuid, uuid128);
-	sdp_uuid128_to_uuid(&uuid);
-	svclass_id = sdp_list_append(NULL, &uuid);
-	sdp_set_service_classes(record, svclass_id);
-	sdp_list_free(svclass_id, NULL);
-
-	sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
-	profile.version = 0x0100;
-	profiles = sdp_list_append(NULL, &profile);
-	sdp_set_profile_descs(record, profiles);
-	sdp_list_free(profiles, NULL);
-
-	sdp_uuid16_create(&l2cap, L2CAP_UUID);
-	proto[0] = sdp_list_append(NULL, &l2cap);
-	apseq = sdp_list_append(NULL, proto[0]);
-
-	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
-	proto[1] = sdp_list_append(NULL, &rfcomm);
-	ch = sdp_data_alloc(SDP_UINT8, &channel);
-	proto[1] = sdp_list_append(proto[1], ch);
-	apseq = sdp_list_append(apseq, proto[1]);
-
-	aproto = sdp_list_append(NULL, apseq);
-	sdp_set_access_protos(record, aproto);
-
-	sdp_add_lang_attr(record);
-
-	sdp_set_info_attr(record, "Serial Proxy", NULL, "Serial Proxy");
-
-	sdp_data_free(ch);
-	sdp_list_free(proto[0], NULL);
-	sdp_list_free(proto[1], NULL);
-	sdp_list_free(apseq, NULL);
-	sdp_list_free(aproto, NULL);
-
-	return record;
-}
-
-static int channel_write(GIOChannel *chan, char *buf, size_t size)
-{
-	size_t wbytes;
-	ssize_t written;
-	int fd;
-
-	fd = g_io_channel_unix_get_fd(chan);
-
-	wbytes = 0;
-	while (wbytes < size) {
-		written = write(fd, buf + wbytes, size - wbytes);
-		if (written < 0)
-			return -errno;
-
-		wbytes += written;
-	}
-
-	return 0;
-}
-
-static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data)
-{
-	char buf[BUF_SIZE];
-	struct serial_proxy *prx = data;
-	GIOChannel *dest;
-	ssize_t rbytes;
-	int fd, err;
-
-	if (cond & G_IO_NVAL)
-		return FALSE;
-
-	dest = (chan == prx->rfcomm) ? prx->local : prx->rfcomm;
-
-	fd = g_io_channel_unix_get_fd(chan);
-
-	if (cond & (G_IO_HUP | G_IO_ERR)) {
-		/* Try forward remaining data */
-		do {
-			rbytes = read(fd, buf, sizeof(buf));
-			if (rbytes <= 0)
-				break;
-
-			err = channel_write(dest, buf, rbytes);
-		} while (err == 0);
-
-		g_io_channel_shutdown(prx->local, TRUE, NULL);
-		g_io_channel_unref(prx->local);
-		prx->local = NULL;
-
-		g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
-		g_io_channel_unref(prx->rfcomm);
-		prx->rfcomm = NULL;
-
-		return FALSE;
-	}
-
-	rbytes = read(fd, buf, sizeof(buf));
-	if (rbytes < 0)
-		return FALSE;
-
-	err = channel_write(dest, buf, rbytes);
-	if (err != 0)
-		return FALSE;
-
-	return TRUE;
-}
-
-static inline int unix_socket_connect(const char *address)
-{
-	struct sockaddr_un addr;
-	int err, sk;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = PF_UNIX;
-
-	if (strncmp("x00", address, 3) == 0) {
-		/*
-		 * Abstract namespace: first byte NULL, x00
-		 * must be removed from the original address.
-		 */
-		strncpy(addr.sun_path + 1, address + 3,
-						sizeof(addr.sun_path) - 2);
-	} else {
-		/* Filesystem address */
-		strncpy(addr.sun_path, address, sizeof(addr.sun_path) - 1);
-	}
-
-	/* Unix socket */
-	sk = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (sk < 0) {
-		err = -errno;
-		error("Unix socket(%s) create failed: %s(%d)",
-				address, strerror(-err), -err);
-		return err;
-	}
-
-	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		err = -errno;
-		error("Unix socket(%s) connect failed: %s(%d)",
-				address, strerror(-err), -err);
-		close(sk);
-		return err;
-	}
-
-	return sk;
-}
-
-static int tcp_socket_connect(const char *address)
-{
-	struct sockaddr_in addr;
-	int err, sk, port;
-
-	memset(&addr, 0, sizeof(addr));
-
-	if (strncmp(address, "localhost", 9) != 0) {
-		error("Address should have the form localhost:port.");
-		return -1;
-	}
-	port = atoi(strchr(address, ':') + 1);
-	if (port <= 0) {
-		error("Invalid port '%d'.", port);
-		return -1;
-	}
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-	addr.sin_port = htons(port);
-
-	sk = socket(PF_INET, SOCK_STREAM, 0);
-	if (sk < 0) {
-		err = -errno;
-		error("TCP socket(%s) create failed %s(%d)", address,
-							strerror(-err), -err);
-		return err;
-	}
-	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		err = -errno;
-		error("TCP socket(%s) connect failed: %s(%d)",
-						address, strerror(-err), -err);
-		close(sk);
-		return err;
-	}
-	return sk;
-}
-
-static inline int tty_open(const char *tty, struct termios *ti)
-{
-	int err, sk;
-
-	sk = open(tty, O_RDWR | O_NOCTTY);
-	if (sk < 0) {
-		err = -errno;
-		error("Can't open TTY %s: %s(%d)", tty, strerror(-err), -err);
-		return err;
-	}
-
-	if (ti && tcsetattr(sk, TCSANOW, ti) < 0) {
-		err = -errno;
-		error("Can't change serial settings: %s(%d)",
-				strerror(-err), -err);
-		close(sk);
-		return err;
-	}
-
-	return sk;
-}
-
-static void connect_event_cb(GIOChannel *chan, GError *conn_err, gpointer data)
-{
-	struct serial_proxy *prx = data;
-	int sk;
-
-	if (conn_err) {
-		error("%s", conn_err->message);
-		goto drop;
-	}
-
-	/* Connect local */
-	switch (prx->type) {
-	case UNIX_SOCKET_PROXY:
-		sk = unix_socket_connect(prx->address);
-		break;
-	case TTY_PROXY:
-		sk = tty_open(prx->address, &prx->proxy_ti);
-		break;
-	case TCP_SOCKET_PROXY:
-		sk = tcp_socket_connect(prx->address);
-		break;
-	default:
-		sk = -1;
-	}
-
-	if (sk < 0)
-		goto drop;
-
-	prx->local = g_io_channel_unix_new(sk);
-
-	g_io_add_watch(prx->rfcomm,
-			G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-			forward_data, prx);
-
-	g_io_add_watch(prx->local,
-			G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-			forward_data, prx);
-
-	return;
-
-drop:
-	g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
-	g_io_channel_unref(prx->rfcomm);
-	prx->rfcomm = NULL;
-}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
-	struct serial_proxy *prx = user_data;
-	GError *err = NULL;
-
-	if (derr) {
-		error("Access denied: %s", derr->message);
-		goto reject;
-	}
-
-	if (!bt_io_accept(prx->rfcomm, connect_event_cb, prx, NULL,
-							&err)) {
-		error("bt_io_accept: %s", err->message);
-		g_error_free(err);
-		goto reject;
-	}
-
-	return;
-
-reject:
-	g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
-	g_io_channel_unref(prx->rfcomm);
-	prx->rfcomm = NULL;
-}
-
-static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
-{
-	struct serial_proxy *prx = user_data;
-	int perr;
-	char address[18];
-	GError *err = NULL;
-
-	bt_io_get(chan, BT_IO_RFCOMM, &err,
-			BT_IO_OPT_DEST_BDADDR, &prx->dst,
-			BT_IO_OPT_DEST, address,
-			BT_IO_OPT_INVALID);
-	if (err) {
-		error("%s", err->message);
-		g_error_free(err);
-		goto drop;
-	}
-
-	if (prx->rfcomm) {
-		error("Refusing connect from %s: Proxy already in use",
-				address);
-		goto drop;
-	}
-
-	DBG("Serial Proxy: incoming connect from %s", address);
-
-	prx->rfcomm = g_io_channel_ref(chan);
-
-	perr = btd_request_authorization(&prx->src, &prx->dst,
-					prx->uuid128, auth_cb, prx);
-	if (perr < 0) {
-		error("Refusing connect from %s: %s (%d)", address,
-				strerror(-perr), -perr);
-		g_io_channel_unref(prx->rfcomm);
-		prx->rfcomm = NULL;
-		goto drop;
-	}
-
-	return;
-
-drop:
-	g_io_channel_shutdown(chan, TRUE, NULL);
-}
-
-static int enable_proxy(struct serial_proxy *prx)
-{
-	sdp_record_t *record;
-	GError *gerr = NULL;
-	int err;
-
-	if (prx->io)
-		return -EALREADY;
-
-	/* Listen */
-	prx->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event_cb, prx,
-				NULL, &gerr,
-				BT_IO_OPT_SOURCE_BDADDR, &prx->src,
-				BT_IO_OPT_INVALID);
-	if (!prx->io)
-		goto failed;
-
-	bt_io_get(prx->io, BT_IO_RFCOMM, &gerr,
-			BT_IO_OPT_CHANNEL, &prx->channel,
-			BT_IO_OPT_INVALID);
-	if (gerr) {
-		g_io_channel_unref(prx->io);
-		prx->io = NULL;
-		goto failed;
-	}
-
-	DBG("Allocated channel %d", prx->channel);
-
-	g_io_channel_set_close_on_unref(prx->io, TRUE);
-
-	record = proxy_record_new(prx->uuid128, prx->channel);
-	if (!record) {
-		g_io_channel_unref(prx->io);
-		return -ENOMEM;
-	}
-
-	err = add_record_to_server(&prx->src, record);
-	if (err < 0) {
-		sdp_record_free(record);
-		g_io_channel_unref(prx->io);
-		return err;
-	}
-
-	prx->record_id = record->handle;
-
-	return 0;
-
-failed:
-	error("%s", gerr->message);
-	g_error_free(gerr);
-	return -EIO;
-
-}
-static DBusMessage *proxy_enable(DBusConnection *conn,
-				DBusMessage *msg, void *data)
-{
-	struct serial_proxy *prx = data;
-	int err;
-
-	err = enable_proxy(prx);
-	if (err < 0)
-		return btd_error_failed(msg, strerror(-err));
-
-	return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *proxy_disable(DBusConnection *conn,
-				DBusMessage *msg, void *data)
-{
-	struct serial_proxy *prx = data;
-
-	if (!prx->io)
-		return btd_error_failed(msg, "Not enabled");
-
-	/* Remove the watches and unregister the record */
-	disable_proxy(prx);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *proxy_get_info(DBusConnection *conn,
-				DBusMessage *msg, void *data)
-{
-	struct serial_proxy *prx = data;
-	DBusMessage *reply;
-	DBusMessageIter iter, dict;
-	dbus_bool_t boolean;
-
-	reply = dbus_message_new_method_return(msg);
-	if (!reply)
-		return NULL;
-
-	dbus_message_iter_init_append(reply, &iter);
-
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-	dict_append_entry(&dict, "uuid", DBUS_TYPE_STRING, &prx->uuid128);
-
-	dict_append_entry(&dict, "address", DBUS_TYPE_STRING, &prx->address);
-
-	if (prx->channel)
-		dict_append_entry(&dict, "channel",
-					DBUS_TYPE_BYTE, &prx->channel);
-
-	boolean = (prx->io ? TRUE : FALSE);
-	dict_append_entry(&dict, "enabled", DBUS_TYPE_BOOLEAN, &boolean);
-
-	boolean = (prx->rfcomm ? TRUE : FALSE);
-	dict_append_entry(&dict, "connected", DBUS_TYPE_BOOLEAN, &boolean);
-
-	/* If connected: append the remote address */
-	if (boolean) {
-		char bda[18];
-		const char *pstr = bda;
-
-		ba2str(&prx->dst, bda);
-		dict_append_entry(&dict, "address", DBUS_TYPE_STRING, &pstr);
-	}
-
-	dbus_message_iter_close_container(&iter, &dict);
-
-	return reply;
-}
-
-static struct {
-	const char	*str;
-	speed_t		speed;
-} supported_speed[]  = {
-	{"50",		B50	},
-	{"300",		B300	},
-	{"600",		B600	},
-	{"1200",	B1200	},
-	{"1800",	B1800	},
-	{"2400",	B2400	},
-	{"4800",	B4800	},
-	{"9600",	B9600	},
-	{"19200",	B19200	},
-	{"38400",	B38400	},
-	{"57600",	B57600	},
-	{"115200",	B115200	},
-	{ NULL,		B0	}
-};
-
-static speed_t str2speed(const char *str, speed_t *speed)
-{
-	int i;
-
-	for (i = 0; supported_speed[i].str; i++) {
-		if (strcmp(supported_speed[i].str, str) != 0)
-			continue;
-
-		if (speed)
-			*speed = supported_speed[i].speed;
-
-		return supported_speed[i].speed;
-	}
-
-	return B0;
-}
-
-static int set_parity(const char *str, tcflag_t *ctrl)
-{
-	if (strcasecmp("even", str) == 0) {
-		*ctrl |= PARENB;
-		*ctrl &= ~PARODD;
-	} else if (strcasecmp("odd", str) == 0) {
-		*ctrl |= PARENB;
-		*ctrl |= PARODD;
-	} else if (strcasecmp("mark", str) == 0)
-		*ctrl |= PARENB;
-	else if ((strcasecmp("none", str) == 0) ||
-			(strcasecmp("space", str) == 0))
-		*ctrl &= ~PARENB;
-	else
-		return -1;
-
-	return 0;
-}
-
-static int set_databits(uint8_t databits, tcflag_t *ctrl)
-{
-	if (databits < 5 || databits > 8)
-		return -EINVAL;
-
-	*ctrl &= ~CSIZE;
-	switch (databits) {
-	case 5:
-		*ctrl |= CS5;
-		break;
-	case 6:
-		*ctrl |= CS6;
-		break;
-	case 7:
-		*ctrl |= CS7;
-		break;
-	case 8:
-		*ctrl |= CS8;
-		break;
-	}
-
-	return 0;
-}
-
-static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl)
-{
-	/* 1.5 will not be allowed */
-	switch (stopbits) {
-	case 1:
-		*ctrl &= ~CSTOPB;
-		return 0;
-	case 2:
-		*ctrl |= CSTOPB;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static DBusMessage *proxy_set_serial_params(DBusConnection *conn,
-						DBusMessage *msg, void *data)
-{
-	struct serial_proxy *prx = data;
-	const char *ratestr, *paritystr;
-	uint8_t databits, stopbits;
-	tcflag_t ctrl;		/* Control mode flags */
-	speed_t speed = B0;	/* In/Out speed */
-
-	/* Don't allow change TTY settings if it is open */
-	if (prx->local)
-		return btd_error_not_authorized(msg);
-
-	if (!dbus_message_get_args(msg, NULL,
-				DBUS_TYPE_STRING, &ratestr,
-				DBUS_TYPE_BYTE, &databits,
-				DBUS_TYPE_BYTE, &stopbits,
-				DBUS_TYPE_STRING, &paritystr,
-				DBUS_TYPE_INVALID))
-		return NULL;
-
-	if (str2speed(ratestr, &speed)  == B0)
-		return btd_error_invalid_args(msg);
-
-	ctrl = prx->proxy_ti.c_cflag;
-	if (set_databits(databits, &ctrl) < 0)
-		return btd_error_invalid_args(msg);
-
-	if (set_stopbits(stopbits, &ctrl) < 0)
-		return btd_error_invalid_args(msg);
-
-	if (set_parity(paritystr, &ctrl) < 0)
-		return btd_error_invalid_args(msg);
-
-	prx->proxy_ti.c_cflag = ctrl;
-	prx->proxy_ti.c_cflag |= (CLOCAL | CREAD);
-	cfsetispeed(&prx->proxy_ti, speed);
-	cfsetospeed(&prx->proxy_ti, speed);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static const GDBusMethodTable proxy_methods[] = {
-	{ GDBUS_METHOD("Enable", NULL, NULL, proxy_enable) },
-	{ GDBUS_METHOD("Disable", NULL, NULL, proxy_disable) },
-	{ GDBUS_METHOD("GetInfo",
-			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-			proxy_get_info) },
-	{ GDBUS_METHOD("SetSerialParameters",
-			GDBUS_ARGS({ "rate", "s" }, { "data", "y" },
-					{ "stop", "y" }, { "parity", "s" }),
-			NULL, proxy_set_serial_params) },
-	{ },
-};
-
-static void proxy_path_unregister(gpointer data)
-{
-	struct serial_proxy *prx = data;
-	int sk;
-
-	DBG("Unregistered proxy: %s", prx->address);
-
-	if (prx->type != TTY_PROXY)
-		goto done;
-
-	/* Restore the initial TTY configuration */
-	sk = open(prx->address, O_RDWR | O_NOCTTY);
-	if (sk >= 0) {
-		tcsetattr(sk, TCSAFLUSH, &prx->sys_ti);
-		close(sk);
-	}
-done:
-
-	proxy_free(prx);
-}
-
-static int register_proxy_object(struct serial_proxy *prx)
-{
-	struct serial_adapter *adapter = prx->adapter;
-	char path[MAX_PATH_LENGTH + 1];
-
-	snprintf(path, MAX_PATH_LENGTH, "%s/proxy%d",
-			adapter_get_path(adapter->btd_adapter), sk_counter++);
-
-	if (!g_dbus_register_interface(adapter->conn, path,
-					SERIAL_PROXY_INTERFACE,
-					proxy_methods, NULL, NULL,
-					prx, proxy_path_unregister)) {
-		error("D-Bus failed to register %s path", path);
-		return -1;
-	}
-
-	prx->path = g_strdup(path);
-	adapter->proxies = g_slist_append(adapter->proxies, prx);
-
-	DBG("Registered proxy: %s", path);
-
-	return 0;
-}
-
-static int proxy_tty_register(struct serial_adapter *adapter,
-				const char *uuid128, const char *address,
-				struct termios *ti,
-				struct serial_proxy **proxy)
-{
-	struct termios sys_ti;
-	struct serial_proxy *prx;
-	int sk, ret;
-
-	sk = open(address, O_RDONLY | O_NOCTTY);
-	if (sk < 0) {
-		error("Can't open TTY: %s(%d)", strerror(errno), errno);
-		return -EINVAL;
-	}
-
-	prx = g_new0(struct serial_proxy, 1);
-	prx->address = g_strdup(address);
-	prx->uuid128 = g_strdup(uuid128);
-	prx->type = TTY_PROXY;
-	adapter_get_address(adapter->btd_adapter, &prx->src);
-	prx->adapter = adapter;
-
-	/* Current TTY settings */
-	memset(&sys_ti, 0, sizeof(sys_ti));
-	tcgetattr(sk, &sys_ti);
-	memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti));
-	close(sk);
-
-	if (!ti) {
-		/* Use current settings */
-		memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti));
-	} else {
-		/* New TTY settings: user provided */
-		memcpy(&prx->proxy_ti, ti, sizeof(*ti));
-	}
-
-	ret = register_proxy_object(prx);
-	if (ret < 0) {
-		proxy_free(prx);
-		return ret;
-	}
-
-	*proxy = prx;
-
-	return ret;
-}
-
-static int proxy_socket_register(struct serial_adapter *adapter,
-				const char *uuid128, const char *address,
-				struct serial_proxy **proxy)
-{
-	struct serial_proxy *prx;
-	int ret;
-
-	prx = g_new0(struct serial_proxy, 1);
-	prx->address = g_strdup(address);
-	prx->uuid128 = g_strdup(uuid128);
-	prx->type = UNIX_SOCKET_PROXY;
-	adapter_get_address(adapter->btd_adapter, &prx->src);
-	prx->adapter = adapter;
-
-	ret = register_proxy_object(prx);
-	if (ret < 0) {
-		proxy_free(prx);
-		return ret;
-	}
-
-	*proxy = prx;
-
-	return ret;
-}
-
-static int proxy_tcp_register(struct serial_adapter *adapter,
-				const char *uuid128, const char *address,
-				struct serial_proxy **proxy)
-{
-	struct serial_proxy *prx;
-	int ret;
-
-	prx = g_new0(struct serial_proxy, 1);
-	prx->address = g_strdup(address);
-	prx->uuid128 = g_strdup(uuid128);
-	prx->type = TCP_SOCKET_PROXY;
-	adapter_get_address(adapter->btd_adapter, &prx->src);
-	prx->adapter = adapter;
-
-	ret = register_proxy_object(prx);
-	if (ret < 0) {
-		proxy_free(prx);
-		return ret;
-	}
-
-	*proxy = prx;
-
-	return ret;
-}
-
-static proxy_type_t addr2type(const char *address)
-{
-	struct stat st;
-
-	if (stat(address, &st) < 0) {
-		/*
-		 * Unix socket: if the sun_path starts with null byte
-		 * it refers to abstract namespace. 'x00' will be used
-		 * to represent the null byte.
-		 */
-		if (strncmp("localhost:", address, 10) == 0)
-			return TCP_SOCKET_PROXY;
-		if (strncmp("x00", address, 3) != 0)
-			return UNKNOWN_PROXY_TYPE;
-		else
-			return UNIX_SOCKET_PROXY;
-	} else {
-		/* Filesystem: char device or unix socket */
-		if (S_ISCHR(st.st_mode) && strncmp("/dev/", address, 4) == 0)
-			return TTY_PROXY;
-		else if (S_ISSOCK(st.st_mode))
-			return UNIX_SOCKET_PROXY;
-		else
-			return UNKNOWN_PROXY_TYPE;
-	}
-}
-
-static int proxy_addrcmp(gconstpointer proxy, gconstpointer addr)
-{
-	const struct serial_proxy *prx = proxy;
-	const char *address = addr;
-
-	return strcmp(prx->address, address);
-}
-
-static int proxy_pathcmp(gconstpointer proxy, gconstpointer p)
-{
-	const struct serial_proxy *prx = proxy;
-	const char *path = p;
-
-	return strcmp(prx->path, path);
-}
-
-static int register_proxy(struct serial_adapter *adapter,
-				const char *uuid_str, const char *address,
-				struct serial_proxy **proxy)
-{
-	proxy_type_t type;
-	int err;
-
-	type = addr2type(address);
-	if (type == UNKNOWN_PROXY_TYPE)
-		return -EINVAL;
-
-	/* Only one proxy per address(TTY or unix socket) is allowed */
-	if (g_slist_find_custom(adapter->proxies, address, proxy_addrcmp))
-		return -EALREADY;
-
-	switch (type) {
-	case UNIX_SOCKET_PROXY:
-		err = proxy_socket_register(adapter, uuid_str, address, proxy);
-		break;
-	case TTY_PROXY:
-		err = proxy_tty_register(adapter, uuid_str, address, NULL,
-					proxy);
-		break;
-	case TCP_SOCKET_PROXY:
-		err = proxy_tcp_register(adapter, uuid_str, address, proxy);
-		break;
-	default:
-		err = -EINVAL;
-	}
-
-	if (err < 0)
-		return err;
-
-	g_dbus_emit_signal(adapter->conn,
-				adapter_get_path(adapter->btd_adapter),
-				SERIAL_MANAGER_INTERFACE, "ProxyCreated",
-				DBUS_TYPE_STRING, &(*proxy)->path,
-				DBUS_TYPE_INVALID);
-
-	return 0;
-}
-
-static void unregister_proxy(struct serial_proxy *proxy)
-{
-	struct serial_adapter *adapter = proxy->adapter;
-	char *path = g_strdup(proxy->path);
-
-	if (proxy->watch > 0)
-		g_dbus_remove_watch(adapter->conn, proxy->watch);
-
-	g_dbus_emit_signal(adapter->conn,
-			adapter_get_path(adapter->btd_adapter),
-			SERIAL_MANAGER_INTERFACE, "ProxyRemoved",
-			DBUS_TYPE_STRING, &path,
-			DBUS_TYPE_INVALID);
-
-	adapter->proxies = g_slist_remove(adapter->proxies, proxy);
-
-	g_dbus_unregister_interface(adapter->conn, path,
-					SERIAL_PROXY_INTERFACE);
-
-	g_free(path);
-}
-
-static void watch_proxy(DBusConnection *connection, void *user_data)
-{
-	struct serial_proxy *proxy = user_data;
-
-	proxy->watch = 0;
-	unregister_proxy(proxy);
-}
-
-static DBusMessage *create_proxy(DBusConnection *conn,
-				DBusMessage *msg, void *data)
-{
-	struct serial_adapter *adapter = data;
-	struct serial_proxy *proxy;
-	const char *pattern, *address;
-	char *uuid_str;
-	int err;
-
-	if (!dbus_message_get_args(msg, NULL,
-				DBUS_TYPE_STRING, &pattern,
-				DBUS_TYPE_STRING, &address,
-				DBUS_TYPE_INVALID))
-		return NULL;
-
-	uuid_str = bt_name2string(pattern);
-	if (!uuid_str)
-		return btd_error_invalid_args(msg);
-
-	err = register_proxy(adapter, uuid_str, address, &proxy);
-	g_free(uuid_str);
-
-	if (err == -EINVAL)
-		return btd_error_invalid_args(msg);
-	else if (err == -EALREADY)
-		return btd_error_already_exists(msg);
-	else if (err < 0)
-		return btd_error_failed(msg, strerror(-err));
-
-	proxy->owner = g_strdup(dbus_message_get_sender(msg));
-	proxy->watch = g_dbus_add_disconnect_watch(conn, proxy->owner,
-						watch_proxy,
-						proxy, NULL);
-
-	return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &proxy->path,
-					DBUS_TYPE_INVALID);
-}
-
-static DBusMessage *list_proxies(DBusConnection *conn,
-				DBusMessage *msg, void *data)
-{
-	struct serial_adapter *adapter = data;
-	const GSList *l;
-	DBusMessage *reply;
-	DBusMessageIter iter, iter_array;
-
-	reply = dbus_message_new_method_return(msg);
-	if (!reply)
-		return NULL;
-
-	dbus_message_iter_init_append(reply, &iter);
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_TYPE_STRING_AS_STRING, &iter_array);
-
-	for (l = adapter->proxies; l; l = l->next) {
-		struct serial_proxy *prx = l->data;
-
-		dbus_message_iter_append_basic(&iter_array,
-				DBUS_TYPE_STRING, &prx->path);
-	}
-
-	dbus_message_iter_close_container(&iter, &iter_array);
-
-	return reply;
-}
-
-static DBusMessage *remove_proxy(DBusConnection *conn,
-				DBusMessage *msg, void *data)
-{
-	struct serial_adapter *adapter = data;
-	struct serial_proxy *prx;
-	const char *path, *sender;
-	GSList *l;
-
-	if (!dbus_message_get_args(msg, NULL,
-				DBUS_TYPE_STRING, &path,
-				DBUS_TYPE_INVALID))
-		return NULL;
-
-	l = g_slist_find_custom(adapter->proxies, path, proxy_pathcmp);
-	if (!l)
-		return btd_error_does_not_exist(msg);
-
-	prx = l->data;
-
-	sender = dbus_message_get_sender(msg);
-	if (g_strcmp0(prx->owner, sender) != 0)
-		return btd_error_not_authorized(msg);
-
-	unregister_proxy(prx);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static void manager_path_unregister(void *data)
-{
-	struct serial_adapter *adapter = data;
-	GSList *l;
-
-	/* Remove proxy objects */
-	for (l = adapter->proxies; l; l = l->next) {
-		struct serial_proxy *prx = l->data;
-		char *path = g_strdup(prx->path);
-
-		g_dbus_unregister_interface(adapter->conn, path,
-					SERIAL_PROXY_INTERFACE);
-		g_free(path);
-	}
-
-	if (adapter->conn)
-		dbus_connection_unref(adapter->conn);
-
-	adapters = g_slist_remove(adapters, adapter);
-	g_slist_free(adapter->proxies);
-	btd_adapter_unref(adapter->btd_adapter);
-	g_free(adapter);
-}
-
-static const GDBusMethodTable manager_methods[] = {
-	{ GDBUS_METHOD("CreateProxy",
-			GDBUS_ARGS({ "pattern", "s" },
-					{ "address", "s" }),
-			GDBUS_ARGS({ "path", "s" }),
-			create_proxy) },
-	{ GDBUS_METHOD("ListProxies",
-			NULL, GDBUS_ARGS({ "paths", "as" }),
-			list_proxies) },
-	{ GDBUS_METHOD("RemoveProxy",
-			GDBUS_ARGS({ "path", "s" }), NULL,
-			remove_proxy) },
-	{ },
-};
-
-static const GDBusSignalTable manager_signals[] = {
-	{ GDBUS_SIGNAL("ProxyCreated", GDBUS_ARGS({ "path", "s" })) },
-	{ GDBUS_SIGNAL("ProxyRemoved", GDBUS_ARGS({ "path", "s" })) },
-	{ }
-};
-
-static struct serial_adapter *find_adapter(GSList *list,
-					struct btd_adapter *btd_adapter)
-{
-	for (; list; list = list->next) {
-		struct serial_adapter *adapter = list->data;
-
-		if (adapter->btd_adapter == btd_adapter)
-			return adapter;
-	}
-
-	return NULL;
-}
-
-static void serial_proxy_init(struct serial_adapter *adapter)
-{
-	GKeyFile *config;
-	GError *gerr = NULL;
-	const char *file = CONFIGDIR "/serial.conf";
-	char **group_list;
-	int i;
-
-	config = g_key_file_new();
-
-	if (!g_key_file_load_from_file(config, file, 0, &gerr)) {
-		error("Parsing %s failed: %s", file, gerr->message);
-		g_error_free(gerr);
-		g_key_file_free(config);
-		return;
-	}
-
-	group_list = g_key_file_get_groups(config, NULL);
-
-	for (i = 0; group_list[i] != NULL; i++) {
-		char *group_str = group_list[i], *uuid_str, *address;
-		int err;
-		struct serial_proxy *prx;
-
-		/* string length of "Proxy" is 5 */
-		if (strlen(group_str) < 5 || strncmp(group_str, "Proxy", 5))
-			continue;
-
-		uuid_str = g_key_file_get_string(config, group_str, "UUID",
-									&gerr);
-		if (gerr) {
-			DBG("%s: %s", file, gerr->message);
-			g_error_free(gerr);
-			g_key_file_free(config);
-			g_strfreev(group_list);
-			return;
-		}
-
-		address = g_key_file_get_string(config, group_str, "Address",
-									&gerr);
-		if (gerr) {
-			DBG("%s: %s", file, gerr->message);
-			g_error_free(gerr);
-			g_key_file_free(config);
-			g_free(uuid_str);
-			g_strfreev(group_list);
-			return;
-		}
-
-		err = register_proxy(adapter, uuid_str, address, &prx);
-		if (err == -EINVAL)
-			error("Invalid address.");
-		else if (err == -EALREADY)
-			DBG("Proxy already exists.");
-		else if (err < 0)
-			error("Proxy creation failed (%s)", strerror(-err));
-		else {
-			err = enable_proxy(prx);
-			if (err < 0)
-				error("Proxy enable failed (%s)",
-						strerror(-err));
-		}
-
-		g_free(uuid_str);
-		g_free(address);
-	}
-
-	g_strfreev(group_list);
-	g_key_file_free(config);
-}
-
-int proxy_register(DBusConnection *conn, struct btd_adapter *btd_adapter)
-{
-	struct serial_adapter *adapter;
-	const char *path;
-
-	adapter = find_adapter(adapters, btd_adapter);
-	if (adapter)
-		return -EINVAL;
-
-	adapter = g_new0(struct serial_adapter, 1);
-	adapter->conn = dbus_connection_ref(conn);
-	adapter->btd_adapter = btd_adapter_ref(btd_adapter);
-
-	path = adapter_get_path(btd_adapter);
-
-	if (!g_dbus_register_interface(conn, path,
-					SERIAL_MANAGER_INTERFACE,
-					manager_methods, manager_signals, NULL,
-					adapter, manager_path_unregister)) {
-		error("Failed to register %s interface to %s",
-				SERIAL_MANAGER_INTERFACE, path);
-		return -1;
-	}
-
-	adapters = g_slist_append(adapters, adapter);
-
-	DBG("Registered interface %s on path %s",
-		SERIAL_MANAGER_INTERFACE, path);
-
-	serial_proxy_init(adapter);
-
-	return 0;
-}
-
-void proxy_unregister(struct btd_adapter *btd_adapter)
-{
-	struct serial_adapter *adapter;
-
-	adapter = find_adapter(adapters, btd_adapter);
-	if (!adapter)
-		return;
-
-	g_dbus_unregister_interface(adapter->conn,
-			adapter_get_path(btd_adapter),
-			SERIAL_MANAGER_INTERFACE);
-}
diff --git a/serial/proxy.h b/serial/proxy.h
deleted file mode 100644
index 7871665..0000000
--- a/serial/proxy.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-int proxy_register(DBusConnection *conn, struct btd_adapter *btd_adapter);
-void proxy_unregister(struct btd_adapter *btd_adapter);
diff --git a/serial/serial.conf b/serial/serial.conf
deleted file mode 100644
index 43ee6af..0000000
--- a/serial/serial.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-# Configuration file for serial
-
-# There could be multiple proxy sections, the format is [Proxy <user chosen name>]
-#[Proxy DUN]
-
-# UUID for DUN proxy service
-#UUID=00001103-0000-1000-8000-00805F9B34FB
-
-# Address for device node
-#Address=/dev/ttyx
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 03/14] btmgmt: move to tools folder
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 02/14] serial: remove the whole serial code Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  2012-07-10  2:36   ` Vinicius Costa Gomes
  2012-07-09 21:10 ` [PATCH 04/14] alert: move alert to profiles dir Gustavo Padovan
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 .gitignore     |    2 +-
 Makefile.tools |    6 +-
 mgmt/main.c    | 1933 --------------------------------------------------------
 3 files changed, 4 insertions(+), 1937 deletions(-)
 delete mode 100644 mgmt/main.c

diff --git a/.gitignore b/.gitignore
index c7d079e..bc65dcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -86,7 +86,7 @@ compat/dund
 compat/hidd
 compat/pand
 unit/test-eir
-mgmt/btmgmt
+tools/mgmt/btmgmt
 monitor/btmon
 emulator/btvirt
 
diff --git a/Makefile.tools b/Makefile.tools
index 3cb105c..56839b7 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -50,10 +50,10 @@ tools_ppporc_LDADD = lib/libbluetooth-private.la
 
 tools_hcieventmask_LDADD = lib/libbluetooth-private.la
 
-noinst_PROGRAMS += mgmt/btmgmt monitor/btmon emulator/btvirt
+noinst_PROGRAMS += tools/btmgmt monitor/btmon emulator/btvirt
 
-mgmt_btmgmt_SOURCES = mgmt/main.c src/glib-helper.c
-mgmt_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
+tools_btmgmt_SOURCES = tools/btmgmt.c src/glib-helper.c
+tools_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
 
 monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
 					monitor/mainloop.h monitor/mainloop.c \
diff --git a/mgmt/main.c b/mgmt/main.c
deleted file mode 100644
index b2d6c3c..0000000
--- a/mgmt/main.c
+++ /dev/null
@@ -1,1933 +0,0 @@
-/*
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011  Intel Corporation. All rights reserved.
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <poll.h>
-#include <getopt.h>
-#include <stdbool.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/mgmt.h>
-
-#include <glib.h>
-#include "glib-helper.h"
-
-static bool monitor = false;
-static bool discovery = false;
-static bool resolve_names = true;
-
-typedef void (*cmd_cb)(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data);
-
-static struct pending_cmd {
-	uint16_t op;
-	uint16_t id;
-	cmd_cb cb;
-	void *user_data;
-	struct pending_cmd *next;
-} *pending = NULL;
-
-static int mgmt_send_cmd(int mgmt_sk, uint16_t op, uint16_t id, void *data,
-				size_t len, cmd_cb func, void *user_data)
-{
-	char buf[1024];
-	struct pending_cmd *cmd;
-	struct mgmt_hdr *hdr = (void *) buf;
-
-	if (len + MGMT_HDR_SIZE > sizeof(buf))
-		return -EINVAL;
-
-	cmd = calloc(1, sizeof(struct pending_cmd));
-	if (cmd == NULL)
-		return -errno;
-
-	cmd->op = op;
-	cmd->id = id;
-	cmd->cb = func;
-	cmd->user_data = user_data;
-
-	memset(buf, 0, sizeof(buf));
-	hdr->opcode = htobs(op);
-	hdr->index = htobs(id);
-	hdr->len = htobs(len);
-	memcpy(buf + MGMT_HDR_SIZE, data, len);
-
-	if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
-		fprintf(stderr, "Unable to write to socket: %s\n",
-							strerror(errno));
-		free(cmd);
-		return -1;
-	}
-
-	cmd->next = pending;
-	pending = cmd;
-
-	return 0;
-}
-
-static int mgmt_open(void)
-{
-	struct sockaddr_hci addr;
-	int sk;
-
-	sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
-	if (sk < 0) {
-		fprintf(stderr, "socket: %s\n", strerror(errno));
-		return sk;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.hci_family = AF_BLUETOOTH;
-	addr.hci_dev = HCI_DEV_NONE;
-	addr.hci_channel = HCI_CHANNEL_CONTROL;
-
-	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		fprintf(stderr, "bind: %s\n", strerror(errno));
-		close(sk);
-		return -1;
-	}
-
-	return sk;
-}
-
-static void mgmt_check_pending(int mgmt_sk, uint16_t op, uint16_t index,
-				uint16_t status, void *data, uint16_t len)
-{
-	struct pending_cmd *c, *prev;
-
-	for (c = pending, prev = NULL; c != NULL; prev = c, c = c->next) {
-		if (c->op != op)
-			continue;
-		if (c->id != index)
-			continue;
-
-		if (c == pending)
-			pending = c->next;
-		else
-			prev->next = c->next;
-
-		c->cb(mgmt_sk, op, index, status, data, len, c->user_data);
-
-		free(c);
-		break;
-	}
-}
-
-static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_cmd_complete *ev, uint16_t len)
-{
-	uint16_t op;
-
-	if (len < sizeof(*ev)) {
-		fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
-									len);
-		return -EINVAL;
-	}
-
-	op = bt_get_le16(&ev->opcode);
-
-	len -= sizeof(*ev);
-
-	if (monitor)
-		printf("%s complete, opcode 0x%04x len %u\n", mgmt_opstr(op),
-								op, len);
-
-	mgmt_check_pending(mgmt_sk, op, index, ev->status, ev->data, len);
-
-	return 0;
-}
-
-static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_cmd_status *ev, uint16_t len)
-{
-	uint16_t opcode;
-
-	if (len < sizeof(*ev)) {
-		fprintf(stderr, "Too short (%u bytes) cmd status event\n",
-									len);
-		return -EINVAL;
-	}
-
-	opcode = bt_get_le16(&ev->opcode);
-
-	if (monitor)
-		printf("cmd status, opcode 0x%04x status 0x%02x (%s)\n",
-				opcode, ev->status, mgmt_errstr(ev->status));
-
-	if (ev->status != 0)
-		mgmt_check_pending(mgmt_sk, opcode, index, ev->status,
-								NULL, 0);
-
-	return 0;
-}
-
-static int mgmt_controller_error(uint16_t index,
-					struct mgmt_ev_controller_error *ev,
-					uint16_t len)
-{
-	if (len < sizeof(*ev)) {
-		fprintf(stderr,
-			"Too short (%u bytes) controller error event\n", len);
-		return -EINVAL;
-	}
-
-	if (monitor)
-		printf("hci%u error 0x%02x\n", index, ev->error_code);
-
-	return 0;
-}
-
-static int mgmt_index_added(int mgmt_sk, uint16_t index)
-{
-	if (monitor)
-		printf("hci%u added\n", index);
-	return 0;
-}
-
-static int mgmt_index_removed(int mgmt_sk, uint16_t index)
-{
-	if (monitor)
-		printf("hci%u removed\n", index);
-	return 0;
-}
-
-static const char *settings_str[] = {
-				"powered",
-				"connectable",
-				"fast-connectable",
-				"discoverable",
-				"pairable",
-				"link-security",
-				"ssp",
-				"br/edr",
-				"hs",
-				"le" ,
-};
-
-static void print_settings(uint32_t settings)
-{
-	unsigned i;
-
-	for (i = 0; i < NELEM(settings_str); i++) {
-		if ((settings & (1 << i)) != 0)
-			printf("%s ", settings_str[i]);
-	}
-}
-
-static int mgmt_new_settings(int mgmt_sk, uint16_t index,
-					uint32_t *ev, uint16_t len)
-{
-	if (len < sizeof(*ev)) {
-		fprintf(stderr, "Too short new_settings event (%u)\n", len);
-		return -EINVAL;
-	}
-
-	if (monitor) {
-		printf("hci%u new_settings: ", index);
-		print_settings(bt_get_le32(ev));
-		printf("\n");
-	}
-
-	return 0;
-}
-
-static int mgmt_discovering(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_discovering *ev, uint16_t len)
-{
-	if (len < sizeof(*ev)) {
-		fprintf(stderr, "Too short (%u bytes) discovering event\n",
-									len);
-		return -EINVAL;
-	}
-
-	if (ev->discovering == 0 && discovery)
-		exit(EXIT_SUCCESS);
-
-	if (monitor)
-		printf("hci%u type %u discovering %s\n", index,
-				ev->type, ev->discovering ? "on" : "off");
-
-	return 0;
-}
-
-static int mgmt_new_link_key(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_new_link_key *ev, uint16_t len)
-{
-
-	if (len != sizeof(*ev)) {
-		fprintf(stderr, "Invalid new_link_key length (%u bytes)\n",
-									len);
-		return -EINVAL;
-	}
-
-	if (monitor) {
-		char addr[18];
-		ba2str(&ev->key.addr.bdaddr, addr);
-		printf("hci%u new_link_key %s type 0x%02x pin_len %d "
-				"store_hint %u\n", index, addr, ev->key.type,
-				ev->key.pin_len, ev->store_hint);
-	}
-
-	return 0;
-}
-
-static const char *typestr(uint8_t type)
-{
-	const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
-
-	if (type <= BDADDR_LE_RANDOM)
-		return str[type];
-
-	return "(unknown)";
-}
-
-static int mgmt_connected(int mgmt_sk, uint16_t index,
-					struct mgmt_ev_device_connected *ev,
-					uint16_t len)
-{
-	uint16_t eir_len;
-
-	if (len < sizeof(*ev)) {
-		fprintf(stderr,
-			"Invalid connected event length (%u bytes)\n", len);
-		return -EINVAL;
-	}
-
-	eir_len = bt_get_le16(&ev->eir_len);
-	if (len != sizeof(*ev) + eir_len) {
-		fprintf(stderr, "Invalid connected event length "
-			"(%u bytes, eir_len %u bytes)\n", len, eir_len);
-		return -EINVAL;
-	}
-
-	if (monitor) {
-		char addr[18];
-		ba2str(&ev->addr.bdaddr, addr);
-		printf("hci%u %s type %s connected eir_len %u\n", index, addr,
-					typestr(ev->addr.type), eir_len);
-	}
-
-	return 0;
-}
-
-static int mgmt_disconnected(int mgmt_sk, uint16_t index,
-				struct mgmt_addr_info *ev, uint16_t len)
-{
-	if (len != sizeof(*ev)) {
-		fprintf(stderr,
-			"Invalid disconnected event length (%u bytes)\n", len);
-		return -EINVAL;
-	}
-
-	if (monitor) {
-		char addr[18];
-		ba2str(&ev->bdaddr, addr);
-		printf("hci%u %s type %s disconnected\n", index, addr,
-							typestr(ev->type));
-	}
-
-	return 0;
-}
-
-static int mgmt_conn_failed(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_connect_failed *ev,
-				uint16_t len)
-{
-	if (len != sizeof(*ev)) {
-		fprintf(stderr,
-			"Invalid connect_failed event length (%u bytes)\n", len);
-		return -EINVAL;
-	}
-
-	if (monitor) {
-		char addr[18];
-		ba2str(&ev->addr.bdaddr, addr);
-		printf("hci%u %s type %s connect failed (status 0x%02x, %s)\n",
-				index, addr, typestr(ev->addr.type), ev->status,
-				mgmt_errstr(ev->status));
-	}
-
-	return 0;
-}
-
-static int mgmt_auth_failed(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_auth_failed *ev,
-				uint16_t len)
-{
-	if (len != sizeof(*ev)) {
-		fprintf(stderr,
-			"Invalid auth_failed event length (%u bytes)\n", len);
-		return -EINVAL;
-	}
-
-	if (monitor) {
-		char addr[18];
-		ba2str(&ev->addr.bdaddr, addr);
-		printf("hci%u %s auth failed with status 0x%02x (%s)\n",
-			index, addr, ev->status, mgmt_errstr(ev->status));
-	}
-
-	return 0;
-}
-
-static int mgmt_name_changed(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_local_name_changed *ev,
-				uint16_t len)
-{
-	if (len != sizeof(*ev)) {
-		fprintf(stderr,
-			"Invalid local_name_changed length (%u bytes)\n", len);
-		return -EINVAL;
-	}
-
-	if (monitor)
-		printf("hci%u name changed: %s\n", index, ev->name);
-
-	return 0;
-}
-
-static void confirm_name_rsp(int mgmt_sk, uint16_t op, uint16_t id,
-				uint8_t status, void *rsp, uint16_t len,
-				void *user_data)
-{
-	struct mgmt_rp_confirm_name *rp = rsp;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		fprintf(stderr,
-			"hci%u confirm_name failed with status 0x%02x (%s)\n",
-					id, status, mgmt_errstr(status));
-		return;
-	}
-
-	if (len != sizeof(*rp)) {
-		fprintf(stderr,
-			"hci%u confirm_name rsp length %u instead of %zu\n",
-			id, len, sizeof(*rp));
-		return;
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status != 0)
-		fprintf(stderr,
-			"hci%u confirm_name for %s failed: 0x%02x (%s)\n",
-			id, addr, status, mgmt_errstr(status));
-	else
-		printf("hci%u confirm_name succeeded for %s\n", id, addr);
-}
-
-static int mgmt_device_found(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_device_found *ev, uint16_t len)
-{
-	uint32_t flags;
-	uint16_t eir_len;
-
-	if (len < sizeof(*ev)) {
-		fprintf(stderr,
-			"Too short device_found length (%u bytes)\n", len);
-		return -EINVAL;
-	}
-
-	flags = btohs(ev->flags);
-
-	eir_len = bt_get_le16(&ev->eir_len);
-	if (len != sizeof(*ev) + eir_len) {
-		fprintf(stderr, "dev_found: expected %zu bytes, got %u bytes",
-						sizeof(*ev) + eir_len, len);
-		return -EINVAL;
-	}
-
-	if (monitor || discovery) {
-		char addr[18];
-		ba2str(&ev->addr.bdaddr, addr);
-		printf("hci%u dev_found: %s type %s rssi %d "
-			"flags 0x%04x eir_len %u\n", index, addr,
-			typestr(ev->addr.type), ev->rssi, flags, eir_len);
-	}
-
-	if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
-		struct mgmt_cp_confirm_name cp;
-
-		memset(&cp, 0, sizeof(cp));
-		memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
-		if (resolve_names)
-			cp.name_known = 0;
-		else
-			cp.name_known = 1;
-
-		mgmt_send_cmd(mgmt_sk, MGMT_OP_CONFIRM_NAME, index,
-					&cp, sizeof(cp), confirm_name_rsp,
-					NULL);
-	}
-
-	return 0;
-}
-
-static void pin_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr,
-			"hci%u PIN Code reply failed with status 0x%02x (%s)",
-					id, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("hci%u PIN Reply successful\n", id);
-}
-
-static int mgmt_pin_reply(int mgmt_sk, uint16_t index,
-						struct mgmt_addr_info *addr,
-						const char *pin, size_t len)
-{
-	struct mgmt_cp_pin_code_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(cp.addr));
-	cp.pin_len = len;
-	memcpy(cp.pin_code, pin, len);
-
-	return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_REPLY, index,
-					&cp, sizeof(cp), pin_rsp, NULL);
-}
-
-static void pin_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr,
-			"hci%u PIN Neg reply failed with status 0x%02x (%s)",
-					id, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("hci%u PIN Negative Reply successful\n", id);
-}
-
-static int mgmt_pin_neg_reply(int mgmt_sk, uint16_t index,
-						struct mgmt_addr_info *addr)
-{
-	struct mgmt_cp_pin_code_neg_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.addr, addr, sizeof(cp.addr));
-
-	return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
-					&cp, sizeof(cp), pin_neg_rsp, NULL);
-}
-
-static int mgmt_request_pin(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_pin_code_request *ev,
-				uint16_t len)
-{
-	char pin[18];
-	size_t pin_len;
-
-	if (len != sizeof(*ev)) {
-		fprintf(stderr,
-			"Invalid pin_code request length (%u bytes)\n", len);
-		return -EINVAL;
-	}
-
-	if (monitor) {
-		char addr[18];
-		ba2str(&ev->addr.bdaddr, addr);
-		printf("hci%u %s request PIN\n", index, addr);
-	}
-
-	printf("PIN Request (press enter to reject) >> ");
-	fflush(stdout);
-
-	memset(pin, 0, sizeof(pin));
-
-	if (fgets(pin, sizeof(pin), stdin) == NULL || pin[0] == '\n')
-		return mgmt_pin_neg_reply(mgmt_sk, index, &ev->addr);
-
-	pin_len = strlen(pin);
-	if (pin[pin_len - 1] == '\n') {
-		pin[pin_len - 1] = '\0';
-		pin_len--;
-	}
-
-	return mgmt_pin_reply(mgmt_sk, index, &ev->addr, pin, pin_len);
-}
-
-static void confirm_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr,
-			"hci%u User Confirm reply failed. status 0x%02x (%s)",
-					id, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("hci%u User Confirm Reply successful\n", id);
-}
-
-static int mgmt_confirm_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
-{
-	struct mgmt_cp_user_confirm_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	bacpy(&cp.addr.bdaddr, bdaddr);
-
-	return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_REPLY, index,
-					&cp, sizeof(cp), confirm_rsp, NULL);
-}
-
-static void confirm_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id,
-				uint8_t status, void *rsp, uint16_t len,
-				void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr,
-			"hci%u Confirm Neg reply failed. status 0x%02x (%s)",
-					id, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("hci%u User Confirm Negative Reply successful\n", id);
-}
-
-static int mgmt_confirm_neg_reply(int mgmt_sk, uint16_t index,
-							bdaddr_t *bdaddr)
-{
-	struct mgmt_cp_user_confirm_reply cp;
-
-	memset(&cp, 0, sizeof(cp));
-	bacpy(&cp.addr.bdaddr, bdaddr);
-
-	return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
-				&cp, sizeof(cp), confirm_neg_rsp, NULL);
-}
-
-
-static int mgmt_user_confirm(int mgmt_sk, uint16_t index,
-				struct mgmt_ev_user_confirm_request *ev,
-				uint16_t len)
-{
-	char rsp[5];
-	size_t rsp_len;
-	uint32_t val;
-	char addr[18];
-
-	if (len != sizeof(*ev)) {
-		fprintf(stderr,
-			"Invalid user_confirm request length (%u)\n", len);
-		return -EINVAL;
-	}
-
-	ba2str(&ev->addr.bdaddr, addr);
-	val = bt_get_le32(&ev->value);
-
-	if (monitor)
-		printf("hci%u %s User Confirm %06u hint %u\n", index, addr,
-							val, ev->confirm_hint);
-
-	if (ev->confirm_hint)
-		printf("Accept pairing with %s (yes/no) >> ", addr);
-	else
-		printf("Confirm value %06u for %s (yes/no) >> ", val, addr);
-
-	fflush(stdout);
-
-	memset(rsp, 0, sizeof(rsp));
-
-	if (fgets(rsp, sizeof(rsp), stdin) == NULL || rsp[0] == '\n')
-		return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
-
-	rsp_len = strlen(rsp);
-	if (rsp[rsp_len - 1] == '\n') {
-		rsp[rsp_len - 1] = '\0';
-		rsp_len--;
-	}
-
-	if (rsp[0] == 'y' || rsp[0] == 'Y')
-		return mgmt_confirm_reply(mgmt_sk, index, &ev->addr.bdaddr);
-	else
-		return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
-}
-
-static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index,
-						void *data, uint16_t len)
-{
-	if (monitor)
-		printf("event: %s\n", mgmt_evstr(ev));
-
-	switch (ev) {
-	case MGMT_EV_CMD_COMPLETE:
-		return mgmt_cmd_complete(mgmt_sk, index, data, len);
-	case MGMT_EV_CMD_STATUS:
-		return mgmt_cmd_status(mgmt_sk, index, data, len);
-	case MGMT_EV_CONTROLLER_ERROR:
-		return mgmt_controller_error(index, data, len);
-	case MGMT_EV_INDEX_ADDED:
-		return mgmt_index_added(mgmt_sk, index);
-	case MGMT_EV_INDEX_REMOVED:
-		return mgmt_index_removed(mgmt_sk, index);
-	case MGMT_EV_NEW_SETTINGS:
-		return mgmt_new_settings(mgmt_sk, index, data, len);
-	case MGMT_EV_DISCOVERING:
-		return mgmt_discovering(mgmt_sk, index, data, len);
-	case MGMT_EV_NEW_LINK_KEY:
-		return mgmt_new_link_key(mgmt_sk, index, data, len);
-	case MGMT_EV_DEVICE_CONNECTED:
-		return mgmt_connected(mgmt_sk, index, data, len);
-	case MGMT_EV_DEVICE_DISCONNECTED:
-		return mgmt_disconnected(mgmt_sk, index, data, len);
-	case MGMT_EV_CONNECT_FAILED:
-		return mgmt_conn_failed(mgmt_sk, index, data, len);
-	case MGMT_EV_AUTH_FAILED:
-		return mgmt_auth_failed(mgmt_sk, index, data, len);
-	case MGMT_EV_LOCAL_NAME_CHANGED:
-		return mgmt_name_changed(mgmt_sk, index, data, len);
-	case MGMT_EV_DEVICE_FOUND:
-		return mgmt_device_found(mgmt_sk, index, data, len);
-	case MGMT_EV_PIN_CODE_REQUEST:
-		return mgmt_request_pin(mgmt_sk, index, data, len);
-	case MGMT_EV_USER_CONFIRM_REQUEST:
-		return mgmt_user_confirm(mgmt_sk, index, data, len);
-	default:
-		if (monitor)
-			printf("Unhandled event 0x%04x (%s)\n", ev, mgmt_evstr(ev));
-		return 0;
-	}
-}
-
-static int mgmt_process_data(int mgmt_sk)
-{
-	char buf[1024];
-	struct mgmt_hdr *hdr = (void *) buf;
-	uint16_t len, ev, index;
-	ssize_t ret;
-
-	ret = read(mgmt_sk, buf, sizeof(buf));
-	if (ret < 0) {
-		fprintf(stderr, "read: %s\n", strerror(errno));
-		return ret;
-	}
-
-	if (ret < MGMT_HDR_SIZE) {
-		fprintf(stderr, "Too small mgmt packet (%zd bytes)\n", ret);
-		return 0;
-	}
-
-	ev = bt_get_le16(&hdr->opcode);
-	index = bt_get_le16(&hdr->index);
-	len = bt_get_le16(&hdr->len);
-
-	if (monitor)
-		printf("event 0x%04x len 0x%04x index 0x%04x\n", ev, len, index);
-
-	if (ret != MGMT_HDR_SIZE + len) {
-		fprintf(stderr, "Packet length mismatch. ret %zd len %u",
-								ret, len);
-		return 0;
-	}
-
-	mgmt_handle_event(mgmt_sk, ev, index, buf + MGMT_HDR_SIZE, len);
-
-	return 0;
-}
-
-static void cmd_monitor(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	printf("Monitoring mgmt events...\n");
-	monitor = true;
-}
-
-static void version_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_rp_read_version *rp = rsp;
-
-	if (status != 0) {
-		fprintf(stderr, "Reading mgmt version failed with status"
-			" 0x%02x (%s)\n", status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		fprintf(stderr, "Too small version reply (%u bytes)\n", len);
-		exit(EXIT_FAILURE);
-	}
-
-	printf("MGMT Version %u, revision %u\n", rp->version,
-						bt_get_le16(&rp->revision));
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_version(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
-					NULL, 0, version_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send read_version cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void commands_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_rp_read_commands *rp = rsp;
-	uint16_t num_commands, num_events, *opcode;
-	size_t expected_len;
-	int i;
-
-	if (status != 0) {
-		fprintf(stderr, "Reading supported commands failed with status"
-			" 0x%02x (%s)\n", status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		fprintf(stderr, "Too small commands reply (%u bytes)\n", len);
-		exit(EXIT_FAILURE);
-	}
-
-	num_commands = bt_get_le16(&rp->num_commands);
-	num_events = bt_get_le16(&rp->num_events);
-
-	expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
-						num_events * sizeof(uint16_t);
-
-	if (len < expected_len) {
-		fprintf(stderr, "Too small commands reply (%u != %zu)\n",
-							len, expected_len);
-		exit(EXIT_FAILURE);
-	}
-
-	opcode = rp->opcodes;
-
-	printf("%u commands:\n", num_commands);
-	for (i = 0; i < num_commands; i++) {
-		uint16_t op = bt_get_le16(opcode++);
-		printf("\t%s (0x%04x)\n", mgmt_opstr(op), op);
-	}
-
-	printf("%u events:\n", num_events);
-	for (i = 0; i < num_events; i++) {
-		uint16_t ev = bt_get_le16(opcode++);
-		printf("\t%s (0x%04x)\n", mgmt_evstr(ev), ev);
-	}
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_commands(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
-					NULL, 0, commands_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send read_commands cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_rp_read_info *rp = rsp;
-	char addr[18];
-
-	if (status != 0) {
-		fprintf(stderr,
-			"Reading hci%u info failed with status 0x%02x (%s)\n",
-					id, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		fprintf(stderr, "Too small info reply (%u bytes)\n", len);
-		exit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->bdaddr, addr);
-	printf("hci%u:\taddr %s version %u manufacturer %u"
-			" class 0x%02x%02x%02x\n",
-			id, addr, rp->version, bt_get_le16(&rp->manufacturer),
-			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
-
-	printf("\tsupported settings: ");
-	print_settings(bt_get_le32(&rp->supported_settings));
-
-	printf("\n\tcurrent settings: ");
-	print_settings(bt_get_le32(&rp->current_settings));
-
-	printf("\n\tname %s\n", rp->name);
-	printf("\tshort name %s\n", rp->short_name);
-
-	if (pending == NULL)
-		exit(EXIT_SUCCESS);
-}
-
-static void index_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_rp_read_index_list *rp = rsp;
-	uint16_t count;
-	unsigned int i;
-
-	if (status != 0) {
-		fprintf(stderr,
-			"Reading index list failed with status 0x%02x (%s)\n",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		fprintf(stderr, "Too small index list reply (%u bytes)\n",
-									len);
-		exit(EXIT_FAILURE);
-	}
-
-	count = bt_get_le16(&rp->num_controllers);
-
-	if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
-		fprintf(stderr,
-			"Index count (%u) doesn't match reply length (%u)\n",
-								count, len);
-		exit(EXIT_FAILURE);
-	}
-
-	if (monitor)
-		printf("Index list with %u item%s\n",
-						count, count > 1 ? "s" : "");
-
-	if (count == 0)
-		exit(EXIT_SUCCESS);
-
-	if (monitor && count > 0)
-		printf("\t");
-
-	for (i = 0; i < count; i++) {
-		uint16_t index;
-
-		index = bt_get_le16(&rp->index[i]);
-
-		if (monitor)
-			printf("hci%u ", index);
-
-		if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
-					0, info_rsp, NULL) < 0) {
-			fprintf(stderr, "Unable to send read_info cmd\n");
-			exit(EXIT_FAILURE);
-		}
-	}
-
-	if (monitor && count > 0)
-		printf("\n");
-}
-
-static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	if (index == MGMT_INDEX_NONE) {
-		if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INDEX_LIST,
-					MGMT_INDEX_NONE, NULL, 0,
-					index_rsp, NULL) < 0) {
-			fprintf(stderr, "Unable to send index_list cmd\n");
-			exit(EXIT_FAILURE);
-		}
-
-		return;
-	}
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
-						0, info_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send read_info cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	uint32_t *rp = rsp;
-
-	if (status != 0) {
-		fprintf(stderr,
-			"%s for hci%u failed with status 0x%02x (%s)\n",
-			mgmt_opstr(op), id, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len < sizeof(*rp)) {
-		fprintf(stderr, "Too small %s response (%u bytes)\n",
-							mgmt_opstr(op), len);
-		exit(EXIT_FAILURE);
-	}
-
-	printf("hci%u %s complete, settings: ", id, mgmt_opstr(op));
-	print_settings(bt_get_le32(rp));
-	printf("\n");
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_setting(int mgmt_sk, uint16_t index, uint16_t op,
-							int argc, char **argv)
-{
-	uint8_t val;
-
-	if (argc < 2) {
-		printf("Specify \"on\" or \"off\"\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
-		val = 1;
-	else if (strcasecmp(argv[1], "off") == 0)
-		val = 0;
-	else
-		val = atoi(argv[1]);
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send_cmd(mgmt_sk, op, index, &val, sizeof(val),
-						setting_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send %s cmd\n", mgmt_opstr(op));
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_power(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	cmd_setting(mgmt_sk, index, MGMT_OP_SET_POWERED, argc, argv);
-}
-
-static void cmd_discov(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_set_discoverable cp;
-
-	if (argc < 2) {
-		printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
-		exit(EXIT_FAILURE);
-	}
-
-	memset(&cp, 0, sizeof(cp));
-
-	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
-		cp.val = 1;
-	else if (strcasecmp(argv[1], "off") == 0)
-		cp.val = 0;
-	else
-		cp.val = atoi(argv[1]);
-
-	if (argc > 2)
-		cp.timeout = htobs(atoi(argv[2]));
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DISCOVERABLE, index,
-				&cp, sizeof(cp), setting_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send set_discoverable cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_connectable(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	cmd_setting(mgmt_sk, index, MGMT_OP_SET_CONNECTABLE, argc, argv);
-}
-
-static void cmd_pairable(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	cmd_setting(mgmt_sk, index, MGMT_OP_SET_PAIRABLE, argc, argv);
-}
-
-static void cmd_linksec(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	cmd_setting(mgmt_sk, index, MGMT_OP_SET_LINK_SECURITY, argc, argv);
-}
-
-static void cmd_ssp(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	cmd_setting(mgmt_sk, index, MGMT_OP_SET_SSP, argc, argv);
-}
-
-static void cmd_hs(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	cmd_setting(mgmt_sk, index, MGMT_OP_SET_HS, argc, argv);
-}
-
-static void cmd_le(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	cmd_setting(mgmt_sk, index, MGMT_OP_SET_LE, argc, argv);
-}
-
-static void class_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_ev_class_of_dev_changed *rp = rsp;
-
-	if (len == 0 && status != 0) {
-		fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
-				mgmt_opstr(op), status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
-		exit(EXIT_FAILURE);
-	}
-
-	printf("%s succeeded. Class 0x%02x%02x%02x\n", mgmt_opstr(op),
-		rp->class_of_dev[2], rp->class_of_dev[1], rp->class_of_dev[0]);
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_class(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	uint8_t class[2];
-
-	if (argc < 3) {
-		printf("Usage: btmgmt %s <major> <minor>\n", argv[0]);
-		exit(EXIT_FAILURE);
-	}
-
-	class[0] = atoi(argv[1]);
-	class[1] = atoi(argv[2]);
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEV_CLASS, index,
-				class, sizeof(class), class_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send set_dev_class cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void disconnect_rsp(int mgmt_sk, uint16_t op, uint16_t id,
-				uint8_t status, void *rsp, uint16_t len,
-				void *user_data)
-{
-	struct mgmt_rp_disconnect *rp = rsp;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		fprintf(stderr, "Disconnect failed with status 0x%02x (%s)\n",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		fprintf(stderr, "Invalid disconnect response length (%u)\n",
-									len);
-		exit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status == 0) {
-		printf("%s disconnected\n", addr);
-		exit(EXIT_SUCCESS);
-	} else {
-		fprintf(stderr,
-			"Disconnecting %s failed with status 0x%02x (%s)\n",
-				addr, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_disconnect(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_disconnect cp;
-
-	if (argc < 2) {
-		printf("Usage: btmgmt %s <address>\n", argv[0]);
-		exit(EXIT_FAILURE);
-	}
-
-	str2ba(argv[1], &cp.addr.bdaddr);
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_DISCONNECT, index,
-				&cp, sizeof(cp), disconnect_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send disconnect cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void con_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_rp_get_connections *rp = rsp;
-	uint16_t count, i;
-
-	if (len < sizeof(*rp)) {
-		fprintf(stderr, "Too small (%u bytes) get_connections rsp\n",
-									len);
-		exit(EXIT_FAILURE);
-	}
-
-	count = bt_get_le16(&rp->conn_count);
-	if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
-		fprintf(stderr, "Invalid get_connections length "
-					" (count=%u, len=%u)\n", count, len);
-		exit(EXIT_FAILURE);
-	}
-
-	for (i = 0; i < count; i++) {
-		char addr[18];
-
-		ba2str(&rp->addr[i].bdaddr, addr);
-
-		printf("%s type %s\n", addr, typestr(rp->addr[i].type));
-	}
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_con(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_GET_CONNECTIONS, index, NULL, 0,
-							con_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send get_connections cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void find_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr,
-			"Unable to start discovery. status 0x%02x (%s)\n",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("Discovery started\n");
-	discovery = true;
-}
-
-static void find_usage(void)
-{
-	printf("Usage: btmgmt find [-l|-b]>\n");
-}
-
-static struct option find_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "le-only",	1, 0, 'l' },
-	{ "bredr-only",	1, 0, 'b' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_find(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_start_discovery cp;
-	uint8_t type;
-	int opt;
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	type = 0;
-	hci_set_bit(BDADDR_BREDR, &type);
-	hci_set_bit(BDADDR_LE_PUBLIC, &type);
-	hci_set_bit(BDADDR_LE_RANDOM, &type);
-
-	while ((opt = getopt_long(argc, argv, "+lbh", find_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 'l':
-			hci_clear_bit(BDADDR_BREDR, &type);
-			hci_set_bit(BDADDR_LE_PUBLIC, &type);
-			hci_set_bit(BDADDR_LE_RANDOM, &type);
-			break;
-		case 'b':
-			hci_set_bit(BDADDR_BREDR, &type);
-			hci_clear_bit(BDADDR_LE_PUBLIC, &type);
-			hci_clear_bit(BDADDR_LE_RANDOM, &type);
-			break;
-		case 'h':
-		default:
-			find_usage();
-			exit(EXIT_SUCCESS);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	cp.type = type;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_START_DISCOVERY, index,
-				&cp, sizeof(cp), find_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send start_discovery cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void name_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr, "Unable to set local name. status 0x%02x (%s)",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_name(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_set_local_name cp;
-
-	if (argc < 2) {
-		printf("Usage: btmgmt %s <name> [shortname]\n", argv[0]);
-		exit(EXIT_FAILURE);
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
-	if (argc > 2)
-		strncpy((char *) cp.short_name, argv[2],
-					MGMT_MAX_SHORT_NAME_LENGTH);
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_LOCAL_NAME, index,
-					&cp, sizeof(cp), name_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send set_name cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void pair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_rp_pair_device *rp = rsp;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		fprintf(stderr, "Pairing failed with status 0x%02x (%s)\n",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		fprintf(stderr, "Unexpected pair_rsp len %u\n", len);
-		exit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status != 0) {
-		fprintf(stderr,
-			"Pairing with %s (%s) failed. status 0x%02x (%s)\n",
-			addr, typestr(rp->addr.type), status,
-			mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("Paired with %s\n", addr);
-
-	exit(EXIT_SUCCESS);
-}
-
-static void pair_usage(void)
-{
-	printf("Usage: btmgmt pair [-c cap] [-t type] <remote address>\n");
-}
-
-static struct option pair_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "capability",	1, 0, 'c' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_pair(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_pair_device cp;
-	uint8_t cap = 0x01;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-
-	while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
-								NULL)) != -1) {
-		switch (opt) {
-		case 'c':
-			cap = strtol(optarg, NULL, 0);
-			break;
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-		default:
-			pair_usage();
-			exit(EXIT_SUCCESS);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		pair_usage();
-		exit(EXIT_FAILURE);
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-	cp.io_cap = cap;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_PAIR_DEVICE, index, &cp, sizeof(cp),
-							pair_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send pair_device cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void unpair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_rp_unpair_device *rp = rsp;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		fprintf(stderr, "Unpair device failed. status 0x%02x (%s)\n",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		fprintf(stderr, "Unexpected unpair_device_rsp len %u\n", len);
-		exit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->addr.bdaddr, addr);
-
-	if (status != 0) {
-		fprintf(stderr,
-			"Unpairing %s failed. status 0x%02x (%s)\n",
-				addr, status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("%s unpaired\n", addr);
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_unpair(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_unpair_device cp;
-
-	if (argc < 2) {
-		printf("Usage: btmgmt %s <remote address>\n", argv[0]);
-		exit(EXIT_FAILURE);
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[1], &cp.addr.bdaddr);
-	cp.disconnect = 1;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNPAIR_DEVICE, index, &cp,
-					sizeof(cp), unpair_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send unpair_device cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void keys_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr, "Load keys failed with status 0x%02x (%s)\n",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("Keys successfully loaded\n");
-
-	exit(EXIT_SUCCESS);
-}
-
-static void cmd_keys(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_load_link_keys cp;
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_LOAD_LINK_KEYS, index,
-				&cp, sizeof(cp), keys_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send load_keys cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void block_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	struct mgmt_addr_info *rp = rsp;
-	char addr[18];
-
-	if (len == 0 && status != 0) {
-		fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
-				mgmt_opstr(op), status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	if (len != sizeof(*rp)) {
-		fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
-		exit(EXIT_FAILURE);
-	}
-
-	ba2str(&rp->bdaddr, addr);
-
-	if (status != 0) {
-		fprintf(stderr, "%s %s (%s) failed. status 0x%02x (%s)\n",
-				mgmt_opstr(op), addr, typestr(rp->type),
-				status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("%s %s succeeded\n", mgmt_opstr(op), addr);
-
-	exit(EXIT_SUCCESS);
-}
-
-static void block_usage(void)
-{
-	printf("Usage: btmgmt block [-t type] <remote address>\n");
-}
-
-static struct option block_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "type",	1, 0, 't' },
-	{ 0, 0, 0, 0 }
-};
-
-static void cmd_block(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_block_device cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
-							NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-		default:
-			block_usage();
-			exit(EXIT_SUCCESS);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		block_usage();
-		exit(EXIT_FAILURE);
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_BLOCK_DEVICE, index,
-				&cp, sizeof(cp), block_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send block_device cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void unblock_usage(void)
-{
-	printf("Usage: btmgmt unblock [-t type] <remote address>\n");
-}
-
-static void cmd_unblock(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_unblock_device cp;
-	uint8_t type = BDADDR_BREDR;
-	int opt;
-
-	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
-							NULL)) != -1) {
-		switch (opt) {
-		case 't':
-			type = strtol(optarg, NULL, 0);
-			break;
-		case 'h':
-		default:
-			unblock_usage();
-			exit(EXIT_SUCCESS);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		unblock_usage();
-		exit(EXIT_FAILURE);
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	memset(&cp, 0, sizeof(cp));
-	str2ba(argv[0], &cp.addr.bdaddr);
-	cp.addr.type = type;
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNBLOCK_DEVICE, index,
-				&cp, sizeof(cp), block_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send unblock_device cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
-{
-	if (uuid->type == SDP_UUID16)
-		sdp_uuid16_to_uuid128(uuid128, uuid);
-	else if (uuid->type == SDP_UUID32)
-		sdp_uuid32_to_uuid128(uuid128, uuid);
-	else
-		memcpy(uuid128, uuid, sizeof(*uuid));
-}
-
-static void cmd_add_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_add_uuid cp;
-	uint128_t uint128;
-	uuid_t uuid, uuid128;
-
-	if (argc < 3) {
-		printf("UUID and service hint needed\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (bt_string2uuid(&uuid, argv[1]) < 0) {
-		printf("Invalid UUID: %s\n", argv[1]);
-		exit(EXIT_FAILURE);
-	}
-
-	memset(&cp, 0, sizeof(cp));
-
-	uuid_to_uuid128(&uuid128, &uuid);
-	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
-	htob128(&uint128, (uint128_t *) cp.uuid);
-
-	cp.svc_hint = atoi(argv[2]);
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_ADD_UUID, index,
-				&cp, sizeof(cp), class_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send add_uuid cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_remove_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_remove_uuid cp;
-	uint128_t uint128;
-	uuid_t uuid, uuid128;
-
-	if (argc < 2) {
-		printf("UUID needed\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	if (bt_string2uuid(&uuid, argv[1]) < 0) {
-		printf("Invalid UUID: %s\n", argv[1]);
-		exit(EXIT_FAILURE);
-	}
-
-	memset(&cp, 0, sizeof(cp));
-
-	uuid_to_uuid128(&uuid128, &uuid);
-	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
-	htob128(&uint128, (uint128_t *) cp.uuid);
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_REMOVE_UUID, index,
-				&cp, sizeof(cp), class_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send remove_uuid cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void cmd_clr_uuids(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	char *uuid_any = "00000000-0000-0000-0000-000000000000";
-	char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
-
-	cmd_remove_uuid(mgmt_sk, index, 2, rm_argv);
-}
-
-static void did_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
-				void *rsp, uint16_t len, void *user_data)
-{
-	if (status != 0) {
-		fprintf(stderr, "Set Device ID failed with status 0x%02x (%s)\n",
-						status, mgmt_errstr(status));
-		exit(EXIT_FAILURE);
-	}
-
-	printf("Device ID successfully set\n");
-
-	exit(EXIT_SUCCESS);
-}
-
-static void did_usage(void)
-{
-	printf("Usage: btmgmt did <source>:<vendor>:<product>:<version>\n");
-	printf("       possible source values: bluetooth, usb\n");
-}
-
-static void cmd_did(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
-	struct mgmt_cp_set_device_id cp;
-	uint16_t vendor, product, version , source;
-	int result;
-
-	if (argc < 2) {
-		did_usage();
-		exit(EXIT_FAILURE);
-	}
-
-	result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
-								&version);
-	if (result == 3) {
-		source = 0x0001;
-		goto done;
-	}
-
-	result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
-								&version);
-	if (result == 3) {
-		source = 0x0002;
-		goto done;
-	}
-
-	did_usage();
-	exit(EXIT_FAILURE);
-
-done:
-	if (index == MGMT_INDEX_NONE)
-		index = 0;
-
-	cp.source = htobs(source);
-	cp.vendor = htobs(vendor);
-	cp.product = htobs(product);
-	cp.version = htobs(version);
-
-	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEVICE_ID, index,
-				&cp, sizeof(cp), did_rsp, NULL) < 0) {
-		fprintf(stderr, "Unable to send set_dev_class cmd\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static struct {
-	char *cmd;
-	void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
-	char *doc;
-} command[] = {
-	{ "monitor",	cmd_monitor,	"Monitor events"		},
-	{ "version",	cmd_version,	"Get the MGMT Version"		},
-	{ "commands",	cmd_commands,	"List supported commands"	},
-	{ "info",	cmd_info,	"Show controller info"		},
-	{ "power",	cmd_power,	"Toggle powered state"		},
-	{ "discov",	cmd_discov,	"Toggle discoverable state"	},
-	{ "connectable",cmd_connectable,"Toggle connectable state"	},
-	{ "pairable",	cmd_pairable,	"Toggle pairable state"		},
-	{ "linksec",	cmd_linksec,	"Toggle link level security"	},
-	{ "ssp",	cmd_ssp,	"Toggle SSP mode"		},
-	{ "hs",		cmd_hs,		"Toggle HS Support"		},
-	{ "le",		cmd_le,		"Toggle LE Support"		},
-	{ "class",	cmd_class,	"Set device major/minor class"	},
-	{ "disconnect", cmd_disconnect, "Disconnect device"		},
-	{ "con",	cmd_con,	"List connections"		},
-	{ "find",	cmd_find,	"Discover nearby devices"	},
-	{ "name",	cmd_name,	"Set local name"		},
-	{ "pair",	cmd_pair,	"Pair with a remote device"	},
-	{ "unpair",	cmd_unpair,	"Unpair device"			},
-	{ "keys",	cmd_keys,	"Load Keys"			},
-	{ "block",	cmd_block,	"Block Device"			},
-	{ "unblock",	cmd_unblock,	"Unblock Device"		},
-	{ "add-uuid",	cmd_add_uuid,	"Add UUID"			},
-	{ "rm-uuid",	cmd_add_uuid,	"Remove UUID"			},
-	{ "clr-uuids",	cmd_clr_uuids,	"Clear UUIDs",			},
-	{ "did",	cmd_did,	"Set Device ID",		},
-	{ NULL, NULL, 0 }
-};
-
-static void usage(void)
-{
-	int i;
-
-	printf("btmgmt ver %s\n", VERSION);
-	printf("Usage:\n"
-		"\tbtmgmt [options] <command> [command parameters]\n");
-
-	printf("Options:\n"
-		"\t--index <id>\tSpecify adapter index\n"
-		"\t--verbose\tEnable extra logging\n"
-		"\t--help\tDisplay help\n");
-
-	printf("Commands:\n");
-	for (i = 0; command[i].cmd; i++)
-		printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
-
-	printf("\n"
-		"For more information on the usage of each command use:\n"
-		"\tbtmgmt <command> --help\n" );
-}
-
-static struct option main_options[] = {
-	{ "index",	1, 0, 'i' },
-	{ "verbose",	0, 0, 'v' },
-	{ "help",	0, 0, 'h' },
-	{ 0, 0, 0, 0 }
-};
-
-int main(int argc, char *argv[])
-{
-	int opt, i, mgmt_sk;
-	uint16_t index = MGMT_INDEX_NONE;
-	struct pollfd pollfd;
-
-	while ((opt = getopt_long(argc, argv, "+hvi:",
-						main_options, NULL)) != -1) {
-		switch (opt) {
-		case 'i':
-			if (strlen(optarg) > 3 &&
-					strncasecmp(optarg, "hci", 3) == 0)
-				index = atoi(&optarg[4]);
-			else
-				index = atoi(optarg);
-			break;
-		case 'v':
-			monitor = true;
-			break;
-		case 'h':
-		default:
-			usage();
-			return 0;
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		usage();
-		return 0;
-	}
-
-	mgmt_sk = mgmt_open();
-	if (mgmt_sk < 0) {
-		fprintf(stderr, "Unable to open mgmt socket\n");
-		return -1;
-	}
-
-	for (i = 0; command[i].cmd; i++) {
-		if (strcmp(command[i].cmd, argv[0]) != 0)
-			continue;
-
-		command[i].func(mgmt_sk, index, argc, argv);
-		break;
-	}
-
-	if (command[i].cmd == NULL) {
-		fprintf(stderr, "Unknown command: %s\n", argv[0]);
-		close(mgmt_sk);
-		return -1;
-	}
-
-	pollfd.fd = mgmt_sk;
-	pollfd.events = POLLIN;
-	pollfd.revents = 0;
-
-	while (poll(&pollfd, 1, -1) >= 0) {
-		if (pollfd.revents & (POLLHUP | POLLERR | POLLNVAL))
-			break;
-
-		if (pollfd.revents & POLLIN)
-			mgmt_process_data(mgmt_sk);
-
-		pollfd.revents = 0;
-	}
-
-	close(mgmt_sk);
-
-	return 0;
-}
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 04/14] alert: move alert to profiles dir
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 02/14] serial: remove the whole serial code Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 03/14] btmgmt: move to tools folder Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 05/14] deviceinfo: move to profiles folder Gustavo Padovan
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 Makefile.am             |    3 ++-
 alert/main.c            |   58 -----------------------------------------------
 alert/server.c          |   38 -------------------------------
 alert/server.h          |   26 ---------------------
 profiles/alert/main.c   |   58 +++++++++++++++++++++++++++++++++++++++++++++++
 profiles/alert/server.c |   38 +++++++++++++++++++++++++++++++
 profiles/alert/server.h |   26 +++++++++++++++++++++
 7 files changed, 124 insertions(+), 123 deletions(-)
 delete mode 100644 alert/main.c
 delete mode 100644 alert/server.c
 delete mode 100644 alert/server.h
 create mode 100644 profiles/alert/main.c
 create mode 100644 profiles/alert/server.c
 create mode 100644 profiles/alert/server.h

diff --git a/Makefile.am b/Makefile.am
index a2c85e2..f0e82d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -219,7 +219,8 @@ builtin_modules += thermometer alert time gatt_example proximity \
 builtin_sources += thermometer/main.c \
 			thermometer/manager.h thermometer/manager.c \
 			thermometer/thermometer.h thermometer/thermometer.c \
-			alert/main.c alert/server.h alert/server.c \
+			profiles/alert/main.c profiles/alert/server.h \
+			profiles/alert/server.c \
 			time/main.c time/server.h time/server.c \
 			time/manager.h time/manager.c \
 			plugins/gatt-example.c \
diff --git a/alert/main.c b/alert/main.c
deleted file mode 100644
index ec4ab6d..0000000
--- a/alert/main.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011  Nokia Corporation
- *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-#include <errno.h>
-
-#include "plugin.h"
-#include "hcid.h"
-#include "log.h"
-#include "server.h"
-
-static int alert_init(void)
-{
-	if (!main_opts.gatt_enabled) {
-		DBG("GATT is disabled");
-		return -ENOTSUP;
-	}
-
-	return alert_server_init();
-}
-
-static void alert_exit(void)
-{
-	if (!main_opts.gatt_enabled)
-		return;
-
-	alert_server_exit();
-}
-
-BLUETOOTH_PLUGIN_DEFINE(alert, VERSION,
-			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
-			alert_init, alert_exit)
diff --git a/alert/server.c b/alert/server.c
deleted file mode 100644
index d91b156..0000000
--- a/alert/server.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011  Nokia Corporation
- *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "server.h"
-
-int alert_server_init(void)
-{
-	return 0;
-}
-
-void alert_server_exit(void)
-{
-}
diff --git a/alert/server.h b/alert/server.h
deleted file mode 100644
index e59bdb1..0000000
--- a/alert/server.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011  Nokia Corporation
- *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-int alert_server_init(void);
-void alert_server_exit(void);
diff --git a/profiles/alert/main.c b/profiles/alert/main.c
new file mode 100644
index 0000000..ec4ab6d
--- /dev/null
+++ b/profiles/alert/main.c
@@ -0,0 +1,58 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  Nokia Corporation
+ *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+
+#include "plugin.h"
+#include "hcid.h"
+#include "log.h"
+#include "server.h"
+
+static int alert_init(void)
+{
+	if (!main_opts.gatt_enabled) {
+		DBG("GATT is disabled");
+		return -ENOTSUP;
+	}
+
+	return alert_server_init();
+}
+
+static void alert_exit(void)
+{
+	if (!main_opts.gatt_enabled)
+		return;
+
+	alert_server_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(alert, VERSION,
+			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+			alert_init, alert_exit)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
new file mode 100644
index 0000000..d91b156
--- /dev/null
+++ b/profiles/alert/server.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  Nokia Corporation
+ *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "server.h"
+
+int alert_server_init(void)
+{
+	return 0;
+}
+
+void alert_server_exit(void)
+{
+}
diff --git a/profiles/alert/server.h b/profiles/alert/server.h
new file mode 100644
index 0000000..e59bdb1
--- /dev/null
+++ b/profiles/alert/server.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  Nokia Corporation
+ *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+int alert_server_init(void);
+void alert_server_exit(void);
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 05/14] deviceinfo: move to profiles folder
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
                   ` (2 preceding siblings ...)
  2012-07-09 21:10 ` [PATCH 04/14] alert: move alert to profiles dir Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 07/14] thermometer: move to the " Gustavo Padovan
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 Makefile.am                      |   11 ++-
 deviceinfo/deviceinfo.c          |  195 --------------------------------------
 deviceinfo/deviceinfo.h          |   24 -----
 deviceinfo/main.c                |   52 ----------
 deviceinfo/manager.c             |   80 ----------------
 deviceinfo/manager.h             |   24 -----
 profiles/deviceinfo/deviceinfo.c |  195 ++++++++++++++++++++++++++++++++++++++
 profiles/deviceinfo/deviceinfo.h |   24 +++++
 profiles/deviceinfo/main.c       |   52 ++++++++++
 profiles/deviceinfo/manager.c    |   80 ++++++++++++++++
 profiles/deviceinfo/manager.h    |   24 +++++
 11 files changed, 381 insertions(+), 380 deletions(-)
 delete mode 100644 deviceinfo/deviceinfo.c
 delete mode 100644 deviceinfo/deviceinfo.h
 delete mode 100644 deviceinfo/main.c
 delete mode 100644 deviceinfo/manager.c
 delete mode 100644 deviceinfo/manager.h
 create mode 100644 profiles/deviceinfo/deviceinfo.c
 create mode 100644 profiles/deviceinfo/deviceinfo.h
 create mode 100644 profiles/deviceinfo/main.c
 create mode 100644 profiles/deviceinfo/manager.c
 create mode 100644 profiles/deviceinfo/manager.h

diff --git a/Makefile.am b/Makefile.am
index f0e82d1..2487368 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -214,8 +214,7 @@ builtin_sources += health/hdp_main.c health/hdp_types.h \
 endif
 
 if GATTMODULES
-builtin_modules += thermometer alert time gatt_example proximity \
-			deviceinfo
+builtin_modules += thermometer alert time gatt_example proximity deviceinfo
 builtin_sources += thermometer/main.c \
 			thermometer/manager.h thermometer/manager.c \
 			thermometer/thermometer.h thermometer/thermometer.c \
@@ -229,9 +228,11 @@ builtin_sources += thermometer/main.c \
 			proximity/reporter.h proximity/reporter.c \
 			proximity/linkloss.h proximity/linkloss.c \
 			proximity/immalert.h proximity/immalert.c \
-			deviceinfo/main.c \
-			deviceinfo/manager.h deviceinfo/manager.c \
-			deviceinfo/deviceinfo.h deviceinfo/deviceinfo.c
+			profiles/deviceinfo/main.c \
+			profiles/deviceinfo/manager.h \
+			profiles/deviceinfo/manager.c \
+			profiles/deviceinfo/deviceinfo.h \
+			profiles/deviceinfo/deviceinfo.c
 endif
 
 
diff --git a/deviceinfo/deviceinfo.c b/deviceinfo/deviceinfo.c
deleted file mode 100644
index 4548553..0000000
--- a/deviceinfo/deviceinfo.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012 Texas Instruments, Inc.
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <bluetooth/uuid.h>
-
-#include "adapter.h"
-#include "device.h"
-#include "gattrib.h"
-#include "attio.h"
-#include "att.h"
-#include "gattrib.h"
-#include "gatt.h"
-#include "log.h"
-#include "deviceinfo.h"
-
-#define PNP_ID_SIZE	7
-
-struct deviceinfo {
-	struct btd_device	*dev;		/* Device reference */
-	GAttrib			*attrib;	/* GATT connection */
-	guint			attioid;	/* Att watcher id */
-	struct att_range	*svc_range;	/* DeviceInfo range */
-	GSList			*chars;		/* Characteristics */
-};
-
-static GSList *servers = NULL;
-
-struct characteristic {
-	struct gatt_char	attr;	/* Characteristic */
-	struct deviceinfo	*d;	/* deviceinfo where the char belongs */
-};
-
-static void deviceinfo_free(gpointer user_data)
-{
-	struct deviceinfo *d = user_data;
-
-	if (d->attioid > 0)
-		btd_device_remove_attio_callback(d->dev, d->attioid);
-
-	if (d->attrib != NULL)
-		g_attrib_unref(d->attrib);
-
-	g_slist_free_full(d->chars, g_free);
-
-	btd_device_unref(d->dev);
-	g_free(d->svc_range);
-	g_free(d);
-}
-
-static gint cmp_device(gconstpointer a, gconstpointer b)
-{
-	const struct deviceinfo *d = a;
-	const struct btd_device *dev = b;
-
-	if (dev == d->dev)
-		return 0;
-
-	return -1;
-}
-
-static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
-							gpointer user_data)
-{
-	struct characteristic *ch = user_data;
-	uint8_t value[PNP_ID_SIZE];
-	ssize_t vlen;
-
-	if (status != 0) {
-		error("Error reading PNP_ID value: %s", att_ecode2str(status));
-		return;
-	}
-
-	vlen = dec_read_resp(pdu, len, value, sizeof(value));
-	if (vlen < 0) {
-		error("Error reading PNP_ID: Protocol error");
-		return;
-	}
-
-	if (vlen < 7) {
-		error("Error reading PNP_ID: Invalid pdu length received");
-		return;
-	}
-
-	device_set_pnpid(ch->d->dev, value[0], att_get_u16(&value[1]),
-				att_get_u16(&value[3]), att_get_u16(&value[5]));
-}
-
-static void process_deviceinfo_char(struct characteristic *ch)
-{
-	if (g_strcmp0(ch->attr.uuid, PNPID_UUID) == 0)
-		gatt_read_char(ch->d->attrib, ch->attr.value_handle, 0,
-							read_pnpid_cb, ch);
-}
-
-static void configure_deviceinfo_cb(GSList *characteristics, guint8 status,
-							gpointer user_data)
-{
-	struct deviceinfo *d = user_data;
-	GSList *l;
-
-	if (status != 0) {
-		error("Discover deviceinfo characteristics: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	for (l = characteristics; l; l = l->next) {
-		struct gatt_char *c = l->data;
-		struct characteristic *ch;
-
-		ch = g_new0(struct characteristic, 1);
-		ch->attr.handle = c->handle;
-		ch->attr.properties = c->properties;
-		ch->attr.value_handle = c->value_handle;
-		memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
-		ch->d = d;
-
-		d->chars = g_slist_append(d->chars, ch);
-
-		process_deviceinfo_char(ch);
-	}
-}
-static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
-{
-	struct deviceinfo *d = user_data;
-
-	d->attrib = g_attrib_ref(attrib);
-
-	gatt_discover_char(d->attrib, d->svc_range->start, d->svc_range->end,
-					NULL, configure_deviceinfo_cb, d);
-}
-
-static void attio_disconnected_cb(gpointer user_data)
-{
-	struct deviceinfo *d = user_data;
-
-	g_attrib_unref(d->attrib);
-	d->attrib = NULL;
-}
-
-int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim)
-{
-	struct deviceinfo *d;
-
-	d = g_new0(struct deviceinfo, 1);
-	d->dev = btd_device_ref(device);
-	d->svc_range = g_new0(struct att_range, 1);
-	d->svc_range->start = prim->range.start;
-	d->svc_range->end = prim->range.end;
-
-	servers = g_slist_prepend(servers, d);
-
-	d->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
-						attio_disconnected_cb, d);
-	return 0;
-}
-
-void deviceinfo_unregister(struct btd_device *device)
-{
-	struct deviceinfo *d;
-	GSList *l;
-
-	l = g_slist_find_custom(servers, device, cmp_device);
-	if (l == NULL)
-		return;
-
-	d = l->data;
-	servers = g_slist_remove(servers, d);
-
-	deviceinfo_free(d);
-}
diff --git a/deviceinfo/deviceinfo.h b/deviceinfo/deviceinfo.h
deleted file mode 100644
index 7a804a5..0000000
--- a/deviceinfo/deviceinfo.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012 Texas Instruments, Inc.
- *
- *  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
- *
- */
-
-int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim);
-void deviceinfo_unregister(struct btd_device *device);
diff --git a/deviceinfo/main.c b/deviceinfo/main.c
deleted file mode 100644
index 82ecc82..0000000
--- a/deviceinfo/main.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012 Texas Instruments, Inc.
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include "plugin.h"
-#include "manager.h"
-#include "hcid.h"
-#include "log.h"
-
-static int deviceinfo_init(void)
-{
-	if (!main_opts.gatt_enabled) {
-		error("DIS cannot start: GATT is disabled");
-		return -ENOTSUP;
-	}
-
-	return deviceinfo_manager_init();
-}
-
-static void deviceinfo_exit(void)
-{
-	deviceinfo_manager_exit();
-}
-
-BLUETOOTH_PLUGIN_DEFINE(deviceinfo, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
-					deviceinfo_init, deviceinfo_exit)
diff --git a/deviceinfo/manager.c b/deviceinfo/manager.c
deleted file mode 100644
index 1d59918..0000000
--- a/deviceinfo/manager.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012 Texas Instruments, Inc.
- *
- *  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 <glib.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-
-#include "adapter.h"
-#include "device.h"
-#include "att.h"
-#include "gattrib.h"
-#include "gatt.h"
-#include "deviceinfo.h"
-#include "manager.h"
-
-static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct gatt_primary *prim = a;
-	const char *uuid = b;
-
-	return g_strcmp0(prim->uuid, uuid);
-}
-
-static int deviceinfo_driver_probe(struct btd_device *device, GSList *uuids)
-{
-	struct gatt_primary *prim;
-	GSList *primaries, *l;
-
-	primaries = btd_device_get_primaries(device);
-
-	l = g_slist_find_custom(primaries, DEVICE_INFORMATION_UUID,
-							primary_uuid_cmp);
-	if (l == NULL)
-		return -EINVAL;
-
-	prim = l->data;
-
-	return deviceinfo_register(device, prim);
-}
-
-static void deviceinfo_driver_remove(struct btd_device *device)
-{
-	deviceinfo_unregister(device);
-}
-
-static struct btd_device_driver deviceinfo_device_driver = {
-	.name	= "deviceinfo-driver",
-	.uuids	= BTD_UUIDS(DEVICE_INFORMATION_UUID),
-	.probe	= deviceinfo_driver_probe,
-	.remove	= deviceinfo_driver_remove
-};
-
-int deviceinfo_manager_init(void)
-{
-	return btd_register_device_driver(&deviceinfo_device_driver);
-}
-
-void deviceinfo_manager_exit(void)
-{
-	btd_unregister_device_driver(&deviceinfo_device_driver);
-}
diff --git a/deviceinfo/manager.h b/deviceinfo/manager.h
deleted file mode 100644
index 0f742ca..0000000
--- a/deviceinfo/manager.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012 Texas Instruments, Inc.
- *
- *  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
- *
- */
-
-int deviceinfo_manager_init(void);
-void deviceinfo_manager_exit(void);
diff --git a/profiles/deviceinfo/deviceinfo.c b/profiles/deviceinfo/deviceinfo.c
new file mode 100644
index 0000000..4548553
--- /dev/null
+++ b/profiles/deviceinfo/deviceinfo.c
@@ -0,0 +1,195 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "gattrib.h"
+#include "attio.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "log.h"
+#include "deviceinfo.h"
+
+#define PNP_ID_SIZE	7
+
+struct deviceinfo {
+	struct btd_device	*dev;		/* Device reference */
+	GAttrib			*attrib;	/* GATT connection */
+	guint			attioid;	/* Att watcher id */
+	struct att_range	*svc_range;	/* DeviceInfo range */
+	GSList			*chars;		/* Characteristics */
+};
+
+static GSList *servers = NULL;
+
+struct characteristic {
+	struct gatt_char	attr;	/* Characteristic */
+	struct deviceinfo	*d;	/* deviceinfo where the char belongs */
+};
+
+static void deviceinfo_free(gpointer user_data)
+{
+	struct deviceinfo *d = user_data;
+
+	if (d->attioid > 0)
+		btd_device_remove_attio_callback(d->dev, d->attioid);
+
+	if (d->attrib != NULL)
+		g_attrib_unref(d->attrib);
+
+	g_slist_free_full(d->chars, g_free);
+
+	btd_device_unref(d->dev);
+	g_free(d->svc_range);
+	g_free(d);
+}
+
+static gint cmp_device(gconstpointer a, gconstpointer b)
+{
+	const struct deviceinfo *d = a;
+	const struct btd_device *dev = b;
+
+	if (dev == d->dev)
+		return 0;
+
+	return -1;
+}
+
+static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct characteristic *ch = user_data;
+	uint8_t value[PNP_ID_SIZE];
+	ssize_t vlen;
+
+	if (status != 0) {
+		error("Error reading PNP_ID value: %s", att_ecode2str(status));
+		return;
+	}
+
+	vlen = dec_read_resp(pdu, len, value, sizeof(value));
+	if (vlen < 0) {
+		error("Error reading PNP_ID: Protocol error");
+		return;
+	}
+
+	if (vlen < 7) {
+		error("Error reading PNP_ID: Invalid pdu length received");
+		return;
+	}
+
+	device_set_pnpid(ch->d->dev, value[0], att_get_u16(&value[1]),
+				att_get_u16(&value[3]), att_get_u16(&value[5]));
+}
+
+static void process_deviceinfo_char(struct characteristic *ch)
+{
+	if (g_strcmp0(ch->attr.uuid, PNPID_UUID) == 0)
+		gatt_read_char(ch->d->attrib, ch->attr.value_handle, 0,
+							read_pnpid_cb, ch);
+}
+
+static void configure_deviceinfo_cb(GSList *characteristics, guint8 status,
+							gpointer user_data)
+{
+	struct deviceinfo *d = user_data;
+	GSList *l;
+
+	if (status != 0) {
+		error("Discover deviceinfo characteristics: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	for (l = characteristics; l; l = l->next) {
+		struct gatt_char *c = l->data;
+		struct characteristic *ch;
+
+		ch = g_new0(struct characteristic, 1);
+		ch->attr.handle = c->handle;
+		ch->attr.properties = c->properties;
+		ch->attr.value_handle = c->value_handle;
+		memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
+		ch->d = d;
+
+		d->chars = g_slist_append(d->chars, ch);
+
+		process_deviceinfo_char(ch);
+	}
+}
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+	struct deviceinfo *d = user_data;
+
+	d->attrib = g_attrib_ref(attrib);
+
+	gatt_discover_char(d->attrib, d->svc_range->start, d->svc_range->end,
+					NULL, configure_deviceinfo_cb, d);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+	struct deviceinfo *d = user_data;
+
+	g_attrib_unref(d->attrib);
+	d->attrib = NULL;
+}
+
+int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim)
+{
+	struct deviceinfo *d;
+
+	d = g_new0(struct deviceinfo, 1);
+	d->dev = btd_device_ref(device);
+	d->svc_range = g_new0(struct att_range, 1);
+	d->svc_range->start = prim->range.start;
+	d->svc_range->end = prim->range.end;
+
+	servers = g_slist_prepend(servers, d);
+
+	d->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
+						attio_disconnected_cb, d);
+	return 0;
+}
+
+void deviceinfo_unregister(struct btd_device *device)
+{
+	struct deviceinfo *d;
+	GSList *l;
+
+	l = g_slist_find_custom(servers, device, cmp_device);
+	if (l == NULL)
+		return;
+
+	d = l->data;
+	servers = g_slist_remove(servers, d);
+
+	deviceinfo_free(d);
+}
diff --git a/profiles/deviceinfo/deviceinfo.h b/profiles/deviceinfo/deviceinfo.h
new file mode 100644
index 0000000..7a804a5
--- /dev/null
+++ b/profiles/deviceinfo/deviceinfo.h
@@ -0,0 +1,24 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ *  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
+ *
+ */
+
+int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim);
+void deviceinfo_unregister(struct btd_device *device);
diff --git a/profiles/deviceinfo/main.c b/profiles/deviceinfo/main.c
new file mode 100644
index 0000000..82ecc82
--- /dev/null
+++ b/profiles/deviceinfo/main.c
@@ -0,0 +1,52 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "plugin.h"
+#include "manager.h"
+#include "hcid.h"
+#include "log.h"
+
+static int deviceinfo_init(void)
+{
+	if (!main_opts.gatt_enabled) {
+		error("DIS cannot start: GATT is disabled");
+		return -ENOTSUP;
+	}
+
+	return deviceinfo_manager_init();
+}
+
+static void deviceinfo_exit(void)
+{
+	deviceinfo_manager_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(deviceinfo, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+					deviceinfo_init, deviceinfo_exit)
diff --git a/profiles/deviceinfo/manager.c b/profiles/deviceinfo/manager.c
new file mode 100644
index 0000000..1d59918
--- /dev/null
+++ b/profiles/deviceinfo/manager.c
@@ -0,0 +1,80 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ *  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 <glib.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "deviceinfo.h"
+#include "manager.h"
+
+static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct gatt_primary *prim = a;
+	const char *uuid = b;
+
+	return g_strcmp0(prim->uuid, uuid);
+}
+
+static int deviceinfo_driver_probe(struct btd_device *device, GSList *uuids)
+{
+	struct gatt_primary *prim;
+	GSList *primaries, *l;
+
+	primaries = btd_device_get_primaries(device);
+
+	l = g_slist_find_custom(primaries, DEVICE_INFORMATION_UUID,
+							primary_uuid_cmp);
+	if (l == NULL)
+		return -EINVAL;
+
+	prim = l->data;
+
+	return deviceinfo_register(device, prim);
+}
+
+static void deviceinfo_driver_remove(struct btd_device *device)
+{
+	deviceinfo_unregister(device);
+}
+
+static struct btd_device_driver deviceinfo_device_driver = {
+	.name	= "deviceinfo-driver",
+	.uuids	= BTD_UUIDS(DEVICE_INFORMATION_UUID),
+	.probe	= deviceinfo_driver_probe,
+	.remove	= deviceinfo_driver_remove
+};
+
+int deviceinfo_manager_init(void)
+{
+	return btd_register_device_driver(&deviceinfo_device_driver);
+}
+
+void deviceinfo_manager_exit(void)
+{
+	btd_unregister_device_driver(&deviceinfo_device_driver);
+}
diff --git a/profiles/deviceinfo/manager.h b/profiles/deviceinfo/manager.h
new file mode 100644
index 0000000..0f742ca
--- /dev/null
+++ b/profiles/deviceinfo/manager.h
@@ -0,0 +1,24 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ *  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
+ *
+ */
+
+int deviceinfo_manager_init(void);
+void deviceinfo_manager_exit(void);
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 07/14] thermometer: move to the profiles folder
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
                   ` (3 preceding siblings ...)
  2012-07-09 21:10 ` [PATCH 05/14] deviceinfo: move to profiles folder Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 08/14] time: " Gustavo Padovan
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 Makefile.am                        |    8 +-
 profiles/thermometer/main.c        |   70 ++
 profiles/thermometer/manager.c     |   92 +++
 profiles/thermometer/manager.h     |   24 +
 profiles/thermometer/thermometer.c | 1274 ++++++++++++++++++++++++++++++++++++
 profiles/thermometer/thermometer.h |   25 +
 thermometer/main.c                 |   70 --
 thermometer/manager.c              |   92 ---
 thermometer/manager.h              |   24 -
 thermometer/thermometer.c          | 1274 ------------------------------------
 thermometer/thermometer.h          |   25 -
 11 files changed, 1490 insertions(+), 1488 deletions(-)
 create mode 100644 profiles/thermometer/main.c
 create mode 100644 profiles/thermometer/manager.c
 create mode 100644 profiles/thermometer/manager.h
 create mode 100644 profiles/thermometer/thermometer.c
 create mode 100644 profiles/thermometer/thermometer.h
 delete mode 100644 thermometer/main.c
 delete mode 100644 thermometer/manager.c
 delete mode 100644 thermometer/manager.h
 delete mode 100644 thermometer/thermometer.c
 delete mode 100644 thermometer/thermometer.h

diff --git a/Makefile.am b/Makefile.am
index 2f6d539..c8b2475 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -215,9 +215,11 @@ endif
 
 if GATTMODULES
 builtin_modules += thermometer alert time gatt_example proximity deviceinfo
-builtin_sources += thermometer/main.c \
-			thermometer/manager.h thermometer/manager.c \
-			thermometer/thermometer.h thermometer/thermometer.c \
+builtin_sources += profiles/thermometer/main.c \
+			profiles/thermometer/manager.h \
+			profiles/thermometer/manager.c \
+			profiles/thermometer/thermometer.h \
+		       	profiles/thermometer/thermometer.c \
 			profiles/alert/main.c profiles/alert/server.h \
 			profiles/alert/server.c \
 			time/main.c time/server.h time/server.c \
diff --git a/profiles/thermometer/main.c b/profiles/thermometer/main.c
new file mode 100644
index 0000000..4447b52
--- /dev/null
+++ b/profiles/thermometer/main.c
@@ -0,0 +1,70 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+#include <gdbus.h>
+
+#include "plugin.h"
+#include "manager.h"
+#include "hcid.h"
+#include "log.h"
+
+static DBusConnection *connection = NULL;
+
+static int thermometer_init(void)
+{
+	if (!main_opts.gatt_enabled) {
+		DBG("GATT is disabled");
+		return -ENOTSUP;
+	}
+
+	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+	if (connection == NULL)
+		return -EIO;
+
+	if (thermometer_manager_init(connection) < 0) {
+		dbus_connection_unref(connection);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void thermometer_exit(void)
+{
+	if (!main_opts.gatt_enabled)
+		return;
+
+	thermometer_manager_exit();
+
+	dbus_connection_unref(connection);
+	connection = NULL;
+}
+
+BLUETOOTH_PLUGIN_DEFINE(thermometer, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+					thermometer_init, thermometer_exit)
diff --git a/profiles/thermometer/manager.c b/profiles/thermometer/manager.c
new file mode 100644
index 0000000..3d5452b
--- /dev/null
+++ b/profiles/thermometer/manager.c
@@ -0,0 +1,92 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  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 <gdbus.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "thermometer.h"
+#include "manager.h"
+
+static DBusConnection *connection = NULL;
+
+static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct gatt_primary *prim = a;
+	const char *uuid = b;
+
+	return g_strcmp0(prim->uuid, uuid);
+}
+
+static int thermometer_driver_probe(struct btd_device *device, GSList *uuids)
+{
+	struct gatt_primary *tattr;
+	GSList *primaries, *l;
+
+	primaries = btd_device_get_primaries(device);
+
+	l = g_slist_find_custom(primaries, HEALTH_THERMOMETER_UUID,
+							primary_uuid_cmp);
+	if (l == NULL)
+		return -EINVAL;
+
+	tattr = l->data;
+
+	return thermometer_register(connection, device, tattr);
+}
+
+static void thermometer_driver_remove(struct btd_device *device)
+{
+	thermometer_unregister(device);
+}
+
+static struct btd_device_driver thermometer_device_driver = {
+	.name	= "thermometer-device-driver",
+	.uuids	= BTD_UUIDS(HEALTH_THERMOMETER_UUID),
+	.probe	= thermometer_driver_probe,
+	.remove	= thermometer_driver_remove
+};
+
+int thermometer_manager_init(DBusConnection *conn)
+{
+	int ret;
+
+	ret = btd_register_device_driver(&thermometer_device_driver);
+	if (ret < 0)
+                return ret;
+
+	connection = dbus_connection_ref(conn);
+	return 0;
+}
+
+void thermometer_manager_exit(void)
+{
+	btd_unregister_device_driver(&thermometer_device_driver);
+
+	dbus_connection_unref(connection);
+	connection = NULL;
+}
diff --git a/profiles/thermometer/manager.h b/profiles/thermometer/manager.h
new file mode 100644
index 0000000..ed928ad
--- /dev/null
+++ b/profiles/thermometer/manager.h
@@ -0,0 +1,24 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  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
+ *
+ */
+
+int thermometer_manager_init(DBusConnection *conn);
+void thermometer_manager_exit(void);
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
new file mode 100644
index 0000000..087662e
--- /dev/null
+++ b/profiles/thermometer/thermometer.c
@@ -0,0 +1,1274 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gdbus.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+
+#include "dbus-common.h"
+#include "adapter.h"
+#include "device.h"
+#include "error.h"
+#include "log.h"
+#include "gattrib.h"
+#include "attio.h"
+#include "att.h"
+#include "gatt.h"
+#include "thermometer.h"
+
+#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
+
+/* Temperature measurement flag fields */
+#define TEMP_UNITS		0x01
+#define TEMP_TIME_STAMP		0x02
+#define TEMP_TYPE		0x04
+
+#define FLOAT_MAX_MANTISSA	16777216 /* 2^24 */
+
+#define VALID_RANGE_DESC_SIZE	4
+#define TEMPERATURE_TYPE_SIZE	1
+#define MEASUREMENT_INTERVAL_SIZE	2
+
+struct thermometer {
+	DBusConnection		*conn;		/* The connection to the bus */
+	struct btd_device	*dev;		/* Device reference */
+	GAttrib			*attrib;	/* GATT connection */
+	struct att_range	*svc_range;	/* Thermometer range */
+	guint			attioid;	/* Att watcher id */
+	guint			attindid;	/* Att incications id */
+	guint			attnotid;	/* Att notifications id */
+	GSList			*chars;		/* Characteristics */
+	GSList			*fwatchers;     /* Final measurements */
+	GSList			*iwatchers;     /* Intermediate measurements */
+	gboolean		intermediate;
+	uint8_t			type;
+	uint16_t		interval;
+	uint16_t		max;
+	uint16_t		min;
+	gboolean		has_type;
+	gboolean		has_interval;
+};
+
+struct characteristic {
+	struct gatt_char		attr;	/* Characteristic */
+	GSList			*desc;	/* Descriptors */
+	struct thermometer	*t;	/* Thermometer where the char belongs */
+};
+
+struct descriptor {
+	struct characteristic	*ch;
+	uint16_t		handle;
+	bt_uuid_t		uuid;
+};
+
+struct watcher {
+	struct thermometer	*t;
+	guint			id;
+	char			*srv;
+	char			*path;
+};
+
+struct measurement {
+	int16_t		exp;
+	int32_t		mant;
+	uint64_t	time;
+	gboolean	suptime;
+	char		*unit;
+	char		*type;
+	char		*value;
+};
+
+struct tmp_interval_data {
+	struct thermometer	*thermometer;
+	uint16_t		interval;
+};
+
+static GSList *thermometers = NULL;
+
+const char *temp_type[] = {
+	"<reserved>",
+	"Armpit",
+	"Body",
+	"Ear",
+	"Finger",
+	"Intestines",
+	"Mouth",
+	"Rectum",
+	"Toe",
+	"Tympanum"
+};
+
+static const gchar *temptype2str(uint8_t value)
+{
+	 if (value > 0 && value < G_N_ELEMENTS(temp_type))
+		return temp_type[value];
+
+	error("Temperature type %d reserved for future use", value);
+	return NULL;
+}
+
+static void destroy_watcher(gpointer user_data)
+{
+	struct watcher *watcher = user_data;
+
+	g_free(watcher->path);
+	g_free(watcher->srv);
+	g_free(watcher);
+}
+
+static void remove_watcher(gpointer user_data)
+{
+	struct watcher *watcher = user_data;
+
+	g_dbus_remove_watch(watcher->t->conn, watcher->id);
+}
+
+static void destroy_char(gpointer user_data)
+{
+	struct characteristic *c = user_data;
+
+	g_slist_free_full(c->desc, g_free);
+	g_free(c);
+}
+
+static void destroy_thermometer(gpointer user_data)
+{
+	struct thermometer *t = user_data;
+
+	if (t->attioid > 0)
+		btd_device_remove_attio_callback(t->dev, t->attioid);
+
+	if (t->attindid > 0)
+		g_attrib_unregister(t->attrib, t->attindid);
+
+	if (t->attnotid > 0)
+		g_attrib_unregister(t->attrib, t->attnotid);
+
+	if (t->attrib != NULL)
+		g_attrib_unref(t->attrib);
+
+	if (t->chars != NULL)
+		g_slist_free_full(t->chars, destroy_char);
+
+	if (t->fwatchers != NULL)
+		g_slist_free_full(t->fwatchers, remove_watcher);
+
+	dbus_connection_unref(t->conn);
+	btd_device_unref(t->dev);
+	g_free(t->svc_range);
+	g_free(t);
+}
+
+static gint cmp_device(gconstpointer a, gconstpointer b)
+{
+	const struct thermometer *t = a;
+	const struct btd_device *dev = b;
+
+	if (dev == t->dev)
+		return 0;
+
+	return -1;
+}
+
+static gint cmp_watcher(gconstpointer a, gconstpointer b)
+{
+	const struct watcher *watcher = a;
+	const struct watcher *match = b;
+	int ret;
+
+	ret = g_strcmp0(watcher->srv, match->srv);
+	if (ret != 0)
+		return ret;
+
+	return g_strcmp0(watcher->path, match->path);
+}
+
+static gint cmp_char_uuid(gconstpointer a, gconstpointer b)
+{
+	const struct characteristic *ch = a;
+	const char *uuid = b;
+
+	return g_strcmp0(ch->attr.uuid, uuid);
+}
+
+static gint cmp_char_val_handle(gconstpointer a, gconstpointer b)
+{
+	const struct characteristic *ch = a;
+	const uint16_t *handle = b;
+
+	return ch->attr.value_handle - *handle;
+}
+
+static gint cmp_descriptor(gconstpointer a, gconstpointer b)
+{
+	const struct descriptor *desc = a;
+	const bt_uuid_t *uuid = b;
+
+	return bt_uuid_cmp(&desc->uuid, uuid);
+}
+
+static struct characteristic *get_characteristic(struct thermometer *t,
+							const char *uuid)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(t->chars, uuid, cmp_char_uuid);
+	if (l == NULL)
+		return NULL;
+
+	return l->data;
+}
+
+static struct descriptor *get_descriptor(struct characteristic *ch,
+							const bt_uuid_t *uuid)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(ch->desc, uuid, cmp_descriptor);
+	if (l == NULL)
+		return NULL;
+
+	return l->data;
+}
+
+static void change_property(struct thermometer *t, const char *name,
+							gpointer value) {
+	if (g_strcmp0(name, "Intermediate") == 0) {
+		gboolean *intermediate = value;
+		if (t->intermediate == *intermediate)
+			return;
+
+		t->intermediate = *intermediate;
+		emit_property_changed(t->conn, device_get_path(t->dev),
+					THERMOMETER_INTERFACE, name,
+					DBUS_TYPE_BOOLEAN, &t->intermediate);
+	} else if (g_strcmp0(name, "Interval") == 0) {
+		uint16_t *interval = value;
+		if (t->has_interval && t->interval == *interval)
+			return;
+
+		t->has_interval = TRUE;
+		t->interval = *interval;
+		emit_property_changed(t->conn, device_get_path(t->dev),
+					THERMOMETER_INTERFACE, name,
+					DBUS_TYPE_UINT16, &t->interval);
+	} else if (g_strcmp0(name, "Maximum") == 0) {
+		uint16_t *max = value;
+		if (t->max == *max)
+			return;
+
+		t->max = *max;
+		emit_property_changed(t->conn, device_get_path(t->dev),
+					THERMOMETER_INTERFACE, name,
+					DBUS_TYPE_UINT16, &t->max);
+	} else if (g_strcmp0(name, "Minimum") == 0) {
+		uint16_t *min = value;
+		if (t->min == *min)
+			return;
+
+		t->min = *min;
+		emit_property_changed(t->conn, device_get_path(t->dev),
+					THERMOMETER_INTERFACE, name,
+					DBUS_TYPE_UINT16, &t->min);
+	} else
+		DBG("%s is not a thermometer property", name);
+}
+
+static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct descriptor *desc = user_data;
+	uint8_t value[VALID_RANGE_DESC_SIZE];
+	uint16_t max, min;
+	ssize_t vlen;
+
+	if (status != 0) {
+		DBG("Valid Range descriptor read failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	vlen = dec_read_resp(pdu, len, value, sizeof(value));
+	if (vlen < 0) {
+		DBG("Protocol error\n");
+		return;
+	}
+
+	if (vlen < 4) {
+		DBG("Invalid range received");
+		return;
+	}
+
+	min = att_get_u16(&value[0]);
+	max = att_get_u16(&value[2]);
+
+	if (min == 0 || min > max) {
+		DBG("Invalid range");
+		return;
+	}
+
+	change_property(desc->ch->t, "Maximum", &max);
+	change_property(desc->ch->t, "Minimum", &min);
+}
+
+static void measurement_cb(guint8 status, const guint8 *pdu,
+						guint16 len, gpointer user_data)
+{
+	char *msg = user_data;
+
+	if (status != 0)
+		error("%s failed", msg);
+
+	g_free(msg);
+}
+
+static void process_thermometer_desc(struct descriptor *desc)
+{
+	struct characteristic *ch = desc->ch;
+	char uuidstr[MAX_LEN_UUID_STR];
+	bt_uuid_t btuuid;
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+	if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
+		uint8_t atval[2];
+		uint16_t val;
+		char *msg;
+
+		if (g_strcmp0(ch->attr.uuid,
+					TEMPERATURE_MEASUREMENT_UUID) == 0) {
+			if (g_slist_length(ch->t->fwatchers) == 0)
+				return;
+
+			val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
+			msg = g_strdup("Enable Temperature Measurement "
+								"indication");
+		} else if (g_strcmp0(ch->attr.uuid,
+					INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+			if (g_slist_length(ch->t->iwatchers) == 0)
+				return;
+
+			val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
+			msg = g_strdup("Enable Intermediate Temperature "
+								"notification");
+		} else if (g_strcmp0(ch->attr.uuid,
+					MEASUREMENT_INTERVAL_UUID) == 0) {
+			val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
+			msg = g_strdup("Enable Measurement Interval "
+								"indication");
+		} else
+			goto done;
+
+		att_put_u16(val, atval);
+		gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
+							measurement_cb, msg);
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CHARAC_VALID_RANGE_UUID);
+
+	if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0 && g_strcmp0(ch->attr.uuid,
+					MEASUREMENT_INTERVAL_UUID) == 0) {
+		gatt_read_char(ch->t->attrib, desc->handle, 0,
+						valid_range_desc_cb, desc);
+		return;
+	}
+
+done:
+	bt_uuid_to_string(&desc->uuid, uuidstr, MAX_LEN_UUID_STR);
+	DBG("Ignored descriptor %s in characteristic %s", uuidstr,
+								ch->attr.uuid);
+}
+
+static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct characteristic *ch = user_data;
+	struct att_data_list *list;
+	uint8_t format;
+	int i;
+
+	if (status != 0) {
+		error("Discover all characteristic descriptors failed [%s]: %s",
+					ch->attr.uuid, att_ecode2str(status));
+		return;
+	}
+
+	list = dec_find_info_resp(pdu, len, &format);
+	if (list == NULL)
+		return;
+
+	for (i = 0; i < list->num; i++) {
+		struct descriptor *desc;
+		uint8_t *value;
+
+		value = list->data[i];
+		desc = g_new0(struct descriptor, 1);
+		desc->handle = att_get_u16(value);
+		desc->ch = ch;
+
+		if (format == 0x01)
+			desc->uuid = att_get_uuid16(&value[2]);
+		else
+			desc->uuid = att_get_uuid128(&value[2]);
+
+		ch->desc = g_slist_append(ch->desc, desc);
+		process_thermometer_desc(desc);
+	}
+
+	att_data_list_free(list);
+}
+
+static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct characteristic *ch = user_data;
+	struct thermometer *t = ch->t;
+	uint8_t value[TEMPERATURE_TYPE_SIZE];
+	ssize_t vlen;
+
+	if (status != 0) {
+		DBG("Temperature Type value read failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	vlen = dec_read_resp(pdu, len, value, sizeof(value));
+	if (vlen < 0) {
+		DBG("Protocol error.");
+		return;
+	}
+
+	if (vlen != 1) {
+		DBG("Invalid length for Temperature type");
+		return;
+	}
+
+	t->has_type = TRUE;
+	t->type = value[0];
+}
+
+static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct characteristic *ch = user_data;
+	uint8_t value[MEASUREMENT_INTERVAL_SIZE];
+	uint16_t interval;
+	ssize_t vlen;
+
+	if (status != 0) {
+		DBG("Measurement Interval value read failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	vlen = dec_read_resp(pdu, len, value, sizeof(value));
+	if (vlen < 0) {
+		DBG("Protocol error\n");
+		return;
+	}
+
+	if (vlen < 2) {
+		DBG("Invalid Interval received");
+		return;
+	}
+
+	interval = att_get_u16(&value[0]);
+	change_property(ch->t, "Interval", &interval);
+}
+
+static void process_thermometer_char(struct characteristic *ch)
+{
+	if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+		gboolean intermediate = TRUE;
+		change_property(ch->t, "Intermediate", &intermediate);
+		return;
+	} else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
+		gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
+							read_temp_type_cb, ch);
+	else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+		gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
+							read_interval_cb, ch);
+}
+
+static void configure_thermometer_cb(GSList *characteristics, guint8 status,
+							gpointer user_data)
+{
+	struct thermometer *t = user_data;
+	GSList *l;
+
+	if (status != 0) {
+		error("Discover thermometer characteristics: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	for (l = characteristics; l; l = l->next) {
+		struct gatt_char *c = l->data;
+		struct characteristic *ch;
+		uint16_t start, end;
+
+		ch = g_new0(struct characteristic, 1);
+		ch->attr.handle = c->handle;
+		ch->attr.properties = c->properties;
+		ch->attr.value_handle = c->value_handle;
+		memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
+		ch->t = t;
+
+		t->chars = g_slist_append(t->chars, ch);
+
+		process_thermometer_char(ch);
+
+		start = c->value_handle + 1;
+
+		if (l->next != NULL) {
+			struct gatt_char *c = l->next->data;
+			if (start == c->handle)
+				continue;
+			end = c->handle - 1;
+		} else if (c->value_handle != t->svc_range->end)
+			end = t->svc_range->end;
+		else
+			continue;
+
+		gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
+	}
+}
+
+static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct thermometer *t = data;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *reply;
+
+	reply = dbus_message_new_method_return(msg);
+	if (reply == NULL)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+	dict_append_entry(&dict, "Intermediate", DBUS_TYPE_BOOLEAN,
+							&t->intermediate);
+
+	if (t->has_interval) {
+		dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT16,
+								&t->interval);
+		dict_append_entry(&dict, "Maximum", DBUS_TYPE_UINT16, &t->max);
+		dict_append_entry(&dict, "Minimum", DBUS_TYPE_UINT16, &t->min);
+	}
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
+}
+
+static void write_interval_cb (guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct tmp_interval_data *data = user_data;
+
+	if (status != 0) {
+		error("Interval Write Request failed %s",
+							att_ecode2str(status));
+		goto done;
+	}
+
+	if (!dec_write_resp(pdu, len)) {
+		error("Interval Write Request: protocol error");
+		goto done;
+	}
+
+	change_property(data->thermometer, "Interval", &data->interval);
+
+done:
+	g_free(user_data);
+}
+
+static DBusMessage *write_attr_interval(struct thermometer *t, DBusMessage *msg,
+								uint16_t value)
+{
+	struct tmp_interval_data *data;
+	struct characteristic *ch;
+	uint8_t atval[2];
+
+	if (t->attrib == NULL)
+		return btd_error_not_connected(msg);
+
+	ch = get_characteristic(t, MEASUREMENT_INTERVAL_UUID);
+	if (ch == NULL)
+		return btd_error_not_available(msg);
+
+	if (value < t->min || value > t->max)
+		return btd_error_invalid_args(msg);
+
+	att_put_u16(value, &atval[0]);
+
+	data = g_new0(struct tmp_interval_data, 1);
+	data->thermometer = t;
+	data->interval = value;
+	gatt_write_char(t->attrib, ch->attr.value_handle, atval, 2,
+						write_interval_cb, data);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct thermometer *t = data;
+	const char *property;
+	DBusMessageIter iter;
+	DBusMessageIter sub;
+	uint16_t value;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &property);
+	if (g_strcmp0("Interval", property) != 0)
+		return btd_error_invalid_args(msg);
+
+	if (!t->has_interval)
+		return btd_error_not_available(msg);
+
+	dbus_message_iter_next(&iter);
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_recurse(&iter, &sub);
+
+	if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_UINT16)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&sub, &value);
+
+	return write_attr_interval(t, msg, value);
+}
+
+static void enable_final_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	char *msg;
+
+	if (t->attrib == NULL)
+		return;
+
+	ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+	if (ch == NULL) {
+		DBG("Temperature measurement characteristic not found");
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	desc = get_descriptor(ch, &btuuid);
+	if (desc == NULL) {
+		DBG("Client characteristic configuration descriptor not found");
+		return;
+	}
+
+	atval[0] = 0x02;
+	atval[1] = 0x00;
+	msg = g_strdup("Enable final measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void enable_intermediate_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	char *msg;
+
+	if (t->attrib == NULL)
+		return;
+
+	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+	if (ch == NULL) {
+		DBG("Intermediate measurement characteristic not found");
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	desc = get_descriptor(ch, &btuuid);
+	if (desc == NULL) {
+		DBG("Client characteristic configuration descriptor not found");
+		return;
+	}
+
+	atval[0] = 0x01;
+	atval[1] = 0x00;
+	msg = g_strdup("Enable intermediate measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void disable_final_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	char *msg;
+
+	if (t->attrib == NULL)
+		return;
+
+	ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+	if (ch == NULL) {
+		DBG("Temperature measurement characteristic not found");
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	desc = get_descriptor(ch, &btuuid);
+	if (desc == NULL) {
+		DBG("Client characteristic configuration descriptor not found");
+		return;
+	}
+
+	atval[0] = 0x00;
+	atval[1] = 0x00;
+	msg = g_strdup("Disable final measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void disable_intermediate_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	char *msg;
+
+	if (t->attrib == NULL)
+		return;
+
+	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+	if (ch == NULL) {
+		DBG("Intermediate measurement characteristic not found");
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	desc = get_descriptor(ch, &btuuid);
+	if (desc == NULL) {
+		DBG("Client characteristic configuration descriptor not found");
+		return;
+	}
+
+	atval[0] = 0x00;
+	atval[1] = 0x00;
+	msg = g_strdup("Disable intermediate measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void remove_int_watcher(struct thermometer *t, struct watcher *w)
+{
+	if (!g_slist_find(t->iwatchers, w))
+		return;
+
+	t->iwatchers = g_slist_remove(t->iwatchers, w);
+
+	if (g_slist_length(t->iwatchers) == 0)
+		disable_intermediate_measurement(t);
+}
+
+static void watcher_exit(DBusConnection *conn, void *user_data)
+{
+	struct watcher *watcher = user_data;
+	struct thermometer *t = watcher->t;
+
+	DBG("Thermometer watcher %s disconnected", watcher->path);
+
+	remove_int_watcher(t, watcher);
+
+	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+	g_dbus_remove_watch(watcher->t->conn, watcher->id);
+
+	if (g_slist_length(t->fwatchers) == 0)
+		disable_final_measurement(t);
+}
+
+static struct watcher *find_watcher(GSList *list, const char *sender,
+							const char *path)
+{
+	struct watcher *match;
+	GSList *l;
+
+	match = g_new0(struct watcher, 1);
+	match->srv = g_strdup(sender);
+	match->path = g_strdup(path);
+
+	l = g_slist_find_custom(list, match, cmp_watcher);
+	destroy_watcher(match);
+
+	if (l != NULL)
+		return l->data;
+
+	return NULL;
+}
+
+static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	const char *sender = dbus_message_get_sender(msg);
+	struct thermometer *t = data;
+	struct watcher *watcher;
+	char *path;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(t->fwatchers, sender, path);
+	if (watcher != NULL)
+		return btd_error_already_exists(msg);
+
+	DBG("Thermometer watcher %s registered", path);
+
+	watcher = g_new0(struct watcher, 1);
+	watcher->srv = g_strdup(sender);
+	watcher->path = g_strdup(path);
+	watcher->t = t;
+	watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
+						watcher, destroy_watcher);
+
+	if (g_slist_length(t->fwatchers) == 0)
+		enable_final_measurement(t);
+
+	t->fwatchers = g_slist_prepend(t->fwatchers, watcher);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	const char *sender = dbus_message_get_sender(msg);
+	struct thermometer *t = data;
+	struct watcher *watcher;
+	char *path;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(t->fwatchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	DBG("Thermometer watcher %s unregistered", path);
+
+	remove_int_watcher(t, watcher);
+
+	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+	g_dbus_remove_watch(watcher->t->conn, watcher->id);
+
+	if (g_slist_length(t->fwatchers) == 0)
+		disable_final_measurement(t);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	const char *sender = dbus_message_get_sender(msg);
+	struct thermometer *t = data;
+	struct watcher *watcher;
+	char *path;
+
+	if (!t->intermediate)
+		return btd_error_not_supported(msg);
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(t->fwatchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	if (find_watcher(t->iwatchers, sender, path))
+		return btd_error_already_exists(msg);
+
+	DBG("Intermediate measurement watcher %s registered", path);
+
+	if (g_slist_length(t->iwatchers) == 0)
+		enable_intermediate_measurement(t);
+
+	t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	const char *sender = dbus_message_get_sender(msg);
+	struct thermometer *t = data;
+	struct watcher *watcher;
+	char *path;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(t->iwatchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	DBG("Intermediate measurement %s unregistered", path);
+
+	remove_int_watcher(t, watcher);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable thermometer_methods[] = {
+	{ GDBUS_METHOD("GetProperties",
+			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+			get_properties) },
+	{ GDBUS_ASYNC_METHOD("SetProperty",
+			GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
+			set_property) },
+	{ GDBUS_METHOD("RegisterWatcher",
+			GDBUS_ARGS({ "agent", "o" }), NULL,
+			register_watcher) },
+	{ GDBUS_METHOD("UnregisterWatcher",
+			GDBUS_ARGS({ "agent", "o" }), NULL,
+			unregister_watcher) },
+	{ GDBUS_METHOD("EnableIntermediateMeasurement",
+			GDBUS_ARGS({ "agent", "o" }), NULL,
+			enable_intermediate) },
+	{ GDBUS_METHOD("DisableIntermediateMeasurement",
+			GDBUS_ARGS({ "agent", "o" }), NULL,
+			disable_intermediate) },
+	{ }
+};
+
+static const GDBusSignalTable thermometer_signals[] = {
+	{ GDBUS_SIGNAL("PropertyChanged",
+			GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+	{ }
+};
+
+static void update_watcher(gpointer data, gpointer user_data)
+{
+	struct watcher *w = data;
+	struct measurement *m = user_data;
+	DBusConnection *conn = w->t->conn;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(w->srv, w->path,
+				"org.bluez.ThermometerWatcher",
+				"MeasurementReceived");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+	dict_append_entry(&dict, "Exponent", DBUS_TYPE_INT16, &m->exp);
+	dict_append_entry(&dict, "Mantissa", DBUS_TYPE_INT32, &m->mant);
+	dict_append_entry(&dict, "Unit", DBUS_TYPE_STRING, &m->unit);
+
+	if (m->suptime)
+		dict_append_entry(&dict, "Time", DBUS_TYPE_UINT64, &m->time);
+
+	dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &m->type);
+	dict_append_entry(&dict, "Measurement", DBUS_TYPE_STRING, &m->value);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	dbus_message_set_no_reply(msg, TRUE);
+	g_dbus_send_message(conn, msg);
+}
+
+static void recv_measurement(struct thermometer *t, struct measurement *m)
+{
+	GSList *wlist;
+
+	if (g_strcmp0(m->value, "Intermediate") == 0)
+		wlist = t->iwatchers;
+	else
+		wlist = t->fwatchers;
+
+	g_slist_foreach(wlist, update_watcher, m);
+}
+
+static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
+						uint16_t len, gboolean final)
+{
+	struct measurement m;
+	const char *type;
+	uint8_t flags;
+	uint32_t raw;
+
+	if (len < 4) {
+		DBG("Mandatory flags are not provided");
+		return;
+	}
+
+	flags = pdu[3];
+	if (flags & TEMP_UNITS)
+		m.unit = "Fahrenheit";
+	else
+		m.unit = "Celsius";
+
+	if (len < 8) {
+		DBG("Temperature measurement value is not provided");
+		return;
+	}
+
+	raw = att_get_u32(&pdu[4]);
+	m.mant = raw & 0x00FFFFFF;
+	m.exp = ((int32_t) raw) >> 24;
+
+	if (m.mant & 0x00800000) {
+		/* convert to C2 negative value */
+		m.mant = m.mant - FLOAT_MAX_MANTISSA;
+	}
+
+	if (flags & TEMP_TIME_STAMP) {
+		struct tm ts;
+		time_t time;
+
+		if (len < 15) {
+			DBG("Can't get time stamp value");
+			return;
+		}
+
+		ts.tm_year = att_get_u16(&pdu[8]) - 1900;
+		ts.tm_mon = pdu[10] - 1;
+		ts.tm_mday = pdu[11];
+		ts.tm_hour = pdu[12];
+		ts.tm_min = pdu[13];
+		ts.tm_sec = pdu[14];
+		ts.tm_isdst = -1;
+
+		time = mktime(&ts);
+		m.time = (uint64_t) time;
+		m.suptime = TRUE;
+	} else
+		m.suptime = FALSE;
+
+	if (flags & TEMP_TYPE) {
+		uint8_t index;
+
+		if (m.suptime && len >= 16)
+			index = 15;
+		else if (!m.suptime && len >= 9)
+			index = 9;
+		else {
+			DBG("Can't get temperature type");
+			return;
+		}
+
+		type = temptype2str(pdu[index]);
+	} else if (t->has_type)
+		type = temptype2str(t->type);
+	else
+		type = NULL;
+
+	m.type = type ? g_strdup(type) : NULL;
+	m.value = final ? "Final" : "Intermediate";
+
+	recv_measurement(t, &m);
+	g_free(m.type);
+}
+
+static void proc_measurement_interval(struct thermometer *t, const uint8_t *pdu,
+								uint16_t len)
+{
+	uint16_t interval;
+
+	if (len < 5) {
+		DBG("Measurement interval value is not provided");
+		return;
+	}
+
+	interval = att_get_u16(&pdu[3]);
+
+	change_property(t, "Interval", &interval);
+}
+
+static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+	struct thermometer *t = user_data;
+	const struct characteristic *ch;
+	uint8_t *opdu;
+	uint16_t handle, olen;
+	GSList *l;
+	int plen;
+
+	if (len < 3) {
+		DBG("Bad pdu received");
+		return;
+	}
+
+	handle = att_get_u16(&pdu[1]);
+	l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
+	if (l == NULL) {
+		DBG("Unexpected handle: 0x%04x", handle);
+		return;
+	}
+
+	ch = l->data;
+
+	if (g_strcmp0(ch->attr.uuid, TEMPERATURE_MEASUREMENT_UUID) == 0)
+		proc_measurement(t, pdu, len, TRUE);
+	else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+		proc_measurement_interval(t, pdu, len);
+
+	opdu = g_attrib_get_buffer(t->attrib, &plen);
+	olen = enc_confirmation(opdu, plen);
+
+	if (olen > 0)
+		g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
+									NULL);
+}
+
+static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+	struct thermometer *t = user_data;
+	const struct characteristic *ch;
+	uint16_t handle;
+	GSList *l;
+
+	if (len < 3) {
+		DBG("Bad pdu received");
+		return;
+	}
+
+	handle = att_get_u16(&pdu[1]);
+	l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
+	if (l == NULL) {
+		DBG("Unexpected handle: 0x%04x", handle);
+		return;
+	}
+
+	ch = l->data;
+	if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0)
+		proc_measurement(t, pdu, len, FALSE);
+}
+
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+	struct thermometer *t = user_data;
+
+	t->attrib = g_attrib_ref(attrib);
+
+	t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
+							ind_handler, t, NULL);
+	t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
+							notif_handler, t, NULL);
+	gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
+					NULL, configure_thermometer_cb, t);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+	struct thermometer *t = user_data;
+
+	DBG("GATT Disconnected");
+
+	if (t->attindid > 0) {
+		g_attrib_unregister(t->attrib, t->attindid);
+		t->attindid = 0;
+	}
+
+	if (t->attnotid > 0) {
+		g_attrib_unregister(t->attrib, t->attnotid);
+		t->attnotid = 0;
+	}
+
+	g_attrib_unref(t->attrib);
+	t->attrib = NULL;
+}
+
+int thermometer_register(DBusConnection *connection, struct btd_device *device,
+						struct gatt_primary *tattr)
+{
+	const gchar *path = device_get_path(device);
+	struct thermometer *t;
+
+	t = g_new0(struct thermometer, 1);
+	t->conn = dbus_connection_ref(connection);
+	t->dev = btd_device_ref(device);
+	t->svc_range = g_new0(struct att_range, 1);
+	t->svc_range->start = tattr->range.start;
+	t->svc_range->end = tattr->range.end;
+
+	if (!g_dbus_register_interface(t->conn, path, THERMOMETER_INTERFACE,
+				thermometer_methods, thermometer_signals,
+				NULL, t, destroy_thermometer)) {
+		error("D-Bus failed to register %s interface",
+							THERMOMETER_INTERFACE);
+		destroy_thermometer(t);
+		return -EIO;
+	}
+
+	thermometers = g_slist_prepend(thermometers, t);
+
+	t->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
+						attio_disconnected_cb, t);
+	return 0;
+}
+
+void thermometer_unregister(struct btd_device *device)
+{
+	struct thermometer *t;
+	GSList *l;
+
+	l = g_slist_find_custom(thermometers, device, cmp_device);
+	if (l == NULL)
+		return;
+
+	t = l->data;
+	thermometers = g_slist_remove(thermometers, t);
+	g_dbus_unregister_interface(t->conn, device_get_path(t->dev),
+							THERMOMETER_INTERFACE);
+}
diff --git a/profiles/thermometer/thermometer.h b/profiles/thermometer/thermometer.h
new file mode 100644
index 0000000..330503c
--- /dev/null
+++ b/profiles/thermometer/thermometer.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  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
+ *
+ */
+
+int thermometer_register(DBusConnection *connection, struct btd_device *device,
+						struct gatt_primary *tattr);
+void thermometer_unregister(struct btd_device *device);
diff --git a/thermometer/main.c b/thermometer/main.c
deleted file mode 100644
index 4447b52..0000000
--- a/thermometer/main.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-#include <errno.h>
-#include <gdbus.h>
-
-#include "plugin.h"
-#include "manager.h"
-#include "hcid.h"
-#include "log.h"
-
-static DBusConnection *connection = NULL;
-
-static int thermometer_init(void)
-{
-	if (!main_opts.gatt_enabled) {
-		DBG("GATT is disabled");
-		return -ENOTSUP;
-	}
-
-	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
-	if (connection == NULL)
-		return -EIO;
-
-	if (thermometer_manager_init(connection) < 0) {
-		dbus_connection_unref(connection);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void thermometer_exit(void)
-{
-	if (!main_opts.gatt_enabled)
-		return;
-
-	thermometer_manager_exit();
-
-	dbus_connection_unref(connection);
-	connection = NULL;
-}
-
-BLUETOOTH_PLUGIN_DEFINE(thermometer, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
-					thermometer_init, thermometer_exit)
diff --git a/thermometer/manager.c b/thermometer/manager.c
deleted file mode 100644
index 3d5452b..0000000
--- a/thermometer/manager.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- *  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 <gdbus.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-
-#include "adapter.h"
-#include "device.h"
-#include "att.h"
-#include "gattrib.h"
-#include "gatt.h"
-#include "thermometer.h"
-#include "manager.h"
-
-static DBusConnection *connection = NULL;
-
-static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct gatt_primary *prim = a;
-	const char *uuid = b;
-
-	return g_strcmp0(prim->uuid, uuid);
-}
-
-static int thermometer_driver_probe(struct btd_device *device, GSList *uuids)
-{
-	struct gatt_primary *tattr;
-	GSList *primaries, *l;
-
-	primaries = btd_device_get_primaries(device);
-
-	l = g_slist_find_custom(primaries, HEALTH_THERMOMETER_UUID,
-							primary_uuid_cmp);
-	if (l == NULL)
-		return -EINVAL;
-
-	tattr = l->data;
-
-	return thermometer_register(connection, device, tattr);
-}
-
-static void thermometer_driver_remove(struct btd_device *device)
-{
-	thermometer_unregister(device);
-}
-
-static struct btd_device_driver thermometer_device_driver = {
-	.name	= "thermometer-device-driver",
-	.uuids	= BTD_UUIDS(HEALTH_THERMOMETER_UUID),
-	.probe	= thermometer_driver_probe,
-	.remove	= thermometer_driver_remove
-};
-
-int thermometer_manager_init(DBusConnection *conn)
-{
-	int ret;
-
-	ret = btd_register_device_driver(&thermometer_device_driver);
-	if (ret < 0)
-                return ret;
-
-	connection = dbus_connection_ref(conn);
-	return 0;
-}
-
-void thermometer_manager_exit(void)
-{
-	btd_unregister_device_driver(&thermometer_device_driver);
-
-	dbus_connection_unref(connection);
-	connection = NULL;
-}
diff --git a/thermometer/manager.h b/thermometer/manager.h
deleted file mode 100644
index ed928ad..0000000
--- a/thermometer/manager.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- *  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
- *
- */
-
-int thermometer_manager_init(DBusConnection *conn);
-void thermometer_manager_exit(void);
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
deleted file mode 100644
index 087662e..0000000
--- a/thermometer/thermometer.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gdbus.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-
-#include "dbus-common.h"
-#include "adapter.h"
-#include "device.h"
-#include "error.h"
-#include "log.h"
-#include "gattrib.h"
-#include "attio.h"
-#include "att.h"
-#include "gatt.h"
-#include "thermometer.h"
-
-#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
-
-/* Temperature measurement flag fields */
-#define TEMP_UNITS		0x01
-#define TEMP_TIME_STAMP		0x02
-#define TEMP_TYPE		0x04
-
-#define FLOAT_MAX_MANTISSA	16777216 /* 2^24 */
-
-#define VALID_RANGE_DESC_SIZE	4
-#define TEMPERATURE_TYPE_SIZE	1
-#define MEASUREMENT_INTERVAL_SIZE	2
-
-struct thermometer {
-	DBusConnection		*conn;		/* The connection to the bus */
-	struct btd_device	*dev;		/* Device reference */
-	GAttrib			*attrib;	/* GATT connection */
-	struct att_range	*svc_range;	/* Thermometer range */
-	guint			attioid;	/* Att watcher id */
-	guint			attindid;	/* Att incications id */
-	guint			attnotid;	/* Att notifications id */
-	GSList			*chars;		/* Characteristics */
-	GSList			*fwatchers;     /* Final measurements */
-	GSList			*iwatchers;     /* Intermediate measurements */
-	gboolean		intermediate;
-	uint8_t			type;
-	uint16_t		interval;
-	uint16_t		max;
-	uint16_t		min;
-	gboolean		has_type;
-	gboolean		has_interval;
-};
-
-struct characteristic {
-	struct gatt_char		attr;	/* Characteristic */
-	GSList			*desc;	/* Descriptors */
-	struct thermometer	*t;	/* Thermometer where the char belongs */
-};
-
-struct descriptor {
-	struct characteristic	*ch;
-	uint16_t		handle;
-	bt_uuid_t		uuid;
-};
-
-struct watcher {
-	struct thermometer	*t;
-	guint			id;
-	char			*srv;
-	char			*path;
-};
-
-struct measurement {
-	int16_t		exp;
-	int32_t		mant;
-	uint64_t	time;
-	gboolean	suptime;
-	char		*unit;
-	char		*type;
-	char		*value;
-};
-
-struct tmp_interval_data {
-	struct thermometer	*thermometer;
-	uint16_t		interval;
-};
-
-static GSList *thermometers = NULL;
-
-const char *temp_type[] = {
-	"<reserved>",
-	"Armpit",
-	"Body",
-	"Ear",
-	"Finger",
-	"Intestines",
-	"Mouth",
-	"Rectum",
-	"Toe",
-	"Tympanum"
-};
-
-static const gchar *temptype2str(uint8_t value)
-{
-	 if (value > 0 && value < G_N_ELEMENTS(temp_type))
-		return temp_type[value];
-
-	error("Temperature type %d reserved for future use", value);
-	return NULL;
-}
-
-static void destroy_watcher(gpointer user_data)
-{
-	struct watcher *watcher = user_data;
-
-	g_free(watcher->path);
-	g_free(watcher->srv);
-	g_free(watcher);
-}
-
-static void remove_watcher(gpointer user_data)
-{
-	struct watcher *watcher = user_data;
-
-	g_dbus_remove_watch(watcher->t->conn, watcher->id);
-}
-
-static void destroy_char(gpointer user_data)
-{
-	struct characteristic *c = user_data;
-
-	g_slist_free_full(c->desc, g_free);
-	g_free(c);
-}
-
-static void destroy_thermometer(gpointer user_data)
-{
-	struct thermometer *t = user_data;
-
-	if (t->attioid > 0)
-		btd_device_remove_attio_callback(t->dev, t->attioid);
-
-	if (t->attindid > 0)
-		g_attrib_unregister(t->attrib, t->attindid);
-
-	if (t->attnotid > 0)
-		g_attrib_unregister(t->attrib, t->attnotid);
-
-	if (t->attrib != NULL)
-		g_attrib_unref(t->attrib);
-
-	if (t->chars != NULL)
-		g_slist_free_full(t->chars, destroy_char);
-
-	if (t->fwatchers != NULL)
-		g_slist_free_full(t->fwatchers, remove_watcher);
-
-	dbus_connection_unref(t->conn);
-	btd_device_unref(t->dev);
-	g_free(t->svc_range);
-	g_free(t);
-}
-
-static gint cmp_device(gconstpointer a, gconstpointer b)
-{
-	const struct thermometer *t = a;
-	const struct btd_device *dev = b;
-
-	if (dev == t->dev)
-		return 0;
-
-	return -1;
-}
-
-static gint cmp_watcher(gconstpointer a, gconstpointer b)
-{
-	const struct watcher *watcher = a;
-	const struct watcher *match = b;
-	int ret;
-
-	ret = g_strcmp0(watcher->srv, match->srv);
-	if (ret != 0)
-		return ret;
-
-	return g_strcmp0(watcher->path, match->path);
-}
-
-static gint cmp_char_uuid(gconstpointer a, gconstpointer b)
-{
-	const struct characteristic *ch = a;
-	const char *uuid = b;
-
-	return g_strcmp0(ch->attr.uuid, uuid);
-}
-
-static gint cmp_char_val_handle(gconstpointer a, gconstpointer b)
-{
-	const struct characteristic *ch = a;
-	const uint16_t *handle = b;
-
-	return ch->attr.value_handle - *handle;
-}
-
-static gint cmp_descriptor(gconstpointer a, gconstpointer b)
-{
-	const struct descriptor *desc = a;
-	const bt_uuid_t *uuid = b;
-
-	return bt_uuid_cmp(&desc->uuid, uuid);
-}
-
-static struct characteristic *get_characteristic(struct thermometer *t,
-							const char *uuid)
-{
-	GSList *l;
-
-	l = g_slist_find_custom(t->chars, uuid, cmp_char_uuid);
-	if (l == NULL)
-		return NULL;
-
-	return l->data;
-}
-
-static struct descriptor *get_descriptor(struct characteristic *ch,
-							const bt_uuid_t *uuid)
-{
-	GSList *l;
-
-	l = g_slist_find_custom(ch->desc, uuid, cmp_descriptor);
-	if (l == NULL)
-		return NULL;
-
-	return l->data;
-}
-
-static void change_property(struct thermometer *t, const char *name,
-							gpointer value) {
-	if (g_strcmp0(name, "Intermediate") == 0) {
-		gboolean *intermediate = value;
-		if (t->intermediate == *intermediate)
-			return;
-
-		t->intermediate = *intermediate;
-		emit_property_changed(t->conn, device_get_path(t->dev),
-					THERMOMETER_INTERFACE, name,
-					DBUS_TYPE_BOOLEAN, &t->intermediate);
-	} else if (g_strcmp0(name, "Interval") == 0) {
-		uint16_t *interval = value;
-		if (t->has_interval && t->interval == *interval)
-			return;
-
-		t->has_interval = TRUE;
-		t->interval = *interval;
-		emit_property_changed(t->conn, device_get_path(t->dev),
-					THERMOMETER_INTERFACE, name,
-					DBUS_TYPE_UINT16, &t->interval);
-	} else if (g_strcmp0(name, "Maximum") == 0) {
-		uint16_t *max = value;
-		if (t->max == *max)
-			return;
-
-		t->max = *max;
-		emit_property_changed(t->conn, device_get_path(t->dev),
-					THERMOMETER_INTERFACE, name,
-					DBUS_TYPE_UINT16, &t->max);
-	} else if (g_strcmp0(name, "Minimum") == 0) {
-		uint16_t *min = value;
-		if (t->min == *min)
-			return;
-
-		t->min = *min;
-		emit_property_changed(t->conn, device_get_path(t->dev),
-					THERMOMETER_INTERFACE, name,
-					DBUS_TYPE_UINT16, &t->min);
-	} else
-		DBG("%s is not a thermometer property", name);
-}
-
-static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
-							gpointer user_data)
-{
-	struct descriptor *desc = user_data;
-	uint8_t value[VALID_RANGE_DESC_SIZE];
-	uint16_t max, min;
-	ssize_t vlen;
-
-	if (status != 0) {
-		DBG("Valid Range descriptor read failed: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	vlen = dec_read_resp(pdu, len, value, sizeof(value));
-	if (vlen < 0) {
-		DBG("Protocol error\n");
-		return;
-	}
-
-	if (vlen < 4) {
-		DBG("Invalid range received");
-		return;
-	}
-
-	min = att_get_u16(&value[0]);
-	max = att_get_u16(&value[2]);
-
-	if (min == 0 || min > max) {
-		DBG("Invalid range");
-		return;
-	}
-
-	change_property(desc->ch->t, "Maximum", &max);
-	change_property(desc->ch->t, "Minimum", &min);
-}
-
-static void measurement_cb(guint8 status, const guint8 *pdu,
-						guint16 len, gpointer user_data)
-{
-	char *msg = user_data;
-
-	if (status != 0)
-		error("%s failed", msg);
-
-	g_free(msg);
-}
-
-static void process_thermometer_desc(struct descriptor *desc)
-{
-	struct characteristic *ch = desc->ch;
-	char uuidstr[MAX_LEN_UUID_STR];
-	bt_uuid_t btuuid;
-
-	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
-
-	if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
-		uint8_t atval[2];
-		uint16_t val;
-		char *msg;
-
-		if (g_strcmp0(ch->attr.uuid,
-					TEMPERATURE_MEASUREMENT_UUID) == 0) {
-			if (g_slist_length(ch->t->fwatchers) == 0)
-				return;
-
-			val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
-			msg = g_strdup("Enable Temperature Measurement "
-								"indication");
-		} else if (g_strcmp0(ch->attr.uuid,
-					INTERMEDIATE_TEMPERATURE_UUID) == 0) {
-			if (g_slist_length(ch->t->iwatchers) == 0)
-				return;
-
-			val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
-			msg = g_strdup("Enable Intermediate Temperature "
-								"notification");
-		} else if (g_strcmp0(ch->attr.uuid,
-					MEASUREMENT_INTERVAL_UUID) == 0) {
-			val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
-			msg = g_strdup("Enable Measurement Interval "
-								"indication");
-		} else
-			goto done;
-
-		att_put_u16(val, atval);
-		gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
-							measurement_cb, msg);
-		return;
-	}
-
-	bt_uuid16_create(&btuuid, GATT_CHARAC_VALID_RANGE_UUID);
-
-	if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0 && g_strcmp0(ch->attr.uuid,
-					MEASUREMENT_INTERVAL_UUID) == 0) {
-		gatt_read_char(ch->t->attrib, desc->handle, 0,
-						valid_range_desc_cb, desc);
-		return;
-	}
-
-done:
-	bt_uuid_to_string(&desc->uuid, uuidstr, MAX_LEN_UUID_STR);
-	DBG("Ignored descriptor %s in characteristic %s", uuidstr,
-								ch->attr.uuid);
-}
-
-static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
-							gpointer user_data)
-{
-	struct characteristic *ch = user_data;
-	struct att_data_list *list;
-	uint8_t format;
-	int i;
-
-	if (status != 0) {
-		error("Discover all characteristic descriptors failed [%s]: %s",
-					ch->attr.uuid, att_ecode2str(status));
-		return;
-	}
-
-	list = dec_find_info_resp(pdu, len, &format);
-	if (list == NULL)
-		return;
-
-	for (i = 0; i < list->num; i++) {
-		struct descriptor *desc;
-		uint8_t *value;
-
-		value = list->data[i];
-		desc = g_new0(struct descriptor, 1);
-		desc->handle = att_get_u16(value);
-		desc->ch = ch;
-
-		if (format == 0x01)
-			desc->uuid = att_get_uuid16(&value[2]);
-		else
-			desc->uuid = att_get_uuid128(&value[2]);
-
-		ch->desc = g_slist_append(ch->desc, desc);
-		process_thermometer_desc(desc);
-	}
-
-	att_data_list_free(list);
-}
-
-static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
-							gpointer user_data)
-{
-	struct characteristic *ch = user_data;
-	struct thermometer *t = ch->t;
-	uint8_t value[TEMPERATURE_TYPE_SIZE];
-	ssize_t vlen;
-
-	if (status != 0) {
-		DBG("Temperature Type value read failed: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	vlen = dec_read_resp(pdu, len, value, sizeof(value));
-	if (vlen < 0) {
-		DBG("Protocol error.");
-		return;
-	}
-
-	if (vlen != 1) {
-		DBG("Invalid length for Temperature type");
-		return;
-	}
-
-	t->has_type = TRUE;
-	t->type = value[0];
-}
-
-static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
-							gpointer user_data)
-{
-	struct characteristic *ch = user_data;
-	uint8_t value[MEASUREMENT_INTERVAL_SIZE];
-	uint16_t interval;
-	ssize_t vlen;
-
-	if (status != 0) {
-		DBG("Measurement Interval value read failed: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	vlen = dec_read_resp(pdu, len, value, sizeof(value));
-	if (vlen < 0) {
-		DBG("Protocol error\n");
-		return;
-	}
-
-	if (vlen < 2) {
-		DBG("Invalid Interval received");
-		return;
-	}
-
-	interval = att_get_u16(&value[0]);
-	change_property(ch->t, "Interval", &interval);
-}
-
-static void process_thermometer_char(struct characteristic *ch)
-{
-	if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
-		gboolean intermediate = TRUE;
-		change_property(ch->t, "Intermediate", &intermediate);
-		return;
-	} else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
-		gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
-							read_temp_type_cb, ch);
-	else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
-		gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
-							read_interval_cb, ch);
-}
-
-static void configure_thermometer_cb(GSList *characteristics, guint8 status,
-							gpointer user_data)
-{
-	struct thermometer *t = user_data;
-	GSList *l;
-
-	if (status != 0) {
-		error("Discover thermometer characteristics: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	for (l = characteristics; l; l = l->next) {
-		struct gatt_char *c = l->data;
-		struct characteristic *ch;
-		uint16_t start, end;
-
-		ch = g_new0(struct characteristic, 1);
-		ch->attr.handle = c->handle;
-		ch->attr.properties = c->properties;
-		ch->attr.value_handle = c->value_handle;
-		memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
-		ch->t = t;
-
-		t->chars = g_slist_append(t->chars, ch);
-
-		process_thermometer_char(ch);
-
-		start = c->value_handle + 1;
-
-		if (l->next != NULL) {
-			struct gatt_char *c = l->next->data;
-			if (start == c->handle)
-				continue;
-			end = c->handle - 1;
-		} else if (c->value_handle != t->svc_range->end)
-			end = t->svc_range->end;
-		else
-			continue;
-
-		gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
-	}
-}
-
-static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	struct thermometer *t = data;
-	DBusMessageIter iter;
-	DBusMessageIter dict;
-	DBusMessage *reply;
-
-	reply = dbus_message_new_method_return(msg);
-	if (reply == NULL)
-		return NULL;
-
-	dbus_message_iter_init_append(reply, &iter);
-
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-	dict_append_entry(&dict, "Intermediate", DBUS_TYPE_BOOLEAN,
-							&t->intermediate);
-
-	if (t->has_interval) {
-		dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT16,
-								&t->interval);
-		dict_append_entry(&dict, "Maximum", DBUS_TYPE_UINT16, &t->max);
-		dict_append_entry(&dict, "Minimum", DBUS_TYPE_UINT16, &t->min);
-	}
-
-	dbus_message_iter_close_container(&iter, &dict);
-
-	return reply;
-}
-
-static void write_interval_cb (guint8 status, const guint8 *pdu, guint16 len,
-							gpointer user_data)
-{
-	struct tmp_interval_data *data = user_data;
-
-	if (status != 0) {
-		error("Interval Write Request failed %s",
-							att_ecode2str(status));
-		goto done;
-	}
-
-	if (!dec_write_resp(pdu, len)) {
-		error("Interval Write Request: protocol error");
-		goto done;
-	}
-
-	change_property(data->thermometer, "Interval", &data->interval);
-
-done:
-	g_free(user_data);
-}
-
-static DBusMessage *write_attr_interval(struct thermometer *t, DBusMessage *msg,
-								uint16_t value)
-{
-	struct tmp_interval_data *data;
-	struct characteristic *ch;
-	uint8_t atval[2];
-
-	if (t->attrib == NULL)
-		return btd_error_not_connected(msg);
-
-	ch = get_characteristic(t, MEASUREMENT_INTERVAL_UUID);
-	if (ch == NULL)
-		return btd_error_not_available(msg);
-
-	if (value < t->min || value > t->max)
-		return btd_error_invalid_args(msg);
-
-	att_put_u16(value, &atval[0]);
-
-	data = g_new0(struct tmp_interval_data, 1);
-	data->thermometer = t;
-	data->interval = value;
-	gatt_write_char(t->attrib, ch->attr.value_handle, atval, 2,
-						write_interval_cb, data);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	struct thermometer *t = data;
-	const char *property;
-	DBusMessageIter iter;
-	DBusMessageIter sub;
-	uint16_t value;
-
-	if (!dbus_message_iter_init(msg, &iter))
-		return btd_error_invalid_args(msg);
-
-	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-		return btd_error_invalid_args(msg);
-
-	dbus_message_iter_get_basic(&iter, &property);
-	if (g_strcmp0("Interval", property) != 0)
-		return btd_error_invalid_args(msg);
-
-	if (!t->has_interval)
-		return btd_error_not_available(msg);
-
-	dbus_message_iter_next(&iter);
-	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
-		return btd_error_invalid_args(msg);
-
-	dbus_message_iter_recurse(&iter, &sub);
-
-	if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_UINT16)
-		return btd_error_invalid_args(msg);
-
-	dbus_message_iter_get_basic(&sub, &value);
-
-	return write_attr_interval(t, msg, value);
-}
-
-static void enable_final_measurement(struct thermometer *t)
-{
-	struct characteristic *ch;
-	struct descriptor *desc;
-	bt_uuid_t btuuid;
-	uint8_t atval[2];
-	char *msg;
-
-	if (t->attrib == NULL)
-		return;
-
-	ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
-	if (ch == NULL) {
-		DBG("Temperature measurement characteristic not found");
-		return;
-	}
-
-	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
-	desc = get_descriptor(ch, &btuuid);
-	if (desc == NULL) {
-		DBG("Client characteristic configuration descriptor not found");
-		return;
-	}
-
-	atval[0] = 0x02;
-	atval[1] = 0x00;
-	msg = g_strdup("Enable final measurement");
-	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void enable_intermediate_measurement(struct thermometer *t)
-{
-	struct characteristic *ch;
-	struct descriptor *desc;
-	bt_uuid_t btuuid;
-	uint8_t atval[2];
-	char *msg;
-
-	if (t->attrib == NULL)
-		return;
-
-	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
-	if (ch == NULL) {
-		DBG("Intermediate measurement characteristic not found");
-		return;
-	}
-
-	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
-	desc = get_descriptor(ch, &btuuid);
-	if (desc == NULL) {
-		DBG("Client characteristic configuration descriptor not found");
-		return;
-	}
-
-	atval[0] = 0x01;
-	atval[1] = 0x00;
-	msg = g_strdup("Enable intermediate measurement");
-	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void disable_final_measurement(struct thermometer *t)
-{
-	struct characteristic *ch;
-	struct descriptor *desc;
-	bt_uuid_t btuuid;
-	uint8_t atval[2];
-	char *msg;
-
-	if (t->attrib == NULL)
-		return;
-
-	ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
-	if (ch == NULL) {
-		DBG("Temperature measurement characteristic not found");
-		return;
-	}
-
-	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
-	desc = get_descriptor(ch, &btuuid);
-	if (desc == NULL) {
-		DBG("Client characteristic configuration descriptor not found");
-		return;
-	}
-
-	atval[0] = 0x00;
-	atval[1] = 0x00;
-	msg = g_strdup("Disable final measurement");
-	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void disable_intermediate_measurement(struct thermometer *t)
-{
-	struct characteristic *ch;
-	struct descriptor *desc;
-	bt_uuid_t btuuid;
-	uint8_t atval[2];
-	char *msg;
-
-	if (t->attrib == NULL)
-		return;
-
-	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
-	if (ch == NULL) {
-		DBG("Intermediate measurement characteristic not found");
-		return;
-	}
-
-	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
-	desc = get_descriptor(ch, &btuuid);
-	if (desc == NULL) {
-		DBG("Client characteristic configuration descriptor not found");
-		return;
-	}
-
-	atval[0] = 0x00;
-	atval[1] = 0x00;
-	msg = g_strdup("Disable intermediate measurement");
-	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void remove_int_watcher(struct thermometer *t, struct watcher *w)
-{
-	if (!g_slist_find(t->iwatchers, w))
-		return;
-
-	t->iwatchers = g_slist_remove(t->iwatchers, w);
-
-	if (g_slist_length(t->iwatchers) == 0)
-		disable_intermediate_measurement(t);
-}
-
-static void watcher_exit(DBusConnection *conn, void *user_data)
-{
-	struct watcher *watcher = user_data;
-	struct thermometer *t = watcher->t;
-
-	DBG("Thermometer watcher %s disconnected", watcher->path);
-
-	remove_int_watcher(t, watcher);
-
-	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
-	g_dbus_remove_watch(watcher->t->conn, watcher->id);
-
-	if (g_slist_length(t->fwatchers) == 0)
-		disable_final_measurement(t);
-}
-
-static struct watcher *find_watcher(GSList *list, const char *sender,
-							const char *path)
-{
-	struct watcher *match;
-	GSList *l;
-
-	match = g_new0(struct watcher, 1);
-	match->srv = g_strdup(sender);
-	match->path = g_strdup(path);
-
-	l = g_slist_find_custom(list, match, cmp_watcher);
-	destroy_watcher(match);
-
-	if (l != NULL)
-		return l->data;
-
-	return NULL;
-}
-
-static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	const char *sender = dbus_message_get_sender(msg);
-	struct thermometer *t = data;
-	struct watcher *watcher;
-	char *path;
-
-	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
-							DBUS_TYPE_INVALID))
-		return btd_error_invalid_args(msg);
-
-	watcher = find_watcher(t->fwatchers, sender, path);
-	if (watcher != NULL)
-		return btd_error_already_exists(msg);
-
-	DBG("Thermometer watcher %s registered", path);
-
-	watcher = g_new0(struct watcher, 1);
-	watcher->srv = g_strdup(sender);
-	watcher->path = g_strdup(path);
-	watcher->t = t;
-	watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
-						watcher, destroy_watcher);
-
-	if (g_slist_length(t->fwatchers) == 0)
-		enable_final_measurement(t);
-
-	t->fwatchers = g_slist_prepend(t->fwatchers, watcher);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	const char *sender = dbus_message_get_sender(msg);
-	struct thermometer *t = data;
-	struct watcher *watcher;
-	char *path;
-
-	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
-							DBUS_TYPE_INVALID))
-		return btd_error_invalid_args(msg);
-
-	watcher = find_watcher(t->fwatchers, sender, path);
-	if (watcher == NULL)
-		return btd_error_does_not_exist(msg);
-
-	DBG("Thermometer watcher %s unregistered", path);
-
-	remove_int_watcher(t, watcher);
-
-	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
-	g_dbus_remove_watch(watcher->t->conn, watcher->id);
-
-	if (g_slist_length(t->fwatchers) == 0)
-		disable_final_measurement(t);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	const char *sender = dbus_message_get_sender(msg);
-	struct thermometer *t = data;
-	struct watcher *watcher;
-	char *path;
-
-	if (!t->intermediate)
-		return btd_error_not_supported(msg);
-
-	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
-							DBUS_TYPE_INVALID))
-		return btd_error_invalid_args(msg);
-
-	watcher = find_watcher(t->fwatchers, sender, path);
-	if (watcher == NULL)
-		return btd_error_does_not_exist(msg);
-
-	if (find_watcher(t->iwatchers, sender, path))
-		return btd_error_already_exists(msg);
-
-	DBG("Intermediate measurement watcher %s registered", path);
-
-	if (g_slist_length(t->iwatchers) == 0)
-		enable_intermediate_measurement(t);
-
-	t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
-								void *data)
-{
-	const char *sender = dbus_message_get_sender(msg);
-	struct thermometer *t = data;
-	struct watcher *watcher;
-	char *path;
-
-	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
-							DBUS_TYPE_INVALID))
-		return btd_error_invalid_args(msg);
-
-	watcher = find_watcher(t->iwatchers, sender, path);
-	if (watcher == NULL)
-		return btd_error_does_not_exist(msg);
-
-	DBG("Intermediate measurement %s unregistered", path);
-
-	remove_int_watcher(t, watcher);
-
-	return dbus_message_new_method_return(msg);
-}
-
-static const GDBusMethodTable thermometer_methods[] = {
-	{ GDBUS_METHOD("GetProperties",
-			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-			get_properties) },
-	{ GDBUS_ASYNC_METHOD("SetProperty",
-			GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
-			set_property) },
-	{ GDBUS_METHOD("RegisterWatcher",
-			GDBUS_ARGS({ "agent", "o" }), NULL,
-			register_watcher) },
-	{ GDBUS_METHOD("UnregisterWatcher",
-			GDBUS_ARGS({ "agent", "o" }), NULL,
-			unregister_watcher) },
-	{ GDBUS_METHOD("EnableIntermediateMeasurement",
-			GDBUS_ARGS({ "agent", "o" }), NULL,
-			enable_intermediate) },
-	{ GDBUS_METHOD("DisableIntermediateMeasurement",
-			GDBUS_ARGS({ "agent", "o" }), NULL,
-			disable_intermediate) },
-	{ }
-};
-
-static const GDBusSignalTable thermometer_signals[] = {
-	{ GDBUS_SIGNAL("PropertyChanged",
-			GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
-	{ }
-};
-
-static void update_watcher(gpointer data, gpointer user_data)
-{
-	struct watcher *w = data;
-	struct measurement *m = user_data;
-	DBusConnection *conn = w->t->conn;
-	DBusMessageIter iter;
-	DBusMessageIter dict;
-	DBusMessage *msg;
-
-	msg = dbus_message_new_method_call(w->srv, w->path,
-				"org.bluez.ThermometerWatcher",
-				"MeasurementReceived");
-	if (msg == NULL)
-		return;
-
-	dbus_message_iter_init_append(msg, &iter);
-
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-	dict_append_entry(&dict, "Exponent", DBUS_TYPE_INT16, &m->exp);
-	dict_append_entry(&dict, "Mantissa", DBUS_TYPE_INT32, &m->mant);
-	dict_append_entry(&dict, "Unit", DBUS_TYPE_STRING, &m->unit);
-
-	if (m->suptime)
-		dict_append_entry(&dict, "Time", DBUS_TYPE_UINT64, &m->time);
-
-	dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &m->type);
-	dict_append_entry(&dict, "Measurement", DBUS_TYPE_STRING, &m->value);
-
-	dbus_message_iter_close_container(&iter, &dict);
-
-	dbus_message_set_no_reply(msg, TRUE);
-	g_dbus_send_message(conn, msg);
-}
-
-static void recv_measurement(struct thermometer *t, struct measurement *m)
-{
-	GSList *wlist;
-
-	if (g_strcmp0(m->value, "Intermediate") == 0)
-		wlist = t->iwatchers;
-	else
-		wlist = t->fwatchers;
-
-	g_slist_foreach(wlist, update_watcher, m);
-}
-
-static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
-						uint16_t len, gboolean final)
-{
-	struct measurement m;
-	const char *type;
-	uint8_t flags;
-	uint32_t raw;
-
-	if (len < 4) {
-		DBG("Mandatory flags are not provided");
-		return;
-	}
-
-	flags = pdu[3];
-	if (flags & TEMP_UNITS)
-		m.unit = "Fahrenheit";
-	else
-		m.unit = "Celsius";
-
-	if (len < 8) {
-		DBG("Temperature measurement value is not provided");
-		return;
-	}
-
-	raw = att_get_u32(&pdu[4]);
-	m.mant = raw & 0x00FFFFFF;
-	m.exp = ((int32_t) raw) >> 24;
-
-	if (m.mant & 0x00800000) {
-		/* convert to C2 negative value */
-		m.mant = m.mant - FLOAT_MAX_MANTISSA;
-	}
-
-	if (flags & TEMP_TIME_STAMP) {
-		struct tm ts;
-		time_t time;
-
-		if (len < 15) {
-			DBG("Can't get time stamp value");
-			return;
-		}
-
-		ts.tm_year = att_get_u16(&pdu[8]) - 1900;
-		ts.tm_mon = pdu[10] - 1;
-		ts.tm_mday = pdu[11];
-		ts.tm_hour = pdu[12];
-		ts.tm_min = pdu[13];
-		ts.tm_sec = pdu[14];
-		ts.tm_isdst = -1;
-
-		time = mktime(&ts);
-		m.time = (uint64_t) time;
-		m.suptime = TRUE;
-	} else
-		m.suptime = FALSE;
-
-	if (flags & TEMP_TYPE) {
-		uint8_t index;
-
-		if (m.suptime && len >= 16)
-			index = 15;
-		else if (!m.suptime && len >= 9)
-			index = 9;
-		else {
-			DBG("Can't get temperature type");
-			return;
-		}
-
-		type = temptype2str(pdu[index]);
-	} else if (t->has_type)
-		type = temptype2str(t->type);
-	else
-		type = NULL;
-
-	m.type = type ? g_strdup(type) : NULL;
-	m.value = final ? "Final" : "Intermediate";
-
-	recv_measurement(t, &m);
-	g_free(m.type);
-}
-
-static void proc_measurement_interval(struct thermometer *t, const uint8_t *pdu,
-								uint16_t len)
-{
-	uint16_t interval;
-
-	if (len < 5) {
-		DBG("Measurement interval value is not provided");
-		return;
-	}
-
-	interval = att_get_u16(&pdu[3]);
-
-	change_property(t, "Interval", &interval);
-}
-
-static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
-{
-	struct thermometer *t = user_data;
-	const struct characteristic *ch;
-	uint8_t *opdu;
-	uint16_t handle, olen;
-	GSList *l;
-	int plen;
-
-	if (len < 3) {
-		DBG("Bad pdu received");
-		return;
-	}
-
-	handle = att_get_u16(&pdu[1]);
-	l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
-	if (l == NULL) {
-		DBG("Unexpected handle: 0x%04x", handle);
-		return;
-	}
-
-	ch = l->data;
-
-	if (g_strcmp0(ch->attr.uuid, TEMPERATURE_MEASUREMENT_UUID) == 0)
-		proc_measurement(t, pdu, len, TRUE);
-	else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
-		proc_measurement_interval(t, pdu, len);
-
-	opdu = g_attrib_get_buffer(t->attrib, &plen);
-	olen = enc_confirmation(opdu, plen);
-
-	if (olen > 0)
-		g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
-									NULL);
-}
-
-static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
-{
-	struct thermometer *t = user_data;
-	const struct characteristic *ch;
-	uint16_t handle;
-	GSList *l;
-
-	if (len < 3) {
-		DBG("Bad pdu received");
-		return;
-	}
-
-	handle = att_get_u16(&pdu[1]);
-	l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
-	if (l == NULL) {
-		DBG("Unexpected handle: 0x%04x", handle);
-		return;
-	}
-
-	ch = l->data;
-	if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0)
-		proc_measurement(t, pdu, len, FALSE);
-}
-
-static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
-{
-	struct thermometer *t = user_data;
-
-	t->attrib = g_attrib_ref(attrib);
-
-	t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
-							ind_handler, t, NULL);
-	t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
-							notif_handler, t, NULL);
-	gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
-					NULL, configure_thermometer_cb, t);
-}
-
-static void attio_disconnected_cb(gpointer user_data)
-{
-	struct thermometer *t = user_data;
-
-	DBG("GATT Disconnected");
-
-	if (t->attindid > 0) {
-		g_attrib_unregister(t->attrib, t->attindid);
-		t->attindid = 0;
-	}
-
-	if (t->attnotid > 0) {
-		g_attrib_unregister(t->attrib, t->attnotid);
-		t->attnotid = 0;
-	}
-
-	g_attrib_unref(t->attrib);
-	t->attrib = NULL;
-}
-
-int thermometer_register(DBusConnection *connection, struct btd_device *device,
-						struct gatt_primary *tattr)
-{
-	const gchar *path = device_get_path(device);
-	struct thermometer *t;
-
-	t = g_new0(struct thermometer, 1);
-	t->conn = dbus_connection_ref(connection);
-	t->dev = btd_device_ref(device);
-	t->svc_range = g_new0(struct att_range, 1);
-	t->svc_range->start = tattr->range.start;
-	t->svc_range->end = tattr->range.end;
-
-	if (!g_dbus_register_interface(t->conn, path, THERMOMETER_INTERFACE,
-				thermometer_methods, thermometer_signals,
-				NULL, t, destroy_thermometer)) {
-		error("D-Bus failed to register %s interface",
-							THERMOMETER_INTERFACE);
-		destroy_thermometer(t);
-		return -EIO;
-	}
-
-	thermometers = g_slist_prepend(thermometers, t);
-
-	t->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
-						attio_disconnected_cb, t);
-	return 0;
-}
-
-void thermometer_unregister(struct btd_device *device)
-{
-	struct thermometer *t;
-	GSList *l;
-
-	l = g_slist_find_custom(thermometers, device, cmp_device);
-	if (l == NULL)
-		return;
-
-	t = l->data;
-	thermometers = g_slist_remove(thermometers, t);
-	g_dbus_unregister_interface(t->conn, device_get_path(t->dev),
-							THERMOMETER_INTERFACE);
-}
diff --git a/thermometer/thermometer.h b/thermometer/thermometer.h
deleted file mode 100644
index 330503c..0000000
--- a/thermometer/thermometer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- *  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
- *
- */
-
-int thermometer_register(DBusConnection *connection, struct btd_device *device,
-						struct gatt_primary *tattr);
-void thermometer_unregister(struct btd_device *device);
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 08/14] time: move to the profiles folder
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
                   ` (4 preceding siblings ...)
  2012-07-09 21:10 ` [PATCH 07/14] thermometer: move to the " Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 12/14] cups: move it to " Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 14/14] plugins: remove unmaintained plugins Gustavo Padovan
  7 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 Makefile.am             |    5 +-
 profiles/time/main.c    |   58 ++++++++++++
 profiles/time/manager.c |   49 ++++++++++
 profiles/time/manager.h |   26 ++++++
 profiles/time/server.c  |  234 +++++++++++++++++++++++++++++++++++++++++++++++
 profiles/time/server.h  |   45 +++++++++
 time/main.c             |   58 ------------
 time/manager.c          |   49 ----------
 time/manager.h          |   26 ------
 time/server.c           |  234 -----------------------------------------------
 time/server.h           |   45 ---------
 11 files changed, 415 insertions(+), 414 deletions(-)
 create mode 100644 profiles/time/main.c
 create mode 100644 profiles/time/manager.c
 create mode 100644 profiles/time/manager.h
 create mode 100644 profiles/time/server.c
 create mode 100644 profiles/time/server.h
 delete mode 100644 time/main.c
 delete mode 100644 time/manager.c
 delete mode 100644 time/manager.h
 delete mode 100644 time/server.c
 delete mode 100644 time/server.h

diff --git a/Makefile.am b/Makefile.am
index c8b2475..7e23f5f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -222,8 +222,9 @@ builtin_sources += profiles/thermometer/main.c \
 		       	profiles/thermometer/thermometer.c \
 			profiles/alert/main.c profiles/alert/server.h \
 			profiles/alert/server.c \
-			time/main.c time/server.h time/server.c \
-			time/manager.h time/manager.c \
+			profiles/time/main.c profiles/time/server.h \
+			profiles/time/server.c profiles/time/manager.c \
+			profiles/time/manager.h \
 			plugins/gatt-example.c \
 			profiles/proximity/main.c profiles/proximity/manager.h \
 		       	profiles/proximity/manager.c \
diff --git a/profiles/time/main.c b/profiles/time/main.c
new file mode 100644
index 0000000..9ef5bf1
--- /dev/null
+++ b/profiles/time/main.c
@@ -0,0 +1,58 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  Nokia Corporation
+ *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+
+#include "plugin.h"
+#include "hcid.h"
+#include "log.h"
+#include "manager.h"
+
+static int time_init(void)
+{
+	if (!main_opts.gatt_enabled) {
+		DBG("GATT is disabled");
+		return -ENOTSUP;
+	}
+
+	return time_manager_init();
+}
+
+static void time_exit(void)
+{
+	if (!main_opts.gatt_enabled)
+		return;
+
+	time_manager_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(time, VERSION,
+			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+			time_init, time_exit)
diff --git a/profiles/time/manager.c b/profiles/time/manager.c
new file mode 100644
index 0000000..285c7b1
--- /dev/null
+++ b/profiles/time/manager.c
@@ -0,0 +1,49 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nokia Corporation
+ *  Copyright (C) 2012  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "adapter.h"
+#include "manager.h"
+#include "server.h"
+
+struct btd_adapter_driver time_server_driver = {
+	.name = "gatt-time-server",
+	.probe = time_server_init,
+	.remove = time_server_exit,
+};
+
+int time_manager_init(void)
+{
+	btd_register_adapter_driver(&time_server_driver);
+
+	return 0;
+}
+
+void time_manager_exit(void)
+{
+	btd_unregister_adapter_driver(&time_server_driver);
+}
diff --git a/profiles/time/manager.h b/profiles/time/manager.h
new file mode 100644
index 0000000..74641d6
--- /dev/null
+++ b/profiles/time/manager.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nokia Corporation
+ *  Copyright (C) 2012  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+int time_manager_init(void);
+void time_manager_exit(void);
diff --git a/profiles/time/server.c b/profiles/time/server.c
new file mode 100644
index 0000000..be6e196
--- /dev/null
+++ b/profiles/time/server.c
@@ -0,0 +1,234 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  Nokia Corporation
+ *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <time.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+#include <adapter.h>
+
+#include "gattrib.h"
+#include "att.h"
+#include "gatt.h"
+#include "att-database.h"
+#include "attrib-server.h"
+#include "gatt-service.h"
+#include "log.h"
+#include "server.h"
+
+#define CURRENT_TIME_SVC_UUID		0x1805
+#define REF_TIME_UPDATE_SVC_UUID	0x1806
+
+#define LOCAL_TIME_INFO_CHR_UUID	0x2A0F
+#define TIME_UPDATE_CTRL_CHR_UUID	0x2A16
+#define TIME_UPDATE_STAT_CHR_UUID	0x2A17
+#define CT_TIME_CHR_UUID		0x2A2B
+
+static int encode_current_time(uint8_t value[10])
+{
+	struct timespec tp;
+	struct tm tm;
+
+	if (clock_gettime(CLOCK_REALTIME, &tp) == -1) {
+		int err = -errno;
+
+		error("clock_gettime: %s", strerror(-err));
+		return err;
+	}
+
+	if (localtime_r(&tp.tv_sec, &tm) == NULL) {
+		error("localtime_r() failed");
+		/* localtime_r() does not set errno */
+		return -EINVAL;
+	}
+
+	att_put_u16(1900 + tm.tm_year, &value[0]); /* Year */
+	value[2] = tm.tm_mon + 1; /* Month */
+	value[3] = tm.tm_mday; /* Day */
+	value[4] = tm.tm_hour; /* Hours */
+	value[5] = tm.tm_min; /* Minutes */
+	value[6] = tm.tm_sec; /* Seconds */
+	value[7] = tm.tm_wday == 0 ? 7 : tm.tm_wday; /* Day of Week */
+	/* From Time Profile spec: "The number of 1/256 fractions of a second."
+	 * In 1s there are 256 fractions, in 1ns there are 256/10^9 fractions.
+	 * To avoid integer overflow, we use the equivalent 1/3906250 ratio. */
+	value[8] = tp.tv_nsec / 3906250; /* Fractions256 */
+	value[9] = 0x00; /* Adjust Reason */
+
+	return 0;
+}
+
+static uint8_t current_time_read(struct attribute *a,
+				 struct btd_device *device, gpointer user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	uint8_t value[10];
+
+	if (encode_current_time(value) < 0)
+		return ATT_ECODE_IO;
+
+	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+
+	return 0;
+}
+
+static uint8_t local_time_info_read(struct attribute *a,
+				struct btd_device *device, gpointer user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	uint8_t value[2];
+
+	DBG("a=%p", a);
+
+	tzset();
+
+	/* FIXME: POSIX "daylight" variable only indicates whether there is DST
+	 * for the local time or not. The offset is unknown. */
+	value[0] = daylight ? 0xff : 0x00;
+
+	/* Convert POSIX "timezone" (seconds West of GMT) to Time Profile
+	 * format (offset from UTC in number of 15 minutes increments). */
+	value[1] = (uint8_t) (-1 * timezone / (60 * 15));
+
+	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+
+	return 0;
+}
+
+static gboolean register_current_time_service(struct btd_adapter *adapter)
+{
+	bt_uuid_t uuid;
+
+	bt_uuid16_create(&uuid, CURRENT_TIME_SVC_UUID);
+
+	/* Current Time service */
+	return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+				/* CT Time characteristic */
+				GATT_OPT_CHR_UUID, CT_TIME_CHR_UUID,
+				GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ |
+							ATT_CHAR_PROPER_NOTIFY,
+				GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+						current_time_read, adapter,
+
+				/* Local Time Information characteristic */
+				GATT_OPT_CHR_UUID, LOCAL_TIME_INFO_CHR_UUID,
+				GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
+				GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+						local_time_info_read, adapter,
+
+				GATT_OPT_INVALID);
+}
+
+static uint8_t time_update_control(struct attribute *a,
+						struct btd_device *device,
+						gpointer user_data)
+{
+	DBG("handle 0x%04x", a->handle);
+
+	if (a->len != 1)
+		DBG("Invalid control point value size: %d", a->len);
+
+	switch (a->data[0]) {
+	case GET_REFERENCE_UPDATE:
+		DBG("Get Reference Update");
+		break;
+	case CANCEL_REFERENCE_UPDATE:
+		DBG("Cancel Reference Update");
+		break;
+	default:
+		DBG("Unknown command: 0x%02x", a->data[0]);
+	}
+
+	return 0;
+}
+
+static uint8_t time_update_status(struct attribute *a,
+						struct btd_device *device,
+						gpointer user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	uint8_t value[2];
+
+	DBG("handle 0x%04x", a->handle);
+
+	value[0] = UPDATE_STATE_IDLE;
+	value[1] = UPDATE_RESULT_SUCCESSFUL;
+	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+
+	return 0;
+}
+
+static gboolean register_ref_time_update_service(struct btd_adapter *adapter)
+{
+	bt_uuid_t uuid;
+
+	bt_uuid16_create(&uuid, REF_TIME_UPDATE_SVC_UUID);
+
+	/* Reference Time Update service */
+	return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+				/* Time Update control point */
+				GATT_OPT_CHR_UUID, TIME_UPDATE_CTRL_CHR_UUID,
+				GATT_OPT_CHR_PROPS,
+					ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
+				GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
+						time_update_control, adapter,
+
+				/* Time Update status */
+				GATT_OPT_CHR_UUID, TIME_UPDATE_STAT_CHR_UUID,
+				GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
+				GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+						time_update_status, adapter,
+
+				GATT_OPT_INVALID);
+}
+
+int time_server_init(struct btd_adapter *adapter)
+{
+	const char *path = adapter_get_path(adapter);
+
+	DBG("path %s", path);
+
+	if (!register_current_time_service(adapter)) {
+		error("Current Time Service could not be registered");
+		return -EIO;
+	}
+
+	if (!register_ref_time_update_service(adapter)) {
+		error("Reference Time Update Service could not be registered");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+void time_server_exit(struct btd_adapter *adapter)
+{
+	const char *path = adapter_get_path(adapter);
+
+	DBG("path %s", path);
+}
diff --git a/profiles/time/server.h b/profiles/time/server.h
new file mode 100644
index 0000000..c7b997d
--- /dev/null
+++ b/profiles/time/server.h
@@ -0,0 +1,45 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  Nokia Corporation
+ *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+enum {
+	UPDATE_RESULT_SUCCESSFUL = 0,
+	UPDATE_RESULT_CANCELED = 1,
+	UPDATE_RESULT_NO_CONN = 2,
+	UPDATE_RESULT_ERROR = 3,
+	UPDATE_RESULT_TIMEOUT = 4,
+	UPDATE_RESULT_NOT_ATTEMPTED = 5,
+};
+
+enum {
+	UPDATE_STATE_IDLE = 0,
+	UPDATE_STATE_PENDING = 1,
+};
+
+enum {
+	GET_REFERENCE_UPDATE = 1,
+	CANCEL_REFERENCE_UPDATE = 2,
+};
+
+int time_server_init(struct btd_adapter *adapter);
+void time_server_exit(struct btd_adapter *adapter);
diff --git a/time/main.c b/time/main.c
deleted file mode 100644
index 9ef5bf1..0000000
--- a/time/main.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011  Nokia Corporation
- *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-#include <errno.h>
-
-#include "plugin.h"
-#include "hcid.h"
-#include "log.h"
-#include "manager.h"
-
-static int time_init(void)
-{
-	if (!main_opts.gatt_enabled) {
-		DBG("GATT is disabled");
-		return -ENOTSUP;
-	}
-
-	return time_manager_init();
-}
-
-static void time_exit(void)
-{
-	if (!main_opts.gatt_enabled)
-		return;
-
-	time_manager_exit();
-}
-
-BLUETOOTH_PLUGIN_DEFINE(time, VERSION,
-			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
-			time_init, time_exit)
diff --git a/time/manager.c b/time/manager.c
deleted file mode 100644
index 285c7b1..0000000
--- a/time/manager.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012  Nokia Corporation
- *  Copyright (C) 2012  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "adapter.h"
-#include "manager.h"
-#include "server.h"
-
-struct btd_adapter_driver time_server_driver = {
-	.name = "gatt-time-server",
-	.probe = time_server_init,
-	.remove = time_server_exit,
-};
-
-int time_manager_init(void)
-{
-	btd_register_adapter_driver(&time_server_driver);
-
-	return 0;
-}
-
-void time_manager_exit(void)
-{
-	btd_unregister_adapter_driver(&time_server_driver);
-}
diff --git a/time/manager.h b/time/manager.h
deleted file mode 100644
index 74641d6..0000000
--- a/time/manager.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012  Nokia Corporation
- *  Copyright (C) 2012  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-int time_manager_init(void);
-void time_manager_exit(void);
diff --git a/time/server.c b/time/server.c
deleted file mode 100644
index be6e196..0000000
--- a/time/server.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011  Nokia Corporation
- *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <time.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-#include <adapter.h>
-
-#include "gattrib.h"
-#include "att.h"
-#include "gatt.h"
-#include "att-database.h"
-#include "attrib-server.h"
-#include "gatt-service.h"
-#include "log.h"
-#include "server.h"
-
-#define CURRENT_TIME_SVC_UUID		0x1805
-#define REF_TIME_UPDATE_SVC_UUID	0x1806
-
-#define LOCAL_TIME_INFO_CHR_UUID	0x2A0F
-#define TIME_UPDATE_CTRL_CHR_UUID	0x2A16
-#define TIME_UPDATE_STAT_CHR_UUID	0x2A17
-#define CT_TIME_CHR_UUID		0x2A2B
-
-static int encode_current_time(uint8_t value[10])
-{
-	struct timespec tp;
-	struct tm tm;
-
-	if (clock_gettime(CLOCK_REALTIME, &tp) == -1) {
-		int err = -errno;
-
-		error("clock_gettime: %s", strerror(-err));
-		return err;
-	}
-
-	if (localtime_r(&tp.tv_sec, &tm) == NULL) {
-		error("localtime_r() failed");
-		/* localtime_r() does not set errno */
-		return -EINVAL;
-	}
-
-	att_put_u16(1900 + tm.tm_year, &value[0]); /* Year */
-	value[2] = tm.tm_mon + 1; /* Month */
-	value[3] = tm.tm_mday; /* Day */
-	value[4] = tm.tm_hour; /* Hours */
-	value[5] = tm.tm_min; /* Minutes */
-	value[6] = tm.tm_sec; /* Seconds */
-	value[7] = tm.tm_wday == 0 ? 7 : tm.tm_wday; /* Day of Week */
-	/* From Time Profile spec: "The number of 1/256 fractions of a second."
-	 * In 1s there are 256 fractions, in 1ns there are 256/10^9 fractions.
-	 * To avoid integer overflow, we use the equivalent 1/3906250 ratio. */
-	value[8] = tp.tv_nsec / 3906250; /* Fractions256 */
-	value[9] = 0x00; /* Adjust Reason */
-
-	return 0;
-}
-
-static uint8_t current_time_read(struct attribute *a,
-				 struct btd_device *device, gpointer user_data)
-{
-	struct btd_adapter *adapter = user_data;
-	uint8_t value[10];
-
-	if (encode_current_time(value) < 0)
-		return ATT_ECODE_IO;
-
-	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
-
-	return 0;
-}
-
-static uint8_t local_time_info_read(struct attribute *a,
-				struct btd_device *device, gpointer user_data)
-{
-	struct btd_adapter *adapter = user_data;
-	uint8_t value[2];
-
-	DBG("a=%p", a);
-
-	tzset();
-
-	/* FIXME: POSIX "daylight" variable only indicates whether there is DST
-	 * for the local time or not. The offset is unknown. */
-	value[0] = daylight ? 0xff : 0x00;
-
-	/* Convert POSIX "timezone" (seconds West of GMT) to Time Profile
-	 * format (offset from UTC in number of 15 minutes increments). */
-	value[1] = (uint8_t) (-1 * timezone / (60 * 15));
-
-	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
-
-	return 0;
-}
-
-static gboolean register_current_time_service(struct btd_adapter *adapter)
-{
-	bt_uuid_t uuid;
-
-	bt_uuid16_create(&uuid, CURRENT_TIME_SVC_UUID);
-
-	/* Current Time service */
-	return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
-				/* CT Time characteristic */
-				GATT_OPT_CHR_UUID, CT_TIME_CHR_UUID,
-				GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ |
-							ATT_CHAR_PROPER_NOTIFY,
-				GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
-						current_time_read, adapter,
-
-				/* Local Time Information characteristic */
-				GATT_OPT_CHR_UUID, LOCAL_TIME_INFO_CHR_UUID,
-				GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
-				GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
-						local_time_info_read, adapter,
-
-				GATT_OPT_INVALID);
-}
-
-static uint8_t time_update_control(struct attribute *a,
-						struct btd_device *device,
-						gpointer user_data)
-{
-	DBG("handle 0x%04x", a->handle);
-
-	if (a->len != 1)
-		DBG("Invalid control point value size: %d", a->len);
-
-	switch (a->data[0]) {
-	case GET_REFERENCE_UPDATE:
-		DBG("Get Reference Update");
-		break;
-	case CANCEL_REFERENCE_UPDATE:
-		DBG("Cancel Reference Update");
-		break;
-	default:
-		DBG("Unknown command: 0x%02x", a->data[0]);
-	}
-
-	return 0;
-}
-
-static uint8_t time_update_status(struct attribute *a,
-						struct btd_device *device,
-						gpointer user_data)
-{
-	struct btd_adapter *adapter = user_data;
-	uint8_t value[2];
-
-	DBG("handle 0x%04x", a->handle);
-
-	value[0] = UPDATE_STATE_IDLE;
-	value[1] = UPDATE_RESULT_SUCCESSFUL;
-	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
-
-	return 0;
-}
-
-static gboolean register_ref_time_update_service(struct btd_adapter *adapter)
-{
-	bt_uuid_t uuid;
-
-	bt_uuid16_create(&uuid, REF_TIME_UPDATE_SVC_UUID);
-
-	/* Reference Time Update service */
-	return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
-				/* Time Update control point */
-				GATT_OPT_CHR_UUID, TIME_UPDATE_CTRL_CHR_UUID,
-				GATT_OPT_CHR_PROPS,
-					ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
-				GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
-						time_update_control, adapter,
-
-				/* Time Update status */
-				GATT_OPT_CHR_UUID, TIME_UPDATE_STAT_CHR_UUID,
-				GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
-				GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
-						time_update_status, adapter,
-
-				GATT_OPT_INVALID);
-}
-
-int time_server_init(struct btd_adapter *adapter)
-{
-	const char *path = adapter_get_path(adapter);
-
-	DBG("path %s", path);
-
-	if (!register_current_time_service(adapter)) {
-		error("Current Time Service could not be registered");
-		return -EIO;
-	}
-
-	if (!register_ref_time_update_service(adapter)) {
-		error("Reference Time Update Service could not be registered");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-void time_server_exit(struct btd_adapter *adapter)
-{
-	const char *path = adapter_get_path(adapter);
-
-	DBG("path %s", path);
-}
diff --git a/time/server.h b/time/server.h
deleted file mode 100644
index c7b997d..0000000
--- a/time/server.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2011  Nokia Corporation
- *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-enum {
-	UPDATE_RESULT_SUCCESSFUL = 0,
-	UPDATE_RESULT_CANCELED = 1,
-	UPDATE_RESULT_NO_CONN = 2,
-	UPDATE_RESULT_ERROR = 3,
-	UPDATE_RESULT_TIMEOUT = 4,
-	UPDATE_RESULT_NOT_ATTEMPTED = 5,
-};
-
-enum {
-	UPDATE_STATE_IDLE = 0,
-	UPDATE_STATE_PENDING = 1,
-};
-
-enum {
-	GET_REFERENCE_UPDATE = 1,
-	CANCEL_REFERENCE_UPDATE = 2,
-};
-
-int time_server_init(struct btd_adapter *adapter);
-void time_server_exit(struct btd_adapter *adapter);
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 12/14] cups: move it to profiles folder
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
                   ` (5 preceding siblings ...)
  2012-07-09 21:10 ` [PATCH 08/14] time: " Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  2012-07-09 21:10 ` [PATCH 14/14] plugins: remove unmaintained plugins Gustavo Padovan
  7 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 Makefile.tools       |   12 +-
 cups/cups.h          |   38 ---
 cups/hcrp.c          |  368 ---------------------
 cups/main.c          |  896 --------------------------------------------------
 cups/sdp.c           |  119 -------
 cups/spp.c           |  118 -------
 profiles/cups/cups.h |   38 +++
 profiles/cups/hcrp.c |  368 +++++++++++++++++++++
 profiles/cups/main.c |  896 ++++++++++++++++++++++++++++++++++++++++++++++++++
 profiles/cups/sdp.c  |  119 +++++++
 profiles/cups/spp.c  |  118 +++++++
 11 files changed, 1547 insertions(+), 1543 deletions(-)
 delete mode 100644 cups/cups.h
 delete mode 100644 cups/hcrp.c
 delete mode 100644 cups/main.c
 delete mode 100644 cups/sdp.c
 delete mode 100644 cups/spp.c
 create mode 100644 profiles/cups/cups.h
 create mode 100644 profiles/cups/hcrp.c
 create mode 100644 profiles/cups/main.c
 create mode 100644 profiles/cups/sdp.c
 create mode 100644 profiles/cups/spp.c

diff --git a/Makefile.tools b/Makefile.tools
index 56839b7..fccac2d 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -148,12 +148,16 @@ EXTRA_DIST += tools/dfubabel.1 tools/avctrl.8
 if CUPS
 cupsdir = $(libdir)/cups/backend
 
-cups_PROGRAMS = cups/bluetooth
+cups_PROGRAMS = profiles/cups/bluetooth
 
-cups_bluetooth_SOURCES = $(gdbus_sources) cups/main.c cups/cups.h \
-					cups/sdp.c cups/spp.c cups/hcrp.c
+profiles_cups_bluetooth_SOURCES = $(gdbus_sources) profiles/cups/main.c \
+					profiles/cups/cups.h \
+					profiles/cups/sdp.c \
+					profiles/cups/spp.c \
+					profiles/cups/hcrp.c
 
-cups_bluetooth_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ lib/libbluetooth-private.la
+profiles_cups_bluetooth_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ \
+				lib/libbluetooth-private.la
 endif
 
 
diff --git a/cups/cups.h b/cups/cups.h
deleted file mode 100644
index f4e0c01..0000000
--- a/cups/cups.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-enum {					/**** Backend exit codes ****/
-	CUPS_BACKEND_OK = 0,		/* Job completed successfully */
-	CUPS_BACKEND_FAILED = 1,	/* Job failed, use error-policy */
-	CUPS_BACKEND_AUTH_REQUIRED = 2,	/* Job failed, authentication required */
-	CUPS_BACKEND_HOLD = 3,		/* Job failed, hold job */
-	CUPS_BACKEND_STOP = 4,		/* Job failed, stop queue */
-	CUPS_BACKEND_CANCEL = 5,	/* Job failed, cancel job */
-	CUPS_BACKEND_RETRY = 6,		/* Failure requires us to retry (BlueZ specific) */
-};
-
-int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);
-int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm);
-
-int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class);
-int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class);
diff --git a/cups/hcrp.c b/cups/hcrp.c
deleted file mode 100644
index a93dda0..0000000
--- a/cups/hcrp.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include <netinet/in.h>
-
-#include "cups.h"
-
-#define HCRP_PDU_CREDIT_GRANT		0x0001
-#define HCRP_PDU_CREDIT_REQUEST		0x0002
-#define HCRP_PDU_GET_LPT_STATUS		0x0005
-
-#define HCRP_STATUS_FEATURE_UNSUPPORTED	0x0000
-#define HCRP_STATUS_SUCCESS		0x0001
-#define HCRP_STATUS_CREDIT_SYNC_ERROR	0x0002
-#define HCRP_STATUS_GENERIC_FAILURE	0xffff
-
-struct hcrp_pdu_hdr {
-	uint16_t pid;
-	uint16_t tid;
-	uint16_t plen;
-} __attribute__ ((packed));
-#define HCRP_PDU_HDR_SIZE 6
-
-struct hcrp_credit_grant_cp {
-	uint32_t credit;
-} __attribute__ ((packed));
-#define HCRP_CREDIT_GRANT_CP_SIZE 4
-
-struct hcrp_credit_grant_rp {
-	uint16_t status;
-} __attribute__ ((packed));
-#define HCRP_CREDIT_GRANT_RP_SIZE 2
-
-struct hcrp_credit_request_rp {
-	uint16_t status;
-	uint32_t credit;
-} __attribute__ ((packed));
-#define HCRP_CREDIT_REQUEST_RP_SIZE 6
-
-struct hcrp_get_lpt_status_rp {
-	uint16_t status;
-	uint8_t  lpt_status;
-} __attribute__ ((packed));
-#define HCRP_GET_LPT_STATUS_RP_SIZE 3
-
-static int hcrp_credit_grant(int sk, uint16_t tid, uint32_t credit)
-{
-	struct hcrp_pdu_hdr hdr;
-	struct hcrp_credit_grant_cp cp;
-	struct hcrp_credit_grant_rp rp;
-	unsigned char buf[128];
-	int len;
-
-	hdr.pid = htons(HCRP_PDU_CREDIT_GRANT);
-	hdr.tid = htons(tid);
-	hdr.plen = htons(HCRP_CREDIT_GRANT_CP_SIZE);
-	cp.credit = credit;
-	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
-	memcpy(buf + HCRP_PDU_HDR_SIZE, &cp, HCRP_CREDIT_GRANT_CP_SIZE);
-	len = write(sk, buf, HCRP_PDU_HDR_SIZE + HCRP_CREDIT_GRANT_CP_SIZE);
-	if (len < 0)
-		return len;
-
-	len = read(sk, buf, sizeof(buf));
-	if (len < 0)
-		return len;
-
-	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
-	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_GRANT_RP_SIZE);
-
-	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
-		errno = EIO;
-		return -1;
-	}
-
-	return 0;
-}
-
-static int hcrp_credit_request(int sk, uint16_t tid, uint32_t *credit)
-{
-	struct hcrp_pdu_hdr hdr;
-	struct hcrp_credit_request_rp rp;
-	unsigned char buf[128];
-	int len;
-
-	hdr.pid = htons(HCRP_PDU_CREDIT_REQUEST);
-	hdr.tid = htons(tid);
-	hdr.plen = htons(0);
-	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
-	len = write(sk, buf, HCRP_PDU_HDR_SIZE);
-	if (len < 0)
-		return len;
-
-	len = read(sk, buf, sizeof(buf));
-	if (len < 0)
-		return len;
-
-	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
-	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_REQUEST_RP_SIZE);
-
-	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
-		errno = EIO;
-		return -1;
-	}
-
-	if (credit)
-		*credit = ntohl(rp.credit);
-
-	return 0;
-}
-
-static int hcrp_get_lpt_status(int sk, uint16_t tid, uint8_t *lpt_status)
-{
-	struct hcrp_pdu_hdr hdr;
-	struct hcrp_get_lpt_status_rp rp;
-	unsigned char buf[128];
-	int len;
-
-	hdr.pid = htons(HCRP_PDU_GET_LPT_STATUS);
-	hdr.tid = htons(tid);
-	hdr.plen = htons(0);
-	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
-	len = write(sk, buf, HCRP_PDU_HDR_SIZE);
-	if (len < 0)
-		return len;
-
-	len = read(sk, buf, sizeof(buf));
-	if (len < 0)
-		return len;
-
-	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
-	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_GET_LPT_STATUS_RP_SIZE);
-
-	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
-		errno = EIO;
-		return -1;
-	}
-
-	if (lpt_status)
-		*lpt_status = rp.lpt_status;
-
-	return 0;
-}
-
-static inline int hcrp_get_next_tid(int tid)
-{
-	if (tid > 0xf000)
-		return 0;
-	else
-		return tid + 1;
-}
-
-int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class)
-{
-	struct sockaddr_l2 addr;
-	struct l2cap_options opts;
-	socklen_t size;
-	unsigned char buf[2048];
-	int i, ctrl_sk, data_sk, count, len, timeout = 0;
-	unsigned int mtu;
-	uint8_t status;
-	uint16_t tid = 0;
-	uint32_t tmp, credit = 0;
-
-	if ((ctrl_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
-		perror("ERROR: Can't create socket");
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.l2_family = AF_BLUETOOTH;
-	bacpy(&addr.l2_bdaddr, src);
-
-	if (bind(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("ERROR: Can't bind socket");
-		close(ctrl_sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.l2_family = AF_BLUETOOTH;
-	bacpy(&addr.l2_bdaddr, dst);
-	addr.l2_psm = htobs(ctrl_psm);
-
-	if (connect(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("ERROR: Can't connect to device");
-		close(ctrl_sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	if ((data_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
-		perror("ERROR: Can't create socket");
-		close(ctrl_sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.l2_family = AF_BLUETOOTH;
-	bacpy(&addr.l2_bdaddr, src);
-
-	if (bind(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("ERROR: Can't bind socket");
-		close(data_sk);
-		close(ctrl_sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.l2_family = AF_BLUETOOTH;
-	bacpy(&addr.l2_bdaddr, dst);
-	addr.l2_psm = htobs(data_psm);
-
-	if (connect(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("ERROR: Can't connect to device");
-		close(data_sk);
-		close(ctrl_sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	fputs("STATE: -connecting-to-device\n", stderr);
-
-	memset(&opts, 0, sizeof(opts));
-	size = sizeof(opts);
-
-	if (getsockopt(data_sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
-		perror("ERROR: Can't get socket options");
-		close(data_sk);
-		close(ctrl_sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	mtu = opts.omtu;
-
-	/* Ignore SIGTERM signals if printing from stdin */
-	if (fd == 0) {
-#ifdef HAVE_SIGSET
-		sigset(SIGTERM, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
-		memset(&action, 0, sizeof(action));
-		sigemptyset(&action.sa_mask);
-		action.sa_handler = SIG_IGN;
-		sigaction(SIGTERM, &action, NULL);
-#else
-		signal(SIGTERM, SIG_IGN);
-#endif /* HAVE_SIGSET */
-	}
-
-	tid = hcrp_get_next_tid(tid);
-	if (hcrp_credit_grant(ctrl_sk, tid, 0) < 0) {
-		fprintf(stderr, "ERROR: Can't grant initial credits\n");
-		close(data_sk);
-		close(ctrl_sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	for (i = 0; i < copies; i++) {
-
-		if (fd != 0) {
-			fprintf(stderr, "PAGE: 1 1\n");
-			lseek(fd, 0, SEEK_SET);
-		}
-
-		while (1) {
-			if (credit < mtu) {
-				tid = hcrp_get_next_tid(tid);
-				if (!hcrp_credit_request(ctrl_sk, tid, &tmp)) {
-					credit += tmp;
-					timeout = 0;
-				}
-			}
-
-			if (!credit) {
-				if (timeout++ > 300) {
-					tid = hcrp_get_next_tid(tid);
-					if (!hcrp_get_lpt_status(ctrl_sk, tid, &status))
-						fprintf(stderr, "ERROR: LPT status 0x%02x\n", status);
-					break;
-				}
-
-				sleep(1);
-				continue;
-			}
-
-			count = read(fd, buf, (credit > mtu) ? mtu : credit);
-			if (count <= 0)
-				break;
-
-			len = write(data_sk, buf, count);
-			if (len < 0) {
-				perror("ERROR: Error writing to device");
-				close(data_sk);
-				close(ctrl_sk);
-				return CUPS_BACKEND_FAILED;
-			}
-
-			if (len != count)
-				fprintf(stderr, "ERROR: Can't send complete data\n");
-
-			credit -= len;
-		}
-
-	}
-
-	close(data_sk);
-	close(ctrl_sk);
-
-	return CUPS_BACKEND_OK;
-}
diff --git a/cups/main.c b/cups/main.c
deleted file mode 100644
index a884c6e..0000000
--- a/cups/main.c
+++ /dev/null
@@ -1,896 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <glib.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include <gdbus.h>
-
-#include "cups.h"
-
-struct cups_device {
-	char *bdaddr;
-	char *name;
-	char *id;
-};
-
-static GSList *device_list = NULL;
-static GMainLoop *loop = NULL;
-static DBusConnection *conn = NULL;
-static gboolean doing_disco = FALSE;
-
-#define ATTRID_1284ID 0x0300
-
-struct context_data {
-	gboolean found;
-	char *id;
-};
-
-static void element_start(GMarkupParseContext *context,
-				const gchar *element_name,
-				const gchar **attribute_names,
-				const gchar **attribute_values,
-				gpointer user_data, GError **err)
-{
-	struct context_data *ctx_data = user_data;
-
-	if (!strcmp(element_name, "record"))
-		return;
-
-	if (!strcmp(element_name, "attribute")) {
-		int i;
-		for (i = 0; attribute_names[i]; i++) {
-			if (strcmp(attribute_names[i], "id") != 0)
-				continue;
-			if (strtol(attribute_values[i], 0, 0) == ATTRID_1284ID)
-				ctx_data->found = TRUE;
-			break;
-		}
-		return;
-	}
-
-	if (ctx_data->found  && !strcmp(element_name, "text")) {
-		int i;
-		for (i = 0; attribute_names[i]; i++) {
-			if (!strcmp(attribute_names[i], "value")) {
-				ctx_data->id = g_strdup(attribute_values[i] + 2);
-				ctx_data->found = FALSE;
-			}
-		}
-	}
-}
-
-static GMarkupParser parser = {
-	element_start, NULL, NULL, NULL, NULL
-};
-
-static char *sdp_xml_parse_record(const char *data)
-{
-	GMarkupParseContext *ctx;
-	struct context_data ctx_data;
-	int size;
-
-	size = strlen(data);
-	ctx_data.found = FALSE;
-	ctx_data.id = NULL;
-	ctx = g_markup_parse_context_new(&parser, 0, &ctx_data, NULL);
-
-	if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
-		g_markup_parse_context_free(ctx);
-		g_free(ctx_data.id);
-		return NULL;
-	}
-
-	g_markup_parse_context_free(ctx);
-
-	return ctx_data.id;
-}
-
-static char *device_get_ieee1284_id(const char *adapter, const char *device)
-{
-	DBusMessage *message, *reply;
-	DBusMessageIter iter, reply_iter;
-	DBusMessageIter reply_iter_entry;
-	const char *hcr_print = "00001126-0000-1000-8000-00805f9b34fb";
-	const char *xml;
-	char *id = NULL;
-
-	/* Look for the service handle of the HCRP service */
-	message = dbus_message_new_method_call("org.bluez", device,
-						"org.bluez.Device",
-						"DiscoverServices");
-	dbus_message_iter_init_append(message, &iter);
-	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &hcr_print);
-
-	reply = dbus_connection_send_with_reply_and_block(conn,
-							message, -1, NULL);
-
-	dbus_message_unref(message);
-
-	if (!reply)
-		return NULL;
-
-	dbus_message_iter_init(reply, &reply_iter);
-
-	if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
-		dbus_message_unref(reply);
-		return NULL;
-	}
-
-	dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
-
-	/* Hopefully we only get one handle, or take a punt */
-	while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
-							DBUS_TYPE_DICT_ENTRY) {
-		guint32 key;
-		DBusMessageIter dict_entry;
-
-		dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
-
-		/* Key ? */
-		dbus_message_iter_get_basic(&dict_entry, &key);
-		if (!key) {
-			dbus_message_iter_next(&reply_iter_entry);
-			continue;
-		}
-
-		/* Try to get the value */
-		if (!dbus_message_iter_next(&dict_entry)) {
-			dbus_message_iter_next(&reply_iter_entry);
-			continue;
-		}
-
-		dbus_message_iter_get_basic(&dict_entry, &xml);
-
-		id = sdp_xml_parse_record(xml);
-		if (id != NULL)
-			break;
-		dbus_message_iter_next(&reply_iter_entry);
-	}
-
-	dbus_message_unref(reply);
-
-	return id;
-}
-
-static void print_printer_details(const char *name, const char *bdaddr,
-								const char *id)
-{
-	char *uri, *escaped;
-
-	escaped = g_strdelimit(g_strdup(name), "\"", '\'');
-	uri = g_strdup_printf("bluetooth://%c%c%c%c%c%c%c%c%c%c%c%c",
-				bdaddr[0], bdaddr[1],
-				bdaddr[3], bdaddr[4],
-				bdaddr[6], bdaddr[7],
-				bdaddr[9], bdaddr[10],
-				bdaddr[12], bdaddr[13],
-				bdaddr[15], bdaddr[16]);
-	printf("direct %s \"%s\" \"%s (Bluetooth)\"", uri, escaped, escaped);
-	if (id != NULL)
-		printf(" \"%s\"\n", id);
-	else
-		printf("\n");
-	g_free(escaped);
-	g_free(uri);
-}
-
-static void add_device_to_list(const char *name, const char *bdaddr,
-								const char *id)
-{
-	struct cups_device *device;
-	GSList *l;
-
-	/* Look for the device in the list */
-	for (l = device_list; l != NULL; l = l->next) {
-		device = (struct cups_device *) l->data;
-
-		if (strcmp(device->bdaddr, bdaddr) == 0) {
-			if (device->name != name) {
-				g_free(device->name);
-				device->name = g_strdup(name);
-			}
-			g_free(device->id);
-			device->id = g_strdup(id);
-			return;
-		}
-	}
-
-	/* Or add it to the list if it's not there */
-	device = g_new0(struct cups_device, 1);
-	device->bdaddr = g_strdup(bdaddr);
-	device->name = g_strdup(name);
-	device->id = g_strdup(id);
-
-	device_list = g_slist_prepend(device_list, device);
-	print_printer_details(device->name, device->bdaddr, device->id);
-}
-
-static gboolean parse_device_properties(DBusMessageIter *reply_iter,
-						char **name, char **bdaddr)
-{
-	guint32 class = 0;
-	DBusMessageIter reply_iter_entry;
-
-	if (dbus_message_iter_get_arg_type(reply_iter) != DBUS_TYPE_ARRAY)
-		return FALSE;
-
-	dbus_message_iter_recurse(reply_iter, &reply_iter_entry);
-
-	while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
-							DBUS_TYPE_DICT_ENTRY) {
-		const char *key;
-		DBusMessageIter dict_entry, iter_dict_val;
-
-		dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
-
-		/* Key == Class ? */
-		dbus_message_iter_get_basic(&dict_entry, &key);
-		if (!key) {
-			dbus_message_iter_next(&reply_iter_entry);
-			continue;
-		}
-
-		if (strcmp(key, "Class") != 0 &&
-				strcmp(key, "Alias") != 0 &&
-				strcmp(key, "Address") != 0) {
-			dbus_message_iter_next(&reply_iter_entry);
-			continue;
-		}
-
-		/* Try to get the value */
-		if (!dbus_message_iter_next(&dict_entry)) {
-			dbus_message_iter_next(&reply_iter_entry);
-			continue;
-		}
-		dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
-		if (strcmp(key, "Class") == 0) {
-			dbus_message_iter_get_basic(&iter_dict_val, &class);
-		} else {
-			const char *value;
-			dbus_message_iter_get_basic(&iter_dict_val, &value);
-			if (strcmp(key, "Alias") == 0) {
-				*name = g_strdup(value);
-			} else if (bdaddr) {
-				*bdaddr = g_strdup(value);
-			}
-		}
-		dbus_message_iter_next(&reply_iter_entry);
-	}
-
-	if (class == 0)
-		return FALSE;
-	if (((class & 0x1f00) >> 8) == 0x06 && (class & 0x80))
-		return TRUE;
-
-	return FALSE;
-}
-
-static gboolean device_is_printer(const char *adapter, const char *device_path, char **name, char **bdaddr)
-{
-	DBusMessage *message, *reply;
-	DBusMessageIter reply_iter;
-	gboolean retval;
-
-	message = dbus_message_new_method_call("org.bluez", device_path,
-							"org.bluez.Device",
-							"GetProperties");
-
-	reply = dbus_connection_send_with_reply_and_block(conn,
-							message, -1, NULL);
-
-	dbus_message_unref(message);
-
-	if (!reply)
-		return FALSE;
-
-	dbus_message_iter_init(reply, &reply_iter);
-
-	retval = parse_device_properties(&reply_iter, name, bdaddr);
-
-	dbus_message_unref(reply);
-
-	return retval;
-}
-
-static void remote_device_found(const char *adapter, const char *bdaddr,
-							const char *name)
-{
-	DBusMessage *message, *reply, *adapter_reply;
-	DBusMessageIter iter;
-	char *object_path = NULL;
-	char *id;
-
-	adapter_reply = NULL;
-
-	if (adapter == NULL) {
-		message = dbus_message_new_method_call("org.bluez", "/",
-							"org.bluez.Manager",
-							"DefaultAdapter");
-
-		adapter_reply = dbus_connection_send_with_reply_and_block(conn,
-							message, -1, NULL);
-
-		dbus_message_unref(message);
-
-		if (!adapter_reply)
-			return;
-
-		if (dbus_message_get_args(adapter_reply, NULL,
-					DBUS_TYPE_OBJECT_PATH, &adapter,
-					DBUS_TYPE_INVALID) == FALSE) {
-			dbus_message_unref(adapter_reply);
-			return;
-		}
-	}
-
-	message = dbus_message_new_method_call("org.bluez", adapter,
-							"org.bluez.Adapter",
-							"FindDevice");
-	dbus_message_iter_init_append(message, &iter);
-	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
-
-	if (adapter_reply != NULL)
-		dbus_message_unref(adapter_reply);
-
-	reply = dbus_connection_send_with_reply_and_block(conn,
-							message, -1, NULL);
-
-	dbus_message_unref(message);
-
-	if (!reply) {
-		message = dbus_message_new_method_call("org.bluez", adapter,
-							"org.bluez.Adapter",
-							"CreateDevice");
-		dbus_message_iter_init_append(message, &iter);
-		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
-
-		reply = dbus_connection_send_with_reply_and_block(conn,
-							message, -1, NULL);
-
-		dbus_message_unref(message);
-
-		if (!reply)
-			return;
-	}
-
-	if (dbus_message_get_args(reply, NULL,
-					DBUS_TYPE_OBJECT_PATH, &object_path,
-					DBUS_TYPE_INVALID) == FALSE) {
-		dbus_message_unref(reply);
-		return;
-	}
-
-	id = device_get_ieee1284_id(adapter, object_path);
-	add_device_to_list(name, bdaddr, id);
-	g_free(id);
-
-	dbus_message_unref(reply);
-}
-
-static void discovery_completed(void)
-{
-	g_slist_free(device_list);
-	device_list = NULL;
-
-	g_main_loop_quit(loop);
-}
-
-static void remote_device_disappeared(const char *bdaddr)
-{
-	GSList *l;
-
-	for (l = device_list; l != NULL; l = l->next) {
-		struct cups_device *device = l->data;
-
-		if (strcmp(device->bdaddr, bdaddr) == 0) {
-			g_free(device->name);
-			g_free(device->bdaddr);
-			g_free(device);
-			device_list = g_slist_delete_link(device_list, l);
-			return;
-		}
-	}
-}
-
-static gboolean list_known_printers(const char *adapter)
-{
-	DBusMessageIter reply_iter, iter_array;
-	DBusError error;
-	DBusMessage *message, *reply;
-
-	message = dbus_message_new_method_call("org.bluez", adapter,
-						"org.bluez.Adapter",
-						"ListDevices");
-	if (message == NULL)
-		return FALSE;
-
-	dbus_error_init(&error);
-	reply = dbus_connection_send_with_reply_and_block(conn, message,
-								-1, &error);
-
-	dbus_message_unref(message);
-
-	if (dbus_error_is_set(&error))
-		return FALSE;
-
-	dbus_message_iter_init(reply, &reply_iter);
-	if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
-		dbus_message_unref(reply);
-		return FALSE;
-	}
-
-	dbus_message_iter_recurse(&reply_iter, &iter_array);
-	while (dbus_message_iter_get_arg_type(&iter_array) ==
-						DBUS_TYPE_OBJECT_PATH) {
-		const char *object_path;
-		char *name = NULL;
-		char *bdaddr = NULL;
-
-		dbus_message_iter_get_basic(&iter_array, &object_path);
-		if (device_is_printer(adapter, object_path, &name, &bdaddr)) {
-			char *id;
-
-			id = device_get_ieee1284_id(adapter, object_path);
-			add_device_to_list(name, bdaddr, id);
-			g_free(id);
-		}
-		g_free(name);
-		g_free(bdaddr);
-		dbus_message_iter_next(&iter_array);
-	}
-
-	dbus_message_unref(reply);
-
-	return FALSE;
-}
-
-static DBusHandlerResult filter_func(DBusConnection *connection,
-					DBusMessage *message, void *user_data)
-{
-	if (dbus_message_is_signal(message, "org.bluez.Adapter",
-						"DeviceFound")) {
-		const char *adapter, *bdaddr;
-		char *name;
-		DBusMessageIter iter;
-
-		dbus_message_iter_init(message, &iter);
-		dbus_message_iter_get_basic(&iter, &bdaddr);
-		dbus_message_iter_next(&iter);
-
-		adapter = dbus_message_get_path(message);
-		if (parse_device_properties(&iter, &name, NULL))
-			remote_device_found(adapter, bdaddr, name);
-		g_free (name);
-	} else if (dbus_message_is_signal(message, "org.bluez.Adapter",
-						"DeviceDisappeared")) {
-		const char *bdaddr;
-
-		dbus_message_get_args(message, NULL,
-					DBUS_TYPE_STRING, &bdaddr,
-					DBUS_TYPE_INVALID);
-		remote_device_disappeared(bdaddr);
-	} else if (dbus_message_is_signal(message, "org.bluez.Adapter",
-						"PropertyChanged")) {
-		DBusMessageIter iter, value_iter;
-		const char *name;
-		gboolean discovering;
-
-		dbus_message_iter_init(message, &iter);
-		dbus_message_iter_get_basic(&iter, &name);
-		if (name == NULL || strcmp(name, "Discovering") != 0)
-			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-		dbus_message_iter_next(&iter);
-		dbus_message_iter_recurse(&iter, &value_iter);
-		dbus_message_iter_get_basic(&value_iter, &discovering);
-
-		if (discovering == FALSE && doing_disco) {
-			doing_disco = FALSE;
-			discovery_completed();
-		}
-	}
-
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static gboolean list_printers(void)
-{
-	/* 1. Connect to the bus
-	 * 2. Get the manager
-	 * 3. Get the default adapter
-	 * 4. Get a list of devices
-	 * 5. Get the class of each device
-	 * 6. Print the details from each printer device
-	 */
-	DBusError error;
-	dbus_bool_t hcid_exists;
-	DBusMessage *reply, *message;
-	DBusMessageIter reply_iter;
-	char *adapter, *match;
-
-	conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
-	if (conn == NULL)
-		return TRUE;
-
-	dbus_error_init(&error);
-	hcid_exists = dbus_bus_name_has_owner(conn, "org.bluez", &error);
-	if (dbus_error_is_set(&error))
-		return TRUE;
-
-	if (!hcid_exists)
-		return TRUE;
-
-	/* Get the default adapter */
-	message = dbus_message_new_method_call("org.bluez", "/",
-						"org.bluez.Manager",
-						"DefaultAdapter");
-	if (message == NULL) {
-		dbus_connection_unref(conn);
-		return FALSE;
-	}
-
-	reply = dbus_connection_send_with_reply_and_block(conn,
-							message, -1, &error);
-
-	dbus_message_unref(message);
-
-	if (dbus_error_is_set(&error)) {
-		dbus_connection_unref(conn);
-		/* No adapter */
-		return TRUE;
-	}
-
-	dbus_message_iter_init(reply, &reply_iter);
-	if (dbus_message_iter_get_arg_type(&reply_iter) !=
-						DBUS_TYPE_OBJECT_PATH) {
-		dbus_message_unref(reply);
-		dbus_connection_unref(conn);
-		return FALSE;
-	}
-
-	dbus_message_iter_get_basic(&reply_iter, &adapter);
-	adapter = g_strdup(adapter);
-	dbus_message_unref(reply);
-
-	if (!dbus_connection_add_filter(conn, filter_func, adapter, g_free)) {
-		g_free(adapter);
-		dbus_connection_unref(conn);
-		return FALSE;
-	}
-
-#define MATCH_FORMAT				\
-	"type='signal',"			\
-	"interface='org.bluez.Adapter',"	\
-	"sender='org.bluez',"			\
-	"path='%s'"
-
-	match = g_strdup_printf(MATCH_FORMAT, adapter);
-	dbus_bus_add_match(conn, match, &error);
-	g_free(match);
-
-	/* Add the the recent devices */
-	list_known_printers(adapter);
-
-	doing_disco = TRUE;
-	message = dbus_message_new_method_call("org.bluez", adapter,
-					"org.bluez.Adapter",
-					"StartDiscovery");
-
-	if (!dbus_connection_send_with_reply(conn, message, NULL, -1)) {
-		dbus_message_unref(message);
-		dbus_connection_unref(conn);
-		g_free(adapter);
-		return FALSE;
-	}
-	dbus_message_unref(message);
-
-	loop = g_main_loop_new(NULL, TRUE);
-	g_main_loop_run(loop);
-
-	g_free(adapter);
-	dbus_connection_unref(conn);
-
-	return TRUE;
-}
-
-static gboolean print_ieee1284(const char *bdaddr)
-{
-	DBusMessage *message, *reply, *adapter_reply;
-	DBusMessageIter iter;
-	char *object_path = NULL;
-	char *adapter;
-	char *id;
-
-	adapter_reply = NULL;
-
-	conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
-	if (conn == NULL)
-		return FALSE;
-
-	message = dbus_message_new_method_call("org.bluez", "/",
-			"org.bluez.Manager",
-			"DefaultAdapter");
-
-	adapter_reply = dbus_connection_send_with_reply_and_block(conn,
-			message, -1, NULL);
-
-	dbus_message_unref(message);
-
-	if (!adapter_reply)
-		return FALSE;
-
-	if (dbus_message_get_args(adapter_reply, NULL,
-			DBUS_TYPE_OBJECT_PATH, &adapter,
-			DBUS_TYPE_INVALID) == FALSE) {
-		dbus_message_unref(adapter_reply);
-		return FALSE;
-	}
-
-	message = dbus_message_new_method_call("org.bluez", adapter,
-			"org.bluez.Adapter",
-			"FindDevice");
-	dbus_message_iter_init_append(message, &iter);
-	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
-
-	if (adapter_reply != NULL)
-		dbus_message_unref(adapter_reply);
-
-	reply = dbus_connection_send_with_reply_and_block(conn,
-			message, -1, NULL);
-
-	dbus_message_unref(message);
-
-	if (!reply) {
-		message = dbus_message_new_method_call("org.bluez", adapter,
-				"org.bluez.Adapter",
-				"CreateDevice");
-		dbus_message_iter_init_append(message, &iter);
-		dbus_message_iter_append_basic(&iter,
-				DBUS_TYPE_STRING, &bdaddr);
-
-		reply = dbus_connection_send_with_reply_and_block(conn,
-				message, -1, NULL);
-
-		dbus_message_unref(message);
-
-		if (!reply)
-			return FALSE;
-	}
-
-	if (dbus_message_get_args(reply, NULL,
-					DBUS_TYPE_OBJECT_PATH, &object_path,
-					DBUS_TYPE_INVALID) == FALSE) {
-		dbus_message_unref(reply);
-		return FALSE;
-	}
-
-	id = device_get_ieee1284_id(adapter, object_path);
-	if (id == NULL) {
-		dbus_message_unref(reply);
-		return FALSE;
-	}
-	printf("%s", id);
-	g_free(id);
-
-	dbus_message_unref(reply);
-
-	return TRUE;
-}
-
-/*
- *  Usage: printer-uri job-id user title copies options [file]
- *
- */
-
-int main(int argc, char *argv[])
-{
-	sdp_session_t *sdp;
-	bdaddr_t bdaddr;
-	unsigned short ctrl_psm, data_psm;
-	uint8_t channel, b[6];
-	char *ptr, str[3], device[18], service[12];
-	const char *uri, *cups_class;
-	int i, err, fd, copies, proto;
-
-	/* Make sure status messages are not buffered */
-	setbuf(stderr, NULL);
-
-	/* Make sure output is not buffered */
-	setbuf(stdout, NULL);
-
-	/* Ignore SIGPIPE signals */
-#ifdef HAVE_SIGSET
-	sigset(SIGPIPE, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
-	memset(&action, 0, sizeof(action));
-	action.sa_handler = SIG_IGN;
-	sigaction(SIGPIPE, &action, NULL);
-#else
-	signal(SIGPIPE, SIG_IGN);
-#endif /* HAVE_SIGSET */
-
-	if (argc == 1) {
-		if (list_printers() == TRUE)
-			return CUPS_BACKEND_OK;
-		else
-			return CUPS_BACKEND_FAILED;
-	} else if (argc == 3 && strcmp(argv[1], "--get-deviceid") == 0) {
-		if (bachk(argv[2]) < 0) {
-			fprintf(stderr, "Invalid Bluetooth address '%s'\n",
-					argv[2]);
-			return CUPS_BACKEND_FAILED;
-		}
-		if (print_ieee1284(argv[2]) == FALSE)
-			return CUPS_BACKEND_FAILED;
-		return CUPS_BACKEND_OK;
-	}
-
-	if (argc < 6 || argc > 7) {
-		fprintf(stderr, "Usage: bluetooth job-id user title copies"
-				" options [file]\n");
-		fprintf(stderr, "       bluetooth --get-deviceid [bdaddr]\n");
-		return CUPS_BACKEND_FAILED;
-	}
-
-	if (argc == 6) {
-		fd = 0;
-		copies = 1;
-	} else {
-		if ((fd = open(argv[6], O_RDONLY)) < 0) {
-			perror("ERROR: Unable to open print file");
-			return CUPS_BACKEND_FAILED;
-		}
-		copies = atoi(argv[4]);
-	}
-
-	uri = getenv("DEVICE_URI");
-	if (!uri)
-		uri = argv[0];
-
-	if (strncasecmp(uri, "bluetooth://", 12)) {
-		fprintf(stderr, "ERROR: No device URI found\n");
-		return CUPS_BACKEND_FAILED;
-	}
-
-	ptr = argv[0] + 12;
-	for (i = 0; i < 6; i++) {
-		strncpy(str, ptr, 2);
-		b[i] = (uint8_t) strtol(str, NULL, 16);
-		ptr += 2;
-	}
-	sprintf(device, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-			b[0], b[1], b[2], b[3], b[4], b[5]);
-
-	str2ba(device, &bdaddr);
-
-	ptr = strchr(ptr, '/');
-	if (ptr) {
-		strncpy(service, ptr + 1, 12);
-
-		if (!strncasecmp(ptr + 1, "spp", 3))
-			proto = 1;
-		else if (!strncasecmp(ptr + 1, "hcrp", 4))
-			proto = 2;
-		else
-			proto = 0;
-	} else {
-		strcpy(service, "auto");
-		proto = 0;
-	}
-
-	cups_class = getenv("CLASS");
-
-	fprintf(stderr,
-		"DEBUG: %s device %s service %s fd %d copies %d class %s\n",
-			argv[0], device, service, fd, copies,
-			cups_class ? cups_class : "(none)");
-
-	fputs("STATE: +connecting-to-device\n", stderr);
-
-service_search:
-	sdp = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
-	if (!sdp) {
-		fprintf(stderr, "ERROR: Can't open Bluetooth connection\n");
-		return CUPS_BACKEND_FAILED;
-	}
-
-	switch (proto) {
-	case 1:
-		err = sdp_search_spp(sdp, &channel);
-		break;
-	case 2:
-		err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
-		break;
-	default:
-		proto = 2;
-		err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
-		if (err) {
-			proto = 1;
-			err = sdp_search_spp(sdp, &channel);
-		}
-		break;
-	}
-
-	sdp_close(sdp);
-
-	if (err) {
-		if (cups_class) {
-			fputs("INFO: Unable to contact printer, queuing on "
-					"next printer in class...\n", stderr);
-			sleep(5);
-			return CUPS_BACKEND_FAILED;
-		}
-		sleep(20);
-		fprintf(stderr, "ERROR: Can't get service information\n");
-		goto service_search;
-	}
-
-connect:
-	switch (proto) {
-	case 1:
-		err = spp_print(BDADDR_ANY, &bdaddr, channel,
-						fd, copies, cups_class);
-		break;
-	case 2:
-		err = hcrp_print(BDADDR_ANY, &bdaddr, ctrl_psm, data_psm,
-						fd, copies, cups_class);
-		break;
-	default:
-		err = CUPS_BACKEND_FAILED;
-		fprintf(stderr, "ERROR: Unsupported protocol\n");
-		break;
-	}
-
-	if (err == CUPS_BACKEND_FAILED && cups_class) {
-		fputs("INFO: Unable to contact printer, queuing on "
-					"next printer in class...\n", stderr);
-		sleep(5);
-		return CUPS_BACKEND_FAILED;
-	} else if (err == CUPS_BACKEND_RETRY) {
-		sleep(20);
-		goto connect;
-	}
-
-	if (fd != 0)
-		close(fd);
-
-	if (!err)
-		fprintf(stderr, "INFO: Ready to print\n");
-
-	return err;
-}
diff --git a/cups/sdp.c b/cups/sdp.c
deleted file mode 100644
index c7f17a4..0000000
--- a/cups/sdp.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include "cups.h"
-
-int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm)
-{
-	sdp_list_t *srch, *attrs, *rsp;
-	uuid_t svclass;
-	uint16_t attr1, attr2;
-	int err;
-
-	if (!sdp)
-		return -1;
-
-	sdp_uuid16_create(&svclass, HCR_PRINT_SVCLASS_ID);
-	srch = sdp_list_append(NULL, &svclass);
-
-	attr1 = SDP_ATTR_PROTO_DESC_LIST;
-	attrs = sdp_list_append(NULL, &attr1);
-	attr2 = SDP_ATTR_ADD_PROTO_DESC_LIST;
-	attrs = sdp_list_append(attrs, &attr2);
-
-	err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
-	if (err)
-		return -1;
-
-	for (; rsp; rsp = rsp->next) {
-		sdp_record_t *rec = (sdp_record_t *) rsp->data;
-		sdp_list_t *protos;
-
-		if (!sdp_get_access_protos(rec, &protos)) {
-			unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
-			if (psm > 0) {
-				*ctrl_psm = psm;
-			}
-		}
-
-		if (!sdp_get_add_access_protos(rec, &protos)) {
-			unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
-			if (psm > 0 && *ctrl_psm > 0) {
-				*data_psm = psm;
-				return 0;
-			}
-		}
-	}
-
-	return -1;
-}
-
-int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel)
-{
-	sdp_list_t *srch, *attrs, *rsp;
-	uuid_t svclass;
-	uint16_t attr;
-	int err;
-
-	if (!sdp)
-		return -1;
-
-	sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID);
-	srch = sdp_list_append(NULL, &svclass);
-
-	attr = SDP_ATTR_PROTO_DESC_LIST;
-	attrs = sdp_list_append(NULL, &attr);
-
-	err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
-	if (err)
-		return -1;
-
-	for (; rsp; rsp = rsp->next) {
-		sdp_record_t *rec = (sdp_record_t *) rsp->data;
-		sdp_list_t *protos;
-
-		if (!sdp_get_access_protos(rec, &protos)) {
-			uint8_t ch = sdp_get_proto_port(protos, RFCOMM_UUID);
-			if (ch > 0) {
-				*channel = ch;
-				return 0;
-			}
-		}
-	}
-
-	return -1;
-}
diff --git a/cups/spp.c b/cups/spp.c
deleted file mode 100644
index d906ed2..0000000
--- a/cups/spp.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include "cups.h"
-
-int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class)
-{
-	struct sockaddr_rc addr;
-	unsigned char buf[2048];
-	int i, sk, err, len;
-
-	if ((sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
-		perror("ERROR: Can't create socket");
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	addr.rc_family = AF_BLUETOOTH;
-	bacpy(&addr.rc_bdaddr, src);
-	addr.rc_channel = 0;
-
-	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("ERROR: Can't bind socket");
-		close(sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	addr.rc_family = AF_BLUETOOTH;
-	bacpy(&addr.rc_bdaddr, dst);
-	addr.rc_channel = channel;
-
-	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("ERROR: Can't connect to device");
-		close(sk);
-		if (cups_class)
-			return CUPS_BACKEND_FAILED;
-		else
-			return CUPS_BACKEND_RETRY;
-	}
-
-	fputs("STATE: -connecting-to-device\n", stderr);
-
-	/* Ignore SIGTERM signals if printing from stdin */
-	if (fd == 0) {
-#ifdef HAVE_SIGSET
-		sigset(SIGTERM, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
-		memset(&action, 0, sizeof(action));
-		sigemptyset(&action.sa_mask);
-		action.sa_handler = SIG_IGN;
-		sigaction(SIGTERM, &action, NULL);
-#else
-		signal(SIGTERM, SIG_IGN);
-#endif /* HAVE_SIGSET */
-	}
-
-	for (i = 0; i < copies; i++) {
-
-		if (fd != 0) {
-			fprintf(stderr, "PAGE: 1 1\n");
-			lseek(fd, 0, SEEK_SET);
-		}
-
-		while ((len = read(fd, buf, sizeof(buf))) > 0) {
-			err = write(sk, buf, len);
-			if (err < 0) {
-				perror("ERROR: Error writing to device");
-				close(sk);
-				return CUPS_BACKEND_FAILED;
-			}
-		}
-
-	}
-
-	close(sk);
-
-	return CUPS_BACKEND_OK;
-}
diff --git a/profiles/cups/cups.h b/profiles/cups/cups.h
new file mode 100644
index 0000000..f4e0c01
--- /dev/null
+++ b/profiles/cups/cups.h
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+enum {					/**** Backend exit codes ****/
+	CUPS_BACKEND_OK = 0,		/* Job completed successfully */
+	CUPS_BACKEND_FAILED = 1,	/* Job failed, use error-policy */
+	CUPS_BACKEND_AUTH_REQUIRED = 2,	/* Job failed, authentication required */
+	CUPS_BACKEND_HOLD = 3,		/* Job failed, hold job */
+	CUPS_BACKEND_STOP = 4,		/* Job failed, stop queue */
+	CUPS_BACKEND_CANCEL = 5,	/* Job failed, cancel job */
+	CUPS_BACKEND_RETRY = 6,		/* Failure requires us to retry (BlueZ specific) */
+};
+
+int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);
+int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm);
+
+int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class);
+int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class);
diff --git a/profiles/cups/hcrp.c b/profiles/cups/hcrp.c
new file mode 100644
index 0000000..a93dda0
--- /dev/null
+++ b/profiles/cups/hcrp.c
@@ -0,0 +1,368 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include <netinet/in.h>
+
+#include "cups.h"
+
+#define HCRP_PDU_CREDIT_GRANT		0x0001
+#define HCRP_PDU_CREDIT_REQUEST		0x0002
+#define HCRP_PDU_GET_LPT_STATUS		0x0005
+
+#define HCRP_STATUS_FEATURE_UNSUPPORTED	0x0000
+#define HCRP_STATUS_SUCCESS		0x0001
+#define HCRP_STATUS_CREDIT_SYNC_ERROR	0x0002
+#define HCRP_STATUS_GENERIC_FAILURE	0xffff
+
+struct hcrp_pdu_hdr {
+	uint16_t pid;
+	uint16_t tid;
+	uint16_t plen;
+} __attribute__ ((packed));
+#define HCRP_PDU_HDR_SIZE 6
+
+struct hcrp_credit_grant_cp {
+	uint32_t credit;
+} __attribute__ ((packed));
+#define HCRP_CREDIT_GRANT_CP_SIZE 4
+
+struct hcrp_credit_grant_rp {
+	uint16_t status;
+} __attribute__ ((packed));
+#define HCRP_CREDIT_GRANT_RP_SIZE 2
+
+struct hcrp_credit_request_rp {
+	uint16_t status;
+	uint32_t credit;
+} __attribute__ ((packed));
+#define HCRP_CREDIT_REQUEST_RP_SIZE 6
+
+struct hcrp_get_lpt_status_rp {
+	uint16_t status;
+	uint8_t  lpt_status;
+} __attribute__ ((packed));
+#define HCRP_GET_LPT_STATUS_RP_SIZE 3
+
+static int hcrp_credit_grant(int sk, uint16_t tid, uint32_t credit)
+{
+	struct hcrp_pdu_hdr hdr;
+	struct hcrp_credit_grant_cp cp;
+	struct hcrp_credit_grant_rp rp;
+	unsigned char buf[128];
+	int len;
+
+	hdr.pid = htons(HCRP_PDU_CREDIT_GRANT);
+	hdr.tid = htons(tid);
+	hdr.plen = htons(HCRP_CREDIT_GRANT_CP_SIZE);
+	cp.credit = credit;
+	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
+	memcpy(buf + HCRP_PDU_HDR_SIZE, &cp, HCRP_CREDIT_GRANT_CP_SIZE);
+	len = write(sk, buf, HCRP_PDU_HDR_SIZE + HCRP_CREDIT_GRANT_CP_SIZE);
+	if (len < 0)
+		return len;
+
+	len = read(sk, buf, sizeof(buf));
+	if (len < 0)
+		return len;
+
+	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
+	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_GRANT_RP_SIZE);
+
+	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
+		errno = EIO;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int hcrp_credit_request(int sk, uint16_t tid, uint32_t *credit)
+{
+	struct hcrp_pdu_hdr hdr;
+	struct hcrp_credit_request_rp rp;
+	unsigned char buf[128];
+	int len;
+
+	hdr.pid = htons(HCRP_PDU_CREDIT_REQUEST);
+	hdr.tid = htons(tid);
+	hdr.plen = htons(0);
+	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
+	len = write(sk, buf, HCRP_PDU_HDR_SIZE);
+	if (len < 0)
+		return len;
+
+	len = read(sk, buf, sizeof(buf));
+	if (len < 0)
+		return len;
+
+	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
+	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_REQUEST_RP_SIZE);
+
+	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
+		errno = EIO;
+		return -1;
+	}
+
+	if (credit)
+		*credit = ntohl(rp.credit);
+
+	return 0;
+}
+
+static int hcrp_get_lpt_status(int sk, uint16_t tid, uint8_t *lpt_status)
+{
+	struct hcrp_pdu_hdr hdr;
+	struct hcrp_get_lpt_status_rp rp;
+	unsigned char buf[128];
+	int len;
+
+	hdr.pid = htons(HCRP_PDU_GET_LPT_STATUS);
+	hdr.tid = htons(tid);
+	hdr.plen = htons(0);
+	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
+	len = write(sk, buf, HCRP_PDU_HDR_SIZE);
+	if (len < 0)
+		return len;
+
+	len = read(sk, buf, sizeof(buf));
+	if (len < 0)
+		return len;
+
+	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
+	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_GET_LPT_STATUS_RP_SIZE);
+
+	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
+		errno = EIO;
+		return -1;
+	}
+
+	if (lpt_status)
+		*lpt_status = rp.lpt_status;
+
+	return 0;
+}
+
+static inline int hcrp_get_next_tid(int tid)
+{
+	if (tid > 0xf000)
+		return 0;
+	else
+		return tid + 1;
+}
+
+int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class)
+{
+	struct sockaddr_l2 addr;
+	struct l2cap_options opts;
+	socklen_t size;
+	unsigned char buf[2048];
+	int i, ctrl_sk, data_sk, count, len, timeout = 0;
+	unsigned int mtu;
+	uint8_t status;
+	uint16_t tid = 0;
+	uint32_t tmp, credit = 0;
+
+	if ((ctrl_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
+		perror("ERROR: Can't create socket");
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, src);
+
+	if (bind(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("ERROR: Can't bind socket");
+		close(ctrl_sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, dst);
+	addr.l2_psm = htobs(ctrl_psm);
+
+	if (connect(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("ERROR: Can't connect to device");
+		close(ctrl_sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	if ((data_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
+		perror("ERROR: Can't create socket");
+		close(ctrl_sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, src);
+
+	if (bind(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("ERROR: Can't bind socket");
+		close(data_sk);
+		close(ctrl_sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, dst);
+	addr.l2_psm = htobs(data_psm);
+
+	if (connect(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("ERROR: Can't connect to device");
+		close(data_sk);
+		close(ctrl_sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	fputs("STATE: -connecting-to-device\n", stderr);
+
+	memset(&opts, 0, sizeof(opts));
+	size = sizeof(opts);
+
+	if (getsockopt(data_sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
+		perror("ERROR: Can't get socket options");
+		close(data_sk);
+		close(ctrl_sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	mtu = opts.omtu;
+
+	/* Ignore SIGTERM signals if printing from stdin */
+	if (fd == 0) {
+#ifdef HAVE_SIGSET
+		sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+		memset(&action, 0, sizeof(action));
+		sigemptyset(&action.sa_mask);
+		action.sa_handler = SIG_IGN;
+		sigaction(SIGTERM, &action, NULL);
+#else
+		signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+	}
+
+	tid = hcrp_get_next_tid(tid);
+	if (hcrp_credit_grant(ctrl_sk, tid, 0) < 0) {
+		fprintf(stderr, "ERROR: Can't grant initial credits\n");
+		close(data_sk);
+		close(ctrl_sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	for (i = 0; i < copies; i++) {
+
+		if (fd != 0) {
+			fprintf(stderr, "PAGE: 1 1\n");
+			lseek(fd, 0, SEEK_SET);
+		}
+
+		while (1) {
+			if (credit < mtu) {
+				tid = hcrp_get_next_tid(tid);
+				if (!hcrp_credit_request(ctrl_sk, tid, &tmp)) {
+					credit += tmp;
+					timeout = 0;
+				}
+			}
+
+			if (!credit) {
+				if (timeout++ > 300) {
+					tid = hcrp_get_next_tid(tid);
+					if (!hcrp_get_lpt_status(ctrl_sk, tid, &status))
+						fprintf(stderr, "ERROR: LPT status 0x%02x\n", status);
+					break;
+				}
+
+				sleep(1);
+				continue;
+			}
+
+			count = read(fd, buf, (credit > mtu) ? mtu : credit);
+			if (count <= 0)
+				break;
+
+			len = write(data_sk, buf, count);
+			if (len < 0) {
+				perror("ERROR: Error writing to device");
+				close(data_sk);
+				close(ctrl_sk);
+				return CUPS_BACKEND_FAILED;
+			}
+
+			if (len != count)
+				fprintf(stderr, "ERROR: Can't send complete data\n");
+
+			credit -= len;
+		}
+
+	}
+
+	close(data_sk);
+	close(ctrl_sk);
+
+	return CUPS_BACKEND_OK;
+}
diff --git a/profiles/cups/main.c b/profiles/cups/main.c
new file mode 100644
index 0000000..a884c6e
--- /dev/null
+++ b/profiles/cups/main.c
@@ -0,0 +1,896 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <glib.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include <gdbus.h>
+
+#include "cups.h"
+
+struct cups_device {
+	char *bdaddr;
+	char *name;
+	char *id;
+};
+
+static GSList *device_list = NULL;
+static GMainLoop *loop = NULL;
+static DBusConnection *conn = NULL;
+static gboolean doing_disco = FALSE;
+
+#define ATTRID_1284ID 0x0300
+
+struct context_data {
+	gboolean found;
+	char *id;
+};
+
+static void element_start(GMarkupParseContext *context,
+				const gchar *element_name,
+				const gchar **attribute_names,
+				const gchar **attribute_values,
+				gpointer user_data, GError **err)
+{
+	struct context_data *ctx_data = user_data;
+
+	if (!strcmp(element_name, "record"))
+		return;
+
+	if (!strcmp(element_name, "attribute")) {
+		int i;
+		for (i = 0; attribute_names[i]; i++) {
+			if (strcmp(attribute_names[i], "id") != 0)
+				continue;
+			if (strtol(attribute_values[i], 0, 0) == ATTRID_1284ID)
+				ctx_data->found = TRUE;
+			break;
+		}
+		return;
+	}
+
+	if (ctx_data->found  && !strcmp(element_name, "text")) {
+		int i;
+		for (i = 0; attribute_names[i]; i++) {
+			if (!strcmp(attribute_names[i], "value")) {
+				ctx_data->id = g_strdup(attribute_values[i] + 2);
+				ctx_data->found = FALSE;
+			}
+		}
+	}
+}
+
+static GMarkupParser parser = {
+	element_start, NULL, NULL, NULL, NULL
+};
+
+static char *sdp_xml_parse_record(const char *data)
+{
+	GMarkupParseContext *ctx;
+	struct context_data ctx_data;
+	int size;
+
+	size = strlen(data);
+	ctx_data.found = FALSE;
+	ctx_data.id = NULL;
+	ctx = g_markup_parse_context_new(&parser, 0, &ctx_data, NULL);
+
+	if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
+		g_markup_parse_context_free(ctx);
+		g_free(ctx_data.id);
+		return NULL;
+	}
+
+	g_markup_parse_context_free(ctx);
+
+	return ctx_data.id;
+}
+
+static char *device_get_ieee1284_id(const char *adapter, const char *device)
+{
+	DBusMessage *message, *reply;
+	DBusMessageIter iter, reply_iter;
+	DBusMessageIter reply_iter_entry;
+	const char *hcr_print = "00001126-0000-1000-8000-00805f9b34fb";
+	const char *xml;
+	char *id = NULL;
+
+	/* Look for the service handle of the HCRP service */
+	message = dbus_message_new_method_call("org.bluez", device,
+						"org.bluez.Device",
+						"DiscoverServices");
+	dbus_message_iter_init_append(message, &iter);
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &hcr_print);
+
+	reply = dbus_connection_send_with_reply_and_block(conn,
+							message, -1, NULL);
+
+	dbus_message_unref(message);
+
+	if (!reply)
+		return NULL;
+
+	dbus_message_iter_init(reply, &reply_iter);
+
+	if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
+		dbus_message_unref(reply);
+		return NULL;
+	}
+
+	dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
+
+	/* Hopefully we only get one handle, or take a punt */
+	while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
+							DBUS_TYPE_DICT_ENTRY) {
+		guint32 key;
+		DBusMessageIter dict_entry;
+
+		dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
+
+		/* Key ? */
+		dbus_message_iter_get_basic(&dict_entry, &key);
+		if (!key) {
+			dbus_message_iter_next(&reply_iter_entry);
+			continue;
+		}
+
+		/* Try to get the value */
+		if (!dbus_message_iter_next(&dict_entry)) {
+			dbus_message_iter_next(&reply_iter_entry);
+			continue;
+		}
+
+		dbus_message_iter_get_basic(&dict_entry, &xml);
+
+		id = sdp_xml_parse_record(xml);
+		if (id != NULL)
+			break;
+		dbus_message_iter_next(&reply_iter_entry);
+	}
+
+	dbus_message_unref(reply);
+
+	return id;
+}
+
+static void print_printer_details(const char *name, const char *bdaddr,
+								const char *id)
+{
+	char *uri, *escaped;
+
+	escaped = g_strdelimit(g_strdup(name), "\"", '\'');
+	uri = g_strdup_printf("bluetooth://%c%c%c%c%c%c%c%c%c%c%c%c",
+				bdaddr[0], bdaddr[1],
+				bdaddr[3], bdaddr[4],
+				bdaddr[6], bdaddr[7],
+				bdaddr[9], bdaddr[10],
+				bdaddr[12], bdaddr[13],
+				bdaddr[15], bdaddr[16]);
+	printf("direct %s \"%s\" \"%s (Bluetooth)\"", uri, escaped, escaped);
+	if (id != NULL)
+		printf(" \"%s\"\n", id);
+	else
+		printf("\n");
+	g_free(escaped);
+	g_free(uri);
+}
+
+static void add_device_to_list(const char *name, const char *bdaddr,
+								const char *id)
+{
+	struct cups_device *device;
+	GSList *l;
+
+	/* Look for the device in the list */
+	for (l = device_list; l != NULL; l = l->next) {
+		device = (struct cups_device *) l->data;
+
+		if (strcmp(device->bdaddr, bdaddr) == 0) {
+			if (device->name != name) {
+				g_free(device->name);
+				device->name = g_strdup(name);
+			}
+			g_free(device->id);
+			device->id = g_strdup(id);
+			return;
+		}
+	}
+
+	/* Or add it to the list if it's not there */
+	device = g_new0(struct cups_device, 1);
+	device->bdaddr = g_strdup(bdaddr);
+	device->name = g_strdup(name);
+	device->id = g_strdup(id);
+
+	device_list = g_slist_prepend(device_list, device);
+	print_printer_details(device->name, device->bdaddr, device->id);
+}
+
+static gboolean parse_device_properties(DBusMessageIter *reply_iter,
+						char **name, char **bdaddr)
+{
+	guint32 class = 0;
+	DBusMessageIter reply_iter_entry;
+
+	if (dbus_message_iter_get_arg_type(reply_iter) != DBUS_TYPE_ARRAY)
+		return FALSE;
+
+	dbus_message_iter_recurse(reply_iter, &reply_iter_entry);
+
+	while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
+							DBUS_TYPE_DICT_ENTRY) {
+		const char *key;
+		DBusMessageIter dict_entry, iter_dict_val;
+
+		dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
+
+		/* Key == Class ? */
+		dbus_message_iter_get_basic(&dict_entry, &key);
+		if (!key) {
+			dbus_message_iter_next(&reply_iter_entry);
+			continue;
+		}
+
+		if (strcmp(key, "Class") != 0 &&
+				strcmp(key, "Alias") != 0 &&
+				strcmp(key, "Address") != 0) {
+			dbus_message_iter_next(&reply_iter_entry);
+			continue;
+		}
+
+		/* Try to get the value */
+		if (!dbus_message_iter_next(&dict_entry)) {
+			dbus_message_iter_next(&reply_iter_entry);
+			continue;
+		}
+		dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
+		if (strcmp(key, "Class") == 0) {
+			dbus_message_iter_get_basic(&iter_dict_val, &class);
+		} else {
+			const char *value;
+			dbus_message_iter_get_basic(&iter_dict_val, &value);
+			if (strcmp(key, "Alias") == 0) {
+				*name = g_strdup(value);
+			} else if (bdaddr) {
+				*bdaddr = g_strdup(value);
+			}
+		}
+		dbus_message_iter_next(&reply_iter_entry);
+	}
+
+	if (class == 0)
+		return FALSE;
+	if (((class & 0x1f00) >> 8) == 0x06 && (class & 0x80))
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean device_is_printer(const char *adapter, const char *device_path, char **name, char **bdaddr)
+{
+	DBusMessage *message, *reply;
+	DBusMessageIter reply_iter;
+	gboolean retval;
+
+	message = dbus_message_new_method_call("org.bluez", device_path,
+							"org.bluez.Device",
+							"GetProperties");
+
+	reply = dbus_connection_send_with_reply_and_block(conn,
+							message, -1, NULL);
+
+	dbus_message_unref(message);
+
+	if (!reply)
+		return FALSE;
+
+	dbus_message_iter_init(reply, &reply_iter);
+
+	retval = parse_device_properties(&reply_iter, name, bdaddr);
+
+	dbus_message_unref(reply);
+
+	return retval;
+}
+
+static void remote_device_found(const char *adapter, const char *bdaddr,
+							const char *name)
+{
+	DBusMessage *message, *reply, *adapter_reply;
+	DBusMessageIter iter;
+	char *object_path = NULL;
+	char *id;
+
+	adapter_reply = NULL;
+
+	if (adapter == NULL) {
+		message = dbus_message_new_method_call("org.bluez", "/",
+							"org.bluez.Manager",
+							"DefaultAdapter");
+
+		adapter_reply = dbus_connection_send_with_reply_and_block(conn,
+							message, -1, NULL);
+
+		dbus_message_unref(message);
+
+		if (!adapter_reply)
+			return;
+
+		if (dbus_message_get_args(adapter_reply, NULL,
+					DBUS_TYPE_OBJECT_PATH, &adapter,
+					DBUS_TYPE_INVALID) == FALSE) {
+			dbus_message_unref(adapter_reply);
+			return;
+		}
+	}
+
+	message = dbus_message_new_method_call("org.bluez", adapter,
+							"org.bluez.Adapter",
+							"FindDevice");
+	dbus_message_iter_init_append(message, &iter);
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
+
+	if (adapter_reply != NULL)
+		dbus_message_unref(adapter_reply);
+
+	reply = dbus_connection_send_with_reply_and_block(conn,
+							message, -1, NULL);
+
+	dbus_message_unref(message);
+
+	if (!reply) {
+		message = dbus_message_new_method_call("org.bluez", adapter,
+							"org.bluez.Adapter",
+							"CreateDevice");
+		dbus_message_iter_init_append(message, &iter);
+		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
+
+		reply = dbus_connection_send_with_reply_and_block(conn,
+							message, -1, NULL);
+
+		dbus_message_unref(message);
+
+		if (!reply)
+			return;
+	}
+
+	if (dbus_message_get_args(reply, NULL,
+					DBUS_TYPE_OBJECT_PATH, &object_path,
+					DBUS_TYPE_INVALID) == FALSE) {
+		dbus_message_unref(reply);
+		return;
+	}
+
+	id = device_get_ieee1284_id(adapter, object_path);
+	add_device_to_list(name, bdaddr, id);
+	g_free(id);
+
+	dbus_message_unref(reply);
+}
+
+static void discovery_completed(void)
+{
+	g_slist_free(device_list);
+	device_list = NULL;
+
+	g_main_loop_quit(loop);
+}
+
+static void remote_device_disappeared(const char *bdaddr)
+{
+	GSList *l;
+
+	for (l = device_list; l != NULL; l = l->next) {
+		struct cups_device *device = l->data;
+
+		if (strcmp(device->bdaddr, bdaddr) == 0) {
+			g_free(device->name);
+			g_free(device->bdaddr);
+			g_free(device);
+			device_list = g_slist_delete_link(device_list, l);
+			return;
+		}
+	}
+}
+
+static gboolean list_known_printers(const char *adapter)
+{
+	DBusMessageIter reply_iter, iter_array;
+	DBusError error;
+	DBusMessage *message, *reply;
+
+	message = dbus_message_new_method_call("org.bluez", adapter,
+						"org.bluez.Adapter",
+						"ListDevices");
+	if (message == NULL)
+		return FALSE;
+
+	dbus_error_init(&error);
+	reply = dbus_connection_send_with_reply_and_block(conn, message,
+								-1, &error);
+
+	dbus_message_unref(message);
+
+	if (dbus_error_is_set(&error))
+		return FALSE;
+
+	dbus_message_iter_init(reply, &reply_iter);
+	if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
+		dbus_message_unref(reply);
+		return FALSE;
+	}
+
+	dbus_message_iter_recurse(&reply_iter, &iter_array);
+	while (dbus_message_iter_get_arg_type(&iter_array) ==
+						DBUS_TYPE_OBJECT_PATH) {
+		const char *object_path;
+		char *name = NULL;
+		char *bdaddr = NULL;
+
+		dbus_message_iter_get_basic(&iter_array, &object_path);
+		if (device_is_printer(adapter, object_path, &name, &bdaddr)) {
+			char *id;
+
+			id = device_get_ieee1284_id(adapter, object_path);
+			add_device_to_list(name, bdaddr, id);
+			g_free(id);
+		}
+		g_free(name);
+		g_free(bdaddr);
+		dbus_message_iter_next(&iter_array);
+	}
+
+	dbus_message_unref(reply);
+
+	return FALSE;
+}
+
+static DBusHandlerResult filter_func(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	if (dbus_message_is_signal(message, "org.bluez.Adapter",
+						"DeviceFound")) {
+		const char *adapter, *bdaddr;
+		char *name;
+		DBusMessageIter iter;
+
+		dbus_message_iter_init(message, &iter);
+		dbus_message_iter_get_basic(&iter, &bdaddr);
+		dbus_message_iter_next(&iter);
+
+		adapter = dbus_message_get_path(message);
+		if (parse_device_properties(&iter, &name, NULL))
+			remote_device_found(adapter, bdaddr, name);
+		g_free (name);
+	} else if (dbus_message_is_signal(message, "org.bluez.Adapter",
+						"DeviceDisappeared")) {
+		const char *bdaddr;
+
+		dbus_message_get_args(message, NULL,
+					DBUS_TYPE_STRING, &bdaddr,
+					DBUS_TYPE_INVALID);
+		remote_device_disappeared(bdaddr);
+	} else if (dbus_message_is_signal(message, "org.bluez.Adapter",
+						"PropertyChanged")) {
+		DBusMessageIter iter, value_iter;
+		const char *name;
+		gboolean discovering;
+
+		dbus_message_iter_init(message, &iter);
+		dbus_message_iter_get_basic(&iter, &name);
+		if (name == NULL || strcmp(name, "Discovering") != 0)
+			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+		dbus_message_iter_next(&iter);
+		dbus_message_iter_recurse(&iter, &value_iter);
+		dbus_message_iter_get_basic(&value_iter, &discovering);
+
+		if (discovering == FALSE && doing_disco) {
+			doing_disco = FALSE;
+			discovery_completed();
+		}
+	}
+
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gboolean list_printers(void)
+{
+	/* 1. Connect to the bus
+	 * 2. Get the manager
+	 * 3. Get the default adapter
+	 * 4. Get a list of devices
+	 * 5. Get the class of each device
+	 * 6. Print the details from each printer device
+	 */
+	DBusError error;
+	dbus_bool_t hcid_exists;
+	DBusMessage *reply, *message;
+	DBusMessageIter reply_iter;
+	char *adapter, *match;
+
+	conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+	if (conn == NULL)
+		return TRUE;
+
+	dbus_error_init(&error);
+	hcid_exists = dbus_bus_name_has_owner(conn, "org.bluez", &error);
+	if (dbus_error_is_set(&error))
+		return TRUE;
+
+	if (!hcid_exists)
+		return TRUE;
+
+	/* Get the default adapter */
+	message = dbus_message_new_method_call("org.bluez", "/",
+						"org.bluez.Manager",
+						"DefaultAdapter");
+	if (message == NULL) {
+		dbus_connection_unref(conn);
+		return FALSE;
+	}
+
+	reply = dbus_connection_send_with_reply_and_block(conn,
+							message, -1, &error);
+
+	dbus_message_unref(message);
+
+	if (dbus_error_is_set(&error)) {
+		dbus_connection_unref(conn);
+		/* No adapter */
+		return TRUE;
+	}
+
+	dbus_message_iter_init(reply, &reply_iter);
+	if (dbus_message_iter_get_arg_type(&reply_iter) !=
+						DBUS_TYPE_OBJECT_PATH) {
+		dbus_message_unref(reply);
+		dbus_connection_unref(conn);
+		return FALSE;
+	}
+
+	dbus_message_iter_get_basic(&reply_iter, &adapter);
+	adapter = g_strdup(adapter);
+	dbus_message_unref(reply);
+
+	if (!dbus_connection_add_filter(conn, filter_func, adapter, g_free)) {
+		g_free(adapter);
+		dbus_connection_unref(conn);
+		return FALSE;
+	}
+
+#define MATCH_FORMAT				\
+	"type='signal',"			\
+	"interface='org.bluez.Adapter',"	\
+	"sender='org.bluez',"			\
+	"path='%s'"
+
+	match = g_strdup_printf(MATCH_FORMAT, adapter);
+	dbus_bus_add_match(conn, match, &error);
+	g_free(match);
+
+	/* Add the the recent devices */
+	list_known_printers(adapter);
+
+	doing_disco = TRUE;
+	message = dbus_message_new_method_call("org.bluez", adapter,
+					"org.bluez.Adapter",
+					"StartDiscovery");
+
+	if (!dbus_connection_send_with_reply(conn, message, NULL, -1)) {
+		dbus_message_unref(message);
+		dbus_connection_unref(conn);
+		g_free(adapter);
+		return FALSE;
+	}
+	dbus_message_unref(message);
+
+	loop = g_main_loop_new(NULL, TRUE);
+	g_main_loop_run(loop);
+
+	g_free(adapter);
+	dbus_connection_unref(conn);
+
+	return TRUE;
+}
+
+static gboolean print_ieee1284(const char *bdaddr)
+{
+	DBusMessage *message, *reply, *adapter_reply;
+	DBusMessageIter iter;
+	char *object_path = NULL;
+	char *adapter;
+	char *id;
+
+	adapter_reply = NULL;
+
+	conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+	if (conn == NULL)
+		return FALSE;
+
+	message = dbus_message_new_method_call("org.bluez", "/",
+			"org.bluez.Manager",
+			"DefaultAdapter");
+
+	adapter_reply = dbus_connection_send_with_reply_and_block(conn,
+			message, -1, NULL);
+
+	dbus_message_unref(message);
+
+	if (!adapter_reply)
+		return FALSE;
+
+	if (dbus_message_get_args(adapter_reply, NULL,
+			DBUS_TYPE_OBJECT_PATH, &adapter,
+			DBUS_TYPE_INVALID) == FALSE) {
+		dbus_message_unref(adapter_reply);
+		return FALSE;
+	}
+
+	message = dbus_message_new_method_call("org.bluez", adapter,
+			"org.bluez.Adapter",
+			"FindDevice");
+	dbus_message_iter_init_append(message, &iter);
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
+
+	if (adapter_reply != NULL)
+		dbus_message_unref(adapter_reply);
+
+	reply = dbus_connection_send_with_reply_and_block(conn,
+			message, -1, NULL);
+
+	dbus_message_unref(message);
+
+	if (!reply) {
+		message = dbus_message_new_method_call("org.bluez", adapter,
+				"org.bluez.Adapter",
+				"CreateDevice");
+		dbus_message_iter_init_append(message, &iter);
+		dbus_message_iter_append_basic(&iter,
+				DBUS_TYPE_STRING, &bdaddr);
+
+		reply = dbus_connection_send_with_reply_and_block(conn,
+				message, -1, NULL);
+
+		dbus_message_unref(message);
+
+		if (!reply)
+			return FALSE;
+	}
+
+	if (dbus_message_get_args(reply, NULL,
+					DBUS_TYPE_OBJECT_PATH, &object_path,
+					DBUS_TYPE_INVALID) == FALSE) {
+		dbus_message_unref(reply);
+		return FALSE;
+	}
+
+	id = device_get_ieee1284_id(adapter, object_path);
+	if (id == NULL) {
+		dbus_message_unref(reply);
+		return FALSE;
+	}
+	printf("%s", id);
+	g_free(id);
+
+	dbus_message_unref(reply);
+
+	return TRUE;
+}
+
+/*
+ *  Usage: printer-uri job-id user title copies options [file]
+ *
+ */
+
+int main(int argc, char *argv[])
+{
+	sdp_session_t *sdp;
+	bdaddr_t bdaddr;
+	unsigned short ctrl_psm, data_psm;
+	uint8_t channel, b[6];
+	char *ptr, str[3], device[18], service[12];
+	const char *uri, *cups_class;
+	int i, err, fd, copies, proto;
+
+	/* Make sure status messages are not buffered */
+	setbuf(stderr, NULL);
+
+	/* Make sure output is not buffered */
+	setbuf(stdout, NULL);
+
+	/* Ignore SIGPIPE signals */
+#ifdef HAVE_SIGSET
+	sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+	memset(&action, 0, sizeof(action));
+	action.sa_handler = SIG_IGN;
+	sigaction(SIGPIPE, &action, NULL);
+#else
+	signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+	if (argc == 1) {
+		if (list_printers() == TRUE)
+			return CUPS_BACKEND_OK;
+		else
+			return CUPS_BACKEND_FAILED;
+	} else if (argc == 3 && strcmp(argv[1], "--get-deviceid") == 0) {
+		if (bachk(argv[2]) < 0) {
+			fprintf(stderr, "Invalid Bluetooth address '%s'\n",
+					argv[2]);
+			return CUPS_BACKEND_FAILED;
+		}
+		if (print_ieee1284(argv[2]) == FALSE)
+			return CUPS_BACKEND_FAILED;
+		return CUPS_BACKEND_OK;
+	}
+
+	if (argc < 6 || argc > 7) {
+		fprintf(stderr, "Usage: bluetooth job-id user title copies"
+				" options [file]\n");
+		fprintf(stderr, "       bluetooth --get-deviceid [bdaddr]\n");
+		return CUPS_BACKEND_FAILED;
+	}
+
+	if (argc == 6) {
+		fd = 0;
+		copies = 1;
+	} else {
+		if ((fd = open(argv[6], O_RDONLY)) < 0) {
+			perror("ERROR: Unable to open print file");
+			return CUPS_BACKEND_FAILED;
+		}
+		copies = atoi(argv[4]);
+	}
+
+	uri = getenv("DEVICE_URI");
+	if (!uri)
+		uri = argv[0];
+
+	if (strncasecmp(uri, "bluetooth://", 12)) {
+		fprintf(stderr, "ERROR: No device URI found\n");
+		return CUPS_BACKEND_FAILED;
+	}
+
+	ptr = argv[0] + 12;
+	for (i = 0; i < 6; i++) {
+		strncpy(str, ptr, 2);
+		b[i] = (uint8_t) strtol(str, NULL, 16);
+		ptr += 2;
+	}
+	sprintf(device, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+			b[0], b[1], b[2], b[3], b[4], b[5]);
+
+	str2ba(device, &bdaddr);
+
+	ptr = strchr(ptr, '/');
+	if (ptr) {
+		strncpy(service, ptr + 1, 12);
+
+		if (!strncasecmp(ptr + 1, "spp", 3))
+			proto = 1;
+		else if (!strncasecmp(ptr + 1, "hcrp", 4))
+			proto = 2;
+		else
+			proto = 0;
+	} else {
+		strcpy(service, "auto");
+		proto = 0;
+	}
+
+	cups_class = getenv("CLASS");
+
+	fprintf(stderr,
+		"DEBUG: %s device %s service %s fd %d copies %d class %s\n",
+			argv[0], device, service, fd, copies,
+			cups_class ? cups_class : "(none)");
+
+	fputs("STATE: +connecting-to-device\n", stderr);
+
+service_search:
+	sdp = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
+	if (!sdp) {
+		fprintf(stderr, "ERROR: Can't open Bluetooth connection\n");
+		return CUPS_BACKEND_FAILED;
+	}
+
+	switch (proto) {
+	case 1:
+		err = sdp_search_spp(sdp, &channel);
+		break;
+	case 2:
+		err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
+		break;
+	default:
+		proto = 2;
+		err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
+		if (err) {
+			proto = 1;
+			err = sdp_search_spp(sdp, &channel);
+		}
+		break;
+	}
+
+	sdp_close(sdp);
+
+	if (err) {
+		if (cups_class) {
+			fputs("INFO: Unable to contact printer, queuing on "
+					"next printer in class...\n", stderr);
+			sleep(5);
+			return CUPS_BACKEND_FAILED;
+		}
+		sleep(20);
+		fprintf(stderr, "ERROR: Can't get service information\n");
+		goto service_search;
+	}
+
+connect:
+	switch (proto) {
+	case 1:
+		err = spp_print(BDADDR_ANY, &bdaddr, channel,
+						fd, copies, cups_class);
+		break;
+	case 2:
+		err = hcrp_print(BDADDR_ANY, &bdaddr, ctrl_psm, data_psm,
+						fd, copies, cups_class);
+		break;
+	default:
+		err = CUPS_BACKEND_FAILED;
+		fprintf(stderr, "ERROR: Unsupported protocol\n");
+		break;
+	}
+
+	if (err == CUPS_BACKEND_FAILED && cups_class) {
+		fputs("INFO: Unable to contact printer, queuing on "
+					"next printer in class...\n", stderr);
+		sleep(5);
+		return CUPS_BACKEND_FAILED;
+	} else if (err == CUPS_BACKEND_RETRY) {
+		sleep(20);
+		goto connect;
+	}
+
+	if (fd != 0)
+		close(fd);
+
+	if (!err)
+		fprintf(stderr, "INFO: Ready to print\n");
+
+	return err;
+}
diff --git a/profiles/cups/sdp.c b/profiles/cups/sdp.c
new file mode 100644
index 0000000..c7f17a4
--- /dev/null
+++ b/profiles/cups/sdp.c
@@ -0,0 +1,119 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "cups.h"
+
+int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm)
+{
+	sdp_list_t *srch, *attrs, *rsp;
+	uuid_t svclass;
+	uint16_t attr1, attr2;
+	int err;
+
+	if (!sdp)
+		return -1;
+
+	sdp_uuid16_create(&svclass, HCR_PRINT_SVCLASS_ID);
+	srch = sdp_list_append(NULL, &svclass);
+
+	attr1 = SDP_ATTR_PROTO_DESC_LIST;
+	attrs = sdp_list_append(NULL, &attr1);
+	attr2 = SDP_ATTR_ADD_PROTO_DESC_LIST;
+	attrs = sdp_list_append(attrs, &attr2);
+
+	err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
+	if (err)
+		return -1;
+
+	for (; rsp; rsp = rsp->next) {
+		sdp_record_t *rec = (sdp_record_t *) rsp->data;
+		sdp_list_t *protos;
+
+		if (!sdp_get_access_protos(rec, &protos)) {
+			unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
+			if (psm > 0) {
+				*ctrl_psm = psm;
+			}
+		}
+
+		if (!sdp_get_add_access_protos(rec, &protos)) {
+			unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
+			if (psm > 0 && *ctrl_psm > 0) {
+				*data_psm = psm;
+				return 0;
+			}
+		}
+	}
+
+	return -1;
+}
+
+int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel)
+{
+	sdp_list_t *srch, *attrs, *rsp;
+	uuid_t svclass;
+	uint16_t attr;
+	int err;
+
+	if (!sdp)
+		return -1;
+
+	sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID);
+	srch = sdp_list_append(NULL, &svclass);
+
+	attr = SDP_ATTR_PROTO_DESC_LIST;
+	attrs = sdp_list_append(NULL, &attr);
+
+	err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
+	if (err)
+		return -1;
+
+	for (; rsp; rsp = rsp->next) {
+		sdp_record_t *rec = (sdp_record_t *) rsp->data;
+		sdp_list_t *protos;
+
+		if (!sdp_get_access_protos(rec, &protos)) {
+			uint8_t ch = sdp_get_proto_port(protos, RFCOMM_UUID);
+			if (ch > 0) {
+				*channel = ch;
+				return 0;
+			}
+		}
+	}
+
+	return -1;
+}
diff --git a/profiles/cups/spp.c b/profiles/cups/spp.c
new file mode 100644
index 0000000..d906ed2
--- /dev/null
+++ b/profiles/cups/spp.c
@@ -0,0 +1,118 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "cups.h"
+
+int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class)
+{
+	struct sockaddr_rc addr;
+	unsigned char buf[2048];
+	int i, sk, err, len;
+
+	if ((sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
+		perror("ERROR: Can't create socket");
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, src);
+	addr.rc_channel = 0;
+
+	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("ERROR: Can't bind socket");
+		close(sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, dst);
+	addr.rc_channel = channel;
+
+	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("ERROR: Can't connect to device");
+		close(sk);
+		if (cups_class)
+			return CUPS_BACKEND_FAILED;
+		else
+			return CUPS_BACKEND_RETRY;
+	}
+
+	fputs("STATE: -connecting-to-device\n", stderr);
+
+	/* Ignore SIGTERM signals if printing from stdin */
+	if (fd == 0) {
+#ifdef HAVE_SIGSET
+		sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+		memset(&action, 0, sizeof(action));
+		sigemptyset(&action.sa_mask);
+		action.sa_handler = SIG_IGN;
+		sigaction(SIGTERM, &action, NULL);
+#else
+		signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+	}
+
+	for (i = 0; i < copies; i++) {
+
+		if (fd != 0) {
+			fprintf(stderr, "PAGE: 1 1\n");
+			lseek(fd, 0, SEEK_SET);
+		}
+
+		while ((len = read(fd, buf, sizeof(buf))) > 0) {
+			err = write(sk, buf, len);
+			if (err < 0) {
+				perror("ERROR: Error writing to device");
+				close(sk);
+				return CUPS_BACKEND_FAILED;
+			}
+		}
+
+	}
+
+	close(sk);
+
+	return CUPS_BACKEND_OK;
+}
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 14/14] plugins: remove unmaintained plugins
  2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
                   ` (6 preceding siblings ...)
  2012-07-09 21:10 ` [PATCH 12/14] cups: move it to " Gustavo Padovan
@ 2012-07-09 21:10 ` Gustavo Padovan
  7 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2012-07-09 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

---
 Makefile.am         |   15 --
 acinclude.m4        |   18 --
 bootstrap-configure |    2 -
 plugins/hal.c       |  144 --------------
 plugins/maemo6.c    |  283 ---------------------------
 plugins/pnat.c      |  526 ---------------------------------------------------
 6 files changed, 988 deletions(-)
 delete mode 100644 plugins/hal.c
 delete mode 100644 plugins/maemo6.c
 delete mode 100644 plugins/pnat.c

diff --git a/Makefile.am b/Makefile.am
index a769228..65d2b78 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,11 +132,6 @@ mcap_sources += profiles/health/mcap_lib.h profiles/health/mcap_internal.h \
 		profiles/health/mcap_sync.c
 endif
 
-if PNATPLUGIN
-builtin_modules += pnat
-builtin_sources += plugins/pnat.c
-endif
-
 if AUDIOPLUGIN
 builtin_modules += audio
 builtin_sources += audio/main.c \
@@ -248,13 +243,8 @@ endif
 builtin_modules += mgmtops
 builtin_sources += plugins/mgmtops.c
 
-if HAL
-builtin_modules += hal
-builtin_sources += plugins/hal.c
-else
 builtin_modules += formfactor
 builtin_sources += plugins/formfactor.c
-endif
 
 EXTRA_DIST += plugins/hal.c plugins/formfactor.c
 
@@ -269,11 +259,6 @@ builtin_modules += wiimote
 builtin_sources += plugins/wiimote.c
 endif
 
-if MAEMO6PLUGIN
-builtin_modules += maemo6
-builtin_sources += plugins/maemo6.c
-endif
-
 if DBUSOOBPLUGIN
 builtin_modules += dbusoob
 builtin_sources += plugins/dbusoob.c
diff --git a/acinclude.m4 b/acinclude.m4
index 842eea3..39b0a18 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -167,7 +167,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	fortify_enable=yes
 	pie_enable=yes
 	sndfile_enable=${sndfile_found}
-	hal_enable=no
 	usb_enable=${usb_found}
 	gstreamer_enable=${gstreamer_found}
 	audio_enable=yes
@@ -176,7 +175,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	sap_enable=no
 	service_enable=yes
 	health_enable=no
-	pnat_enable=no
 	tools_enable=yes
 	cups_enable=no
 	test_enable=no
@@ -186,7 +184,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	dfutool_enable=no
 	datafiles_enable=yes
 	telephony_driver=dummy
-	maemo6_enable=no
 	sap_driver=dummy
 	dbusoob_enable=no
 	wiimote_enable=no
@@ -233,10 +230,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		health_enable=${enableval}
 	])
 
-	AC_ARG_ENABLE(pnat, AC_HELP_STRING([--enable-pnat], [enable pnat plugin]), [
-		pnat_enable=${enableval}
-	])
-
 	AC_ARG_ENABLE(gstreamer, AC_HELP_STRING([--enable-gstreamer], [enable GStreamer support]), [
 		gstreamer_enable=${enableval}
 	])
@@ -287,10 +280,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 
 	AC_SUBST([TELEPHONY_DRIVER], [telephony-${telephony_driver}.c])
 
-	AC_ARG_ENABLE(maemo6, AC_HELP_STRING([--enable-maemo6], [compile with maemo6 plugin]), [
-		maemo6_enable=${enableval}
-	])
-
 	AC_ARG_ENABLE(dbusoob, AC_HELP_STRING([--enable-dbusoob], [compile with D-Bus OOB plugin]), [
 		dbusoob_enable=${enableval}
 	])
@@ -299,10 +288,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		wiimote_enable=${enableval}
 	])
 
-	AC_ARG_ENABLE(hal, AC_HELP_STRING([--enable-hal], [Use HAL to determine adapter class]), [
-		hal_enable=${enableval}
-	])
-
 	AC_ARG_ENABLE(gatt, AC_HELP_STRING([--enable-gatt], [enable gatt module]), [
 		gatt_enable=${enableval}
 	])
@@ -345,9 +330,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes")
 	AM_CONDITIONAL(HEALTHPLUGIN, test "${health_enable}" = "yes")
 	AM_CONDITIONAL(MCAP, test "${health_enable}" = "yes")
-	AM_CONDITIONAL(HAL, test "${hal_enable}" = "yes")
 	AM_CONDITIONAL(READLINE, test "${readline_found}" = "yes")
-	AM_CONDITIONAL(PNATPLUGIN, test "${pnat_enable}" = "yes")
 	AM_CONDITIONAL(CUPS, test "${cups_enable}" = "yes")
 	AM_CONDITIONAL(TEST, test "${test_enable}" = "yes" && test "${check_found}" = "yes")
 	AM_CONDITIONAL(TOOLS, test "${tools_enable}" = "yes")
@@ -356,7 +339,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(HID2HCI, test "${hid2hci_enable}" = "yes" && test "${usb_found}" = "yes" && test "${udev_found}" = "yes")
 	AM_CONDITIONAL(DFUTOOL, test "${dfutool_enable}" = "yes" && test "${usb_found}" = "yes")
 	AM_CONDITIONAL(DATAFILES, test "${datafiles_enable}" = "yes")
-	AM_CONDITIONAL(MAEMO6PLUGIN, test "${maemo6_enable}" = "yes")
 	AM_CONDITIONAL(DBUSOOBPLUGIN, test "${dbusoob_enable}" = "yes")
 	AM_CONDITIONAL(WIIMOTEPLUGIN, test "${wiimote_enable}" = "yes")
 	AM_CONDITIONAL(GATTMODULES, test "${gatt_enable}" = "yes")
diff --git a/bootstrap-configure b/bootstrap-configure
index ff63c58..7177c65 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -24,8 +24,6 @@ fi
 		--enable-test \
 		--enable-cups \
 		--enable-dbusoob \
-		--enable-maemo6 \
-		--enable-pnat \
 		--enable-sap \
 		--enable-wiimote \
 		--disable-pcmcia \
diff --git a/plugins/hal.c b/plugins/hal.c
deleted file mode 100644
index 21d7688..0000000
--- a/plugins/hal.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <dbus/dbus.h>
-
-#include <bluetooth/bluetooth.h>
-
-#include "plugin.h"
-#include "adapter.h"
-#include "log.h"
-
-static void formfactor_reply(DBusPendingCall *call, void *user_data)
-{
-	struct btd_adapter *adapter = user_data;
-	const char *formfactor = NULL;
-	DBusMessage *reply;
-	uint8_t minor = 0;
-
-	reply = dbus_pending_call_steal_reply(call);
-
-	if (dbus_set_error_from_message(NULL, reply) == TRUE) {
-		error("Failed to access HAL");
-		dbus_message_unref(reply);
-		return;
-	}
-
-	if (dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &formfactor,
-						DBUS_TYPE_INVALID) == FALSE) {
-		error("Wrong formfactor arguments");
-		dbus_message_unref(reply);
-		return;
-	}
-
-	DBG("Computer is classified as %s", formfactor);
-
-	if (formfactor != NULL) {
-		if (g_str_equal(formfactor, "laptop") == TRUE)
-			minor |= (1 << 2) | (1 << 3);
-		else if (g_str_equal(formfactor, "desktop") == TRUE)
-			minor |= 1 << 2;
-		else if (g_str_equal(formfactor, "server") == TRUE)
-			minor |= 1 << 3;
-		else if (g_str_equal(formfactor, "handheld") == TRUE)
-			minor += 1 << 4;
-	}
-
-	dbus_message_unref(reply);
-
-	/* Computer major class */
-	DBG("Setting 0x%06x for major/minor device class", (1 << 8) | minor);
-
-	btd_adapter_set_class(adapter, 0x01, minor);
-}
-
-static DBusConnection *connection;
-
-static int hal_probe(struct btd_adapter *adapter)
-{
-	const char *property = "system.formfactor";
-	DBusMessage *message;
-	DBusPendingCall *call;
-
-	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
-	if (connection == NULL)
-		return -ENOMEM;
-
-	message = dbus_message_new_method_call("org.freedesktop.Hal",
-				"/org/freedesktop/Hal/devices/computer",
-						"org.freedesktop.Hal.Device",
-							"GetPropertyString");
-	if (message == NULL) {
-		error("Failed to create formfactor request");
-		dbus_connection_unref(connection);
-		return -ENOMEM;
-	}
-
-	dbus_message_append_args(message, DBUS_TYPE_STRING, &property,
-							DBUS_TYPE_INVALID);
-
-	if (dbus_connection_send_with_reply(connection, message,
-						&call, -1) == FALSE) {
-		error("Failed to send formfactor request");
-		dbus_message_unref(message);
-		dbus_connection_unref(connection);
-		return -EIO;
-	}
-
-	dbus_pending_call_set_notify(call, formfactor_reply, adapter, NULL);
-
-	dbus_pending_call_unref(call);
-
-	dbus_message_unref(message);
-
-	return 0;
-}
-
-static void hal_remove(struct btd_adapter *adapter)
-{
-	dbus_connection_unref(connection);
-}
-
-static struct btd_adapter_driver hal_driver = {
-	.name	= "hal",
-	.probe	= hal_probe,
-	.remove	= hal_remove,
-};
-
-static int hal_init(void)
-{
-	return btd_register_adapter_driver(&hal_driver);
-}
-
-static void hal_exit(void)
-{
-	btd_unregister_adapter_driver(&hal_driver);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(hal, VERSION,
-		BLUETOOTH_PLUGIN_PRIORITY_LOW, hal_init, hal_exit)
diff --git a/plugins/maemo6.c b/plugins/maemo6.c
deleted file mode 100644
index 4819af4..0000000
--- a/plugins/maemo6.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2006-2010  Nokia Corporation
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <dbus/dbus.h>
-
-#include "adapter.h"
-#include "plugin.h"
-#include "log.h"
-#include "gdbus.h"
-
-/* from mce/mode-names.h */
-#define MCE_RADIO_STATE_BLUETOOTH	(1 << 3)
-
-/* from mce/dbus-names.h */
-#define MCE_SERVICE			"com.nokia.mce"
-#define MCE_REQUEST_IF			"com.nokia.mce.request"
-#define MCE_SIGNAL_IF			"com.nokia.mce.signal"
-#define MCE_REQUEST_PATH		"/com/nokia/mce/request"
-#define MCE_SIGNAL_PATH			"/com/nokia/mce/signal"
-#define MCE_RADIO_STATES_CHANGE_REQ	"req_radio_states_change"
-#define MCE_RADIO_STATES_GET		"get_radio_states"
-#define MCE_RADIO_STATES_SIG		"radio_states_ind"
-#define MCE_TKLOCK_MODE_SIG		"tklock_mode_ind"
-
-static guint watch_id;
-static guint tklock_watch_id;
-static DBusConnection *conn = NULL;
-static gboolean mce_bt_set = FALSE;
-static gboolean mce_bt_on = FALSE;
-
-static gboolean mce_tklock_mode_cb(DBusConnection *connection,
-					DBusMessage *message, void *user_data)
-{
-	struct btd_adapter *adapter = user_data;
-	DBusMessageIter args;
-	const char *sigvalue;
-
-	if (!dbus_message_iter_init(message, &args)) {
-		error("message has no arguments");
-	} else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
-		error("argument is not string");
-	} else {
-
-		dbus_message_iter_get_basic(&args, &sigvalue);
-		DBG("got signal with value %s", sigvalue);
-
-		if (g_strcmp0("unlocked", sigvalue) == 0 && mce_bt_on)
-			btd_adapter_enable_auto_connect(adapter);
-	}
-
-	return TRUE;
-}
-
-static gboolean mce_signal_callback(DBusConnection *connection,
-					DBusMessage *message, void *user_data)
-{
-	DBusMessageIter args;
-	uint32_t sigvalue;
-	struct btd_adapter *adapter = user_data;
-	int err;
-
-	DBG("received mce signal");
-
-	if (!dbus_message_iter_init(message, &args))
-		error("message has no arguments");
-	else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
-		error("argument is not uint32");
-	else {
-		dbus_message_iter_get_basic(&args, &sigvalue);
-		DBG("got signal with value %u", sigvalue);
-
-		/* set the adapter according to the mce signal
-		   and remember the value */
-		mce_bt_on = sigvalue & MCE_RADIO_STATE_BLUETOOTH ? TRUE : FALSE;
-
-		if (mce_bt_on)
-			err = btd_adapter_switch_online(adapter);
-		else
-			err = btd_adapter_switch_offline(adapter);
-
-		if (err == 0)
-			mce_bt_set = TRUE;
-
-	}
-
-	return TRUE;
-}
-
-static void read_radio_states_cb(DBusPendingCall *call, void *user_data)
-{
-	DBusError derr;
-	DBusMessage *reply;
-	dbus_uint32_t radio_states;
-	struct btd_adapter *adapter = user_data;
-	int err;
-
-	reply = dbus_pending_call_steal_reply(call);
-
-	dbus_error_init(&derr);
-	if (dbus_set_error_from_message(&derr, reply)) {
-		error("mce replied with an error: %s, %s",
-				derr.name, derr.message);
-		dbus_error_free(&derr);
-		goto done;
-	}
-
-	if (dbus_message_get_args(reply, &derr,
-				DBUS_TYPE_UINT32, &radio_states,
-				DBUS_TYPE_INVALID) == FALSE) {
-		error("unable to parse get_radio_states reply: %s, %s",
-							derr.name, derr.message);
-		dbus_error_free(&derr);
-		goto done;
-	}
-
-	DBG("radio_states: %d", radio_states);
-
-	mce_bt_on = radio_states & MCE_RADIO_STATE_BLUETOOTH ? TRUE : FALSE;
-
-	if (mce_bt_on)
-		err = btd_adapter_switch_online(adapter);
-	else
-		err = btd_adapter_switch_offline(adapter);
-
-	if (err == 0)
-		mce_bt_set = TRUE;
-
-done:
-	dbus_message_unref(reply);
-}
-
-static void adapter_powered(struct btd_adapter *adapter, gboolean powered)
-{
-	DBusMessage *msg;
-	static gboolean startup = TRUE;
-
-	DBG("adapter_powered called with %d", powered);
-
-	if (startup) {
-		DBusPendingCall *call;
-
-		/* Initialization: sync adapter state and MCE radio state */
-
-		DBG("Startup: reading MCE Bluetooth radio state...");
-		startup = FALSE;
-
-		msg = dbus_message_new_method_call(MCE_SERVICE,
-					MCE_REQUEST_PATH, MCE_REQUEST_IF,
-					MCE_RADIO_STATES_GET);
-
-		if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
-			error("calling %s failed", MCE_RADIO_STATES_GET);
-			dbus_message_unref(msg);
-			return;
-		}
-
-		dbus_pending_call_set_notify(call, read_radio_states_cb,
-								adapter, NULL);
-		dbus_pending_call_unref(call);
-		dbus_message_unref(msg);
-		return;
-	}
-
-	/* MCE initiated operation */
-	if (mce_bt_set == TRUE) {
-		mce_bt_set = FALSE;
-		return;
-	}
-
-	/* Non MCE operation: set MCE according to adapter state */
-	if (mce_bt_on != powered) {
-		dbus_uint32_t radio_states;
-		dbus_uint32_t radio_mask = MCE_RADIO_STATE_BLUETOOTH;
-
-		msg = dbus_message_new_method_call(MCE_SERVICE,
-					MCE_REQUEST_PATH, MCE_REQUEST_IF,
-					MCE_RADIO_STATES_CHANGE_REQ);
-
-		radio_states = (powered ? MCE_RADIO_STATE_BLUETOOTH : 0);
-
-		DBG("Changing MCE Bluetooth radio state to: %d", radio_states);
-
-		dbus_message_append_args(msg, DBUS_TYPE_UINT32, &radio_states,
-					DBUS_TYPE_UINT32, &radio_mask,
-					DBUS_TYPE_INVALID);
-
-		if (dbus_connection_send(conn, msg, NULL))
-			mce_bt_on = powered;
-		else
-			error("calling %s failed", MCE_RADIO_STATES_CHANGE_REQ);
-
-		dbus_message_unref(msg);
-	}
-}
-
-static int mce_probe(struct btd_adapter *adapter)
-{
-
-	DBG("path %s", adapter_get_path(adapter));
-
-	watch_id = g_dbus_add_signal_watch(conn, NULL, MCE_SIGNAL_PATH,
-					MCE_SIGNAL_IF, MCE_RADIO_STATES_SIG,
-					mce_signal_callback, adapter, NULL);
-
-	tklock_watch_id = g_dbus_add_signal_watch(conn, NULL, MCE_SIGNAL_PATH,
-					MCE_SIGNAL_IF, MCE_TKLOCK_MODE_SIG,
-					mce_tklock_mode_cb, adapter, NULL);
-
-	btd_adapter_register_powered_callback(adapter, adapter_powered);
-
-	return 0;
-}
-
-static void mce_remove(struct btd_adapter *adapter)
-{
-	DBG("path %s", adapter_get_path(adapter));
-
-	if (watch_id > 0)
-		g_dbus_remove_watch(conn, watch_id);
-
-	if (tklock_watch_id > 0)
-		g_dbus_remove_watch(conn, tklock_watch_id);
-
-	btd_adapter_unregister_powered_callback(adapter, adapter_powered);
-}
-
-static struct btd_adapter_driver mce_driver = {
-	.name	= "mce",
-	.probe	= mce_probe,
-	.remove	= mce_remove,
-};
-
-static int maemo6_init(void)
-{
-	DBG("init maemo6 plugin");
-
-	conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
-	if (conn == NULL) {
-		error("Unable to connect to D-Bus");
-		return -1;
-	}
-
-	return btd_register_adapter_driver(&mce_driver);
-}
-
-static void maemo6_exit(void)
-{
-	DBG("exit maemo6 plugin");
-
-	if (conn != NULL)
-		dbus_connection_unref(conn);
-
-	btd_unregister_adapter_driver(&mce_driver);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(maemo6, VERSION,
-		BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, maemo6_init, maemo6_exit)
diff --git a/plugins/pnat.c b/plugins/pnat.c
deleted file mode 100644
index 3c611a9..0000000
--- a/plugins/pnat.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2010  Nokia Corporation
- *  Copyright (C) 2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/uuid.h>
-
-#include <glib.h>
-
-#include <gdbus.h>
-
-#include "plugin.h"
-#include "sdpd.h"
-#include "btio.h"
-#include "adapter.h"
-#include "log.h"
-
-/* FIXME: This location should be build-time configurable */
-#define PNATD "/usr/bin/phonet-at"
-
-#define DUN_CHANNEL 1
-
-#define TTY_TIMEOUT 100
-#define TTY_TRIES 10
-
-struct dun_client {
-	bdaddr_t bda;
-
-	GIOChannel *io;	/* Client socket */
-	guint io_watch;	/* Client IO watch id */
-
-	guint tty_timer;
-	int tty_tries;
-	gboolean tty_open;
-	int tty_id;
-	char tty_name[PATH_MAX];
-
-	GPid pnatd_pid;
-};
-
-struct dun_server {
-	bdaddr_t bda;		/* Local adapter address */
-
-	uint32_t record_handle; /* Local SDP record handle */
-	GIOChannel *server;	/* Server socket */
-
-	int rfcomm_ctl;
-
-	struct dun_client client;
-};
-
-static GSList *servers = NULL;
-
-static void disconnect(struct dun_server *server)
-{
-	struct dun_client *client = &server->client;
-
-	if (!client->io)
-		return;
-
-	if (client->io_watch > 0) {
-		g_source_remove(client->io_watch);
-		client->io_watch = 0;
-	}
-
-	g_io_channel_shutdown(client->io, TRUE, NULL);
-	g_io_channel_unref(client->io);
-	client->io = NULL;
-
-	if (client->pnatd_pid > 0) {
-		kill(client->pnatd_pid, SIGTERM);
-		client->pnatd_pid = 0;
-	}
-
-	if (client->tty_timer > 0) {
-		g_source_remove(client->tty_timer);
-		client->tty_timer = 0;
-	}
-
-	if (client->tty_id >= 0) {
-		struct rfcomm_dev_req req;
-
-		memset(&req, 0, sizeof(req));
-		req.dev_id = client->tty_id;
-		req.flags = (1 << RFCOMM_HANGUP_NOW);
-		ioctl(server->rfcomm_ctl, RFCOMMRELEASEDEV, &req);
-
-		client->tty_name[0] = '\0';
-		client->tty_open = FALSE;
-		client->tty_id = -1;
-	}
-}
-
-static gboolean client_event(GIOChannel *chan,
-					GIOCondition cond, gpointer data)
-{
-	struct dun_server *server = data;
-	struct dun_client *client = &server->client;
-	char addr[18];
-
-	ba2str(&client->bda, addr);
-
-	DBG("Disconnected DUN from %s (%s)", addr, client->tty_name);
-
-	client->io_watch = 0;
-	disconnect(server);
-
-	return FALSE;
-}
-
-static void pnatd_exit(GPid pid, gint status, gpointer user_data)
-{
-	struct dun_server *server = user_data;
-	struct dun_client *client = &server->client;
-
-        if (WIFEXITED(status))
-                DBG("pnatd (%d) exited with status %d", pid,
-							WEXITSTATUS(status));
-        else
-                DBG("pnatd (%d) was killed by signal %d", pid,
-							WTERMSIG(status));
-	g_spawn_close_pid(pid);
-
-	if (pid != client->pnatd_pid)
-		return;
-
-	/* So disconnect() doesn't send SIGTERM to a non-existing process */
-	client->pnatd_pid = 0;
-
-	disconnect(server);
-}
-
-static gboolean start_pnatd(struct dun_server *server)
-{
-	struct dun_client *client = &server->client;
-	GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH;
-	char *argv[] = { PNATD, client->tty_name, NULL };
-	GError *err = NULL;
-	GPid pid;
-
-	g_spawn_async(NULL, argv, NULL, flags, NULL, NULL, &pid, &err);
-	if (err != NULL) {
-		error("Unable to spawn pnatd: %s", err->message);
-		g_error_free(err);
-		return FALSE;
-	}
-
-	DBG("pnatd started for %s with pid %d", client->tty_name, pid);
-
-	client->pnatd_pid = pid;
-
-	/* We do not store the GSource id since g_remove_source doesn't
-	 * make sense for a child watch. If the callback gets removed
-	 * waitpid won't be called and the child remains as a zombie)
-	 */
-	g_child_watch_add(pid, pnatd_exit, server);
-
-	return TRUE;
-}
-
-static gboolean tty_try_open(gpointer user_data)
-{
-	struct dun_server *server = user_data;
-	struct dun_client *client = &server->client;
-	int tty_fd;
-
-	tty_fd = open(client->tty_name, O_RDONLY | O_NOCTTY);
-	if (tty_fd < 0) {
-		if (errno == EACCES)
-			goto disconnect;
-
-		client->tty_tries--;
-
-		if (client->tty_tries <= 0)
-			goto disconnect;
-
-		return TRUE;
-	}
-
-	DBG("%s created for DUN", client->tty_name);
-
-	client->tty_open = TRUE;
-	client->tty_timer = 0;
-
-	g_io_channel_unref(client->io);
-	g_source_remove(client->io_watch);
-
-	client->io = g_io_channel_unix_new(tty_fd);
-	client->io_watch = g_io_add_watch(client->io,
-					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-					client_event, server);
-
-	if (!start_pnatd(server))
-		goto disconnect;
-
-	return FALSE;
-
-disconnect:
-	client->tty_timer = 0;
-	disconnect(server);
-	return FALSE;
-}
-
-static gboolean create_tty(struct dun_server *server)
-{
-	struct dun_client *client = &server->client;
-	struct rfcomm_dev_req req;
-	int sk = g_io_channel_unix_get_fd(client->io);
-
-	memset(&req, 0, sizeof(req));
-	req.dev_id = -1;
-	req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
-
-	bacpy(&req.src, &server->bda);
-	bacpy(&req.dst, &client->bda);
-
-	bt_io_get(client->io, BT_IO_RFCOMM, NULL,
-			BT_IO_OPT_DEST_CHANNEL, &req.channel,
-			BT_IO_OPT_INVALID);
-
-	client->tty_id = ioctl(sk, RFCOMMCREATEDEV, &req);
-	if (client->tty_id < 0) {
-		error("Can't create RFCOMM TTY: %s", strerror(errno));
-		return FALSE;
-	}
-
-	snprintf(client->tty_name, PATH_MAX - 1, "/dev/rfcomm%d",
-							client->tty_id);
-
-	client->tty_tries = TTY_TRIES;
-
-	tty_try_open(server);
-	if (!client->tty_open && client->tty_tries > 0)
-		client->tty_timer = g_timeout_add(TTY_TIMEOUT,
-							tty_try_open, server);
-
-	return TRUE;
-}
-
-static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
-{
-	struct dun_server *server = user_data;
-
-	if (err) {
-		error("Accepting DUN connection failed: %s", err->message);
-		disconnect(server);
-		return;
-	}
-
-	if (!create_tty(server)) {
-		error("Device creation failed");
-		disconnect(server);
-	}
-}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
-	struct dun_server *server = user_data;
-	struct dun_client *client = &server->client;
-	GError *err = NULL;
-
-	if (derr && dbus_error_is_set(derr)) {
-		error("DUN access denied: %s", derr->message);
-		goto drop;
-	}
-
-	if (!bt_io_accept(client->io, connect_cb, server, NULL, &err)) {
-		error("bt_io_accept: %s", err->message);
-		g_error_free(err);
-		goto drop;
-	}
-
-	return;
-
-drop:
-	disconnect(server);
-}
-
-static gboolean auth_watch(GIOChannel *chan, GIOCondition cond, gpointer data)
-{
-	struct dun_server *server = data;
-	struct dun_client *client = &server->client;
-
-	error("DUN client disconnected while waiting for authorization");
-
-	btd_cancel_authorization(&server->bda, &client->bda);
-
-	disconnect(server);
-
-	return FALSE;
-}
-
-static void confirm_cb(GIOChannel *io, gpointer user_data)
-{
-	struct dun_server *server = user_data;
-	struct dun_client *client = &server->client;
-	GError *err = NULL;
-
-	if (client->io) {
-		error("Rejecting DUN connection since one already exists");
-		return;
-	}
-
-	bt_io_get(io, BT_IO_RFCOMM, &err,
-			BT_IO_OPT_DEST_BDADDR, &client->bda,
-			BT_IO_OPT_INVALID);
-	if (err != NULL) {
-		error("Unable to get DUN source and dest address: %s",
-								err->message);
-		g_error_free(err);
-		return;
-	}
-
-	if (btd_request_authorization(&server->bda, &client->bda, DUN_GW_UUID,
-						auth_cb, user_data) < 0) {
-		error("Requesting DUN authorization failed");
-		return;
-	}
-
-	client->io_watch = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-						(GIOFunc) auth_watch, server);
-	client->io = g_io_channel_ref(io);
-}
-
-static sdp_record_t *dun_record(uint8_t ch)
-{
-	sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto;
-	uuid_t root_uuid, dun, gn, l2cap, rfcomm;
-	sdp_profile_desc_t profile;
-	sdp_list_t *proto[2];
-	sdp_record_t *record;
-	sdp_data_t *channel;
-
-	record = sdp_record_alloc();
-	if (!record)
-		return NULL;
-
-	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
-	root = sdp_list_append(NULL, &root_uuid);
-	sdp_set_browse_groups(record, root);
-
-	sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
-	svclass_id = sdp_list_append(NULL, &dun);
-	sdp_uuid16_create(&gn,  GENERIC_NETWORKING_SVCLASS_ID);
-	svclass_id = sdp_list_append(svclass_id, &gn);
-	sdp_set_service_classes(record, svclass_id);
-
-	sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
-	profile.version = 0x0100;
-	pfseq = sdp_list_append(NULL, &profile);
-	sdp_set_profile_descs(record, pfseq);
-
-	sdp_uuid16_create(&l2cap, L2CAP_UUID);
-	proto[0] = sdp_list_append(NULL, &l2cap);
-	apseq = sdp_list_append(NULL, proto[0]);
-
-	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
-	proto[1] = sdp_list_append(NULL, &rfcomm);
-	channel = sdp_data_alloc(SDP_UINT8, &ch);
-	proto[1] = sdp_list_append(proto[1], channel);
-	apseq = sdp_list_append(apseq, proto[1]);
-
-	aproto = sdp_list_append(0, apseq);
-	sdp_set_access_protos(record, aproto);
-
-	sdp_set_info_attr(record, "Dial-Up Networking", 0, 0);
-
-	sdp_data_free(channel);
-	sdp_list_free(root, NULL);
-	sdp_list_free(svclass_id, NULL);
-	sdp_list_free(proto[0], NULL);
-	sdp_list_free(proto[1], NULL);
-	sdp_list_free(pfseq, NULL);
-	sdp_list_free(apseq, NULL);
-	sdp_list_free(aproto, NULL);
-
-	return record;
-}
-
-static gint server_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct dun_server *server = a;
-	const bdaddr_t *src = b;
-
-	return bacmp(src, &server->bda);
-}
-
-static int pnat_probe(struct btd_adapter *adapter)
-{
-	struct dun_server *server;
-	GIOChannel *io;
-	GError *err = NULL;
-	sdp_record_t *record;
-	bdaddr_t src;
-
-	adapter_get_address(adapter, &src);
-
-	server = g_new0(struct dun_server, 1);
-
-	io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_cb, server, NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR, &src,
-				BT_IO_OPT_CHANNEL, DUN_CHANNEL,
-				BT_IO_OPT_INVALID);
-	if (err != NULL) {
-		error("Failed to start DUN server: %s", err->message);
-		g_error_free(err);
-		goto fail;
-	}
-
-	record = dun_record(DUN_CHANNEL);
-	if (!record) {
-		error("Unable to allocate new service record");
-		goto fail;
-	}
-
-	if (add_record_to_server(&src, record) < 0) {
-		error("Unable to register DUN service record");
-		goto fail;
-	}
-
-	server->rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
-	if (server->rfcomm_ctl < 0) {
-		error("Unable to create RFCOMM control socket: %s (%d)",
-						strerror(errno), errno);
-		goto fail;
-	}
-
-	server->server = io;
-	server->record_handle = record->handle;
-	bacpy(&server->bda, &src);
-
-	servers = g_slist_append(servers, server);
-
-	return 0;
-
-fail:
-	if (io != NULL)
-		g_io_channel_unref(io);
-	g_free(server);
-	return -EIO;
-}
-
-static void pnat_remove(struct btd_adapter *adapter)
-{
-	struct dun_server *server;
-	GSList *match;
-	bdaddr_t src;
-
-	adapter_get_address(adapter, &src);
-
-	match = g_slist_find_custom(servers, &src, server_cmp);
-	if (match == NULL)
-		return;
-
-	server = match->data;
-
-	servers = g_slist_delete_link(servers, match);
-
-	disconnect(server);
-
-	remove_record_from_server(server->record_handle);
-	close(server->rfcomm_ctl);
-	g_io_channel_shutdown(server->server, TRUE, NULL);
-	g_io_channel_unref(server->server);
-	g_free(server);
-}
-
-static struct btd_adapter_driver pnat_server = {
-	.name	= "pnat-server",
-	.probe	= pnat_probe,
-	.remove	= pnat_remove,
-};
-
-static int pnat_init(void)
-{
-	DBG("Setup Phonet AT (DUN) plugin");
-
-	return btd_register_adapter_driver(&pnat_server);
-}
-
-static void pnat_exit(void)
-{
-	DBG("Cleanup Phonet AT (DUN) plugin");
-
-	btd_unregister_adapter_driver(&pnat_server);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(pnat, VERSION,
-			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
-			pnat_init, pnat_exit)
-- 
1.7.10.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 03/14] btmgmt: move to tools folder
  2012-07-09 21:10 ` [PATCH 03/14] btmgmt: move to tools folder Gustavo Padovan
@ 2012-07-10  2:36   ` Vinicius Costa Gomes
  0 siblings, 0 replies; 10+ messages in thread
From: Vinicius Costa Gomes @ 2012-07-10  2:36 UTC (permalink / raw)
  To: Gustavo Padovan; +Cc: linux-bluetooth, Gustavo Padovan

Hi Gustavo,

On 18:10 Mon 09 Jul, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> ---
>  .gitignore     |    2 +-
>  Makefile.tools |    6 +-
>  mgmt/main.c    | 1933 --------------------------------------------------------
>  3 files changed, 4 insertions(+), 1937 deletions(-)
>  delete mode 100644 mgmt/main.c

It may be that I am missing something, but this doesn't look like a move.

> 
> diff --git a/.gitignore b/.gitignore
> index c7d079e..bc65dcf 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -86,7 +86,7 @@ compat/dund
>  compat/hidd
>  compat/pand
>  unit/test-eir
> -mgmt/btmgmt
> +tools/mgmt/btmgmt

Wouldn't it be just "tools/btmgmt"?

>  monitor/btmon
>  emulator/btvirt
>  
> diff --git a/Makefile.tools b/Makefile.tools
> index 3cb105c..56839b7 100644
> --- a/Makefile.tools
> +++ b/Makefile.tools
> @@ -50,10 +50,10 @@ tools_ppporc_LDADD = lib/libbluetooth-private.la
>  
>  tools_hcieventmask_LDADD = lib/libbluetooth-private.la
>  
> -noinst_PROGRAMS += mgmt/btmgmt monitor/btmon emulator/btvirt
> +noinst_PROGRAMS += tools/btmgmt monitor/btmon emulator/btvirt
>  
> -mgmt_btmgmt_SOURCES = mgmt/main.c src/glib-helper.c
> -mgmt_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
> +tools_btmgmt_SOURCES = tools/btmgmt.c src/glib-helper.c
> +tools_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
>  
>  monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
>  					monitor/mainloop.h monitor/mainloop.c \
> diff --git a/mgmt/main.c b/mgmt/main.c
> deleted file mode 100644
> index b2d6c3c..0000000
> --- a/mgmt/main.c
> +++ /dev/null
> @@ -1,1933 +0,0 @@
> -/*
> - *  BlueZ - Bluetooth protocol stack for Linux
> - *
> - *  Copyright (C) 2011  Intel Corporation. All rights reserved.
> - *
> - *  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
> - *
> - */
> -
> -#ifdef HAVE_CONFIG_H
> -#include <config.h>
> -#endif
> -
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <unistd.h>
> -#include <errno.h>
> -#include <string.h>
> -#include <sys/types.h>
> -#include <sys/socket.h>
> -#include <poll.h>
> -#include <getopt.h>
> -#include <stdbool.h>
> -
> -#include <bluetooth/bluetooth.h>
> -#include <bluetooth/hci.h>
> -#include <bluetooth/hci_lib.h>
> -#include <bluetooth/sdp.h>
> -#include <bluetooth/sdp_lib.h>
> -#include <bluetooth/mgmt.h>
> -
> -#include <glib.h>
> -#include "glib-helper.h"
> -
> -static bool monitor = false;
> -static bool discovery = false;
> -static bool resolve_names = true;
> -
> -typedef void (*cmd_cb)(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data);
> -
> -static struct pending_cmd {
> -	uint16_t op;
> -	uint16_t id;
> -	cmd_cb cb;
> -	void *user_data;
> -	struct pending_cmd *next;
> -} *pending = NULL;
> -
> -static int mgmt_send_cmd(int mgmt_sk, uint16_t op, uint16_t id, void *data,
> -				size_t len, cmd_cb func, void *user_data)
> -{
> -	char buf[1024];
> -	struct pending_cmd *cmd;
> -	struct mgmt_hdr *hdr = (void *) buf;
> -
> -	if (len + MGMT_HDR_SIZE > sizeof(buf))
> -		return -EINVAL;
> -
> -	cmd = calloc(1, sizeof(struct pending_cmd));
> -	if (cmd == NULL)
> -		return -errno;
> -
> -	cmd->op = op;
> -	cmd->id = id;
> -	cmd->cb = func;
> -	cmd->user_data = user_data;
> -
> -	memset(buf, 0, sizeof(buf));
> -	hdr->opcode = htobs(op);
> -	hdr->index = htobs(id);
> -	hdr->len = htobs(len);
> -	memcpy(buf + MGMT_HDR_SIZE, data, len);
> -
> -	if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
> -		fprintf(stderr, "Unable to write to socket: %s\n",
> -							strerror(errno));
> -		free(cmd);
> -		return -1;
> -	}
> -
> -	cmd->next = pending;
> -	pending = cmd;
> -
> -	return 0;
> -}
> -
> -static int mgmt_open(void)
> -{
> -	struct sockaddr_hci addr;
> -	int sk;
> -
> -	sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
> -	if (sk < 0) {
> -		fprintf(stderr, "socket: %s\n", strerror(errno));
> -		return sk;
> -	}
> -
> -	memset(&addr, 0, sizeof(addr));
> -	addr.hci_family = AF_BLUETOOTH;
> -	addr.hci_dev = HCI_DEV_NONE;
> -	addr.hci_channel = HCI_CHANNEL_CONTROL;
> -
> -	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> -		fprintf(stderr, "bind: %s\n", strerror(errno));
> -		close(sk);
> -		return -1;
> -	}
> -
> -	return sk;
> -}
> -
> -static void mgmt_check_pending(int mgmt_sk, uint16_t op, uint16_t index,
> -				uint16_t status, void *data, uint16_t len)
> -{
> -	struct pending_cmd *c, *prev;
> -
> -	for (c = pending, prev = NULL; c != NULL; prev = c, c = c->next) {
> -		if (c->op != op)
> -			continue;
> -		if (c->id != index)
> -			continue;
> -
> -		if (c == pending)
> -			pending = c->next;
> -		else
> -			prev->next = c->next;
> -
> -		c->cb(mgmt_sk, op, index, status, data, len, c->user_data);
> -
> -		free(c);
> -		break;
> -	}
> -}
> -
> -static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_cmd_complete *ev, uint16_t len)
> -{
> -	uint16_t op;
> -
> -	if (len < sizeof(*ev)) {
> -		fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
> -									len);
> -		return -EINVAL;
> -	}
> -
> -	op = bt_get_le16(&ev->opcode);
> -
> -	len -= sizeof(*ev);
> -
> -	if (monitor)
> -		printf("%s complete, opcode 0x%04x len %u\n", mgmt_opstr(op),
> -								op, len);
> -
> -	mgmt_check_pending(mgmt_sk, op, index, ev->status, ev->data, len);
> -
> -	return 0;
> -}
> -
> -static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_cmd_status *ev, uint16_t len)
> -{
> -	uint16_t opcode;
> -
> -	if (len < sizeof(*ev)) {
> -		fprintf(stderr, "Too short (%u bytes) cmd status event\n",
> -									len);
> -		return -EINVAL;
> -	}
> -
> -	opcode = bt_get_le16(&ev->opcode);
> -
> -	if (monitor)
> -		printf("cmd status, opcode 0x%04x status 0x%02x (%s)\n",
> -				opcode, ev->status, mgmt_errstr(ev->status));
> -
> -	if (ev->status != 0)
> -		mgmt_check_pending(mgmt_sk, opcode, index, ev->status,
> -								NULL, 0);
> -
> -	return 0;
> -}
> -
> -static int mgmt_controller_error(uint16_t index,
> -					struct mgmt_ev_controller_error *ev,
> -					uint16_t len)
> -{
> -	if (len < sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Too short (%u bytes) controller error event\n", len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor)
> -		printf("hci%u error 0x%02x\n", index, ev->error_code);
> -
> -	return 0;
> -}
> -
> -static int mgmt_index_added(int mgmt_sk, uint16_t index)
> -{
> -	if (monitor)
> -		printf("hci%u added\n", index);
> -	return 0;
> -}
> -
> -static int mgmt_index_removed(int mgmt_sk, uint16_t index)
> -{
> -	if (monitor)
> -		printf("hci%u removed\n", index);
> -	return 0;
> -}
> -
> -static const char *settings_str[] = {
> -				"powered",
> -				"connectable",
> -				"fast-connectable",
> -				"discoverable",
> -				"pairable",
> -				"link-security",
> -				"ssp",
> -				"br/edr",
> -				"hs",
> -				"le" ,
> -};
> -
> -static void print_settings(uint32_t settings)
> -{
> -	unsigned i;
> -
> -	for (i = 0; i < NELEM(settings_str); i++) {
> -		if ((settings & (1 << i)) != 0)
> -			printf("%s ", settings_str[i]);
> -	}
> -}
> -
> -static int mgmt_new_settings(int mgmt_sk, uint16_t index,
> -					uint32_t *ev, uint16_t len)
> -{
> -	if (len < sizeof(*ev)) {
> -		fprintf(stderr, "Too short new_settings event (%u)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor) {
> -		printf("hci%u new_settings: ", index);
> -		print_settings(bt_get_le32(ev));
> -		printf("\n");
> -	}
> -
> -	return 0;
> -}
> -
> -static int mgmt_discovering(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_discovering *ev, uint16_t len)
> -{
> -	if (len < sizeof(*ev)) {
> -		fprintf(stderr, "Too short (%u bytes) discovering event\n",
> -									len);
> -		return -EINVAL;
> -	}
> -
> -	if (ev->discovering == 0 && discovery)
> -		exit(EXIT_SUCCESS);
> -
> -	if (monitor)
> -		printf("hci%u type %u discovering %s\n", index,
> -				ev->type, ev->discovering ? "on" : "off");
> -
> -	return 0;
> -}
> -
> -static int mgmt_new_link_key(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_new_link_key *ev, uint16_t len)
> -{
> -
> -	if (len != sizeof(*ev)) {
> -		fprintf(stderr, "Invalid new_link_key length (%u bytes)\n",
> -									len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor) {
> -		char addr[18];
> -		ba2str(&ev->key.addr.bdaddr, addr);
> -		printf("hci%u new_link_key %s type 0x%02x pin_len %d "
> -				"store_hint %u\n", index, addr, ev->key.type,
> -				ev->key.pin_len, ev->store_hint);
> -	}
> -
> -	return 0;
> -}
> -
> -static const char *typestr(uint8_t type)
> -{
> -	const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
> -
> -	if (type <= BDADDR_LE_RANDOM)
> -		return str[type];
> -
> -	return "(unknown)";
> -}
> -
> -static int mgmt_connected(int mgmt_sk, uint16_t index,
> -					struct mgmt_ev_device_connected *ev,
> -					uint16_t len)
> -{
> -	uint16_t eir_len;
> -
> -	if (len < sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Invalid connected event length (%u bytes)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	eir_len = bt_get_le16(&ev->eir_len);
> -	if (len != sizeof(*ev) + eir_len) {
> -		fprintf(stderr, "Invalid connected event length "
> -			"(%u bytes, eir_len %u bytes)\n", len, eir_len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor) {
> -		char addr[18];
> -		ba2str(&ev->addr.bdaddr, addr);
> -		printf("hci%u %s type %s connected eir_len %u\n", index, addr,
> -					typestr(ev->addr.type), eir_len);
> -	}
> -
> -	return 0;
> -}
> -
> -static int mgmt_disconnected(int mgmt_sk, uint16_t index,
> -				struct mgmt_addr_info *ev, uint16_t len)
> -{
> -	if (len != sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Invalid disconnected event length (%u bytes)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor) {
> -		char addr[18];
> -		ba2str(&ev->bdaddr, addr);
> -		printf("hci%u %s type %s disconnected\n", index, addr,
> -							typestr(ev->type));
> -	}
> -
> -	return 0;
> -}
> -
> -static int mgmt_conn_failed(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_connect_failed *ev,
> -				uint16_t len)
> -{
> -	if (len != sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Invalid connect_failed event length (%u bytes)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor) {
> -		char addr[18];
> -		ba2str(&ev->addr.bdaddr, addr);
> -		printf("hci%u %s type %s connect failed (status 0x%02x, %s)\n",
> -				index, addr, typestr(ev->addr.type), ev->status,
> -				mgmt_errstr(ev->status));
> -	}
> -
> -	return 0;
> -}
> -
> -static int mgmt_auth_failed(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_auth_failed *ev,
> -				uint16_t len)
> -{
> -	if (len != sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Invalid auth_failed event length (%u bytes)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor) {
> -		char addr[18];
> -		ba2str(&ev->addr.bdaddr, addr);
> -		printf("hci%u %s auth failed with status 0x%02x (%s)\n",
> -			index, addr, ev->status, mgmt_errstr(ev->status));
> -	}
> -
> -	return 0;
> -}
> -
> -static int mgmt_name_changed(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_local_name_changed *ev,
> -				uint16_t len)
> -{
> -	if (len != sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Invalid local_name_changed length (%u bytes)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor)
> -		printf("hci%u name changed: %s\n", index, ev->name);
> -
> -	return 0;
> -}
> -
> -static void confirm_name_rsp(int mgmt_sk, uint16_t op, uint16_t id,
> -				uint8_t status, void *rsp, uint16_t len,
> -				void *user_data)
> -{
> -	struct mgmt_rp_confirm_name *rp = rsp;
> -	char addr[18];
> -
> -	if (len == 0 && status != 0) {
> -		fprintf(stderr,
> -			"hci%u confirm_name failed with status 0x%02x (%s)\n",
> -					id, status, mgmt_errstr(status));
> -		return;
> -	}
> -
> -	if (len != sizeof(*rp)) {
> -		fprintf(stderr,
> -			"hci%u confirm_name rsp length %u instead of %zu\n",
> -			id, len, sizeof(*rp));
> -		return;
> -	}
> -
> -	ba2str(&rp->addr.bdaddr, addr);
> -
> -	if (status != 0)
> -		fprintf(stderr,
> -			"hci%u confirm_name for %s failed: 0x%02x (%s)\n",
> -			id, addr, status, mgmt_errstr(status));
> -	else
> -		printf("hci%u confirm_name succeeded for %s\n", id, addr);
> -}
> -
> -static int mgmt_device_found(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_device_found *ev, uint16_t len)
> -{
> -	uint32_t flags;
> -	uint16_t eir_len;
> -
> -	if (len < sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Too short device_found length (%u bytes)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	flags = btohs(ev->flags);
> -
> -	eir_len = bt_get_le16(&ev->eir_len);
> -	if (len != sizeof(*ev) + eir_len) {
> -		fprintf(stderr, "dev_found: expected %zu bytes, got %u bytes",
> -						sizeof(*ev) + eir_len, len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor || discovery) {
> -		char addr[18];
> -		ba2str(&ev->addr.bdaddr, addr);
> -		printf("hci%u dev_found: %s type %s rssi %d "
> -			"flags 0x%04x eir_len %u\n", index, addr,
> -			typestr(ev->addr.type), ev->rssi, flags, eir_len);
> -	}
> -
> -	if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
> -		struct mgmt_cp_confirm_name cp;
> -
> -		memset(&cp, 0, sizeof(cp));
> -		memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
> -		if (resolve_names)
> -			cp.name_known = 0;
> -		else
> -			cp.name_known = 1;
> -
> -		mgmt_send_cmd(mgmt_sk, MGMT_OP_CONFIRM_NAME, index,
> -					&cp, sizeof(cp), confirm_name_rsp,
> -					NULL);
> -	}
> -
> -	return 0;
> -}
> -
> -static void pin_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"hci%u PIN Code reply failed with status 0x%02x (%s)",
> -					id, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("hci%u PIN Reply successful\n", id);
> -}
> -
> -static int mgmt_pin_reply(int mgmt_sk, uint16_t index,
> -						struct mgmt_addr_info *addr,
> -						const char *pin, size_t len)
> -{
> -	struct mgmt_cp_pin_code_reply cp;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	memcpy(&cp.addr, addr, sizeof(cp.addr));
> -	cp.pin_len = len;
> -	memcpy(cp.pin_code, pin, len);
> -
> -	return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_REPLY, index,
> -					&cp, sizeof(cp), pin_rsp, NULL);
> -}
> -
> -static void pin_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"hci%u PIN Neg reply failed with status 0x%02x (%s)",
> -					id, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("hci%u PIN Negative Reply successful\n", id);
> -}
> -
> -static int mgmt_pin_neg_reply(int mgmt_sk, uint16_t index,
> -						struct mgmt_addr_info *addr)
> -{
> -	struct mgmt_cp_pin_code_neg_reply cp;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	memcpy(&cp.addr, addr, sizeof(cp.addr));
> -
> -	return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
> -					&cp, sizeof(cp), pin_neg_rsp, NULL);
> -}
> -
> -static int mgmt_request_pin(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_pin_code_request *ev,
> -				uint16_t len)
> -{
> -	char pin[18];
> -	size_t pin_len;
> -
> -	if (len != sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Invalid pin_code request length (%u bytes)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	if (monitor) {
> -		char addr[18];
> -		ba2str(&ev->addr.bdaddr, addr);
> -		printf("hci%u %s request PIN\n", index, addr);
> -	}
> -
> -	printf("PIN Request (press enter to reject) >> ");
> -	fflush(stdout);
> -
> -	memset(pin, 0, sizeof(pin));
> -
> -	if (fgets(pin, sizeof(pin), stdin) == NULL || pin[0] == '\n')
> -		return mgmt_pin_neg_reply(mgmt_sk, index, &ev->addr);
> -
> -	pin_len = strlen(pin);
> -	if (pin[pin_len - 1] == '\n') {
> -		pin[pin_len - 1] = '\0';
> -		pin_len--;
> -	}
> -
> -	return mgmt_pin_reply(mgmt_sk, index, &ev->addr, pin, pin_len);
> -}
> -
> -static void confirm_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"hci%u User Confirm reply failed. status 0x%02x (%s)",
> -					id, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("hci%u User Confirm Reply successful\n", id);
> -}
> -
> -static int mgmt_confirm_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
> -{
> -	struct mgmt_cp_user_confirm_reply cp;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	bacpy(&cp.addr.bdaddr, bdaddr);
> -
> -	return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_REPLY, index,
> -					&cp, sizeof(cp), confirm_rsp, NULL);
> -}
> -
> -static void confirm_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id,
> -				uint8_t status, void *rsp, uint16_t len,
> -				void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"hci%u Confirm Neg reply failed. status 0x%02x (%s)",
> -					id, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("hci%u User Confirm Negative Reply successful\n", id);
> -}
> -
> -static int mgmt_confirm_neg_reply(int mgmt_sk, uint16_t index,
> -							bdaddr_t *bdaddr)
> -{
> -	struct mgmt_cp_user_confirm_reply cp;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	bacpy(&cp.addr.bdaddr, bdaddr);
> -
> -	return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
> -				&cp, sizeof(cp), confirm_neg_rsp, NULL);
> -}
> -
> -
> -static int mgmt_user_confirm(int mgmt_sk, uint16_t index,
> -				struct mgmt_ev_user_confirm_request *ev,
> -				uint16_t len)
> -{
> -	char rsp[5];
> -	size_t rsp_len;
> -	uint32_t val;
> -	char addr[18];
> -
> -	if (len != sizeof(*ev)) {
> -		fprintf(stderr,
> -			"Invalid user_confirm request length (%u)\n", len);
> -		return -EINVAL;
> -	}
> -
> -	ba2str(&ev->addr.bdaddr, addr);
> -	val = bt_get_le32(&ev->value);
> -
> -	if (monitor)
> -		printf("hci%u %s User Confirm %06u hint %u\n", index, addr,
> -							val, ev->confirm_hint);
> -
> -	if (ev->confirm_hint)
> -		printf("Accept pairing with %s (yes/no) >> ", addr);
> -	else
> -		printf("Confirm value %06u for %s (yes/no) >> ", val, addr);
> -
> -	fflush(stdout);
> -
> -	memset(rsp, 0, sizeof(rsp));
> -
> -	if (fgets(rsp, sizeof(rsp), stdin) == NULL || rsp[0] == '\n')
> -		return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
> -
> -	rsp_len = strlen(rsp);
> -	if (rsp[rsp_len - 1] == '\n') {
> -		rsp[rsp_len - 1] = '\0';
> -		rsp_len--;
> -	}
> -
> -	if (rsp[0] == 'y' || rsp[0] == 'Y')
> -		return mgmt_confirm_reply(mgmt_sk, index, &ev->addr.bdaddr);
> -	else
> -		return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
> -}
> -
> -static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index,
> -						void *data, uint16_t len)
> -{
> -	if (monitor)
> -		printf("event: %s\n", mgmt_evstr(ev));
> -
> -	switch (ev) {
> -	case MGMT_EV_CMD_COMPLETE:
> -		return mgmt_cmd_complete(mgmt_sk, index, data, len);
> -	case MGMT_EV_CMD_STATUS:
> -		return mgmt_cmd_status(mgmt_sk, index, data, len);
> -	case MGMT_EV_CONTROLLER_ERROR:
> -		return mgmt_controller_error(index, data, len);
> -	case MGMT_EV_INDEX_ADDED:
> -		return mgmt_index_added(mgmt_sk, index);
> -	case MGMT_EV_INDEX_REMOVED:
> -		return mgmt_index_removed(mgmt_sk, index);
> -	case MGMT_EV_NEW_SETTINGS:
> -		return mgmt_new_settings(mgmt_sk, index, data, len);
> -	case MGMT_EV_DISCOVERING:
> -		return mgmt_discovering(mgmt_sk, index, data, len);
> -	case MGMT_EV_NEW_LINK_KEY:
> -		return mgmt_new_link_key(mgmt_sk, index, data, len);
> -	case MGMT_EV_DEVICE_CONNECTED:
> -		return mgmt_connected(mgmt_sk, index, data, len);
> -	case MGMT_EV_DEVICE_DISCONNECTED:
> -		return mgmt_disconnected(mgmt_sk, index, data, len);
> -	case MGMT_EV_CONNECT_FAILED:
> -		return mgmt_conn_failed(mgmt_sk, index, data, len);
> -	case MGMT_EV_AUTH_FAILED:
> -		return mgmt_auth_failed(mgmt_sk, index, data, len);
> -	case MGMT_EV_LOCAL_NAME_CHANGED:
> -		return mgmt_name_changed(mgmt_sk, index, data, len);
> -	case MGMT_EV_DEVICE_FOUND:
> -		return mgmt_device_found(mgmt_sk, index, data, len);
> -	case MGMT_EV_PIN_CODE_REQUEST:
> -		return mgmt_request_pin(mgmt_sk, index, data, len);
> -	case MGMT_EV_USER_CONFIRM_REQUEST:
> -		return mgmt_user_confirm(mgmt_sk, index, data, len);
> -	default:
> -		if (monitor)
> -			printf("Unhandled event 0x%04x (%s)\n", ev, mgmt_evstr(ev));
> -		return 0;
> -	}
> -}
> -
> -static int mgmt_process_data(int mgmt_sk)
> -{
> -	char buf[1024];
> -	struct mgmt_hdr *hdr = (void *) buf;
> -	uint16_t len, ev, index;
> -	ssize_t ret;
> -
> -	ret = read(mgmt_sk, buf, sizeof(buf));
> -	if (ret < 0) {
> -		fprintf(stderr, "read: %s\n", strerror(errno));
> -		return ret;
> -	}
> -
> -	if (ret < MGMT_HDR_SIZE) {
> -		fprintf(stderr, "Too small mgmt packet (%zd bytes)\n", ret);
> -		return 0;
> -	}
> -
> -	ev = bt_get_le16(&hdr->opcode);
> -	index = bt_get_le16(&hdr->index);
> -	len = bt_get_le16(&hdr->len);
> -
> -	if (monitor)
> -		printf("event 0x%04x len 0x%04x index 0x%04x\n", ev, len, index);
> -
> -	if (ret != MGMT_HDR_SIZE + len) {
> -		fprintf(stderr, "Packet length mismatch. ret %zd len %u",
> -								ret, len);
> -		return 0;
> -	}
> -
> -	mgmt_handle_event(mgmt_sk, ev, index, buf + MGMT_HDR_SIZE, len);
> -
> -	return 0;
> -}
> -
> -static void cmd_monitor(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	printf("Monitoring mgmt events...\n");
> -	monitor = true;
> -}
> -
> -static void version_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_rp_read_version *rp = rsp;
> -
> -	if (status != 0) {
> -		fprintf(stderr, "Reading mgmt version failed with status"
> -			" 0x%02x (%s)\n", status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len < sizeof(*rp)) {
> -		fprintf(stderr, "Too small version reply (%u bytes)\n", len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("MGMT Version %u, revision %u\n", rp->version,
> -						bt_get_le16(&rp->revision));
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_version(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
> -					NULL, 0, version_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send read_version cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void commands_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_rp_read_commands *rp = rsp;
> -	uint16_t num_commands, num_events, *opcode;
> -	size_t expected_len;
> -	int i;
> -
> -	if (status != 0) {
> -		fprintf(stderr, "Reading supported commands failed with status"
> -			" 0x%02x (%s)\n", status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len < sizeof(*rp)) {
> -		fprintf(stderr, "Too small commands reply (%u bytes)\n", len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	num_commands = bt_get_le16(&rp->num_commands);
> -	num_events = bt_get_le16(&rp->num_events);
> -
> -	expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
> -						num_events * sizeof(uint16_t);
> -
> -	if (len < expected_len) {
> -		fprintf(stderr, "Too small commands reply (%u != %zu)\n",
> -							len, expected_len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	opcode = rp->opcodes;
> -
> -	printf("%u commands:\n", num_commands);
> -	for (i = 0; i < num_commands; i++) {
> -		uint16_t op = bt_get_le16(opcode++);
> -		printf("\t%s (0x%04x)\n", mgmt_opstr(op), op);
> -	}
> -
> -	printf("%u events:\n", num_events);
> -	for (i = 0; i < num_events; i++) {
> -		uint16_t ev = bt_get_le16(opcode++);
> -		printf("\t%s (0x%04x)\n", mgmt_evstr(ev), ev);
> -	}
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_commands(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
> -					NULL, 0, commands_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send read_commands cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_rp_read_info *rp = rsp;
> -	char addr[18];
> -
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"Reading hci%u info failed with status 0x%02x (%s)\n",
> -					id, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len < sizeof(*rp)) {
> -		fprintf(stderr, "Too small info reply (%u bytes)\n", len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	ba2str(&rp->bdaddr, addr);
> -	printf("hci%u:\taddr %s version %u manufacturer %u"
> -			" class 0x%02x%02x%02x\n",
> -			id, addr, rp->version, bt_get_le16(&rp->manufacturer),
> -			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
> -
> -	printf("\tsupported settings: ");
> -	print_settings(bt_get_le32(&rp->supported_settings));
> -
> -	printf("\n\tcurrent settings: ");
> -	print_settings(bt_get_le32(&rp->current_settings));
> -
> -	printf("\n\tname %s\n", rp->name);
> -	printf("\tshort name %s\n", rp->short_name);
> -
> -	if (pending == NULL)
> -		exit(EXIT_SUCCESS);
> -}
> -
> -static void index_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_rp_read_index_list *rp = rsp;
> -	uint16_t count;
> -	unsigned int i;
> -
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"Reading index list failed with status 0x%02x (%s)\n",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len < sizeof(*rp)) {
> -		fprintf(stderr, "Too small index list reply (%u bytes)\n",
> -									len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	count = bt_get_le16(&rp->num_controllers);
> -
> -	if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
> -		fprintf(stderr,
> -			"Index count (%u) doesn't match reply length (%u)\n",
> -								count, len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (monitor)
> -		printf("Index list with %u item%s\n",
> -						count, count > 1 ? "s" : "");
> -
> -	if (count == 0)
> -		exit(EXIT_SUCCESS);
> -
> -	if (monitor && count > 0)
> -		printf("\t");
> -
> -	for (i = 0; i < count; i++) {
> -		uint16_t index;
> -
> -		index = bt_get_le16(&rp->index[i]);
> -
> -		if (monitor)
> -			printf("hci%u ", index);
> -
> -		if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
> -					0, info_rsp, NULL) < 0) {
> -			fprintf(stderr, "Unable to send read_info cmd\n");
> -			exit(EXIT_FAILURE);
> -		}
> -	}
> -
> -	if (monitor && count > 0)
> -		printf("\n");
> -}
> -
> -static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	if (index == MGMT_INDEX_NONE) {
> -		if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INDEX_LIST,
> -					MGMT_INDEX_NONE, NULL, 0,
> -					index_rsp, NULL) < 0) {
> -			fprintf(stderr, "Unable to send index_list cmd\n");
> -			exit(EXIT_FAILURE);
> -		}
> -
> -		return;
> -	}
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
> -						0, info_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send read_info cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	uint32_t *rp = rsp;
> -
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"%s for hci%u failed with status 0x%02x (%s)\n",
> -			mgmt_opstr(op), id, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len < sizeof(*rp)) {
> -		fprintf(stderr, "Too small %s response (%u bytes)\n",
> -							mgmt_opstr(op), len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("hci%u %s complete, settings: ", id, mgmt_opstr(op));
> -	print_settings(bt_get_le32(rp));
> -	printf("\n");
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_setting(int mgmt_sk, uint16_t index, uint16_t op,
> -							int argc, char **argv)
> -{
> -	uint8_t val;
> -
> -	if (argc < 2) {
> -		printf("Specify \"on\" or \"off\"\n");
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
> -		val = 1;
> -	else if (strcasecmp(argv[1], "off") == 0)
> -		val = 0;
> -	else
> -		val = atoi(argv[1]);
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	if (mgmt_send_cmd(mgmt_sk, op, index, &val, sizeof(val),
> -						setting_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send %s cmd\n", mgmt_opstr(op));
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void cmd_power(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	cmd_setting(mgmt_sk, index, MGMT_OP_SET_POWERED, argc, argv);
> -}
> -
> -static void cmd_discov(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_set_discoverable cp;
> -
> -	if (argc < 2) {
> -		printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	memset(&cp, 0, sizeof(cp));
> -
> -	if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
> -		cp.val = 1;
> -	else if (strcasecmp(argv[1], "off") == 0)
> -		cp.val = 0;
> -	else
> -		cp.val = atoi(argv[1]);
> -
> -	if (argc > 2)
> -		cp.timeout = htobs(atoi(argv[2]));
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DISCOVERABLE, index,
> -				&cp, sizeof(cp), setting_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send set_discoverable cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void cmd_connectable(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	cmd_setting(mgmt_sk, index, MGMT_OP_SET_CONNECTABLE, argc, argv);
> -}
> -
> -static void cmd_pairable(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	cmd_setting(mgmt_sk, index, MGMT_OP_SET_PAIRABLE, argc, argv);
> -}
> -
> -static void cmd_linksec(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	cmd_setting(mgmt_sk, index, MGMT_OP_SET_LINK_SECURITY, argc, argv);
> -}
> -
> -static void cmd_ssp(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	cmd_setting(mgmt_sk, index, MGMT_OP_SET_SSP, argc, argv);
> -}
> -
> -static void cmd_hs(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	cmd_setting(mgmt_sk, index, MGMT_OP_SET_HS, argc, argv);
> -}
> -
> -static void cmd_le(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	cmd_setting(mgmt_sk, index, MGMT_OP_SET_LE, argc, argv);
> -}
> -
> -static void class_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_ev_class_of_dev_changed *rp = rsp;
> -
> -	if (len == 0 && status != 0) {
> -		fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
> -				mgmt_opstr(op), status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len != sizeof(*rp)) {
> -		fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("%s succeeded. Class 0x%02x%02x%02x\n", mgmt_opstr(op),
> -		rp->class_of_dev[2], rp->class_of_dev[1], rp->class_of_dev[0]);
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_class(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	uint8_t class[2];
> -
> -	if (argc < 3) {
> -		printf("Usage: btmgmt %s <major> <minor>\n", argv[0]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	class[0] = atoi(argv[1]);
> -	class[1] = atoi(argv[2]);
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEV_CLASS, index,
> -				class, sizeof(class), class_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send set_dev_class cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void disconnect_rsp(int mgmt_sk, uint16_t op, uint16_t id,
> -				uint8_t status, void *rsp, uint16_t len,
> -				void *user_data)
> -{
> -	struct mgmt_rp_disconnect *rp = rsp;
> -	char addr[18];
> -
> -	if (len == 0 && status != 0) {
> -		fprintf(stderr, "Disconnect failed with status 0x%02x (%s)\n",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len != sizeof(*rp)) {
> -		fprintf(stderr, "Invalid disconnect response length (%u)\n",
> -									len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	ba2str(&rp->addr.bdaddr, addr);
> -
> -	if (status == 0) {
> -		printf("%s disconnected\n", addr);
> -		exit(EXIT_SUCCESS);
> -	} else {
> -		fprintf(stderr,
> -			"Disconnecting %s failed with status 0x%02x (%s)\n",
> -				addr, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void cmd_disconnect(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_disconnect cp;
> -
> -	if (argc < 2) {
> -		printf("Usage: btmgmt %s <address>\n", argv[0]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	str2ba(argv[1], &cp.addr.bdaddr);
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_DISCONNECT, index,
> -				&cp, sizeof(cp), disconnect_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send disconnect cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void con_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_rp_get_connections *rp = rsp;
> -	uint16_t count, i;
> -
> -	if (len < sizeof(*rp)) {
> -		fprintf(stderr, "Too small (%u bytes) get_connections rsp\n",
> -									len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	count = bt_get_le16(&rp->conn_count);
> -	if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
> -		fprintf(stderr, "Invalid get_connections length "
> -					" (count=%u, len=%u)\n", count, len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	for (i = 0; i < count; i++) {
> -		char addr[18];
> -
> -		ba2str(&rp->addr[i].bdaddr, addr);
> -
> -		printf("%s type %s\n", addr, typestr(rp->addr[i].type));
> -	}
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_con(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_GET_CONNECTIONS, index, NULL, 0,
> -							con_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send get_connections cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void find_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"Unable to start discovery. status 0x%02x (%s)\n",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("Discovery started\n");
> -	discovery = true;
> -}
> -
> -static void find_usage(void)
> -{
> -	printf("Usage: btmgmt find [-l|-b]>\n");
> -}
> -
> -static struct option find_options[] = {
> -	{ "help",	0, 0, 'h' },
> -	{ "le-only",	1, 0, 'l' },
> -	{ "bredr-only",	1, 0, 'b' },
> -	{ 0, 0, 0, 0 }
> -};
> -
> -static void cmd_find(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_start_discovery cp;
> -	uint8_t type;
> -	int opt;
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	type = 0;
> -	hci_set_bit(BDADDR_BREDR, &type);
> -	hci_set_bit(BDADDR_LE_PUBLIC, &type);
> -	hci_set_bit(BDADDR_LE_RANDOM, &type);
> -
> -	while ((opt = getopt_long(argc, argv, "+lbh", find_options,
> -								NULL)) != -1) {
> -		switch (opt) {
> -		case 'l':
> -			hci_clear_bit(BDADDR_BREDR, &type);
> -			hci_set_bit(BDADDR_LE_PUBLIC, &type);
> -			hci_set_bit(BDADDR_LE_RANDOM, &type);
> -			break;
> -		case 'b':
> -			hci_set_bit(BDADDR_BREDR, &type);
> -			hci_clear_bit(BDADDR_LE_PUBLIC, &type);
> -			hci_clear_bit(BDADDR_LE_RANDOM, &type);
> -			break;
> -		case 'h':
> -		default:
> -			find_usage();
> -			exit(EXIT_SUCCESS);
> -		}
> -	}
> -
> -	argc -= optind;
> -	argv += optind;
> -	optind = 0;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	cp.type = type;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_START_DISCOVERY, index,
> -				&cp, sizeof(cp), find_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send start_discovery cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void name_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr, "Unable to set local name. status 0x%02x (%s)",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_name(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_set_local_name cp;
> -
> -	if (argc < 2) {
> -		printf("Usage: btmgmt %s <name> [shortname]\n", argv[0]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
> -	if (argc > 2)
> -		strncpy((char *) cp.short_name, argv[2],
> -					MGMT_MAX_SHORT_NAME_LENGTH);
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_LOCAL_NAME, index,
> -					&cp, sizeof(cp), name_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send set_name cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void pair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_rp_pair_device *rp = rsp;
> -	char addr[18];
> -
> -	if (len == 0 && status != 0) {
> -		fprintf(stderr, "Pairing failed with status 0x%02x (%s)\n",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len != sizeof(*rp)) {
> -		fprintf(stderr, "Unexpected pair_rsp len %u\n", len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	ba2str(&rp->addr.bdaddr, addr);
> -
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"Pairing with %s (%s) failed. status 0x%02x (%s)\n",
> -			addr, typestr(rp->addr.type), status,
> -			mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("Paired with %s\n", addr);
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void pair_usage(void)
> -{
> -	printf("Usage: btmgmt pair [-c cap] [-t type] <remote address>\n");
> -}
> -
> -static struct option pair_options[] = {
> -	{ "help",	0, 0, 'h' },
> -	{ "capability",	1, 0, 'c' },
> -	{ "type",	1, 0, 't' },
> -	{ 0, 0, 0, 0 }
> -};
> -
> -static void cmd_pair(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_pair_device cp;
> -	uint8_t cap = 0x01;
> -	uint8_t type = BDADDR_BREDR;
> -	int opt;
> -
> -	while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
> -								NULL)) != -1) {
> -		switch (opt) {
> -		case 'c':
> -			cap = strtol(optarg, NULL, 0);
> -			break;
> -		case 't':
> -			type = strtol(optarg, NULL, 0);
> -			break;
> -		case 'h':
> -		default:
> -			pair_usage();
> -			exit(EXIT_SUCCESS);
> -		}
> -	}
> -
> -	argc -= optind;
> -	argv += optind;
> -	optind = 0;
> -
> -	if (argc < 1) {
> -		pair_usage();
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	str2ba(argv[0], &cp.addr.bdaddr);
> -	cp.addr.type = type;
> -	cp.io_cap = cap;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_PAIR_DEVICE, index, &cp, sizeof(cp),
> -							pair_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send pair_device cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void unpair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_rp_unpair_device *rp = rsp;
> -	char addr[18];
> -
> -	if (len == 0 && status != 0) {
> -		fprintf(stderr, "Unpair device failed. status 0x%02x (%s)\n",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len != sizeof(*rp)) {
> -		fprintf(stderr, "Unexpected unpair_device_rsp len %u\n", len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	ba2str(&rp->addr.bdaddr, addr);
> -
> -	if (status != 0) {
> -		fprintf(stderr,
> -			"Unpairing %s failed. status 0x%02x (%s)\n",
> -				addr, status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("%s unpaired\n", addr);
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_unpair(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_unpair_device cp;
> -
> -	if (argc < 2) {
> -		printf("Usage: btmgmt %s <remote address>\n", argv[0]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	str2ba(argv[1], &cp.addr.bdaddr);
> -	cp.disconnect = 1;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNPAIR_DEVICE, index, &cp,
> -					sizeof(cp), unpair_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send unpair_device cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void keys_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr, "Load keys failed with status 0x%02x (%s)\n",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("Keys successfully loaded\n");
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_keys(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_load_link_keys cp;
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	memset(&cp, 0, sizeof(cp));
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_LOAD_LINK_KEYS, index,
> -				&cp, sizeof(cp), keys_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send load_keys cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void block_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	struct mgmt_addr_info *rp = rsp;
> -	char addr[18];
> -
> -	if (len == 0 && status != 0) {
> -		fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
> -				mgmt_opstr(op), status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (len != sizeof(*rp)) {
> -		fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	ba2str(&rp->bdaddr, addr);
> -
> -	if (status != 0) {
> -		fprintf(stderr, "%s %s (%s) failed. status 0x%02x (%s)\n",
> -				mgmt_opstr(op), addr, typestr(rp->type),
> -				status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("%s %s succeeded\n", mgmt_opstr(op), addr);
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void block_usage(void)
> -{
> -	printf("Usage: btmgmt block [-t type] <remote address>\n");
> -}
> -
> -static struct option block_options[] = {
> -	{ "help",	0, 0, 'h' },
> -	{ "type",	1, 0, 't' },
> -	{ 0, 0, 0, 0 }
> -};
> -
> -static void cmd_block(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_block_device cp;
> -	uint8_t type = BDADDR_BREDR;
> -	int opt;
> -
> -	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
> -							NULL)) != -1) {
> -		switch (opt) {
> -		case 't':
> -			type = strtol(optarg, NULL, 0);
> -			break;
> -		case 'h':
> -		default:
> -			block_usage();
> -			exit(EXIT_SUCCESS);
> -		}
> -	}
> -
> -	argc -= optind;
> -	argv += optind;
> -	optind = 0;
> -
> -	if (argc < 1) {
> -		block_usage();
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	str2ba(argv[0], &cp.addr.bdaddr);
> -	cp.addr.type = type;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_BLOCK_DEVICE, index,
> -				&cp, sizeof(cp), block_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send block_device cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void unblock_usage(void)
> -{
> -	printf("Usage: btmgmt unblock [-t type] <remote address>\n");
> -}
> -
> -static void cmd_unblock(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_unblock_device cp;
> -	uint8_t type = BDADDR_BREDR;
> -	int opt;
> -
> -	while ((opt = getopt_long(argc, argv, "+t:h", block_options,
> -							NULL)) != -1) {
> -		switch (opt) {
> -		case 't':
> -			type = strtol(optarg, NULL, 0);
> -			break;
> -		case 'h':
> -		default:
> -			unblock_usage();
> -			exit(EXIT_SUCCESS);
> -		}
> -	}
> -
> -	argc -= optind;
> -	argv += optind;
> -	optind = 0;
> -
> -	if (argc < 1) {
> -		unblock_usage();
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	memset(&cp, 0, sizeof(cp));
> -	str2ba(argv[0], &cp.addr.bdaddr);
> -	cp.addr.type = type;
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNBLOCK_DEVICE, index,
> -				&cp, sizeof(cp), block_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send unblock_device cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
> -{
> -	if (uuid->type == SDP_UUID16)
> -		sdp_uuid16_to_uuid128(uuid128, uuid);
> -	else if (uuid->type == SDP_UUID32)
> -		sdp_uuid32_to_uuid128(uuid128, uuid);
> -	else
> -		memcpy(uuid128, uuid, sizeof(*uuid));
> -}
> -
> -static void cmd_add_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_add_uuid cp;
> -	uint128_t uint128;
> -	uuid_t uuid, uuid128;
> -
> -	if (argc < 3) {
> -		printf("UUID and service hint needed\n");
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	if (bt_string2uuid(&uuid, argv[1]) < 0) {
> -		printf("Invalid UUID: %s\n", argv[1]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	memset(&cp, 0, sizeof(cp));
> -
> -	uuid_to_uuid128(&uuid128, &uuid);
> -	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> -	htob128(&uint128, (uint128_t *) cp.uuid);
> -
> -	cp.svc_hint = atoi(argv[2]);
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_ADD_UUID, index,
> -				&cp, sizeof(cp), class_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send add_uuid cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void cmd_remove_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_remove_uuid cp;
> -	uint128_t uint128;
> -	uuid_t uuid, uuid128;
> -
> -	if (argc < 2) {
> -		printf("UUID needed\n");
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	if (bt_string2uuid(&uuid, argv[1]) < 0) {
> -		printf("Invalid UUID: %s\n", argv[1]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	memset(&cp, 0, sizeof(cp));
> -
> -	uuid_to_uuid128(&uuid128, &uuid);
> -	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> -	htob128(&uint128, (uint128_t *) cp.uuid);
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_REMOVE_UUID, index,
> -				&cp, sizeof(cp), class_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send remove_uuid cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static void cmd_clr_uuids(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	char *uuid_any = "00000000-0000-0000-0000-000000000000";
> -	char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
> -
> -	cmd_remove_uuid(mgmt_sk, index, 2, rm_argv);
> -}
> -
> -static void did_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> -				void *rsp, uint16_t len, void *user_data)
> -{
> -	if (status != 0) {
> -		fprintf(stderr, "Set Device ID failed with status 0x%02x (%s)\n",
> -						status, mgmt_errstr(status));
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	printf("Device ID successfully set\n");
> -
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static void did_usage(void)
> -{
> -	printf("Usage: btmgmt did <source>:<vendor>:<product>:<version>\n");
> -	printf("       possible source values: bluetooth, usb\n");
> -}
> -
> -static void cmd_did(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> -	struct mgmt_cp_set_device_id cp;
> -	uint16_t vendor, product, version , source;
> -	int result;
> -
> -	if (argc < 2) {
> -		did_usage();
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
> -								&version);
> -	if (result == 3) {
> -		source = 0x0001;
> -		goto done;
> -	}
> -
> -	result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
> -								&version);
> -	if (result == 3) {
> -		source = 0x0002;
> -		goto done;
> -	}
> -
> -	did_usage();
> -	exit(EXIT_FAILURE);
> -
> -done:
> -	if (index == MGMT_INDEX_NONE)
> -		index = 0;
> -
> -	cp.source = htobs(source);
> -	cp.vendor = htobs(vendor);
> -	cp.product = htobs(product);
> -	cp.version = htobs(version);
> -
> -	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEVICE_ID, index,
> -				&cp, sizeof(cp), did_rsp, NULL) < 0) {
> -		fprintf(stderr, "Unable to send set_dev_class cmd\n");
> -		exit(EXIT_FAILURE);
> -	}
> -}
> -
> -static struct {
> -	char *cmd;
> -	void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
> -	char *doc;
> -} command[] = {
> -	{ "monitor",	cmd_monitor,	"Monitor events"		},
> -	{ "version",	cmd_version,	"Get the MGMT Version"		},
> -	{ "commands",	cmd_commands,	"List supported commands"	},
> -	{ "info",	cmd_info,	"Show controller info"		},
> -	{ "power",	cmd_power,	"Toggle powered state"		},
> -	{ "discov",	cmd_discov,	"Toggle discoverable state"	},
> -	{ "connectable",cmd_connectable,"Toggle connectable state"	},
> -	{ "pairable",	cmd_pairable,	"Toggle pairable state"		},
> -	{ "linksec",	cmd_linksec,	"Toggle link level security"	},
> -	{ "ssp",	cmd_ssp,	"Toggle SSP mode"		},
> -	{ "hs",		cmd_hs,		"Toggle HS Support"		},
> -	{ "le",		cmd_le,		"Toggle LE Support"		},
> -	{ "class",	cmd_class,	"Set device major/minor class"	},
> -	{ "disconnect", cmd_disconnect, "Disconnect device"		},
> -	{ "con",	cmd_con,	"List connections"		},
> -	{ "find",	cmd_find,	"Discover nearby devices"	},
> -	{ "name",	cmd_name,	"Set local name"		},
> -	{ "pair",	cmd_pair,	"Pair with a remote device"	},
> -	{ "unpair",	cmd_unpair,	"Unpair device"			},
> -	{ "keys",	cmd_keys,	"Load Keys"			},
> -	{ "block",	cmd_block,	"Block Device"			},
> -	{ "unblock",	cmd_unblock,	"Unblock Device"		},
> -	{ "add-uuid",	cmd_add_uuid,	"Add UUID"			},
> -	{ "rm-uuid",	cmd_add_uuid,	"Remove UUID"			},
> -	{ "clr-uuids",	cmd_clr_uuids,	"Clear UUIDs",			},
> -	{ "did",	cmd_did,	"Set Device ID",		},
> -	{ NULL, NULL, 0 }
> -};
> -
> -static void usage(void)
> -{
> -	int i;
> -
> -	printf("btmgmt ver %s\n", VERSION);
> -	printf("Usage:\n"
> -		"\tbtmgmt [options] <command> [command parameters]\n");
> -
> -	printf("Options:\n"
> -		"\t--index <id>\tSpecify adapter index\n"
> -		"\t--verbose\tEnable extra logging\n"
> -		"\t--help\tDisplay help\n");
> -
> -	printf("Commands:\n");
> -	for (i = 0; command[i].cmd; i++)
> -		printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
> -
> -	printf("\n"
> -		"For more information on the usage of each command use:\n"
> -		"\tbtmgmt <command> --help\n" );
> -}
> -
> -static struct option main_options[] = {
> -	{ "index",	1, 0, 'i' },
> -	{ "verbose",	0, 0, 'v' },
> -	{ "help",	0, 0, 'h' },
> -	{ 0, 0, 0, 0 }
> -};
> -
> -int main(int argc, char *argv[])
> -{
> -	int opt, i, mgmt_sk;
> -	uint16_t index = MGMT_INDEX_NONE;
> -	struct pollfd pollfd;
> -
> -	while ((opt = getopt_long(argc, argv, "+hvi:",
> -						main_options, NULL)) != -1) {
> -		switch (opt) {
> -		case 'i':
> -			if (strlen(optarg) > 3 &&
> -					strncasecmp(optarg, "hci", 3) == 0)
> -				index = atoi(&optarg[4]);
> -			else
> -				index = atoi(optarg);
> -			break;
> -		case 'v':
> -			monitor = true;
> -			break;
> -		case 'h':
> -		default:
> -			usage();
> -			return 0;
> -		}
> -	}
> -
> -	argc -= optind;
> -	argv += optind;
> -	optind = 0;
> -
> -	if (argc < 1) {
> -		usage();
> -		return 0;
> -	}
> -
> -	mgmt_sk = mgmt_open();
> -	if (mgmt_sk < 0) {
> -		fprintf(stderr, "Unable to open mgmt socket\n");
> -		return -1;
> -	}
> -
> -	for (i = 0; command[i].cmd; i++) {
> -		if (strcmp(command[i].cmd, argv[0]) != 0)
> -			continue;
> -
> -		command[i].func(mgmt_sk, index, argc, argv);
> -		break;
> -	}
> -
> -	if (command[i].cmd == NULL) {
> -		fprintf(stderr, "Unknown command: %s\n", argv[0]);
> -		close(mgmt_sk);
> -		return -1;
> -	}
> -
> -	pollfd.fd = mgmt_sk;
> -	pollfd.events = POLLIN;
> -	pollfd.revents = 0;
> -
> -	while (poll(&pollfd, 1, -1) >= 0) {
> -		if (pollfd.revents & (POLLHUP | POLLERR | POLLNVAL))
> -			break;
> -
> -		if (pollfd.revents & POLLIN)
> -			mgmt_process_data(mgmt_sk);
> -
> -		pollfd.revents = 0;
> -	}
> -
> -	close(mgmt_sk);
> -
> -	return 0;
> -}
> -- 
> 1.7.10.2
> 
> --
> 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


Cheers,
-- 
Vinicius

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-07-10  2:36 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-09 21:10 [PATCH 01/14] input: remove unneeded header inclusions Gustavo Padovan
2012-07-09 21:10 ` [PATCH 02/14] serial: remove the whole serial code Gustavo Padovan
2012-07-09 21:10 ` [PATCH 03/14] btmgmt: move to tools folder Gustavo Padovan
2012-07-10  2:36   ` Vinicius Costa Gomes
2012-07-09 21:10 ` [PATCH 04/14] alert: move alert to profiles dir Gustavo Padovan
2012-07-09 21:10 ` [PATCH 05/14] deviceinfo: move to profiles folder Gustavo Padovan
2012-07-09 21:10 ` [PATCH 07/14] thermometer: move to the " Gustavo Padovan
2012-07-09 21:10 ` [PATCH 08/14] time: " Gustavo Padovan
2012-07-09 21:10 ` [PATCH 12/14] cups: move it to " Gustavo Padovan
2012-07-09 21:10 ` [PATCH 14/14] plugins: remove unmaintained plugins Gustavo Padovan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).