All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ v2 00/18] GATT API: External Services
@ 2014-01-21 13:26 Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 01/18] doc: Add GATT API Claudio Takahasi
                   ` (18 more replies)
  0 siblings, 19 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patchset implements the minimal support for adding local services
declarations.

Limitation: Remove services and multiple services exported by the same
remote will be implemented the next series.

Changes from PATCH v1 to PATCH v2:
* Rebase
* Included patch "doc: Add GATT API"
* Interfaces renamed: s/Service1/GattService1, and
  s/ServiceManager1/GattServiceManager1
* Removed patch "gatt: Implement UnregisterService" from this patchset

Changes from PATCH v0 to PATCH v1:
* Rebase

Changes from RFC v0 to PATCH v0:
* Changed copyright year : s/2013/2014
* Fixed coding style
* Added gatt-service binary to gitignore
* Added extra comment in the source code

Features:
* API for internal and external services declaration
* Unix socket for testing purpose: services are exported
through unix sockets to avoid breaking the current attribute
server.

How to test:
Run bluetoothd with EXPERIMENTAL flag (-E)
Replace /etc/dbus-1/system.d/bluetooth.conf and reload DBus settings
$gatttool -L --primary (or interactive mode)

Roughly upstreaming plan (steps):
* GATT Server: External Services
* GATT Server: External Characteristics (Server)
* GATT Server: External Descriptors (Server)
* Replace attribute server

Alvaro Silva (6):
  gatt: Add stub for gatt.{c, h} files
  gatt: Register Manager D-Bus Interface
  gatt: Add registering external service
  gatt: Add external services tracking
  gatt: Register ATT command/event handler
  gatt: Add Discover All Primary Services

Andre Guedes (1):
  gatt: Add helper for creating GATT services

Claudio Takahasi (11):
  doc: Add GATT API
  lib: Move GATT UUID to uuid.h
  gatt: Add server unix socket
  gattrib: Use default ATT LE MTU for non-standard sockets
  test: Add external service GATT skeleton
  gitignore: Add test/gatt-service
  test: Add signal handling for gatt-service
  test: Add registering external service
  gatttool: Add unix socket connect
  gatttool: Add unix socket support for interactive mode
  bluetooth.conf: Add ObjectManager interface

 .gitignore           |   1 +
 Makefile.am          |   2 +
 Makefile.tools       |   5 +
 attrib/gatt.h        |  25 ----
 attrib/gattrib.c     |  16 +--
 attrib/gatttool.c    |  27 +++-
 attrib/gatttool.h    |   1 +
 attrib/interactive.c |  19 +--
 attrib/utils.c       |  54 ++++++++
 doc/gatt-api.txt     | 145 +++++++++++++++++++
 lib/uuid.h           |  30 ++++
 src/bluetooth.conf   |   1 +
 src/gatt-dbus.c      | 271 ++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h      |  25 ++++
 src/gatt.c           | 383 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h           |  36 +++++
 src/main.c           |   4 +
 test/gatt-service.c  | 254 ++++++++++++++++++++++++++++++++++
 18 files changed, 1251 insertions(+), 48 deletions(-)
 create mode 100644 doc/gatt-api.txt
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h
 create mode 100644 test/gatt-service.c

-- 
1.8.3.1


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

* [PATCH BlueZ v2 01/18] doc: Add GATT API
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 16:50   ` Marcel Holtmann
  2014-01-21 13:26 ` [PATCH BlueZ v2 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch proposes an unified GATT API for local and remote services.
---
 doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)
 create mode 100644 doc/gatt-api.txt

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
new file mode 100644
index 0000000..df60fb8
--- /dev/null
+++ b/doc/gatt-api.txt
@@ -0,0 +1,145 @@
+BlueZ D-Bus GATT API description
+********************************
+
+GATT local and remote services share the same high-level D-Bus API. Local
+refers to GATT based service exported by a BlueZ plugin or an external
+application. Remote refers to GATT services exported by the peer.
+
+BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
+Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
+external services to allow seamless GATT declarations (Service, Characteristic
+and Descriptors) discovery.
+
+Service hierarchy
+=================
+
+GATT remote and local service representation. Object path for local services
+is freely definable.
+
+External applications implementing local services must register the services
+using GattServiceManager1 registration method and must implement the methods
+and properties defined in GattService1 interface.
+
+Service		org.bluez
+Interface	org.bluez.GattService1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+
+Methods		void Release()
+
+			Release this service. At this point, it will not be
+			used by BlueZ anymore and can be destroyed by the
+			owner. Method applicable to external GATT services
+			implementations only (GATT servers).
+
+Properties	string UUID [read-only]
+
+			128-bit service UUID.
+
+		array{object} Includes [read-only]: Not implemented
+
+			Array of object paths representing the included
+			services of this service.
+
+
+Characteristic hierarchy
+========================
+
+For local GATT defined services, the object paths need to follow the service
+path hierarchy and are freely definable.
+
+Service		org.bluez
+Interface	org.bluez.Characteristic1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+
+Properties	string UUID [read-only]
+
+			128-bit characteristic UUID.
+
+		object Service [read-only]
+
+			Object path of the GATT service the characteristc
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Value read from the remote Bluetooth device or from
+			the external application implementing GATT services.
+
+		array{string} Flags [read-only, optional]
+
+			Defines how the characteristic value can be used. See
+			Core spec page 1898, "Table 3.5: Characteristic
+			Properties bit field" and page 1900, "Table 3.8:
+			Characteristic Extended Properties bit field". Allowed
+			values: "broadcast", "read", "write-without-response",
+			"write", "notify", "indicate",
+			"authenticated-signed-writes", "reliable-write", and
+			"writable-auxiliaries".
+
+
+Characteristic Descriptors hierarchy
+====================================
+
+Local or remote GATT characteristic descriptors hierarchy.
+
+Service		org.bluez
+Interface	org.bluez.Descriptor1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+
+Properties	string UUID [read-only]
+
+			128-bit descriptor UUID.
+
+		object Characteristic [read-only]
+
+			Object path of the GATT characteristc the descriptor
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Raw characteristic descriptor value read from the
+			remote Bluetooth device or from the external
+			application implementing GATT services.
+
+		string Permissions [read-only]: To be defined
+
+			Defines read/write authentication and authorization
+			requirements.
+
+Service Manager hierarchy
+=============================
+
+Service Manager allows external applications to register GATT based
+services. Services must follow the API for Service and Characteristic
+described above.
+
+Local GATT services, characteristics and characteristic descriptors are
+discovered automatically using the D-Bus Object Manager interface.
+
+Service		org.bluez
+Interface	org.bluez.GattServiceManager1 [Experimental]
+Object path	/org/bluez
+
+Methods		RegisterService(object service, dict options)
+
+			Registers remote application service exported under
+			interface GattService1. Characteristic objects must
+			be hierarchical to their service and must use the
+			interface Characteristic1. D-Bus Object Manager is
+			used to fetch the exported objects.
+
+			"service" object path together with the D-Bus system
+			bus connection ID define the identification of the
+			application registering a GATT based service.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		UnregisterService(object service)
+
+			This unregisters the service that has been
+			previously registered. The object path parameter
+			must match the same value that has been used
+			on registration.
+
+			Possible errors: org.bluez.Error.DoesNotExist
-- 
1.8.3.1


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

* [PATCH BlueZ v2 02/18] gatt: Add stub for gatt.{c, h} files
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 01/18] doc: Add GATT API Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

These files implement functions to manipulate ATT transactions, and expose
functions to allow other entities to manage GATT based services.
---
 Makefile.am |  1 +
 src/gatt.c  | 38 ++++++++++++++++++++++++++++++++++++++
 src/gatt.h  | 26 ++++++++++++++++++++++++++
 src/main.c  |  4 ++++
 4 files changed, 69 insertions(+)
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h

diff --git a/Makefile.am b/Makefile.am
index f68e1ec..45c9f16 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
 			src/eir.h src/eir.c \
diff --git a/src/gatt.c b/src/gatt.c
new file mode 100644
index 0000000..06619f0
--- /dev/null
+++ b/src/gatt.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 "gatt.h"
+
+void gatt_init(void)
+{
+
+}
+
+void gatt_cleanup(void)
+{
+
+}
diff --git a/src/gatt.h b/src/gatt.h
new file mode 100644
index 0000000..3a320b4
--- /dev/null
+++ b/src/gatt.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 gatt_init(void);
+
+void gatt_cleanup(void);
diff --git a/src/main.c b/src/main.c
index 91d90b4..fccc838 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,6 +55,7 @@
 #include "dbus-common.h"
 #include "agent.h"
 #include "profile.h"
+#include "gatt.h"
 #include "systemd.h"
 
 #define BLUEZ_NAME "org.bluez"
@@ -545,6 +546,8 @@ int main(int argc, char *argv[])
 
 	g_dbus_set_flags(gdbus_flags);
 
+	gatt_init();
+
 	if (option_compat == TRUE)
 		sdp_flags |= SDP_SERVER_COMPAT;
 
@@ -595,6 +598,7 @@ int main(int argc, char *argv[])
 	btd_profile_cleanup();
 	btd_agent_cleanup();
 	btd_device_cleanup();
+	gatt_cleanup();
 
 	adapter_cleanup();
 
-- 
1.8.3.1


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

* [PATCH BlueZ v2 03/18] gatt: Register Manager D-Bus Interface
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 01/18] doc: Add GATT API Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 04/18] gatt: Add registering external service Claudio Takahasi
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers the Service Manager D-Bus Interface. This
interface implements the methods to allow external application register
and unregister GATT Services.
---
 Makefile.am     |  1 +
 src/gatt-dbus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h | 25 +++++++++++++++++++
 src/gatt.c      |  9 +++++++
 4 files changed, 110 insertions(+)
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h

diff --git a/Makefile.am b/Makefile.am
index 45c9f16..ed9083e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt-dbus.h src/gatt-dbus.c \
 			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
new file mode 100644
index 0000000..95c47de
--- /dev/null
+++ b/src/gatt-dbus.c
@@ -0,0 +1,75 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include "dbus-common.h"
+#include "log.h"
+
+#include "gatt-dbus.h"
+
+#define SERVICE_MGR_IFACE		"org.bluez.GattServiceManager1"
+
+static DBusMessage *register_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable methods[] = {
+	{ GDBUS_EXPERIMENTAL_METHOD("RegisterService",
+				GDBUS_ARGS({ "service", "o"},
+						{ "options", "a{sv}"}),
+				NULL, register_service) },
+	{ GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
+				GDBUS_ARGS({"service", "o"}),
+				NULL, unregister_service) },
+	{ }
+};
+
+gboolean gatt_dbus_manager_register(void)
+{
+	return g_dbus_register_interface(btd_get_dbus_connection(),
+					"/org/bluez", SERVICE_MGR_IFACE,
+					methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+							SERVICE_MGR_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
new file mode 100644
index 0000000..310cfa9
--- /dev/null
+++ b/src/gatt-dbus.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *
+ */
+
+gboolean gatt_dbus_manager_register(void);
+void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 06619f0..e8b691a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,14 +25,23 @@
 #include <config.h>
 #endif
 
+#include <glib.h>
+
+#include "log.h"
+
+#include "gatt-dbus.h"
 #include "gatt.h"
 
 void gatt_init(void)
 {
+	DBG("Starting GATT server");
 
+	gatt_dbus_manager_register();
 }
 
 void gatt_cleanup(void)
 {
+	DBG("Stopping GATT server");
 
+	gatt_dbus_manager_unregister();
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v2 04/18] gatt: Add registering external service
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (2 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch allows external applications register a given service on
Bluez. Applications must provide an object path and a dictionary of
options. Options dictionary will be used later to provide additional
service information.
---
 src/gatt-dbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 95c47de..b4d32cd 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -26,22 +26,109 @@
 #endif
 
 #include <stdint.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#include "adapter.h"
+#include "device.h"
+#include "lib/uuid.h"
 #include "dbus-common.h"
 #include "log.h"
 
+#include "error.h"
 #include "gatt-dbus.h"
 
 #define SERVICE_MGR_IFACE		"org.bluez.GattServiceManager1"
 
+struct external_app {
+	char *owner;
+	char *path;
+	GDBusClient *client;
+	unsigned int watch;
+};
+
+static GSList *external_apps;
+
+static int external_app_path_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct external_app *eapp = a;
+	const char *path = b;
+
+	return g_strcmp0(eapp->path, path);
+}
+
+static void external_app_watch_destroy(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+
+	/* TODO: Remove from the database */
+
+	external_apps = g_slist_remove(external_apps, eapp);
+
+	g_dbus_client_unref(eapp->client);
+
+	g_free(eapp->owner);
+	g_free(eapp->path);
+	g_free(eapp);
+}
+
+static struct external_app *new_external_app(DBusConnection *conn,
+					const char *sender, const char *path)
+{
+	struct external_app *eapp;
+	GDBusClient *client;
+
+	client = g_dbus_client_new(conn, sender, "/");
+	if (client == NULL)
+		return NULL;
+
+	eapp = g_new0(struct external_app, 1);
+
+	eapp->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
+			sender, NULL, eapp, external_app_watch_destroy);
+	if (eapp->watch == 0) {
+		g_dbus_client_unref(client);
+		g_free(eapp);
+		return NULL;
+	}
+
+	eapp->owner = g_strdup(sender);
+	eapp->client = client;
+	eapp->path = g_strdup(path);
+
+	return eapp;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
-	return dbus_message_new_method_return(msg);
+	struct external_app *eapp;
+	DBusMessageIter iter;
+	const char *path;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &path);
+
+	if (g_slist_find_custom(external_apps, path, external_app_path_cmp))
+		return btd_error_already_exists(msg);
+
+	eapp = new_external_app(conn, dbus_message_get_sender(msg), path);
+	if (eapp == NULL)
+		return btd_error_failed(msg, "Not enough resources");
+
+	external_apps = g_slist_prepend(external_apps, eapp);
+
+	DBG("New app %p: %s", eapp, path);
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
 static DBusMessage *unregister_service(DBusConnection *conn,
-- 
1.8.3.1


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

* [PATCH BlueZ v2 05/18] lib: Move GATT UUID to uuid.h
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (3 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 04/18] gatt: Add registering external service Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch moves GATT UUIDs definitions to a common header. uuid.h contains
helper functions to manipulate Bluetooth UUIDs and some common BR/EDR services
UUIDs.
---
 attrib/gatt.h | 25 -------------------------
 lib/uuid.h    | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0f113e7..4fea3eb 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,31 +24,6 @@
 
 #include <bluetooth/sdp.h>
 
-/* GATT Profile Attribute types */
-#define GATT_PRIM_SVC_UUID		0x2800
-#define GATT_SND_SVC_UUID		0x2801
-#define GATT_INCLUDE_UUID		0x2802
-#define GATT_CHARAC_UUID		0x2803
-
-/* GATT Characteristic Types */
-#define GATT_CHARAC_DEVICE_NAME			0x2A00
-#define GATT_CHARAC_APPEARANCE			0x2A01
-#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG	0x2A02
-#define GATT_CHARAC_RECONNECTION_ADDRESS	0x2A03
-#define GATT_CHARAC_PERIPHERAL_PREF_CONN	0x2A04
-#define GATT_CHARAC_SERVICE_CHANGED		0x2A05
-
-/* GATT Characteristic Descriptors */
-#define GATT_CHARAC_EXT_PROPER_UUID	0x2900
-#define GATT_CHARAC_USER_DESC_UUID	0x2901
-#define GATT_CLIENT_CHARAC_CFG_UUID	0x2902
-#define GATT_SERVER_CHARAC_CFG_UUID	0x2903
-#define GATT_CHARAC_FMT_UUID		0x2904
-#define GATT_CHARAC_AGREG_FMT_UUID	0x2905
-#define GATT_CHARAC_VALID_RANGE_UUID	0x2906
-#define GATT_EXTERNAL_REPORT_REFERENCE	0x2907
-#define GATT_REPORT_REFERENCE		0x2908
-
 /* Client Characteristic Configuration bit field */
 #define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT	0x0001
 #define GATT_CLIENT_CHARAC_CFG_IND_BIT		0x0002
diff --git a/lib/uuid.h b/lib/uuid.h
index 95e5a9a..c24cee5 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -105,6 +105,31 @@ extern "C" {
 #define OBEX_MNS_UUID		"00001133-0000-1000-8000-00805f9b34fb"
 #define OBEX_MAP_UUID		"00001134-0000-1000-8000-00805f9b34fb"
 
+/* GATT UUIDs section */
+#define GATT_PRIM_SVC_UUID				0x2800
+#define GATT_SND_SVC_UUID				0x2801
+#define GATT_INCLUDE_UUID				0x2802
+#define GATT_CHARAC_UUID				0x2803
+
+/* GATT Characteristic Types */
+#define GATT_CHARAC_DEVICE_NAME				0x2A00
+#define GATT_CHARAC_APPEARANCE				0x2A01
+#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG		0x2A02
+#define GATT_CHARAC_RECONNECTION_ADDRESS		0x2A03
+#define GATT_CHARAC_PERIPHERAL_PREF_CONN		0x2A04
+#define GATT_CHARAC_SERVICE_CHANGED			0x2A05
+
+/* GATT Characteristic Descriptors */
+#define GATT_CHARAC_EXT_PROPER_UUID			0x2900
+#define GATT_CHARAC_USER_DESC_UUID			0x2901
+#define GATT_CLIENT_CHARAC_CFG_UUID			0x2902
+#define GATT_SERVER_CHARAC_CFG_UUID			0x2903
+#define GATT_CHARAC_FMT_UUID				0x2904
+#define GATT_CHARAC_AGREG_FMT_UUID			0x2905
+#define GATT_CHARAC_VALID_RANGE_UUID			0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE			0x2907
+#define GATT_REPORT_REFERENCE				0x2908
+
 typedef struct {
 	enum {
 		BT_UUID_UNSPEC = 0,
-- 
1.8.3.1


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

* [PATCH BlueZ v2 06/18] gatt: Add helper for creating GATT services
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (4 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 07/18] gatt: Add external services tracking Claudio Takahasi
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes

From: Andre Guedes <andre.guedes@openbossa.org>

This patch adds the btd_gatt_add_service() helper which adds a
GATT Service declaration to the local attribute database.
---
 lib/uuid.h |  5 +++++
 src/gatt.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h | 10 ++++++++++
 3 files changed, 77 insertions(+)

diff --git a/lib/uuid.h b/lib/uuid.h
index c24cee5..237145b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -158,6 +158,11 @@ void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
 int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
 int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
 
+static inline int bt_uuid_len(const bt_uuid_t *uuid)
+{
+	return uuid->type / 8;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gatt.c b/src/gatt.c
index e8b691a..ee045b1 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -27,11 +27,73 @@
 
 #include <glib.h>
 
+#include "adapter.h"
+#include "device.h"
+
 #include "log.h"
+#include "lib/uuid.h"
+#include "attrib/att.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
 
+/* Common GATT UUIDs */
+static const bt_uuid_t primary_uuid  = { .type = BT_UUID16,
+					.value.u16 = GATT_PRIM_SVC_UUID };
+
+struct btd_attribute {
+	uint16_t handle;
+	bt_uuid_t type;
+	uint16_t value_len;
+	uint8_t value[0];
+};
+
+static GList *local_attribute_db;
+static uint16_t next_handle = 0x0001;
+
+static int local_database_add(uint16_t handle, struct btd_attribute *attr)
+{
+	attr->handle = handle;
+
+	local_attribute_db = g_list_append(local_attribute_db, attr);
+
+	return 0;
+}
+
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
+{
+	uint16_t len = bt_uuid_len(uuid);
+	struct btd_attribute *attr = g_malloc0(sizeof(struct btd_attribute) +
+									len);
+
+	/*
+	 * Service DECLARATION
+	 *
+	 *   TYPE         ATTRIBUTE VALUE
+	 * +-------+---------------------------------+
+	 * |0x2800 | 0xYYYY...                       |
+	 * | (1)   | (2)                             |
+	 * +------+----------------------------------+
+	 * (1) - 2 octets: Primary/Secondary Service UUID
+	 * (2) - 2 or 16 octets: Service UUID
+	 */
+
+	attr->type = primary_uuid;
+
+	att_put_uuid(*uuid, attr->value);
+	attr->value_len = len;
+
+	if (local_database_add(next_handle, attr) < 0) {
+		g_free(attr);
+		return NULL;
+	}
+
+	/* TODO: missing overflow checking */
+	next_handle = next_handle + 1;
+
+	return attr;
+}
+
 void gatt_init(void)
 {
 	DBG("Starting GATT server");
diff --git a/src/gatt.h b/src/gatt.h
index 3a320b4..8dd1312 100644
--- a/src/gatt.h
+++ b/src/gatt.h
@@ -21,6 +21,16 @@
  *
  */
 
+struct btd_attribute;
+
 void gatt_init(void);
 
 void gatt_cleanup(void);
+
+/* btd_gatt_add_service - Add a service declaration to local attribute database.
+ * @uuid:	Service UUID.
+ *
+ * Returns a reference to service declaration attribute. In case of error,
+ * NULL is returned.
+ */
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
-- 
1.8.3.1


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

* [PATCH BlueZ v2 07/18] gatt: Add external services tracking
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (5 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 08/18] gatt: Add server unix socket Claudio Takahasi
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

All primary services declarations provided by an external application
will be automatically inserted in the attribute database.
---
 src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index b4d32cd..2196dc7 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -39,15 +39,21 @@
 #include "log.h"
 
 #include "error.h"
+#include "gatt.h"
 #include "gatt-dbus.h"
 
 #define SERVICE_MGR_IFACE		"org.bluez.GattServiceManager1"
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+#define REGISTER_TIMER         1
 
 struct external_app {
 	char *owner;
 	char *path;
 	GDBusClient *client;
+	GSList *proxies;
 	unsigned int watch;
+	guint register_timer;
 };
 
 static GSList *external_apps;
@@ -60,6 +66,36 @@ static int external_app_path_cmp(gconstpointer a, gconstpointer b)
 	return g_strcmp0(eapp->path, path);
 }
 
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	if (g_strcmp0(interface, SERVICE_IFACE) != 0)
+		return;
+
+	eapp->proxies = g_slist_append(eapp->proxies, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	eapp->proxies = g_slist_remove(eapp->proxies, proxy);
+}
+
+
 static void external_app_watch_destroy(gpointer user_data)
 {
 	struct external_app *eapp = user_data;
@@ -70,6 +106,9 @@ static void external_app_watch_destroy(gpointer user_data)
 
 	g_dbus_client_unref(eapp->client);
 
+	if (eapp->register_timer)
+		g_source_remove(eapp->register_timer);
+
 	g_free(eapp->owner);
 	g_free(eapp->path);
 	g_free(eapp);
@@ -99,9 +138,75 @@ static struct external_app *new_external_app(DBusConnection *conn,
 	eapp->client = client;
 	eapp->path = g_strdup(path);
 
+	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+								NULL, eapp);
+
 	return eapp;
 }
 
+static int register_external_service(GDBusProxy *proxy)
+{
+	DBusMessageIter iter;
+	const char *uuid;
+	bt_uuid_t btuuid;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return -EINVAL;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return -EINVAL;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (bt_string_to_uuid(&btuuid, uuid) < 0)
+		return -EINVAL;
+
+	if (btd_gatt_add_service(&btuuid) == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static gboolean finish_register(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+	GSList *list;
+
+	/*
+	 * It is not possible to detect when the last proxy object
+	 * was reported. "Proxy added" handler reports objects
+	 * added on demand or returned by GetManagedObjects().
+	 * This timer helps to register all the GATT declarations
+	 * (services, characteristics and descriptors) after fetching
+	 * all the D-Bus objects.
+	 */
+
+	eapp->register_timer = 0;
+
+	for (list = eapp->proxies; list; list = g_slist_next(list)) {
+		const char *interface, *path;
+		GDBusProxy *proxy = list->data;
+
+		interface = g_dbus_proxy_get_interface(proxy);
+		path = g_dbus_proxy_get_path(proxy);
+
+		if (g_strcmp0(SERVICE_IFACE, interface) != 0)
+			continue;
+
+		if (g_strcmp0(path, eapp->path) != 0)
+			continue;
+
+		if (register_external_service(proxy) < 0) {
+			DBG("Inconsistent external service: %s", path);
+			continue;
+		}
+
+		DBG("External service: %s", path);
+	}
+
+	return FALSE;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -109,6 +214,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	DBusMessageIter iter;
 	const char *path;
 
+	DBG("Registering GATT Service");
+
 	if (!dbus_message_iter_init(msg, &iter))
 		return btd_error_invalid_args(msg);
 
@@ -127,6 +234,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	external_apps = g_slist_prepend(external_apps, eapp);
 
 	DBG("New app %p: %s", eapp, path);
+	eapp->register_timer = g_timeout_add_seconds(REGISTER_TIMER,
+							finish_register, eapp);
 
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v2 08/18] gatt: Add server unix socket
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (6 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 07/18] gatt: Add external services tracking Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds a server unix socket to handle local ATT traffic. This
is a development purpose feature used to allow local testing without
breaking the current attribute server.
---
 src/gatt.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/src/gatt.c b/src/gatt.c
index ee045b1..4806205 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,6 +25,11 @@
 #include <config.h>
 #endif
 
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include "adapter.h"
@@ -50,6 +55,7 @@ struct btd_attribute {
 
 static GList *local_attribute_db;
 static uint16_t next_handle = 0x0001;
+static guint unix_watch;
 
 static int local_database_add(uint16_t handle, struct btd_attribute *attr)
 {
@@ -94,11 +100,71 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct sockaddr_un uaddr;
+	socklen_t len = sizeof(uaddr);
+	GIOChannel *nio;
+	int err, nsk, sk;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	nsk = accept(sk, (struct sockaddr *) &uaddr, &len);
+	if (nsk < 0) {
+		err = errno;
+		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
+		return TRUE;
+	}
+
+	nio = g_io_channel_unix_new(nsk);
+	g_io_channel_set_close_on_unref(nio, TRUE);
+	DBG("ATT UNIX socket: %p new client", nio);
+	g_io_channel_unref(nio);
+
+	return TRUE;
+}
+
 void gatt_init(void)
 {
+	struct sockaddr_un uaddr  = {
+		.sun_family     = AF_UNIX,
+		.sun_path       = "\0/bluetooth/unix_att",
+	};
+	GIOChannel *io;
+	int sk, err;
+
 	DBG("Starting GATT server");
 
 	gatt_dbus_manager_register();
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		err = errno;
+		error("ATT UNIX socket: %s(%d)", strerror(err), err);
+		return;
+	}
+
+	if (bind(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		err = errno;
+		error("binding ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	if (listen(sk, 5) < 0) {
+		err = errno;
+		error("listen ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+	unix_watch = g_io_add_watch(io,
+				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+				unix_accept_cb, NULL);
+	g_io_channel_unref(io);
 }
 
 void gatt_cleanup(void)
@@ -106,4 +172,5 @@ void gatt_cleanup(void)
 	DBG("Stopping GATT server");
 
 	gatt_dbus_manager_unregister();
+	g_source_remove(unix_watch);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v2 09/18] gattrib: Use default ATT LE MTU for non-standard sockets
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (7 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 08/18] gatt: Add server unix socket Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 10/18] gatt: Register ATT command/event handler Claudio Takahasi
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch forces the MTU to 23 (default ATT MTU) if the transport
is not Bluetooth. This is a development purpose change to allow
testing GATT procedures over non-Bluetooth sockets.
---
 attrib/gattrib.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 609b908..fccb2bf 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -468,18 +468,18 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	struct _GAttrib *attrib;
 	uint16_t imtu;
 	uint16_t att_mtu;
-	uint16_t cid;
-	GError *gerr = NULL;
+	uint16_t cid = 0;
 
 	g_io_channel_set_encoding(io, NULL, NULL);
 	g_io_channel_set_buffered(io, FALSE);
 
-	bt_io_get(io, &gerr, BT_IO_OPT_IMTU, &imtu,
-				BT_IO_OPT_CID, &cid, BT_IO_OPT_INVALID);
-	if (gerr) {
-		error("%s", gerr->message);
-		g_error_free(gerr);
-		return NULL;
+	if (bt_io_get(io, NULL, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_CID, &cid,
+						BT_IO_OPT_INVALID) == FALSE) {
+		/*
+		 * Use default ATT LE MTU for non-standard transports. Used
+		 * for testing purpose only. eg: Unix sockets
+		 */
+		imtu = ATT_DEFAULT_LE_MTU;
 	}
 
 	attrib = g_try_new0(struct _GAttrib, 1);
-- 
1.8.3.1


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

* [PATCH BlueZ v2 10/18] gatt: Register ATT command/event handler
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (8 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers the ATT channel handler to manage incoming ATT
commands and events.
---
 src/gatt.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/src/gatt.c b/src/gatt.c
index 4806205..33c3b6a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -38,6 +38,7 @@
 #include "log.h"
 #include "lib/uuid.h"
 #include "attrib/att.h"
+#include "attrib/gattrib.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
@@ -100,12 +101,83 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static void send_error(GAttrib *attrib, uint8_t opcode, uint16_t handle,
+								uint8_t ecode)
+{
+	uint8_t pdu[ATT_DEFAULT_LE_MTU];
+	size_t plen;
+
+	plen = enc_error_resp(opcode, handle, ecode, pdu, sizeof(pdu));
+
+	g_attrib_send(attrib, 0, pdu, plen, NULL, NULL, NULL);
+}
+
+static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
+							gpointer user_data)
+{
+	GAttrib *attrib = user_data;
+
+	switch (ipdu[0]) {
+	case ATT_OP_ERROR:
+		break;
+
+	/* Requests */
+	case ATT_OP_WRITE_CMD:
+	case ATT_OP_WRITE_REQ:
+	case ATT_OP_READ_REQ:
+	case ATT_OP_READ_BY_TYPE_REQ:
+	case ATT_OP_MTU_REQ:
+	case ATT_OP_FIND_INFO_REQ:
+	case ATT_OP_FIND_BY_TYPE_REQ:
+	case ATT_OP_READ_BLOB_REQ:
+	case ATT_OP_READ_MULTI_REQ:
+	case ATT_OP_PREP_WRITE_REQ:
+	case ATT_OP_EXEC_WRITE_REQ:
+	case ATT_OP_READ_BY_GROUP_REQ:
+	case ATT_OP_SIGNED_WRITE_CMD:
+		send_error(attrib, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
+		break;
+
+	/* Responses */
+	case ATT_OP_MTU_RESP:
+	case ATT_OP_FIND_INFO_RESP:
+	case ATT_OP_FIND_BY_TYPE_RESP:
+	case ATT_OP_READ_BY_TYPE_RESP:
+	case ATT_OP_READ_RESP:
+	case ATT_OP_READ_BLOB_RESP:
+	case ATT_OP_READ_MULTI_RESP:
+	case ATT_OP_READ_BY_GROUP_RESP:
+	case ATT_OP_WRITE_RESP:
+	case ATT_OP_PREP_WRITE_RESP:
+	case ATT_OP_EXEC_WRITE_RESP:
+	case ATT_OP_HANDLE_CNF:
+		break;
+
+	/* Notification & Indication */
+	case ATT_OP_HANDLE_NOTIFY:
+	case ATT_OP_HANDLE_IND:
+		break;
+	}
+}
+
+static gboolean unix_hup_cb(GIOChannel *io, GIOCondition cond,
+						gpointer user_data)
+{
+	GAttrib *attrib = user_data;
+
+	g_attrib_unregister_all(attrib);
+	g_attrib_unref(attrib);
+
+	return FALSE;
+}
+
 static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct sockaddr_un uaddr;
 	socklen_t len = sizeof(uaddr);
 	GIOChannel *nio;
+	GAttrib *attrib;
 	int err, nsk, sk;
 
 	sk = g_io_channel_unix_get_fd(io);
@@ -120,6 +192,14 @@ static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
 	nio = g_io_channel_unix_new(nsk);
 	g_io_channel_set_close_on_unref(nio, TRUE);
 	DBG("ATT UNIX socket: %p new client", nio);
+
+	attrib = g_attrib_new(nio);
+
+	g_attrib_register(attrib, GATTRIB_ALL_EVENTS, GATTRIB_ALL_HANDLES,
+					channel_handler_cb, attrib, NULL);
+
+	g_io_add_watch(nio, G_IO_HUP, unix_hup_cb, attrib);
+
 	g_io_channel_unref(nio);
 
 	return TRUE;
-- 
1.8.3.1


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

* [PATCH BlueZ v2 11/18] gatt: Add Discover All Primary Services
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (9 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 10/18] gatt: Register ATT command/event handler Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 12/18] test: Add external service GATT skeleton Claudio Takahasi
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch adds ATT Read By Group request handling to the attribute
server. It is the primitive to implement Discover All Primary Services
procedure.
---
 src/gatt.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 1 deletion(-)

diff --git a/src/gatt.c b/src/gatt.c
index 33c3b6a..b204f9c 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -112,6 +112,130 @@ static void send_error(GAttrib *attrib, uint8_t opcode, uint16_t handle,
 	g_attrib_send(attrib, 0, pdu, plen, NULL, NULL, NULL);
 }
 
+static void read_by_group_resp(GAttrib *attrib, uint16_t start,
+					uint16_t end, bt_uuid_t *pattern)
+{
+	uint8_t opdu[ATT_DEFAULT_LE_MTU];
+	GList *list;
+	struct btd_attribute *last = NULL;
+	uint8_t *group_start, *group_end = NULL, *group_uuid;
+	unsigned int uuid_type = BT_UUID_UNSPEC;
+	size_t group_len = 0, plen = 0;
+
+	/*
+	 * Read By Group Type Response format:
+	 *    Attribute Opcode: 1 byte
+	 *    Length: 1 byte (size of each group)
+	 *    Group: start | end | <<UUID>>
+	 */
+
+	opdu[0] = ATT_OP_READ_BY_GROUP_RESP;
+	group_start = &opdu[2];
+	group_uuid = &opdu[6];
+
+	for (list = local_attribute_db; list;
+			last = list->data, list = g_list_next(list)) {
+		struct btd_attribute *attr = list->data;
+
+		if (attr->handle < start)
+			continue;
+
+		if (attr->handle > end)
+			break;
+
+		if (bt_uuid_cmp(&attr->type, pattern) != 0)
+			continue;
+
+		if (uuid_type != BT_UUID_UNSPEC &&
+						uuid_type != attr->type.type) {
+			/*
+			 * Groups should contain the same length: UUID16 and
+			 * UUID128 should be sent on different ATT PDUs
+			 */
+			break;
+		}
+
+		/*
+		 * MTU checking should not be shifted up, otherwise the
+		 * handle of last end group will not be set properly.
+		 */
+		if ((plen + group_len) >= ATT_DEFAULT_LE_MTU)
+			break;
+
+		/* Start Grouping handle */
+		att_put_u16(attr->handle, group_start);
+
+		/* Grouping <<UUID>>: Value is little endian */
+		memcpy(group_uuid, attr->value, attr->value_len);
+
+		if (last && group_end) {
+			att_put_u16(last->handle, group_end);
+			group_end += group_len;
+			plen += group_len;
+		}
+
+		/* Grouping initial settings: First grouping */
+		if (uuid_type == BT_UUID_UNSPEC) {
+			uuid_type = attr->type.type;
+
+			/* start(0xXXXX) | end(0xXXXX) | <<UUID>> */
+			group_len = 2 + 2 + bt_uuid_len(&attr->type);
+
+			/* 2: ATT Opcode and Length */
+			plen = 2 + group_len;
+
+			/* Size of each Attribute Data */
+			opdu[1] = group_len;
+
+			group_end = &opdu[4];
+		}
+
+		group_start += group_len;
+		group_uuid += group_len;
+	}
+
+	if (plen == 0) {
+		send_error(attrib, ATT_OP_READ_BY_GROUP_REQ, start,
+						ATT_ECODE_ATTR_NOT_FOUND);
+		return;
+	}
+
+	if (group_end)
+		att_put_u16(last->handle, group_end);
+
+	g_attrib_send(attrib, 0, opdu, plen, NULL, NULL, NULL);
+}
+
+static void read_by_group(GAttrib *attrib, const uint8_t *ipdu, size_t ilen)
+{
+	uint16_t decoded, start, end;
+	bt_uuid_t pattern;
+
+	decoded = dec_read_by_grp_req(ipdu, ilen, &start, &end, &pattern);
+	if (decoded == 0) {
+		send_error(attrib, ipdu[0], 0x0000, ATT_ECODE_INVALID_PDU);
+		return;
+	}
+
+	if (start > end || start == 0x0000) {
+		send_error(attrib, ipdu[0], start, ATT_ECODE_INVALID_HANDLE);
+		return;
+	}
+
+	 /*
+	  * Restricting Read By Group Type to <<Primary>>.
+	  * Removing the checking below requires changes to support
+	  * dynamic values(defined in the upper layer) and additional
+	  * security verification.
+	  */
+	if (bt_uuid_cmp(&pattern, &primary_uuid) != 0) {
+		send_error(attrib, ipdu[0], start, ATT_ECODE_UNSUPP_GRP_TYPE);
+		return;
+	}
+
+	read_by_group_resp(attrib, start, end, &pattern);
+}
+
 static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
 							gpointer user_data)
 {
@@ -133,11 +257,14 @@ static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
 	case ATT_OP_READ_MULTI_REQ:
 	case ATT_OP_PREP_WRITE_REQ:
 	case ATT_OP_EXEC_WRITE_REQ:
-	case ATT_OP_READ_BY_GROUP_REQ:
 	case ATT_OP_SIGNED_WRITE_CMD:
 		send_error(attrib, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
 		break;
 
+	case ATT_OP_READ_BY_GROUP_REQ:
+		read_by_group(attrib, ipdu, ilen);
+		break;
+
 	/* Responses */
 	case ATT_OP_MTU_RESP:
 	case ATT_OP_FIND_INFO_RESP:
-- 
1.8.3.1


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

* [PATCH BlueZ v2 12/18] test: Add external service GATT skeleton
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (10 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 13/18] gitignore: Add test/gatt-service Claudio Takahasi
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial code for an external GATT service example.
It implements the API defined at doc/gatt-api.txt
---
 Makefile.tools      |   5 ++
 test/gatt-service.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 test/gatt-service.c

diff --git a/Makefile.tools b/Makefile.tools
index cd2d1ca..7beeeb6 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -367,3 +367,8 @@ test_scripts += test/sap_client.py test/bluezutils.py \
 		test/test-heartrate test/test-alert test/test-hfp \
 		test/test-cyclingspeed test/opp-client test/ftp-client \
 		test/pbap-client test/map-client
+
+noinst_PROGRAMS += test/gatt-service
+
+test_gatt_service_SOURCES = test/gatt-service.c
+test_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la
diff --git a/test/gatt-service.c b/test/gatt-service.c
new file mode 100644
index 0000000..bf5cba9
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,136 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+/* Immediate Alert Service UUID */
+#define IAS_UUID			"00001802-0000-1000-8000-00805f9b34fb"
+
+static GMainLoop *main_loop;
+static GSList *services;
+
+static gboolean service_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	const char *uuid = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+	return TRUE;
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	return TRUE;
+}
+
+static gboolean service_exist_includes(const GDBusPropertyTable *property,
+							void *user_data)
+{
+	return FALSE;
+}
+
+static DBusMessage *service_release(DBusConnection *conn,
+				DBusMessage *msg, void *user_data)
+{
+	fprintf(stderr, "Terminating...\n");
+
+	g_main_loop_quit(main_loop);
+
+	return NULL;
+}
+
+static const GDBusMethodTable service_methods[] = {
+	{ GDBUS_NOREPLY_METHOD("Release", NULL, NULL, service_release) },
+	{ }
+};
+
+static const GDBusPropertyTable service_properties[] = {
+	{ "UUID", "s", service_get_uuid },
+	{ "Includes", "ao", service_get_includes, NULL,
+					service_exist_includes },
+	{ }
+};
+
+static char *register_service(DBusConnection *conn, const char *uuid)
+{
+	static int id = 1;
+	char *path;
+
+	path = g_strdup_printf("/service%d", id++);
+	if (g_dbus_register_interface(conn, path, SERVICE_IFACE,
+				service_methods, NULL, service_properties,
+				g_strdup(uuid), g_free) == FALSE) {
+		fprintf(stderr, "Couldn't register service interface\n");
+		g_free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+static void create_services(DBusConnection *conn)
+{
+	char *service_path;
+
+	service_path = register_service(conn, IAS_UUID);
+
+	services = g_slist_prepend(services, service_path);
+
+	printf("Registered service: %s\n", service_path);
+}
+
+int main(int argc, char *argv[])
+{
+	DBusConnection *dbus_conn;
+
+	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+
+	main_loop = g_main_loop_new(NULL, FALSE);
+
+	g_dbus_attach_object_manager(dbus_conn);
+
+	printf("gatt-service unique name: %s\n",
+				dbus_bus_get_unique_name(dbus_conn));
+
+	create_services(dbus_conn);
+
+	g_main_loop_run(main_loop);
+
+	g_slist_free_full(services, g_free);
+	dbus_connection_unref(dbus_conn);
+
+	return 0;
+}
-- 
1.8.3.1


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

* [PATCH BlueZ v2 13/18] gitignore: Add test/gatt-service
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (11 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 12/18] test: Add external service GATT skeleton Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 14/18] test: Add signal handling for gatt-service Claudio Takahasi
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 67e9850..48fcf57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,6 +73,7 @@ tools/3dsp
 tools/obexctl
 test/sap_client.pyc
 test/bluezutils.pyc
+test/gatt-service
 unit/test-eir
 unit/test-uuid
 unit/test-crc
-- 
1.8.3.1


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

* [PATCH BlueZ v2 14/18] test: Add signal handling for gatt-service
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (12 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 13/18] gitignore: Add test/gatt-service Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 15/18] test: Add registering external service Claudio Takahasi
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch implements signal handling to run cleanup tasks before
exiting.
---
 test/gatt-service.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index bf5cba9..e9d73c0 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,12 +27,14 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <sys/signalfd.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
 #define SERVICE_IFACE			"org.bluez.GattService1"
+#define SERVICE_MGR_IFACE		"org.bluez.GattServiceManager1"
 
 /* Immediate Alert Service UUID */
 #define IAS_UUID			"00001802-0000-1000-8000-00805f9b34fb"
@@ -112,9 +114,57 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
+							gpointer user_data)
+{
+	g_main_loop_quit(main_loop);
+
+	return FALSE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int main(int argc, char *argv[])
 {
 	DBusConnection *dbus_conn;
+	guint signal;
+
+	signal = setup_signalfd();
+	if (signal == 0)
+		return -errno;
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
 
@@ -129,6 +179,8 @@ int main(int argc, char *argv[])
 
 	g_main_loop_run(main_loop);
 
+	g_source_remove(signal);
+
 	g_slist_free_full(services, g_free);
 	dbus_connection_unref(dbus_conn);
 
-- 
1.8.3.1


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

* [PATCH BlueZ v2 15/18] test: Add registering external service
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (13 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 14/18] test: Add signal handling for gatt-service Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 16/18] gatttool: Add unix socket connect Claudio Takahasi
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch extends gatt-service to call RegisterService() when org.bluez
service gets connected to the system bus.
---
 test/gatt-service.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index e9d73c0..bad3ffe 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -114,6 +114,65 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static void register_external_service_reply(DBusPendingCall *call,
+							void *user_data)
+{
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	dbus_set_error_from_message(&derr, reply);
+
+	if (dbus_error_is_set(&derr))
+		fprintf(stderr, "RegisterService: %s\n", derr.message);
+	else
+		printf("RegisterService: OK\n");
+
+	dbus_message_unref(reply);
+	dbus_error_free(&derr);
+}
+
+static void register_external_service(gpointer a, gpointer b)
+{
+	DBusConnection *conn = b;
+	const char *path = a;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	DBusMessageIter iter, dict;
+
+	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+					SERVICE_MGR_IFACE, "RegisterService");
+	if (msg == NULL) {
+		fprintf(stderr, "Couldn't allocate D-Bus message\n");
+		return;
+	}
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	/* TODO: Add options dictionary */
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
+		dbus_message_unref(msg);
+		return;
+	}
+
+	dbus_pending_call_set_notify(call, register_external_service_reply,
+								NULL, NULL);
+
+	dbus_pending_call_unref(call);
+}
+
+static void connect_handler(DBusConnection *conn, void *user_data)
+{
+	g_slist_foreach(services, register_external_service, conn);
+}
+
 static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
 							gpointer user_data)
 {
@@ -159,6 +218,7 @@ static guint setup_signalfd(void)
 
 int main(int argc, char *argv[])
 {
+	GDBusClient *client;
 	DBusConnection *dbus_conn;
 	guint signal;
 
@@ -177,8 +237,14 @@ int main(int argc, char *argv[])
 
 	create_services(dbus_conn);
 
+	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+	g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+
 	g_main_loop_run(main_loop);
 
+	g_dbus_client_unref(client);
+
 	g_source_remove(signal);
 
 	g_slist_free_full(services, g_free);
-- 
1.8.3.1


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

* [PATCH BlueZ v2 16/18] gatttool: Add unix socket connect
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (14 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 15/18] test: Add registering external service Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial support for GATT procedures over unix
socket transport on command line mode (one-shot command). Temporary
solution to allow local GATT procedures testing.
---
 attrib/gatttool.c | 27 ++++++++++++++++++++-------
 attrib/gatttool.h |  1 +
 attrib/utils.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index ebc8123..d701f7b 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <glib.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
@@ -53,6 +52,7 @@ static int opt_end = 0xffff;
 static int opt_handle = -1;
 static int opt_mtu = 0;
 static int opt_psm = 0;
+static gboolean opt_local = FALSE;
 static gboolean opt_primary = FALSE;
 static gboolean opt_characteristics = FALSE;
 static gboolean opt_char_read = FALSE;
@@ -511,6 +511,8 @@ static GOptionEntry options[] = {
 		"Specify local adapter interface", "hciX" },
 	{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
 		"Specify remote Bluetooth address", "MAC" },
+	{ "local", 'L', 0, G_OPTION_ARG_NONE, &opt_local,
+		"Use unix socket transport (local communication)", NULL },
 	{ "addr-type", 't', 0, G_OPTION_ARG_STRING, &opt_dst_type,
 		"Set LE address type. Default: public", "[public | random]"},
 	{ "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu,
@@ -563,6 +565,11 @@ int main(int argc, char *argv[])
 		g_clear_error(&gerr);
 	}
 
+	if (opt_local) {
+		opt_src = NULL;
+		opt_dst = NULL;
+	}
+
 	if (opt_interactive) {
 		interactive(opt_src, opt_dst, opt_dst_type, opt_psm);
 		goto done;
@@ -588,14 +595,20 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
-	if (opt_dst == NULL) {
-		g_print("Remote Bluetooth address required\n");
-		got_error = TRUE;
-		goto done;
+	if (opt_local)
+		chan = unix_connect(connect_cb, &gerr);
+	else {
+		if (opt_dst == NULL) {
+			g_print("Remote Bluetooth address required\n");
+			got_error = TRUE;
+			goto done;
+		}
+
+		chan = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
 	}
 
-	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
 		g_printerr("%s\n", gerr->message);
 		g_clear_error(&gerr);
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 8f0913c..be8e236 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -27,4 +27,5 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 			const char *dst_type, const char *sec_level,
 			int psm, int mtu, BtIOConnect connect_cb,
 			GError **gerr);
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/utils.c b/attrib/utils.c
index 77bab27..de7b00a 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -25,7 +25,12 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include <bluetooth/bluetooth.h>
@@ -101,6 +106,55 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 	return chan;
 }
 
+static gboolean unix_connect_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	BtIOConnect connect_cb = user_data;
+	GError *gerr;
+
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		gerr = g_error_new_literal(G_IO_CHANNEL_ERROR,
+						G_IO_CHANNEL_ERROR_FAILED,
+						"connection attempt failed");
+		connect_cb(io, gerr, user_data);
+		g_clear_error(&gerr);
+	} else {
+		connect_cb(io, NULL, user_data);
+	}
+
+	return FALSE;
+}
+
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr)
+{
+	GIOChannel *io;
+	struct sockaddr_un uaddr  = {
+		.sun_family	= AF_UNIX,
+		.sun_path	= "\0/bluetooth/unix_att",
+	};
+	int sk;
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		return NULL;
+	}
+
+	if (connect(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		close(sk);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+						unix_connect_cb, connect_cb);
+
+	return io;
+}
+
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data)
 {
 	char tmp[3];
-- 
1.8.3.1


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

* [PATCH BlueZ v2 17/18] gatttool: Add unix socket support for interactive mode
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (15 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 16/18] gatttool: Add unix socket connect Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-21 13:26 ` [PATCH BlueZ v2 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch allows running GATT operations over unix socket on
interactive mode.
---
 attrib/interactive.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9826a4b..febebaa 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -84,7 +84,7 @@ static char *get_prompt(void)
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
-		g_string_append_printf(prompt, "[%17s]", "");
+		g_string_append_printf(prompt, "[LOCAL]");
 
 	if (conn_state == STATE_CONNECTED)
 		g_string_append(prompt, COLOR_OFF);
@@ -405,15 +405,18 @@ static void cmd_connect(int argcp, char **argvp)
 			opt_dst_type = g_strdup("public");
 	}
 
-	if (opt_dst == NULL) {
-		error("Remote Bluetooth address required\n");
-		return;
+	if (opt_dst) {
+
+		rl_printf("Attempting to connect to %s\n", opt_dst);
+		set_state(STATE_CONNECTING);
+		iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
+	} else {
+		rl_printf("Local connection\n");
+		iochannel = unix_connect(connect_cb, &gerr);
 	}
 
-	rl_printf("Attempting to connect to %s\n", opt_dst);
-	set_state(STATE_CONNECTING);
-	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
 		set_state(STATE_DISCONNECTED);
 		error("%s\n", gerr->message);
-- 
1.8.3.1


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

* [PATCH BlueZ v2 18/18] bluetooth.conf: Add ObjectManager interface
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (16 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
@ 2014-01-21 13:26 ` Claudio Takahasi
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 13:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 src/bluetooth.conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..ad8891a 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -18,6 +18,7 @@
     <allow send_interface="org.bluez.Profile1"/>
     <allow send_interface="org.bluez.HeartRateWatcher1"/>
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
+    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
   </policy>
 
   <policy at_console="true">
-- 
1.8.3.1


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

* Re: [PATCH BlueZ v2 01/18] doc: Add GATT API
  2014-01-21 13:26 ` [PATCH BlueZ v2 01/18] doc: Add GATT API Claudio Takahasi
@ 2014-01-21 16:50   ` Marcel Holtmann
  2014-01-21 19:40     ` Claudio Takahasi
  0 siblings, 1 reply; 123+ messages in thread
From: Marcel Holtmann @ 2014-01-21 16:50 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth@vger.kernel.org development

Hi Claudio,

> This patch proposes an unified GATT API for local and remote services.
> ---
> doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 145 insertions(+)
> create mode 100644 doc/gatt-api.txt
> 
> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
> new file mode 100644
> index 0000000..df60fb8
> --- /dev/null
> +++ b/doc/gatt-api.txt
> @@ -0,0 +1,145 @@
> +BlueZ D-Bus GATT API description
> +********************************
> +
> +GATT local and remote services share the same high-level D-Bus API. Local
> +refers to GATT based service exported by a BlueZ plugin or an external
> +application. Remote refers to GATT services exported by the peer.
> +
> +BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
> +Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
> +external services to allow seamless GATT declarations (Service, Characteristic
> +and Descriptors) discovery.
> +
> +Service hierarchy
> +=================
> +
> +GATT remote and local service representation. Object path for local services
> +is freely definable.
> +
> +External applications implementing local services must register the services
> +using GattServiceManager1 registration method and must implement the methods
> +and properties defined in GattService1 interface.
> +
> +Service		org.bluez
> +Interface	org.bluez.GattService1 [Experimental]
> +Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
> +
> +Methods		void Release()
> +
> +			Release this service. At this point, it will not be
> +			used by BlueZ anymore and can be destroyed by the
> +			owner. Method applicable to external GATT services
> +			implementations only (GATT servers).
> +
> +Properties	string UUID [read-only]
> +
> +			128-bit service UUID.
> +
> +		array{object} Includes [read-only]: Not implemented
> +
> +			Array of object paths representing the included
> +			services of this service.
> +
> +
> +Characteristic hierarchy
> +========================
> +
> +For local GATT defined services, the object paths need to follow the service
> +path hierarchy and are freely definable.
> +
> +Service		org.bluez
> +Interface	org.bluez.Characteristic1 [Experimental]
> +Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY

this is an all or nothing deal. So better GattCharacteristic1.

> +
> +Properties	string UUID [read-only]
> +
> +			128-bit characteristic UUID.
> +
> +		object Service [read-only]
> +
> +			Object path of the GATT service the characteristc
> +			belongs to.
> +
> +		array{byte} Value [read-write]
> +
> +			Value read from the remote Bluetooth device or from
> +			the external application implementing GATT services.
> +
> +		array{string} Flags [read-only, optional]
> +
> +			Defines how the characteristic value can be used. See
> +			Core spec page 1898, "Table 3.5: Characteristic
> +			Properties bit field" and page 1900, "Table 3.8:
> +			Characteristic Extended Properties bit field". Allowed
> +			values: "broadcast", "read", "write-without-response",
> +			"write", "notify", "indicate",
> +			"authenticated-signed-writes", "reliable-write", and
> +			"writable-auxiliaries".
> +
> +
> +Characteristic Descriptors hierarchy
> +====================================
> +
> +Local or remote GATT characteristic descriptors hierarchy.
> +
> +Service		org.bluez
> +Interface	org.bluez.Descriptor1 [Experimental]
> +Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ

Same here. GattDescriptor1.

> +
> +Properties	string UUID [read-only]
> +
> +			128-bit descriptor UUID.
> +
> +		object Characteristic [read-only]
> +
> +			Object path of the GATT characteristc the descriptor
> +			belongs to.
> +
> +		array{byte} Value [read-write]
> +
> +			Raw characteristic descriptor value read from the
> +			remote Bluetooth device or from the external
> +			application implementing GATT services.
> +
> +		string Permissions [read-only]: To be defined
> +
> +			Defines read/write authentication and authorization
> +			requirements.
> +
> +Service Manager hierarchy
> +=============================
> +
> +Service Manager allows external applications to register GATT based
> +services. Services must follow the API for Service and Characteristic
> +described above.
> +
> +Local GATT services, characteristics and characteristic descriptors are
> +discovered automatically using the D-Bus Object Manager interface.
> +
> +Service		org.bluez
> +Interface	org.bluez.GattServiceManager1 [Experimental]
> +Object path	/org/bluez

Here we could discuss to use GattManager1 to make it shorter, but I am not sure if that actually helps. I currently tend to leave it as GattServiceManager1.

> +
> +Methods		RegisterService(object service, dict options)
> +
> +			Registers remote application service exported under
> +			interface GattService1. Characteristic objects must
> +			be hierarchical to their service and must use the
> +			interface Characteristic1. D-Bus Object Manager is
> +			used to fetch the exported objects.
> +
> +			"service" object path together with the D-Bus system
> +			bus connection ID define the identification of the
> +			application registering a GATT based service.
> +
> +			Possible errors: org.bluez.Error.InvalidArguments
> +					 org.bluez.Error.AlreadyExists
> +
> +		UnregisterService(object service)
> +
> +			This unregisters the service that has been
> +			previously registered. The object path parameter
> +			must match the same value that has been used
> +			on registration.
> +
> +			Possible errors: org.bluez.Error.DoesNotExist

Regards

Marcel


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

* Re: [PATCH BlueZ v2 01/18] doc: Add GATT API
  2014-01-21 16:50   ` Marcel Holtmann
@ 2014-01-21 19:40     ` Claudio Takahasi
  2014-01-21 19:48       ` Johan Hedberg
  0 siblings, 1 reply; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-21 19:40 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg
  Cc: linux-bluetooth@vger.kernel.org development

Hi Marcel/Johan:

On Tue, Jan 21, 2014 at 1:50 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Claudio,
>
>> This patch proposes an unified GATT API for local and remote services.
>> ---
>> doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 145 insertions(+)
>> create mode 100644 doc/gatt-api.txt
>>
>> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
>> new file mode 100644
>> index 0000000..df60fb8
>> --- /dev/null
>> +++ b/doc/gatt-api.txt
>> @@ -0,0 +1,145 @@
>> +BlueZ D-Bus GATT API description
>> +********************************
>> +
>> +GATT local and remote services share the same high-level D-Bus API. Local
>> +refers to GATT based service exported by a BlueZ plugin or an external
>> +application. Remote refers to GATT services exported by the peer.
>> +
>> +BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
>> +Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
>> +external services to allow seamless GATT declarations (Service, Characteristic
>> +and Descriptors) discovery.
>> +
>> +Service hierarchy
>> +=================
>> +
>> +GATT remote and local service representation. Object path for local services
>> +is freely definable.
>> +
>> +External applications implementing local services must register the services
>> +using GattServiceManager1 registration method and must implement the methods
>> +and properties defined in GattService1 interface.
>> +
>> +Service              org.bluez
>> +Interface    org.bluez.GattService1 [Experimental]
>> +Object path  [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
>> +
>> +Methods              void Release()
>> +
>> +                     Release this service. At this point, it will not be
>> +                     used by BlueZ anymore and can be destroyed by the
>> +                     owner. Method applicable to external GATT services
>> +                     implementations only (GATT servers).
>> +
>> +Properties   string UUID [read-only]
>> +
>> +                     128-bit service UUID.
>> +
>> +             array{object} Includes [read-only]: Not implemented
>> +
>> +                     Array of object paths representing the included
>> +                     services of this service.
>> +
>> +
>> +Characteristic hierarchy
>> +========================
>> +
>> +For local GATT defined services, the object paths need to follow the service
>> +path hierarchy and are freely definable.
>> +
>> +Service              org.bluez
>> +Interface    org.bluez.Characteristic1 [Experimental]
>> +Object path  [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
>
> this is an all or nothing deal. So better GattCharacteristic1.

OK. It will be changed in the next patchset.

>
>> +
>> +Properties   string UUID [read-only]
>> +
>> +                     128-bit characteristic UUID.
>> +
>> +             object Service [read-only]
>> +
>> +                     Object path of the GATT service the characteristc
>> +                     belongs to.
>> +
>> +             array{byte} Value [read-write]
>> +
>> +                     Value read from the remote Bluetooth device or from
>> +                     the external application implementing GATT services.
>> +
>> +             array{string} Flags [read-only, optional]
>> +
>> +                     Defines how the characteristic value can be used. See
>> +                     Core spec page 1898, "Table 3.5: Characteristic
>> +                     Properties bit field" and page 1900, "Table 3.8:
>> +                     Characteristic Extended Properties bit field". Allowed
>> +                     values: "broadcast", "read", "write-without-response",
>> +                     "write", "notify", "indicate",
>> +                     "authenticated-signed-writes", "reliable-write", and
>> +                     "writable-auxiliaries".
>> +
>> +
>> +Characteristic Descriptors hierarchy
>> +====================================
>> +
>> +Local or remote GATT characteristic descriptors hierarchy.
>> +
>> +Service              org.bluez
>> +Interface    org.bluez.Descriptor1 [Experimental]
>> +Object path  [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
>
> Same here. GattDescriptor1.

OK. It will be changed in the next patchset.

>
>> +
>> +Properties   string UUID [read-only]
>> +
>> +                     128-bit descriptor UUID.
>> +
>> +             object Characteristic [read-only]
>> +
>> +                     Object path of the GATT characteristc the descriptor
>> +                     belongs to.
>> +
>> +             array{byte} Value [read-write]
>> +
>> +                     Raw characteristic descriptor value read from the
>> +                     remote Bluetooth device or from the external
>> +                     application implementing GATT services.
>> +
>> +             string Permissions [read-only]: To be defined
>> +
>> +                     Defines read/write authentication and authorization
>> +                     requirements.
>> +
>> +Service Manager hierarchy
>> +=============================
>> +
>> +Service Manager allows external applications to register GATT based
>> +services. Services must follow the API for Service and Characteristic
>> +described above.
>> +
>> +Local GATT services, characteristics and characteristic descriptors are
>> +discovered automatically using the D-Bus Object Manager interface.
>> +
>> +Service              org.bluez
>> +Interface    org.bluez.GattServiceManager1 [Experimental]
>> +Object path  /org/bluez
>
> Here we could discuss to use GattManager1 to make it shorter, but I am not sure if that actually helps. I currently tend to leave it as GattServiceManager1.

I prefer GattManager1. I have two reasons:
* "Service" is included in the methods names: RegisterService and
UnregisterService
* GattManager1 name is more generic and we can use it for other GATT
methods not directly related to "Service". At the moment, I don't have
examples, but I was thinking on potential methods related to GATT
Client.

Marcel/Johan: Please define which name will be used.

>
>> +
>> +Methods              RegisterService(object service, dict options)
>> +
>> +                     Registers remote application service exported under
>> +                     interface GattService1. Characteristic objects must
>> +                     be hierarchical to their service and must use the
>> +                     interface Characteristic1. D-Bus Object Manager is
>> +                     used to fetch the exported objects.
>> +
>> +                     "service" object path together with the D-Bus system
>> +                     bus connection ID define the identification of the
>> +                     application registering a GATT based service.
>> +
>> +                     Possible errors: org.bluez.Error.InvalidArguments
>> +                                      org.bluez.Error.AlreadyExists
>> +
>> +             UnregisterService(object service)
>> +
>> +                     This unregisters the service that has been
>> +                     previously registered. The object path parameter
>> +                     must match the same value that has been used
>> +                     on registration.
>> +
>> +                     Possible errors: org.bluez.Error.DoesNotExist
>
> Regards
>
> Marcel

Regards,
Claudio

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

* Re: [PATCH BlueZ v2 01/18] doc: Add GATT API
  2014-01-21 19:40     ` Claudio Takahasi
@ 2014-01-21 19:48       ` Johan Hedberg
  2014-01-21 19:51         ` Marcel Holtmann
  0 siblings, 1 reply; 123+ messages in thread
From: Johan Hedberg @ 2014-01-21 19:48 UTC (permalink / raw)
  To: Claudio Takahasi
  Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development

Hi Claudio,

On Tue, Jan 21, 2014, Claudio Takahasi wrote:
> >> +Interface    org.bluez.GattServiceManager1 [Experimental]
> >> +Object path  /org/bluez
> >
> > Here we could discuss to use GattManager1 to make it shorter, but I
> > am not sure if that actually helps. I currently tend to leave it as
> > GattServiceManager1.
> 
> I prefer GattManager1. I have two reasons:
> * "Service" is included in the methods names: RegisterService and
> UnregisterService
> * GattManager1 name is more generic and we can use it for other GATT
> methods not directly related to "Service". At the moment, I don't have
> examples, but I was thinking on potential methods related to GATT
> Client.
> 
> Marcel/Johan: Please define which name will be used.

I'm voting for GattManager1, but Marcel has veto rights :)

Johan

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

* Re: [PATCH BlueZ v2 01/18] doc: Add GATT API
  2014-01-21 19:48       ` Johan Hedberg
@ 2014-01-21 19:51         ` Marcel Holtmann
  0 siblings, 0 replies; 123+ messages in thread
From: Marcel Holtmann @ 2014-01-21 19:51 UTC (permalink / raw)
  To: Johan Hedberg
  Cc: Claudio Takahasi, linux-bluetooth@vger.kernel.org development

Hi Johan,

>>>> +Interface    org.bluez.GattServiceManager1 [Experimental]
>>>> +Object path  /org/bluez
>>> 
>>> Here we could discuss to use GattManager1 to make it shorter, but I
>>> am not sure if that actually helps. I currently tend to leave it as
>>> GattServiceManager1.
>> 
>> I prefer GattManager1. I have two reasons:
>> * "Service" is included in the methods names: RegisterService and
>> UnregisterService
>> * GattManager1 name is more generic and we can use it for other GATT
>> methods not directly related to "Service". At the moment, I don't have
>> examples, but I was thinking on potential methods related to GATT
>> Client.
>> 
>> Marcel/Johan: Please define which name will be used.
> 
> I'm voting for GattManager1, but Marcel has veto rights :)

lets go with GattManager1 and see where it takes us.

Regards

Marcel


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

* [PATCH BlueZ v3 00/18] GATT API: External Services
  2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
                   ` (17 preceding siblings ...)
  2014-01-21 13:26 ` [PATCH BlueZ v2 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
@ 2014-01-22 13:40 ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 01/18] doc: Add GATT API Claudio Takahasi
                     ` (18 more replies)
  18 siblings, 19 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patchset implements the minimal support for adding local services
declarations.

Limitation: Remove services and multiple services exported by the same
remote will be implemented the next series.

Changes from PATCH v2 to PATCH v3:
* Rebase
* Interfaces renamed: s/GattServiceManager1/GattManager1,
  s/Characteristic1/GattCharacteristic1, s/Descriptor/GattDescriptor1
* test/gatt-service.c: s/fprintf/printf

Changes from PATCH v1 to PATCH v2:
* Rebase
* Included patch "doc: Add GATT API"
* Interfaces renamed: s/Service1/GattService1, and
  s/ServiceManager1/GattServiceManager1
  * Removed patch "gatt: Implement UnregisterService" from this patchset

  Changes from PATCH v0 to PATCH v1:
  * Rebase

  Changes from RFC v0 to PATCH v0:
  * Changed copyright year : s/2013/2014
  * Fixed coding style
  * Added gatt-service binary to gitignore
  * Added extra comment in the source code

  Features:
  * API for internal and external services declaration
  * Unix socket for testing purpose: services are exported
  through unix sockets to avoid breaking the current attribute
  server.

  How to test:
  Run bluetoothd with EXPERIMENTAL flag (-E)
  Replace /etc/dbus-1/system.d/bluetooth.conf and reload DBus settings
  $gatttool -L --primary (or interactive mode)

  Roughly upstreaming plan (steps):
  * GATT Server: External Services -> pathset GATT API: External Services
  * GATT Server: External Characteristics (Server)
  * GATT Server: External Descriptors (Server)
  * Replace attribute server

Alvaro Silva (6):
  gatt: Add stub for gatt.{c, h} files
  gatt: Register Manager D-Bus Interface
  gatt: Add registering external service
  gatt: Add external services tracking
  gatt: Register ATT command/event handler
  gatt: Add Discover All Primary Services

Andre Guedes (1):
  gatt: Add helper for creating GATT services

Claudio Takahasi (11):
  doc: Add GATT API
  lib: Move GATT UUID to uuid.h
  gatt: Add server unix socket
  gattrib: Use default ATT LE MTU for non-standard sockets
  test: Add external service GATT skeleton
  gitignore: Add test/gatt-service
  test: Add signal handling for gatt-service
  test: Add registering external service
  gatttool: Add unix socket connect
  gatttool: Add unix socket support for interactive mode
  bluetooth.conf: Add ObjectManager interface

 .gitignore           |   1 +
 Makefile.am          |   2 +
 Makefile.tools       |   5 +
 attrib/gatt.h        |  25 ----
 attrib/gattrib.c     |  16 +--
 attrib/gatttool.c    |  27 +++-
 attrib/gatttool.h    |   1 +
 attrib/interactive.c |  19 +--
 attrib/utils.c       |  54 ++++++++
 doc/gatt-api.txt     | 145 +++++++++++++++++++
 lib/uuid.h           |  30 ++++
 src/bluetooth.conf   |   1 +
 src/gatt-dbus.c      | 271 ++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h      |  25 ++++
 src/gatt.c           | 383 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h           |  36 +++++
 src/main.c           |   4 +
 test/gatt-service.c  | 254 ++++++++++++++++++++++++++++++++++
 18 files changed, 1251 insertions(+), 48 deletions(-)
 create mode 100644 doc/gatt-api.txt
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h
 create mode 100644 test/gatt-service.c

-- 
1.8.3.1


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

* [PATCH BlueZ v3 01/18] doc: Add GATT API
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
                     ` (17 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch proposes an unified GATT API for local and remote services.
---
 doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)
 create mode 100644 doc/gatt-api.txt

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
new file mode 100644
index 0000000..2d92f03
--- /dev/null
+++ b/doc/gatt-api.txt
@@ -0,0 +1,145 @@
+BlueZ D-Bus GATT API description
+********************************
+
+GATT local and remote services share the same high-level D-Bus API. Local
+refers to GATT based service exported by a BlueZ plugin or an external
+application. Remote refers to GATT services exported by the peer.
+
+BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
+Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
+external services to allow seamless GATT declarations (Service, Characteristic
+and Descriptors) discovery.
+
+Service hierarchy
+=================
+
+GATT remote and local service representation. Object path for local services
+is freely definable.
+
+External applications implementing local services must register the services
+using GattManager1 registration method and must implement the methods and
+properties defined in GattService1 interface.
+
+Service		org.bluez
+Interface	org.bluez.GattService1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+
+Methods		void Release()
+
+			Release this service. At this point, it will not be
+			used by BlueZ anymore and can be destroyed by the
+			owner. Method applicable to external GATT services
+			implementations only (GATT servers).
+
+Properties	string UUID [read-only]
+
+			128-bit service UUID.
+
+		array{object} Includes [read-only]: Not implemented
+
+			Array of object paths representing the included
+			services of this service.
+
+
+Characteristic hierarchy
+========================
+
+For local GATT defined services, the object paths need to follow the service
+path hierarchy and are freely definable.
+
+Service		org.bluez
+Interface	org.bluez.GattCharacteristic1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+
+Properties	string UUID [read-only]
+
+			128-bit characteristic UUID.
+
+		object Service [read-only]
+
+			Object path of the GATT service the characteristc
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Value read from the remote Bluetooth device or from
+			the external application implementing GATT services.
+
+		array{string} Flags [read-only, optional]
+
+			Defines how the characteristic value can be used. See
+			Core spec page 1898, "Table 3.5: Characteristic
+			Properties bit field" and page 1900, "Table 3.8:
+			Characteristic Extended Properties bit field". Allowed
+			values: "broadcast", "read", "write-without-response",
+			"write", "notify", "indicate",
+			"authenticated-signed-writes", "reliable-write", and
+			"writable-auxiliaries".
+
+
+Characteristic Descriptors hierarchy
+====================================
+
+Local or remote GATT characteristic descriptors hierarchy.
+
+Service		org.bluez
+Interface	org.bluez.GattDescriptor1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+
+Properties	string UUID [read-only]
+
+			128-bit descriptor UUID.
+
+		object Characteristic [read-only]
+
+			Object path of the GATT characteristc the descriptor
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Raw characteristic descriptor value read from the
+			remote Bluetooth device or from the external
+			application implementing GATT services.
+
+		string Permissions [read-only]: To be defined
+
+			Defines read/write authentication and authorization
+			requirements.
+
+Service Manager hierarchy
+=============================
+
+Service Manager allows external applications to register GATT based
+services. Services must follow the API for Service and Characteristic
+described above.
+
+Local GATT services, characteristics and characteristic descriptors are
+discovered automatically using the D-Bus Object Manager interface.
+
+Service		org.bluez
+Interface	org.bluez.GattManager1 [Experimental]
+Object path	/org/bluez
+
+Methods		RegisterService(object service, dict options)
+
+			Registers remote application service exported under
+			interface GattService1. Characteristic objects must
+			be hierarchical to their service and must use the
+			interface GattCharacteristic1. D-Bus Object Manager
+			is used to fetch the exported objects.
+
+			"service" object path together with the D-Bus system
+			bus connection ID define the identification of the
+			application registering a GATT based service.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		UnregisterService(object service)
+
+			This unregisters the service that has been
+			previously registered. The object path parameter
+			must match the same value that has been used
+			on registration.
+
+			Possible errors: org.bluez.Error.DoesNotExist
-- 
1.8.3.1


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

* [PATCH BlueZ v3 02/18] gatt: Add stub for gatt.{c, h} files
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 01/18] doc: Add GATT API Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
                     ` (16 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

These files implement functions to handle ATT transactions, and expose
functions to allow other entities to manage GATT based services. It
is a replacement for src/attrib-server.c.
---
 Makefile.am |  1 +
 src/gatt.c  | 38 ++++++++++++++++++++++++++++++++++++++
 src/gatt.h  | 26 ++++++++++++++++++++++++++
 src/main.c  |  4 ++++
 4 files changed, 69 insertions(+)
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h

diff --git a/Makefile.am b/Makefile.am
index 6c10ed3..3346ff5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
 			src/eir.h src/eir.c \
diff --git a/src/gatt.c b/src/gatt.c
new file mode 100644
index 0000000..06619f0
--- /dev/null
+++ b/src/gatt.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 "gatt.h"
+
+void gatt_init(void)
+{
+
+}
+
+void gatt_cleanup(void)
+{
+
+}
diff --git a/src/gatt.h b/src/gatt.h
new file mode 100644
index 0000000..3a320b4
--- /dev/null
+++ b/src/gatt.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 gatt_init(void);
+
+void gatt_cleanup(void);
diff --git a/src/main.c b/src/main.c
index 91d90b4..fccc838 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,6 +55,7 @@
 #include "dbus-common.h"
 #include "agent.h"
 #include "profile.h"
+#include "gatt.h"
 #include "systemd.h"
 
 #define BLUEZ_NAME "org.bluez"
@@ -545,6 +546,8 @@ int main(int argc, char *argv[])
 
 	g_dbus_set_flags(gdbus_flags);
 
+	gatt_init();
+
 	if (option_compat == TRUE)
 		sdp_flags |= SDP_SERVER_COMPAT;
 
@@ -595,6 +598,7 @@ int main(int argc, char *argv[])
 	btd_profile_cleanup();
 	btd_agent_cleanup();
 	btd_device_cleanup();
+	gatt_cleanup();
 
 	adapter_cleanup();
 
-- 
1.8.3.1


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

* [PATCH BlueZ v3 03/18] gatt: Register Manager D-Bus Interface
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 01/18] doc: Add GATT API Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 04/18] gatt: Add registering external service Claudio Takahasi
                     ` (15 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers GATT Service Manager D-Bus Interface. This
interface implements the methods to allow external application register
and unregister GATT Services.
---
 Makefile.am     |  1 +
 src/gatt-dbus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h | 25 +++++++++++++++++++
 src/gatt.c      |  9 +++++++
 4 files changed, 110 insertions(+)
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h

diff --git a/Makefile.am b/Makefile.am
index 3346ff5..d81302f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt-dbus.h src/gatt-dbus.c \
 			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
new file mode 100644
index 0000000..183c611
--- /dev/null
+++ b/src/gatt-dbus.c
@@ -0,0 +1,75 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include "dbus-common.h"
+#include "log.h"
+
+#include "gatt-dbus.h"
+
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
+
+static DBusMessage *register_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable methods[] = {
+	{ GDBUS_EXPERIMENTAL_METHOD("RegisterService",
+				GDBUS_ARGS({ "service", "o"},
+						{ "options", "a{sv}"}),
+				NULL, register_service) },
+	{ GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
+				GDBUS_ARGS({"service", "o"}),
+				NULL, unregister_service) },
+	{ }
+};
+
+gboolean gatt_dbus_manager_register(void)
+{
+	return g_dbus_register_interface(btd_get_dbus_connection(),
+					"/org/bluez", GATT_MGR_IFACE,
+					methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+							GATT_MGR_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
new file mode 100644
index 0000000..310cfa9
--- /dev/null
+++ b/src/gatt-dbus.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *
+ */
+
+gboolean gatt_dbus_manager_register(void);
+void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 06619f0..e8b691a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,14 +25,23 @@
 #include <config.h>
 #endif
 
+#include <glib.h>
+
+#include "log.h"
+
+#include "gatt-dbus.h"
 #include "gatt.h"
 
 void gatt_init(void)
 {
+	DBG("Starting GATT server");
 
+	gatt_dbus_manager_register();
 }
 
 void gatt_cleanup(void)
 {
+	DBG("Stopping GATT server");
 
+	gatt_dbus_manager_unregister();
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v3 04/18] gatt: Add registering external service
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (2 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
                     ` (14 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch allows external applications register a given service on
Bluez. Applications must provide an object path and a dictionary of
options. Options dictionary will be used later to provide additional
service information.
---
 src/gatt-dbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 183c611..fd614f9 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -26,22 +26,109 @@
 #endif
 
 #include <stdint.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#include "adapter.h"
+#include "device.h"
+#include "lib/uuid.h"
 #include "dbus-common.h"
 #include "log.h"
 
+#include "error.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
 
+struct external_app {
+	char *owner;
+	char *path;
+	GDBusClient *client;
+	unsigned int watch;
+};
+
+static GSList *external_apps;
+
+static int external_app_path_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct external_app *eapp = a;
+	const char *path = b;
+
+	return g_strcmp0(eapp->path, path);
+}
+
+static void external_app_watch_destroy(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+
+	/* TODO: Remove from the database */
+
+	external_apps = g_slist_remove(external_apps, eapp);
+
+	g_dbus_client_unref(eapp->client);
+
+	g_free(eapp->owner);
+	g_free(eapp->path);
+	g_free(eapp);
+}
+
+static struct external_app *new_external_app(DBusConnection *conn,
+					const char *sender, const char *path)
+{
+	struct external_app *eapp;
+	GDBusClient *client;
+
+	client = g_dbus_client_new(conn, sender, "/");
+	if (client == NULL)
+		return NULL;
+
+	eapp = g_new0(struct external_app, 1);
+
+	eapp->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
+			sender, NULL, eapp, external_app_watch_destroy);
+	if (eapp->watch == 0) {
+		g_dbus_client_unref(client);
+		g_free(eapp);
+		return NULL;
+	}
+
+	eapp->owner = g_strdup(sender);
+	eapp->client = client;
+	eapp->path = g_strdup(path);
+
+	return eapp;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
-	return dbus_message_new_method_return(msg);
+	struct external_app *eapp;
+	DBusMessageIter iter;
+	const char *path;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &path);
+
+	if (g_slist_find_custom(external_apps, path, external_app_path_cmp))
+		return btd_error_already_exists(msg);
+
+	eapp = new_external_app(conn, dbus_message_get_sender(msg), path);
+	if (eapp == NULL)
+		return btd_error_failed(msg, "Not enough resources");
+
+	external_apps = g_slist_prepend(external_apps, eapp);
+
+	DBG("New app %p: %s", eapp, path);
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
 static DBusMessage *unregister_service(DBusConnection *conn,
-- 
1.8.3.1


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

* [PATCH BlueZ v3 05/18] lib: Move GATT UUID to uuid.h
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (3 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 04/18] gatt: Add registering external service Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
                     ` (13 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch moves GATT UUIDs definitions to a common header. uuid.h contains
helper functions to manipulate Bluetooth UUIDs and some common BR/EDR services
UUIDs.
---
 attrib/gatt.h | 25 -------------------------
 lib/uuid.h    | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0f113e7..4fea3eb 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,31 +24,6 @@
 
 #include <bluetooth/sdp.h>
 
-/* GATT Profile Attribute types */
-#define GATT_PRIM_SVC_UUID		0x2800
-#define GATT_SND_SVC_UUID		0x2801
-#define GATT_INCLUDE_UUID		0x2802
-#define GATT_CHARAC_UUID		0x2803
-
-/* GATT Characteristic Types */
-#define GATT_CHARAC_DEVICE_NAME			0x2A00
-#define GATT_CHARAC_APPEARANCE			0x2A01
-#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG	0x2A02
-#define GATT_CHARAC_RECONNECTION_ADDRESS	0x2A03
-#define GATT_CHARAC_PERIPHERAL_PREF_CONN	0x2A04
-#define GATT_CHARAC_SERVICE_CHANGED		0x2A05
-
-/* GATT Characteristic Descriptors */
-#define GATT_CHARAC_EXT_PROPER_UUID	0x2900
-#define GATT_CHARAC_USER_DESC_UUID	0x2901
-#define GATT_CLIENT_CHARAC_CFG_UUID	0x2902
-#define GATT_SERVER_CHARAC_CFG_UUID	0x2903
-#define GATT_CHARAC_FMT_UUID		0x2904
-#define GATT_CHARAC_AGREG_FMT_UUID	0x2905
-#define GATT_CHARAC_VALID_RANGE_UUID	0x2906
-#define GATT_EXTERNAL_REPORT_REFERENCE	0x2907
-#define GATT_REPORT_REFERENCE		0x2908
-
 /* Client Characteristic Configuration bit field */
 #define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT	0x0001
 #define GATT_CLIENT_CHARAC_CFG_IND_BIT		0x0002
diff --git a/lib/uuid.h b/lib/uuid.h
index 95e5a9a..c24cee5 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -105,6 +105,31 @@ extern "C" {
 #define OBEX_MNS_UUID		"00001133-0000-1000-8000-00805f9b34fb"
 #define OBEX_MAP_UUID		"00001134-0000-1000-8000-00805f9b34fb"
 
+/* GATT UUIDs section */
+#define GATT_PRIM_SVC_UUID				0x2800
+#define GATT_SND_SVC_UUID				0x2801
+#define GATT_INCLUDE_UUID				0x2802
+#define GATT_CHARAC_UUID				0x2803
+
+/* GATT Characteristic Types */
+#define GATT_CHARAC_DEVICE_NAME				0x2A00
+#define GATT_CHARAC_APPEARANCE				0x2A01
+#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG		0x2A02
+#define GATT_CHARAC_RECONNECTION_ADDRESS		0x2A03
+#define GATT_CHARAC_PERIPHERAL_PREF_CONN		0x2A04
+#define GATT_CHARAC_SERVICE_CHANGED			0x2A05
+
+/* GATT Characteristic Descriptors */
+#define GATT_CHARAC_EXT_PROPER_UUID			0x2900
+#define GATT_CHARAC_USER_DESC_UUID			0x2901
+#define GATT_CLIENT_CHARAC_CFG_UUID			0x2902
+#define GATT_SERVER_CHARAC_CFG_UUID			0x2903
+#define GATT_CHARAC_FMT_UUID				0x2904
+#define GATT_CHARAC_AGREG_FMT_UUID			0x2905
+#define GATT_CHARAC_VALID_RANGE_UUID			0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE			0x2907
+#define GATT_REPORT_REFERENCE				0x2908
+
 typedef struct {
 	enum {
 		BT_UUID_UNSPEC = 0,
-- 
1.8.3.1


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

* [PATCH BlueZ v3 06/18] gatt: Add helper for creating GATT services
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (4 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 07/18] gatt: Add external services tracking Claudio Takahasi
                     ` (12 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes

From: Andre Guedes <andre.guedes@openbossa.org>

This patch adds the btd_gatt_add_service() helper which adds a
GATT Service declaration to the local attribute database.
---
 lib/uuid.h |  5 +++++
 src/gatt.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h | 10 ++++++++++
 3 files changed, 77 insertions(+)

diff --git a/lib/uuid.h b/lib/uuid.h
index c24cee5..237145b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -158,6 +158,11 @@ void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
 int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
 int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
 
+static inline int bt_uuid_len(const bt_uuid_t *uuid)
+{
+	return uuid->type / 8;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gatt.c b/src/gatt.c
index e8b691a..ee045b1 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -27,11 +27,73 @@
 
 #include <glib.h>
 
+#include "adapter.h"
+#include "device.h"
+
 #include "log.h"
+#include "lib/uuid.h"
+#include "attrib/att.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
 
+/* Common GATT UUIDs */
+static const bt_uuid_t primary_uuid  = { .type = BT_UUID16,
+					.value.u16 = GATT_PRIM_SVC_UUID };
+
+struct btd_attribute {
+	uint16_t handle;
+	bt_uuid_t type;
+	uint16_t value_len;
+	uint8_t value[0];
+};
+
+static GList *local_attribute_db;
+static uint16_t next_handle = 0x0001;
+
+static int local_database_add(uint16_t handle, struct btd_attribute *attr)
+{
+	attr->handle = handle;
+
+	local_attribute_db = g_list_append(local_attribute_db, attr);
+
+	return 0;
+}
+
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
+{
+	uint16_t len = bt_uuid_len(uuid);
+	struct btd_attribute *attr = g_malloc0(sizeof(struct btd_attribute) +
+									len);
+
+	/*
+	 * Service DECLARATION
+	 *
+	 *   TYPE         ATTRIBUTE VALUE
+	 * +-------+---------------------------------+
+	 * |0x2800 | 0xYYYY...                       |
+	 * | (1)   | (2)                             |
+	 * +------+----------------------------------+
+	 * (1) - 2 octets: Primary/Secondary Service UUID
+	 * (2) - 2 or 16 octets: Service UUID
+	 */
+
+	attr->type = primary_uuid;
+
+	att_put_uuid(*uuid, attr->value);
+	attr->value_len = len;
+
+	if (local_database_add(next_handle, attr) < 0) {
+		g_free(attr);
+		return NULL;
+	}
+
+	/* TODO: missing overflow checking */
+	next_handle = next_handle + 1;
+
+	return attr;
+}
+
 void gatt_init(void)
 {
 	DBG("Starting GATT server");
diff --git a/src/gatt.h b/src/gatt.h
index 3a320b4..8dd1312 100644
--- a/src/gatt.h
+++ b/src/gatt.h
@@ -21,6 +21,16 @@
  *
  */
 
+struct btd_attribute;
+
 void gatt_init(void);
 
 void gatt_cleanup(void);
+
+/* btd_gatt_add_service - Add a service declaration to local attribute database.
+ * @uuid:	Service UUID.
+ *
+ * Returns a reference to service declaration attribute. In case of error,
+ * NULL is returned.
+ */
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
-- 
1.8.3.1


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

* [PATCH BlueZ v3 07/18] gatt: Add external services tracking
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (5 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 08/18] gatt: Add server unix socket Claudio Takahasi
                     ` (11 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

All primary services declarations provided by an external application
will be automatically inserted in the attribute database.
---
 src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index fd614f9..000d7ae 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -39,15 +39,21 @@
 #include "log.h"
 
 #include "error.h"
+#include "gatt.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+#define REGISTER_TIMER         1
 
 struct external_app {
 	char *owner;
 	char *path;
 	GDBusClient *client;
+	GSList *proxies;
 	unsigned int watch;
+	guint register_timer;
 };
 
 static GSList *external_apps;
@@ -60,6 +66,36 @@ static int external_app_path_cmp(gconstpointer a, gconstpointer b)
 	return g_strcmp0(eapp->path, path);
 }
 
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	if (g_strcmp0(interface, SERVICE_IFACE) != 0)
+		return;
+
+	eapp->proxies = g_slist_append(eapp->proxies, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	eapp->proxies = g_slist_remove(eapp->proxies, proxy);
+}
+
+
 static void external_app_watch_destroy(gpointer user_data)
 {
 	struct external_app *eapp = user_data;
@@ -70,6 +106,9 @@ static void external_app_watch_destroy(gpointer user_data)
 
 	g_dbus_client_unref(eapp->client);
 
+	if (eapp->register_timer)
+		g_source_remove(eapp->register_timer);
+
 	g_free(eapp->owner);
 	g_free(eapp->path);
 	g_free(eapp);
@@ -99,9 +138,75 @@ static struct external_app *new_external_app(DBusConnection *conn,
 	eapp->client = client;
 	eapp->path = g_strdup(path);
 
+	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+								NULL, eapp);
+
 	return eapp;
 }
 
+static int register_external_service(GDBusProxy *proxy)
+{
+	DBusMessageIter iter;
+	const char *uuid;
+	bt_uuid_t btuuid;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return -EINVAL;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return -EINVAL;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (bt_string_to_uuid(&btuuid, uuid) < 0)
+		return -EINVAL;
+
+	if (btd_gatt_add_service(&btuuid) == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static gboolean finish_register(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+	GSList *list;
+
+	/*
+	 * It is not possible to detect when the last proxy object
+	 * was reported. "Proxy added" handler reports objects
+	 * added on demand or returned by GetManagedObjects().
+	 * This timer helps to register all the GATT declarations
+	 * (services, characteristics and descriptors) after fetching
+	 * all the D-Bus objects.
+	 */
+
+	eapp->register_timer = 0;
+
+	for (list = eapp->proxies; list; list = g_slist_next(list)) {
+		const char *interface, *path;
+		GDBusProxy *proxy = list->data;
+
+		interface = g_dbus_proxy_get_interface(proxy);
+		path = g_dbus_proxy_get_path(proxy);
+
+		if (g_strcmp0(SERVICE_IFACE, interface) != 0)
+			continue;
+
+		if (g_strcmp0(path, eapp->path) != 0)
+			continue;
+
+		if (register_external_service(proxy) < 0) {
+			DBG("Inconsistent external service: %s", path);
+			continue;
+		}
+
+		DBG("External service: %s", path);
+	}
+
+	return FALSE;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -109,6 +214,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	DBusMessageIter iter;
 	const char *path;
 
+	DBG("Registering GATT Service");
+
 	if (!dbus_message_iter_init(msg, &iter))
 		return btd_error_invalid_args(msg);
 
@@ -127,6 +234,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	external_apps = g_slist_prepend(external_apps, eapp);
 
 	DBG("New app %p: %s", eapp, path);
+	eapp->register_timer = g_timeout_add_seconds(REGISTER_TIMER,
+							finish_register, eapp);
 
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v3 08/18] gatt: Add server unix socket
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (6 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 07/18] gatt: Add external services tracking Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
                     ` (10 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds a server unix socket to handle local ATT traffic. This
is a development purpose feature used to allow local testing without
breaking the current attribute server.
---
 src/gatt.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/src/gatt.c b/src/gatt.c
index ee045b1..4806205 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,6 +25,11 @@
 #include <config.h>
 #endif
 
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include "adapter.h"
@@ -50,6 +55,7 @@ struct btd_attribute {
 
 static GList *local_attribute_db;
 static uint16_t next_handle = 0x0001;
+static guint unix_watch;
 
 static int local_database_add(uint16_t handle, struct btd_attribute *attr)
 {
@@ -94,11 +100,71 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct sockaddr_un uaddr;
+	socklen_t len = sizeof(uaddr);
+	GIOChannel *nio;
+	int err, nsk, sk;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	nsk = accept(sk, (struct sockaddr *) &uaddr, &len);
+	if (nsk < 0) {
+		err = errno;
+		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
+		return TRUE;
+	}
+
+	nio = g_io_channel_unix_new(nsk);
+	g_io_channel_set_close_on_unref(nio, TRUE);
+	DBG("ATT UNIX socket: %p new client", nio);
+	g_io_channel_unref(nio);
+
+	return TRUE;
+}
+
 void gatt_init(void)
 {
+	struct sockaddr_un uaddr  = {
+		.sun_family     = AF_UNIX,
+		.sun_path       = "\0/bluetooth/unix_att",
+	};
+	GIOChannel *io;
+	int sk, err;
+
 	DBG("Starting GATT server");
 
 	gatt_dbus_manager_register();
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		err = errno;
+		error("ATT UNIX socket: %s(%d)", strerror(err), err);
+		return;
+	}
+
+	if (bind(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		err = errno;
+		error("binding ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	if (listen(sk, 5) < 0) {
+		err = errno;
+		error("listen ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+	unix_watch = g_io_add_watch(io,
+				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+				unix_accept_cb, NULL);
+	g_io_channel_unref(io);
 }
 
 void gatt_cleanup(void)
@@ -106,4 +172,5 @@ void gatt_cleanup(void)
 	DBG("Stopping GATT server");
 
 	gatt_dbus_manager_unregister();
+	g_source_remove(unix_watch);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v3 09/18] gattrib: Use default ATT LE MTU for non-standard sockets
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (7 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 08/18] gatt: Add server unix socket Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 10/18] gatt: Register ATT command/event handler Claudio Takahasi
                     ` (9 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch forces the MTU to 23 (default ATT MTU) if the transport
is not Bluetooth. This is a development purpose change to allow
testing GATT procedures over non-Bluetooth sockets.
---
 attrib/gattrib.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 609b908..fccb2bf 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -468,18 +468,18 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	struct _GAttrib *attrib;
 	uint16_t imtu;
 	uint16_t att_mtu;
-	uint16_t cid;
-	GError *gerr = NULL;
+	uint16_t cid = 0;
 
 	g_io_channel_set_encoding(io, NULL, NULL);
 	g_io_channel_set_buffered(io, FALSE);
 
-	bt_io_get(io, &gerr, BT_IO_OPT_IMTU, &imtu,
-				BT_IO_OPT_CID, &cid, BT_IO_OPT_INVALID);
-	if (gerr) {
-		error("%s", gerr->message);
-		g_error_free(gerr);
-		return NULL;
+	if (bt_io_get(io, NULL, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_CID, &cid,
+						BT_IO_OPT_INVALID) == FALSE) {
+		/*
+		 * Use default ATT LE MTU for non-standard transports. Used
+		 * for testing purpose only. eg: Unix sockets
+		 */
+		imtu = ATT_DEFAULT_LE_MTU;
 	}
 
 	attrib = g_try_new0(struct _GAttrib, 1);
-- 
1.8.3.1


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

* [PATCH BlueZ v3 10/18] gatt: Register ATT command/event handler
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (8 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
                     ` (8 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers the ATT channel handler to manage incoming ATT
commands and events.
---
 src/gatt.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/src/gatt.c b/src/gatt.c
index 4806205..33c3b6a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -38,6 +38,7 @@
 #include "log.h"
 #include "lib/uuid.h"
 #include "attrib/att.h"
+#include "attrib/gattrib.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
@@ -100,12 +101,83 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static void send_error(GAttrib *attrib, uint8_t opcode, uint16_t handle,
+								uint8_t ecode)
+{
+	uint8_t pdu[ATT_DEFAULT_LE_MTU];
+	size_t plen;
+
+	plen = enc_error_resp(opcode, handle, ecode, pdu, sizeof(pdu));
+
+	g_attrib_send(attrib, 0, pdu, plen, NULL, NULL, NULL);
+}
+
+static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
+							gpointer user_data)
+{
+	GAttrib *attrib = user_data;
+
+	switch (ipdu[0]) {
+	case ATT_OP_ERROR:
+		break;
+
+	/* Requests */
+	case ATT_OP_WRITE_CMD:
+	case ATT_OP_WRITE_REQ:
+	case ATT_OP_READ_REQ:
+	case ATT_OP_READ_BY_TYPE_REQ:
+	case ATT_OP_MTU_REQ:
+	case ATT_OP_FIND_INFO_REQ:
+	case ATT_OP_FIND_BY_TYPE_REQ:
+	case ATT_OP_READ_BLOB_REQ:
+	case ATT_OP_READ_MULTI_REQ:
+	case ATT_OP_PREP_WRITE_REQ:
+	case ATT_OP_EXEC_WRITE_REQ:
+	case ATT_OP_READ_BY_GROUP_REQ:
+	case ATT_OP_SIGNED_WRITE_CMD:
+		send_error(attrib, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
+		break;
+
+	/* Responses */
+	case ATT_OP_MTU_RESP:
+	case ATT_OP_FIND_INFO_RESP:
+	case ATT_OP_FIND_BY_TYPE_RESP:
+	case ATT_OP_READ_BY_TYPE_RESP:
+	case ATT_OP_READ_RESP:
+	case ATT_OP_READ_BLOB_RESP:
+	case ATT_OP_READ_MULTI_RESP:
+	case ATT_OP_READ_BY_GROUP_RESP:
+	case ATT_OP_WRITE_RESP:
+	case ATT_OP_PREP_WRITE_RESP:
+	case ATT_OP_EXEC_WRITE_RESP:
+	case ATT_OP_HANDLE_CNF:
+		break;
+
+	/* Notification & Indication */
+	case ATT_OP_HANDLE_NOTIFY:
+	case ATT_OP_HANDLE_IND:
+		break;
+	}
+}
+
+static gboolean unix_hup_cb(GIOChannel *io, GIOCondition cond,
+						gpointer user_data)
+{
+	GAttrib *attrib = user_data;
+
+	g_attrib_unregister_all(attrib);
+	g_attrib_unref(attrib);
+
+	return FALSE;
+}
+
 static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct sockaddr_un uaddr;
 	socklen_t len = sizeof(uaddr);
 	GIOChannel *nio;
+	GAttrib *attrib;
 	int err, nsk, sk;
 
 	sk = g_io_channel_unix_get_fd(io);
@@ -120,6 +192,14 @@ static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
 	nio = g_io_channel_unix_new(nsk);
 	g_io_channel_set_close_on_unref(nio, TRUE);
 	DBG("ATT UNIX socket: %p new client", nio);
+
+	attrib = g_attrib_new(nio);
+
+	g_attrib_register(attrib, GATTRIB_ALL_EVENTS, GATTRIB_ALL_HANDLES,
+					channel_handler_cb, attrib, NULL);
+
+	g_io_add_watch(nio, G_IO_HUP, unix_hup_cb, attrib);
+
 	g_io_channel_unref(nio);
 
 	return TRUE;
-- 
1.8.3.1


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

* [PATCH BlueZ v3 11/18] gatt: Add Discover All Primary Services
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (9 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 10/18] gatt: Register ATT command/event handler Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 12/18] test: Add external service GATT skeleton Claudio Takahasi
                     ` (7 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch adds ATT Read By Group request handling to the attribute
server. It is the primitive to implement Discover All Primary Services
procedure.
---
 src/gatt.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 1 deletion(-)

diff --git a/src/gatt.c b/src/gatt.c
index 33c3b6a..b204f9c 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -112,6 +112,130 @@ static void send_error(GAttrib *attrib, uint8_t opcode, uint16_t handle,
 	g_attrib_send(attrib, 0, pdu, plen, NULL, NULL, NULL);
 }
 
+static void read_by_group_resp(GAttrib *attrib, uint16_t start,
+					uint16_t end, bt_uuid_t *pattern)
+{
+	uint8_t opdu[ATT_DEFAULT_LE_MTU];
+	GList *list;
+	struct btd_attribute *last = NULL;
+	uint8_t *group_start, *group_end = NULL, *group_uuid;
+	unsigned int uuid_type = BT_UUID_UNSPEC;
+	size_t group_len = 0, plen = 0;
+
+	/*
+	 * Read By Group Type Response format:
+	 *    Attribute Opcode: 1 byte
+	 *    Length: 1 byte (size of each group)
+	 *    Group: start | end | <<UUID>>
+	 */
+
+	opdu[0] = ATT_OP_READ_BY_GROUP_RESP;
+	group_start = &opdu[2];
+	group_uuid = &opdu[6];
+
+	for (list = local_attribute_db; list;
+			last = list->data, list = g_list_next(list)) {
+		struct btd_attribute *attr = list->data;
+
+		if (attr->handle < start)
+			continue;
+
+		if (attr->handle > end)
+			break;
+
+		if (bt_uuid_cmp(&attr->type, pattern) != 0)
+			continue;
+
+		if (uuid_type != BT_UUID_UNSPEC &&
+						uuid_type != attr->type.type) {
+			/*
+			 * Groups should contain the same length: UUID16 and
+			 * UUID128 should be sent on different ATT PDUs
+			 */
+			break;
+		}
+
+		/*
+		 * MTU checking should not be shifted up, otherwise the
+		 * handle of last end group will not be set properly.
+		 */
+		if ((plen + group_len) >= ATT_DEFAULT_LE_MTU)
+			break;
+
+		/* Start Grouping handle */
+		att_put_u16(attr->handle, group_start);
+
+		/* Grouping <<UUID>>: Value is little endian */
+		memcpy(group_uuid, attr->value, attr->value_len);
+
+		if (last && group_end) {
+			att_put_u16(last->handle, group_end);
+			group_end += group_len;
+			plen += group_len;
+		}
+
+		/* Grouping initial settings: First grouping */
+		if (uuid_type == BT_UUID_UNSPEC) {
+			uuid_type = attr->type.type;
+
+			/* start(0xXXXX) | end(0xXXXX) | <<UUID>> */
+			group_len = 2 + 2 + bt_uuid_len(&attr->type);
+
+			/* 2: ATT Opcode and Length */
+			plen = 2 + group_len;
+
+			/* Size of each Attribute Data */
+			opdu[1] = group_len;
+
+			group_end = &opdu[4];
+		}
+
+		group_start += group_len;
+		group_uuid += group_len;
+	}
+
+	if (plen == 0) {
+		send_error(attrib, ATT_OP_READ_BY_GROUP_REQ, start,
+						ATT_ECODE_ATTR_NOT_FOUND);
+		return;
+	}
+
+	if (group_end)
+		att_put_u16(last->handle, group_end);
+
+	g_attrib_send(attrib, 0, opdu, plen, NULL, NULL, NULL);
+}
+
+static void read_by_group(GAttrib *attrib, const uint8_t *ipdu, size_t ilen)
+{
+	uint16_t decoded, start, end;
+	bt_uuid_t pattern;
+
+	decoded = dec_read_by_grp_req(ipdu, ilen, &start, &end, &pattern);
+	if (decoded == 0) {
+		send_error(attrib, ipdu[0], 0x0000, ATT_ECODE_INVALID_PDU);
+		return;
+	}
+
+	if (start > end || start == 0x0000) {
+		send_error(attrib, ipdu[0], start, ATT_ECODE_INVALID_HANDLE);
+		return;
+	}
+
+	 /*
+	  * Restricting Read By Group Type to <<Primary>>.
+	  * Removing the checking below requires changes to support
+	  * dynamic values(defined in the upper layer) and additional
+	  * security verification.
+	  */
+	if (bt_uuid_cmp(&pattern, &primary_uuid) != 0) {
+		send_error(attrib, ipdu[0], start, ATT_ECODE_UNSUPP_GRP_TYPE);
+		return;
+	}
+
+	read_by_group_resp(attrib, start, end, &pattern);
+}
+
 static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
 							gpointer user_data)
 {
@@ -133,11 +257,14 @@ static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
 	case ATT_OP_READ_MULTI_REQ:
 	case ATT_OP_PREP_WRITE_REQ:
 	case ATT_OP_EXEC_WRITE_REQ:
-	case ATT_OP_READ_BY_GROUP_REQ:
 	case ATT_OP_SIGNED_WRITE_CMD:
 		send_error(attrib, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
 		break;
 
+	case ATT_OP_READ_BY_GROUP_REQ:
+		read_by_group(attrib, ipdu, ilen);
+		break;
+
 	/* Responses */
 	case ATT_OP_MTU_RESP:
 	case ATT_OP_FIND_INFO_RESP:
-- 
1.8.3.1


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

* [PATCH BlueZ v3 12/18] test: Add external service GATT skeleton
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (10 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 13/18] gitignore: Add test/gatt-service Claudio Takahasi
                     ` (6 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial code for an external GATT service example.
It implements the API defined at doc/gatt-api.txt
---
 Makefile.tools      |   5 ++
 test/gatt-service.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 test/gatt-service.c

diff --git a/Makefile.tools b/Makefile.tools
index 52e49fb..ef8d56c 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -367,3 +367,8 @@ test_scripts += test/sap_client.py test/bluezutils.py \
 		test/test-heartrate test/test-alert test/test-hfp \
 		test/test-cyclingspeed test/opp-client test/ftp-client \
 		test/pbap-client test/map-client
+
+noinst_PROGRAMS += test/gatt-service
+
+test_gatt_service_SOURCES = test/gatt-service.c
+test_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la
diff --git a/test/gatt-service.c b/test/gatt-service.c
new file mode 100644
index 0000000..1cb0913
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,136 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+/* Immediate Alert Service UUID */
+#define IAS_UUID			"00001802-0000-1000-8000-00805f9b34fb"
+
+static GMainLoop *main_loop;
+static GSList *services;
+
+static gboolean service_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	const char *uuid = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+	return TRUE;
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	return TRUE;
+}
+
+static gboolean service_exist_includes(const GDBusPropertyTable *property,
+							void *user_data)
+{
+	return FALSE;
+}
+
+static DBusMessage *service_release(DBusConnection *conn,
+				DBusMessage *msg, void *user_data)
+{
+	printf("Terminating...\n");
+
+	g_main_loop_quit(main_loop);
+
+	return NULL;
+}
+
+static const GDBusMethodTable service_methods[] = {
+	{ GDBUS_NOREPLY_METHOD("Release", NULL, NULL, service_release) },
+	{ }
+};
+
+static const GDBusPropertyTable service_properties[] = {
+	{ "UUID", "s", service_get_uuid },
+	{ "Includes", "ao", service_get_includes, NULL,
+					service_exist_includes },
+	{ }
+};
+
+static char *register_service(DBusConnection *conn, const char *uuid)
+{
+	static int id = 1;
+	char *path;
+
+	path = g_strdup_printf("/service%d", id++);
+	if (g_dbus_register_interface(conn, path, SERVICE_IFACE,
+				service_methods, NULL, service_properties,
+				g_strdup(uuid), g_free) == FALSE) {
+		printf("Couldn't register service interface\n");
+		g_free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+static void create_services(DBusConnection *conn)
+{
+	char *service_path;
+
+	service_path = register_service(conn, IAS_UUID);
+
+	services = g_slist_prepend(services, service_path);
+
+	printf("Registered service: %s\n", service_path);
+}
+
+int main(int argc, char *argv[])
+{
+	DBusConnection *dbus_conn;
+
+	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+
+	main_loop = g_main_loop_new(NULL, FALSE);
+
+	g_dbus_attach_object_manager(dbus_conn);
+
+	printf("gatt-service unique name: %s\n",
+				dbus_bus_get_unique_name(dbus_conn));
+
+	create_services(dbus_conn);
+
+	g_main_loop_run(main_loop);
+
+	g_slist_free_full(services, g_free);
+	dbus_connection_unref(dbus_conn);
+
+	return 0;
+}
-- 
1.8.3.1


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

* [PATCH BlueZ v3 13/18] gitignore: Add test/gatt-service
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (11 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 12/18] test: Add external service GATT skeleton Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 14/18] test: Add signal handling for gatt-service Claudio Takahasi
                     ` (5 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 67e9850..48fcf57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,6 +73,7 @@ tools/3dsp
 tools/obexctl
 test/sap_client.pyc
 test/bluezutils.pyc
+test/gatt-service
 unit/test-eir
 unit/test-uuid
 unit/test-crc
-- 
1.8.3.1


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

* [PATCH BlueZ v3 14/18] test: Add signal handling for gatt-service
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (12 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 13/18] gitignore: Add test/gatt-service Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 15/18] test: Add registering external service Claudio Takahasi
                     ` (4 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch implements signal handling to run cleanup tasks before
exiting.
---
 test/gatt-service.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 1cb0913..ea801de 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,6 +27,7 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <sys/signalfd.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -112,9 +113,57 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
+							gpointer user_data)
+{
+	g_main_loop_quit(main_loop);
+
+	return FALSE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int main(int argc, char *argv[])
 {
 	DBusConnection *dbus_conn;
+	guint signal;
+
+	signal = setup_signalfd();
+	if (signal == 0)
+		return -errno;
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
 
@@ -129,6 +178,8 @@ int main(int argc, char *argv[])
 
 	g_main_loop_run(main_loop);
 
+	g_source_remove(signal);
+
 	g_slist_free_full(services, g_free);
 	dbus_connection_unref(dbus_conn);
 
-- 
1.8.3.1


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

* [PATCH BlueZ v3 15/18] test: Add registering external service
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (13 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 14/18] test: Add signal handling for gatt-service Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 16/18] gatttool: Add unix socket connect Claudio Takahasi
                     ` (3 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch extends gatt-service to call RegisterService() when org.bluez
service gets connected to the system bus.
---
 test/gatt-service.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index ea801de..380f56b 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -33,6 +33,7 @@
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
 #define SERVICE_IFACE			"org.bluez.GattService1"
 
 /* Immediate Alert Service UUID */
@@ -113,6 +114,65 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static void register_external_service_reply(DBusPendingCall *call,
+							void *user_data)
+{
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	dbus_set_error_from_message(&derr, reply);
+
+	if (dbus_error_is_set(&derr))
+		printf("RegisterService: %s\n", derr.message);
+	else
+		printf("RegisterService: OK\n");
+
+	dbus_message_unref(reply);
+	dbus_error_free(&derr);
+}
+
+static void register_external_service(gpointer a, gpointer b)
+{
+	DBusConnection *conn = b;
+	const char *path = a;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	DBusMessageIter iter, dict;
+
+	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+					GATT_MGR_IFACE, "RegisterService");
+	if (msg == NULL) {
+		printf("Couldn't allocate D-Bus message\n");
+		return;
+	}
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	/* TODO: Add options dictionary */
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
+		dbus_message_unref(msg);
+		return;
+	}
+
+	dbus_pending_call_set_notify(call, register_external_service_reply,
+								NULL, NULL);
+
+	dbus_pending_call_unref(call);
+}
+
+static void connect_handler(DBusConnection *conn, void *user_data)
+{
+	g_slist_foreach(services, register_external_service, conn);
+}
+
 static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
 							gpointer user_data)
 {
@@ -158,6 +218,7 @@ static guint setup_signalfd(void)
 
 int main(int argc, char *argv[])
 {
+	GDBusClient *client;
 	DBusConnection *dbus_conn;
 	guint signal;
 
@@ -176,8 +237,14 @@ int main(int argc, char *argv[])
 
 	create_services(dbus_conn);
 
+	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+	g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+
 	g_main_loop_run(main_loop);
 
+	g_dbus_client_unref(client);
+
 	g_source_remove(signal);
 
 	g_slist_free_full(services, g_free);
-- 
1.8.3.1


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

* [PATCH BlueZ v3 16/18] gatttool: Add unix socket connect
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (14 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 15/18] test: Add registering external service Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
                     ` (2 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial support for GATT procedures over unix
socket transport on command line mode (one-shot command). Temporary
solution to allow local GATT procedures testing.
---
 attrib/gatttool.c | 27 ++++++++++++++++++++-------
 attrib/gatttool.h |  1 +
 attrib/utils.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index ebc8123..d701f7b 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <glib.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
@@ -53,6 +52,7 @@ static int opt_end = 0xffff;
 static int opt_handle = -1;
 static int opt_mtu = 0;
 static int opt_psm = 0;
+static gboolean opt_local = FALSE;
 static gboolean opt_primary = FALSE;
 static gboolean opt_characteristics = FALSE;
 static gboolean opt_char_read = FALSE;
@@ -511,6 +511,8 @@ static GOptionEntry options[] = {
 		"Specify local adapter interface", "hciX" },
 	{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
 		"Specify remote Bluetooth address", "MAC" },
+	{ "local", 'L', 0, G_OPTION_ARG_NONE, &opt_local,
+		"Use unix socket transport (local communication)", NULL },
 	{ "addr-type", 't', 0, G_OPTION_ARG_STRING, &opt_dst_type,
 		"Set LE address type. Default: public", "[public | random]"},
 	{ "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu,
@@ -563,6 +565,11 @@ int main(int argc, char *argv[])
 		g_clear_error(&gerr);
 	}
 
+	if (opt_local) {
+		opt_src = NULL;
+		opt_dst = NULL;
+	}
+
 	if (opt_interactive) {
 		interactive(opt_src, opt_dst, opt_dst_type, opt_psm);
 		goto done;
@@ -588,14 +595,20 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
-	if (opt_dst == NULL) {
-		g_print("Remote Bluetooth address required\n");
-		got_error = TRUE;
-		goto done;
+	if (opt_local)
+		chan = unix_connect(connect_cb, &gerr);
+	else {
+		if (opt_dst == NULL) {
+			g_print("Remote Bluetooth address required\n");
+			got_error = TRUE;
+			goto done;
+		}
+
+		chan = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
 	}
 
-	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
 		g_printerr("%s\n", gerr->message);
 		g_clear_error(&gerr);
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 8f0913c..be8e236 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -27,4 +27,5 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 			const char *dst_type, const char *sec_level,
 			int psm, int mtu, BtIOConnect connect_cb,
 			GError **gerr);
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/utils.c b/attrib/utils.c
index 77bab27..de7b00a 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -25,7 +25,12 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include <bluetooth/bluetooth.h>
@@ -101,6 +106,55 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 	return chan;
 }
 
+static gboolean unix_connect_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	BtIOConnect connect_cb = user_data;
+	GError *gerr;
+
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		gerr = g_error_new_literal(G_IO_CHANNEL_ERROR,
+						G_IO_CHANNEL_ERROR_FAILED,
+						"connection attempt failed");
+		connect_cb(io, gerr, user_data);
+		g_clear_error(&gerr);
+	} else {
+		connect_cb(io, NULL, user_data);
+	}
+
+	return FALSE;
+}
+
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr)
+{
+	GIOChannel *io;
+	struct sockaddr_un uaddr  = {
+		.sun_family	= AF_UNIX,
+		.sun_path	= "\0/bluetooth/unix_att",
+	};
+	int sk;
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		return NULL;
+	}
+
+	if (connect(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		close(sk);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+						unix_connect_cb, connect_cb);
+
+	return io;
+}
+
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data)
 {
 	char tmp[3];
-- 
1.8.3.1


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

* [PATCH BlueZ v3 17/18] gatttool: Add unix socket support for interactive mode
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (15 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 16/18] gatttool: Add unix socket connect Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-22 13:40   ` [PATCH BlueZ v3 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch allows running GATT operations over unix socket on
interactive mode.
---
 attrib/interactive.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9826a4b..febebaa 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -84,7 +84,7 @@ static char *get_prompt(void)
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
-		g_string_append_printf(prompt, "[%17s]", "");
+		g_string_append_printf(prompt, "[LOCAL]");
 
 	if (conn_state == STATE_CONNECTED)
 		g_string_append(prompt, COLOR_OFF);
@@ -405,15 +405,18 @@ static void cmd_connect(int argcp, char **argvp)
 			opt_dst_type = g_strdup("public");
 	}
 
-	if (opt_dst == NULL) {
-		error("Remote Bluetooth address required\n");
-		return;
+	if (opt_dst) {
+
+		rl_printf("Attempting to connect to %s\n", opt_dst);
+		set_state(STATE_CONNECTING);
+		iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
+	} else {
+		rl_printf("Local connection\n");
+		iochannel = unix_connect(connect_cb, &gerr);
 	}
 
-	rl_printf("Attempting to connect to %s\n", opt_dst);
-	set_state(STATE_CONNECTING);
-	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
 		set_state(STATE_DISCONNECTED);
 		error("%s\n", gerr->message);
-- 
1.8.3.1


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

* [PATCH BlueZ v3 18/18] bluetooth.conf: Add ObjectManager interface
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (16 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
@ 2014-01-22 13:40   ` Claudio Takahasi
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-22 13:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 src/bluetooth.conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..ad8891a 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -18,6 +18,7 @@
     <allow send_interface="org.bluez.Profile1"/>
     <allow send_interface="org.bluez.HeartRateWatcher1"/>
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
+    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
   </policy>
 
   <policy at_console="true">
-- 
1.8.3.1


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

* [PATCH BlueZ v4 00/18] GATT API: External Services
  2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
                     ` (17 preceding siblings ...)
  2014-01-22 13:40   ` [PATCH BlueZ v3 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
@ 2014-01-27 18:00   ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 01/18] doc: Add GATT API Claudio Takahasi
                       ` (18 more replies)
  18 siblings, 19 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patchset implements the minimal support for adding local services
declarations.

Limitation: Remove services and multiple services exported by the same
remote will be implemented the next series.

Changes from PATCH v3 to PATCH v4:
* Rebase
* src/gatt.c: Replaced GIOChannel/GAttrib by "io".

Changes from PATCH v2 to PATCH v3:
* Rebase
* Interfaces renamed: s/GattServiceManager1/GattManager1,
  s/Characteristic1/GattCharacteristic1, s/Descriptor/GattDescriptor1
* test/gatt-service.c: s/fprintf/printf

Changes from PATCH v1 to PATCH v2:
* Rebase
* Included patch "doc: Add GATT API"
* Interfaces renamed: s/Service1/GattService1, and
  s/ServiceManager1/GattServiceManager1
* Removed patch "gatt: Implement UnregisterService" from this patchset

Changes from PATCH v0 to PATCH v1:
* Rebase

Changes from RFC v0 to PATCH v0:
* Changed copyright year : s/2013/2014
* Fixed coding style
* Added gatt-service binary to gitignore
* Added extra comment in the source code

Features:
* API for internal and external services declaration
* Unix socket for testing purpose: services are exported through unix
  sockets to avoid breaking the current attribute server.

How to test:
Run bluetoothd with EXPERIMENTAL flag (-E)
Replace /etc/dbus-1/system.d/bluetooth.conf and reload DBus settings
$gatttool -L --primary (or interactive mode)

Roughly upstreaming plan (steps):
* GATT Server: External Services -> pathset GATT API: External Services
* GATT Server: External Characteristics (Server)
* GATT Server: External Descriptors (Server)
* Replace attribute server
* Remove ATTIO and automatic connection mechanism from userspace
* Fix all GATT internal plugins
* GATT Client: Remote Services

Alvaro Silva (6):
  gatt: Add stub for gatt.{c, h} files
  gatt: Register Manager D-Bus Interface
  gatt: Add registering external service
  gatt: Add external services tracking
  gatt: Register ATT command/event handler
  gatt: Add Discover All Primary Services

Andre Guedes (1):
  gatt: Add helper for creating GATT services

Claudio Takahasi (11):
  doc: Add GATT API
  lib: Move GATT UUID to uuid.h
  gatt: Add server unix socket
  gattrib: Use default ATT LE MTU for non-standard sockets
  test: Add external service GATT skeleton
  gitignore: Add test/gatt-service
  test: Add signal handling for gatt-service
  test: Add registering external service
  gatttool: Add unix socket connect
  gatttool: Add unix socket support for interactive mode
  bluetooth.conf: Add ObjectManager interface

 .gitignore           |   1 +
 Makefile.am          |   2 +
 Makefile.tools       |   5 +
 attrib/gatt.h        |  25 ----
 attrib/gattrib.c     |  16 +--
 attrib/gatttool.c    |  27 +++-
 attrib/gatttool.h    |   1 +
 attrib/interactive.c |  19 +--
 attrib/utils.c       |  54 ++++++++
 doc/gatt-api.txt     | 145 ++++++++++++++++++++
 lib/uuid.h           |  30 ++++
 src/bluetooth.conf   |   1 +
 src/gatt-dbus.c      | 271 ++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h      |  25 ++++
 src/gatt.c           | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h           |  36 +++++
 src/main.c           |   4 +
 test/gatt-service.c  | 282 ++++++++++++++++++++++++++++++++++++++
 18 files changed, 1275 insertions(+), 48 deletions(-)
 create mode 100644 doc/gatt-api.txt
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h
 create mode 100644 test/gatt-service.c

-- 
1.8.3.1

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

* [PATCH BlueZ v4 01/18] doc: Add GATT API
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:15       ` Marcel Holtmann
  2014-01-27 18:00     ` [PATCH BlueZ v4 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
                       ` (17 subsequent siblings)
  18 siblings, 1 reply; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch proposes an unified GATT API for local and remote services.
---
 doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)
 create mode 100644 doc/gatt-api.txt

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
new file mode 100644
index 0000000..2d92f03
--- /dev/null
+++ b/doc/gatt-api.txt
@@ -0,0 +1,145 @@
+BlueZ D-Bus GATT API description
+********************************
+
+GATT local and remote services share the same high-level D-Bus API. Local
+refers to GATT based service exported by a BlueZ plugin or an external
+application. Remote refers to GATT services exported by the peer.
+
+BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
+Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
+external services to allow seamless GATT declarations (Service, Characteristic
+and Descriptors) discovery.
+
+Service hierarchy
+=================
+
+GATT remote and local service representation. Object path for local services
+is freely definable.
+
+External applications implementing local services must register the services
+using GattManager1 registration method and must implement the methods and
+properties defined in GattService1 interface.
+
+Service		org.bluez
+Interface	org.bluez.GattService1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+
+Methods		void Release()
+
+			Release this service. At this point, it will not be
+			used by BlueZ anymore and can be destroyed by the
+			owner. Method applicable to external GATT services
+			implementations only (GATT servers).
+
+Properties	string UUID [read-only]
+
+			128-bit service UUID.
+
+		array{object} Includes [read-only]: Not implemented
+
+			Array of object paths representing the included
+			services of this service.
+
+
+Characteristic hierarchy
+========================
+
+For local GATT defined services, the object paths need to follow the service
+path hierarchy and are freely definable.
+
+Service		org.bluez
+Interface	org.bluez.GattCharacteristic1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+
+Properties	string UUID [read-only]
+
+			128-bit characteristic UUID.
+
+		object Service [read-only]
+
+			Object path of the GATT service the characteristc
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Value read from the remote Bluetooth device or from
+			the external application implementing GATT services.
+
+		array{string} Flags [read-only, optional]
+
+			Defines how the characteristic value can be used. See
+			Core spec page 1898, "Table 3.5: Characteristic
+			Properties bit field" and page 1900, "Table 3.8:
+			Characteristic Extended Properties bit field". Allowed
+			values: "broadcast", "read", "write-without-response",
+			"write", "notify", "indicate",
+			"authenticated-signed-writes", "reliable-write", and
+			"writable-auxiliaries".
+
+
+Characteristic Descriptors hierarchy
+====================================
+
+Local or remote GATT characteristic descriptors hierarchy.
+
+Service		org.bluez
+Interface	org.bluez.GattDescriptor1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+
+Properties	string UUID [read-only]
+
+			128-bit descriptor UUID.
+
+		object Characteristic [read-only]
+
+			Object path of the GATT characteristc the descriptor
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Raw characteristic descriptor value read from the
+			remote Bluetooth device or from the external
+			application implementing GATT services.
+
+		string Permissions [read-only]: To be defined
+
+			Defines read/write authentication and authorization
+			requirements.
+
+Service Manager hierarchy
+=============================
+
+Service Manager allows external applications to register GATT based
+services. Services must follow the API for Service and Characteristic
+described above.
+
+Local GATT services, characteristics and characteristic descriptors are
+discovered automatically using the D-Bus Object Manager interface.
+
+Service		org.bluez
+Interface	org.bluez.GattManager1 [Experimental]
+Object path	/org/bluez
+
+Methods		RegisterService(object service, dict options)
+
+			Registers remote application service exported under
+			interface GattService1. Characteristic objects must
+			be hierarchical to their service and must use the
+			interface GattCharacteristic1. D-Bus Object Manager
+			is used to fetch the exported objects.
+
+			"service" object path together with the D-Bus system
+			bus connection ID define the identification of the
+			application registering a GATT based service.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		UnregisterService(object service)
+
+			This unregisters the service that has been
+			previously registered. The object path parameter
+			must match the same value that has been used
+			on registration.
+
+			Possible errors: org.bluez.Error.DoesNotExist
-- 
1.8.3.1


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

* [PATCH BlueZ v4 02/18] gatt: Add stub for gatt.{c, h} files
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 01/18] doc: Add GATT API Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
                       ` (16 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

These files implement functions to handle ATT transactions, and expose
functions to allow other entities to manage GATT based services. It
is a replacement for src/attrib-server.c.
---
 Makefile.am |  1 +
 src/gatt.c  | 38 ++++++++++++++++++++++++++++++++++++++
 src/gatt.h  | 26 ++++++++++++++++++++++++++
 src/main.c  |  4 ++++
 4 files changed, 69 insertions(+)
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h

diff --git a/Makefile.am b/Makefile.am
index 3a1e6dc..101d5de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
 			src/eir.h src/eir.c \
diff --git a/src/gatt.c b/src/gatt.c
new file mode 100644
index 0000000..06619f0
--- /dev/null
+++ b/src/gatt.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 "gatt.h"
+
+void gatt_init(void)
+{
+
+}
+
+void gatt_cleanup(void)
+{
+
+}
diff --git a/src/gatt.h b/src/gatt.h
new file mode 100644
index 0000000..3a320b4
--- /dev/null
+++ b/src/gatt.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 gatt_init(void);
+
+void gatt_cleanup(void);
diff --git a/src/main.c b/src/main.c
index 91d90b4..fccc838 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,6 +55,7 @@
 #include "dbus-common.h"
 #include "agent.h"
 #include "profile.h"
+#include "gatt.h"
 #include "systemd.h"
 
 #define BLUEZ_NAME "org.bluez"
@@ -545,6 +546,8 @@ int main(int argc, char *argv[])
 
 	g_dbus_set_flags(gdbus_flags);
 
+	gatt_init();
+
 	if (option_compat == TRUE)
 		sdp_flags |= SDP_SERVER_COMPAT;
 
@@ -595,6 +598,7 @@ int main(int argc, char *argv[])
 	btd_profile_cleanup();
 	btd_agent_cleanup();
 	btd_device_cleanup();
+	gatt_cleanup();
 
 	adapter_cleanup();
 
-- 
1.8.3.1


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

* [PATCH BlueZ v4 03/18] gatt: Register Manager D-Bus Interface
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 01/18] doc: Add GATT API Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 04/18] gatt: Add registering external service Claudio Takahasi
                       ` (15 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers GATT Service Manager D-Bus Interface. This
interface implements the methods to allow external application register
and unregister GATT Services.
---
 Makefile.am     |  1 +
 src/gatt-dbus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h | 25 +++++++++++++++++++
 src/gatt.c      |  9 +++++++
 4 files changed, 110 insertions(+)
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h

diff --git a/Makefile.am b/Makefile.am
index 101d5de..fbae2c8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt-dbus.h src/gatt-dbus.c \
 			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
new file mode 100644
index 0000000..183c611
--- /dev/null
+++ b/src/gatt-dbus.c
@@ -0,0 +1,75 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include "dbus-common.h"
+#include "log.h"
+
+#include "gatt-dbus.h"
+
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
+
+static DBusMessage *register_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable methods[] = {
+	{ GDBUS_EXPERIMENTAL_METHOD("RegisterService",
+				GDBUS_ARGS({ "service", "o"},
+						{ "options", "a{sv}"}),
+				NULL, register_service) },
+	{ GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
+				GDBUS_ARGS({"service", "o"}),
+				NULL, unregister_service) },
+	{ }
+};
+
+gboolean gatt_dbus_manager_register(void)
+{
+	return g_dbus_register_interface(btd_get_dbus_connection(),
+					"/org/bluez", GATT_MGR_IFACE,
+					methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+							GATT_MGR_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
new file mode 100644
index 0000000..310cfa9
--- /dev/null
+++ b/src/gatt-dbus.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *
+ */
+
+gboolean gatt_dbus_manager_register(void);
+void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 06619f0..e8b691a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,14 +25,23 @@
 #include <config.h>
 #endif
 
+#include <glib.h>
+
+#include "log.h"
+
+#include "gatt-dbus.h"
 #include "gatt.h"
 
 void gatt_init(void)
 {
+	DBG("Starting GATT server");
 
+	gatt_dbus_manager_register();
 }
 
 void gatt_cleanup(void)
 {
+	DBG("Stopping GATT server");
 
+	gatt_dbus_manager_unregister();
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v4 04/18] gatt: Add registering external service
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (2 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
                       ` (14 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch allows external applications register a given service on
Bluez. Applications must provide an object path and a dictionary of
options. Options dictionary will be used later to provide additional
service information.
---
 src/gatt-dbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 183c611..fd614f9 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -26,22 +26,109 @@
 #endif
 
 #include <stdint.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#include "adapter.h"
+#include "device.h"
+#include "lib/uuid.h"
 #include "dbus-common.h"
 #include "log.h"
 
+#include "error.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
 
+struct external_app {
+	char *owner;
+	char *path;
+	GDBusClient *client;
+	unsigned int watch;
+};
+
+static GSList *external_apps;
+
+static int external_app_path_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct external_app *eapp = a;
+	const char *path = b;
+
+	return g_strcmp0(eapp->path, path);
+}
+
+static void external_app_watch_destroy(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+
+	/* TODO: Remove from the database */
+
+	external_apps = g_slist_remove(external_apps, eapp);
+
+	g_dbus_client_unref(eapp->client);
+
+	g_free(eapp->owner);
+	g_free(eapp->path);
+	g_free(eapp);
+}
+
+static struct external_app *new_external_app(DBusConnection *conn,
+					const char *sender, const char *path)
+{
+	struct external_app *eapp;
+	GDBusClient *client;
+
+	client = g_dbus_client_new(conn, sender, "/");
+	if (client == NULL)
+		return NULL;
+
+	eapp = g_new0(struct external_app, 1);
+
+	eapp->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
+			sender, NULL, eapp, external_app_watch_destroy);
+	if (eapp->watch == 0) {
+		g_dbus_client_unref(client);
+		g_free(eapp);
+		return NULL;
+	}
+
+	eapp->owner = g_strdup(sender);
+	eapp->client = client;
+	eapp->path = g_strdup(path);
+
+	return eapp;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
-	return dbus_message_new_method_return(msg);
+	struct external_app *eapp;
+	DBusMessageIter iter;
+	const char *path;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &path);
+
+	if (g_slist_find_custom(external_apps, path, external_app_path_cmp))
+		return btd_error_already_exists(msg);
+
+	eapp = new_external_app(conn, dbus_message_get_sender(msg), path);
+	if (eapp == NULL)
+		return btd_error_failed(msg, "Not enough resources");
+
+	external_apps = g_slist_prepend(external_apps, eapp);
+
+	DBG("New app %p: %s", eapp, path);
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
 static DBusMessage *unregister_service(DBusConnection *conn,
-- 
1.8.3.1


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

* [PATCH BlueZ v4 05/18] lib: Move GATT UUID to uuid.h
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (3 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 04/18] gatt: Add registering external service Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
                       ` (13 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch moves GATT UUIDs definitions to a common header. uuid.h contains
helper functions to manipulate Bluetooth UUIDs and some common BR/EDR services
UUIDs.
---
 attrib/gatt.h | 25 -------------------------
 lib/uuid.h    | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0f113e7..4fea3eb 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,31 +24,6 @@
 
 #include <bluetooth/sdp.h>
 
-/* GATT Profile Attribute types */
-#define GATT_PRIM_SVC_UUID		0x2800
-#define GATT_SND_SVC_UUID		0x2801
-#define GATT_INCLUDE_UUID		0x2802
-#define GATT_CHARAC_UUID		0x2803
-
-/* GATT Characteristic Types */
-#define GATT_CHARAC_DEVICE_NAME			0x2A00
-#define GATT_CHARAC_APPEARANCE			0x2A01
-#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG	0x2A02
-#define GATT_CHARAC_RECONNECTION_ADDRESS	0x2A03
-#define GATT_CHARAC_PERIPHERAL_PREF_CONN	0x2A04
-#define GATT_CHARAC_SERVICE_CHANGED		0x2A05
-
-/* GATT Characteristic Descriptors */
-#define GATT_CHARAC_EXT_PROPER_UUID	0x2900
-#define GATT_CHARAC_USER_DESC_UUID	0x2901
-#define GATT_CLIENT_CHARAC_CFG_UUID	0x2902
-#define GATT_SERVER_CHARAC_CFG_UUID	0x2903
-#define GATT_CHARAC_FMT_UUID		0x2904
-#define GATT_CHARAC_AGREG_FMT_UUID	0x2905
-#define GATT_CHARAC_VALID_RANGE_UUID	0x2906
-#define GATT_EXTERNAL_REPORT_REFERENCE	0x2907
-#define GATT_REPORT_REFERENCE		0x2908
-
 /* Client Characteristic Configuration bit field */
 #define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT	0x0001
 #define GATT_CLIENT_CHARAC_CFG_IND_BIT		0x0002
diff --git a/lib/uuid.h b/lib/uuid.h
index 95e5a9a..c24cee5 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -105,6 +105,31 @@ extern "C" {
 #define OBEX_MNS_UUID		"00001133-0000-1000-8000-00805f9b34fb"
 #define OBEX_MAP_UUID		"00001134-0000-1000-8000-00805f9b34fb"
 
+/* GATT UUIDs section */
+#define GATT_PRIM_SVC_UUID				0x2800
+#define GATT_SND_SVC_UUID				0x2801
+#define GATT_INCLUDE_UUID				0x2802
+#define GATT_CHARAC_UUID				0x2803
+
+/* GATT Characteristic Types */
+#define GATT_CHARAC_DEVICE_NAME				0x2A00
+#define GATT_CHARAC_APPEARANCE				0x2A01
+#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG		0x2A02
+#define GATT_CHARAC_RECONNECTION_ADDRESS		0x2A03
+#define GATT_CHARAC_PERIPHERAL_PREF_CONN		0x2A04
+#define GATT_CHARAC_SERVICE_CHANGED			0x2A05
+
+/* GATT Characteristic Descriptors */
+#define GATT_CHARAC_EXT_PROPER_UUID			0x2900
+#define GATT_CHARAC_USER_DESC_UUID			0x2901
+#define GATT_CLIENT_CHARAC_CFG_UUID			0x2902
+#define GATT_SERVER_CHARAC_CFG_UUID			0x2903
+#define GATT_CHARAC_FMT_UUID				0x2904
+#define GATT_CHARAC_AGREG_FMT_UUID			0x2905
+#define GATT_CHARAC_VALID_RANGE_UUID			0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE			0x2907
+#define GATT_REPORT_REFERENCE				0x2908
+
 typedef struct {
 	enum {
 		BT_UUID_UNSPEC = 0,
-- 
1.8.3.1


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

* [PATCH BlueZ v4 06/18] gatt: Add helper for creating GATT services
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (4 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 07/18] gatt: Add external services tracking Claudio Takahasi
                       ` (12 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes

From: Andre Guedes <andre.guedes@openbossa.org>

This patch adds the btd_gatt_add_service() helper which adds a
GATT Service declaration to the local attribute database.
---
 lib/uuid.h |  5 +++++
 src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h | 10 ++++++++++
 3 files changed, 74 insertions(+)

diff --git a/lib/uuid.h b/lib/uuid.h
index c24cee5..237145b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -158,6 +158,11 @@ void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
 int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
 int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
 
+static inline int bt_uuid_len(const bt_uuid_t *uuid)
+{
+	return uuid->type / 8;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gatt.c b/src/gatt.c
index e8b691a..f7b74d6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -28,10 +28,69 @@
 #include <glib.h>
 
 #include "log.h"
+#include "lib/uuid.h"
+#include "attrib/att.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
 
+/* Common GATT UUIDs */
+static const bt_uuid_t primary_uuid  = { .type = BT_UUID16,
+					.value.u16 = GATT_PRIM_SVC_UUID };
+
+struct btd_attribute {
+	uint16_t handle;
+	bt_uuid_t type;
+	uint16_t value_len;
+	uint8_t value[0];
+};
+
+static GList *local_attribute_db;
+static uint16_t next_handle = 0x0001;
+
+static int local_database_add(uint16_t handle, struct btd_attribute *attr)
+{
+	attr->handle = handle;
+
+	local_attribute_db = g_list_append(local_attribute_db, attr);
+
+	return 0;
+}
+
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
+{
+	uint16_t len = bt_uuid_len(uuid);
+	struct btd_attribute *attr = g_malloc0(sizeof(struct btd_attribute) +
+									len);
+
+	/*
+	 * Service DECLARATION
+	 *
+	 *   TYPE         ATTRIBUTE VALUE
+	 * +-------+---------------------------------+
+	 * |0x2800 | 0xYYYY...                       |
+	 * | (1)   | (2)                             |
+	 * +------+----------------------------------+
+	 * (1) - 2 octets: Primary/Secondary Service UUID
+	 * (2) - 2 or 16 octets: Service UUID
+	 */
+
+	attr->type = primary_uuid;
+
+	att_put_uuid(*uuid, attr->value);
+	attr->value_len = len;
+
+	if (local_database_add(next_handle, attr) < 0) {
+		g_free(attr);
+		return NULL;
+	}
+
+	/* TODO: missing overflow checking */
+	next_handle = next_handle + 1;
+
+	return attr;
+}
+
 void gatt_init(void)
 {
 	DBG("Starting GATT server");
diff --git a/src/gatt.h b/src/gatt.h
index 3a320b4..8dd1312 100644
--- a/src/gatt.h
+++ b/src/gatt.h
@@ -21,6 +21,16 @@
  *
  */
 
+struct btd_attribute;
+
 void gatt_init(void);
 
 void gatt_cleanup(void);
+
+/* btd_gatt_add_service - Add a service declaration to local attribute database.
+ * @uuid:	Service UUID.
+ *
+ * Returns a reference to service declaration attribute. In case of error,
+ * NULL is returned.
+ */
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
-- 
1.8.3.1


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

* [PATCH BlueZ v4 07/18] gatt: Add external services tracking
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (5 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 08/18] gatt: Add server unix socket Claudio Takahasi
                       ` (11 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

All primary services declarations provided by an external application
will be automatically inserted in the attribute database.
---
 src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index fd614f9..000d7ae 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -39,15 +39,21 @@
 #include "log.h"
 
 #include "error.h"
+#include "gatt.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+#define REGISTER_TIMER         1
 
 struct external_app {
 	char *owner;
 	char *path;
 	GDBusClient *client;
+	GSList *proxies;
 	unsigned int watch;
+	guint register_timer;
 };
 
 static GSList *external_apps;
@@ -60,6 +66,36 @@ static int external_app_path_cmp(gconstpointer a, gconstpointer b)
 	return g_strcmp0(eapp->path, path);
 }
 
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	if (g_strcmp0(interface, SERVICE_IFACE) != 0)
+		return;
+
+	eapp->proxies = g_slist_append(eapp->proxies, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	eapp->proxies = g_slist_remove(eapp->proxies, proxy);
+}
+
+
 static void external_app_watch_destroy(gpointer user_data)
 {
 	struct external_app *eapp = user_data;
@@ -70,6 +106,9 @@ static void external_app_watch_destroy(gpointer user_data)
 
 	g_dbus_client_unref(eapp->client);
 
+	if (eapp->register_timer)
+		g_source_remove(eapp->register_timer);
+
 	g_free(eapp->owner);
 	g_free(eapp->path);
 	g_free(eapp);
@@ -99,9 +138,75 @@ static struct external_app *new_external_app(DBusConnection *conn,
 	eapp->client = client;
 	eapp->path = g_strdup(path);
 
+	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+								NULL, eapp);
+
 	return eapp;
 }
 
+static int register_external_service(GDBusProxy *proxy)
+{
+	DBusMessageIter iter;
+	const char *uuid;
+	bt_uuid_t btuuid;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return -EINVAL;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return -EINVAL;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (bt_string_to_uuid(&btuuid, uuid) < 0)
+		return -EINVAL;
+
+	if (btd_gatt_add_service(&btuuid) == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static gboolean finish_register(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+	GSList *list;
+
+	/*
+	 * It is not possible to detect when the last proxy object
+	 * was reported. "Proxy added" handler reports objects
+	 * added on demand or returned by GetManagedObjects().
+	 * This timer helps to register all the GATT declarations
+	 * (services, characteristics and descriptors) after fetching
+	 * all the D-Bus objects.
+	 */
+
+	eapp->register_timer = 0;
+
+	for (list = eapp->proxies; list; list = g_slist_next(list)) {
+		const char *interface, *path;
+		GDBusProxy *proxy = list->data;
+
+		interface = g_dbus_proxy_get_interface(proxy);
+		path = g_dbus_proxy_get_path(proxy);
+
+		if (g_strcmp0(SERVICE_IFACE, interface) != 0)
+			continue;
+
+		if (g_strcmp0(path, eapp->path) != 0)
+			continue;
+
+		if (register_external_service(proxy) < 0) {
+			DBG("Inconsistent external service: %s", path);
+			continue;
+		}
+
+		DBG("External service: %s", path);
+	}
+
+	return FALSE;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -109,6 +214,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	DBusMessageIter iter;
 	const char *path;
 
+	DBG("Registering GATT Service");
+
 	if (!dbus_message_iter_init(msg, &iter))
 		return btd_error_invalid_args(msg);
 
@@ -127,6 +234,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	external_apps = g_slist_prepend(external_apps, eapp);
 
 	DBG("New app %p: %s", eapp, path);
+	eapp->register_timer = g_timeout_add_seconds(REGISTER_TIMER,
+							finish_register, eapp);
 
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v4 08/18] gatt: Add server unix socket
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (6 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 07/18] gatt: Add external services tracking Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
                       ` (10 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds a server unix socket to handle local ATT traffic. This
is a development purpose feature used to allow local testing without
breaking the current attribute server.
---
 src/gatt.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/src/gatt.c b/src/gatt.c
index f7b74d6..2f0466a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,11 +25,17 @@
 #include <config.h>
 #endif
 
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include "log.h"
 #include "lib/uuid.h"
 #include "attrib/att.h"
+#include "src/shared/io.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
@@ -47,6 +53,7 @@ struct btd_attribute {
 
 static GList *local_attribute_db;
 static uint16_t next_handle = 0x0001;
+static guint unix_watch;
 
 static int local_database_add(uint16_t handle, struct btd_attribute *attr)
 {
@@ -91,11 +98,69 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static bool unix_accept_cb(struct io *io, void *user_data)
+{
+	struct sockaddr_un uaddr;
+	socklen_t len = sizeof(uaddr);
+	int err, nsk, sk;
+
+	sk = io_get_fd(io);
+
+	nsk = accept(sk, (struct sockaddr *) &uaddr, &len);
+	if (nsk < 0) {
+		err = errno;
+		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
+		return TRUE;
+	}
+
+	DBG("ATT UNIX socket: %d", nsk);
+
+	return TRUE;
+}
+
+static void accept_watch_destroy(void *user_data)
+{
+	struct io *io = user_data;
+
+	io_destroy(io);
+}
+
 void gatt_init(void)
 {
+	struct sockaddr_un uaddr  = {
+		.sun_family     = AF_UNIX,
+		.sun_path       = "\0/bluetooth/unix_att",
+	};
+	struct io *io;
+	int sk, err;
+
 	DBG("Starting GATT server");
 
 	gatt_dbus_manager_register();
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		err = errno;
+		error("ATT UNIX socket: %s(%d)", strerror(err), err);
+		return;
+	}
+
+	if (bind(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		err = errno;
+		error("binding ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	if (listen(sk, 5) < 0) {
+		err = errno;
+		error("listen ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	io = io_new(sk);
+	io_set_read_handler(io, unix_accept_cb, io, accept_watch_destroy);
 }
 
 void gatt_cleanup(void)
@@ -103,4 +168,5 @@ void gatt_cleanup(void)
 	DBG("Stopping GATT server");
 
 	gatt_dbus_manager_unregister();
+	g_source_remove(unix_watch);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v4 09/18] gattrib: Use default ATT LE MTU for non-standard sockets
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (7 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 08/18] gatt: Add server unix socket Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 10/18] gatt: Register ATT command/event handler Claudio Takahasi
                       ` (9 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch forces the MTU to 23 (default ATT MTU) if the transport
is not Bluetooth. This is a development purpose change to allow
testing GATT procedures over non-Bluetooth sockets.
---
 attrib/gattrib.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index daf6312..b5b8529 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -468,18 +468,18 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	struct _GAttrib *attrib;
 	uint16_t imtu;
 	uint16_t att_mtu;
-	uint16_t cid;
-	GError *gerr = NULL;
+	uint16_t cid = 0;
 
 	g_io_channel_set_encoding(io, NULL, NULL);
 	g_io_channel_set_buffered(io, FALSE);
 
-	bt_io_get(io, &gerr, BT_IO_OPT_IMTU, &imtu,
-				BT_IO_OPT_CID, &cid, BT_IO_OPT_INVALID);
-	if (gerr) {
-		error("%s", gerr->message);
-		g_error_free(gerr);
-		return NULL;
+	if (bt_io_get(io, NULL, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_CID, &cid,
+						BT_IO_OPT_INVALID) == FALSE) {
+		/*
+		 * Use default ATT LE MTU for non-standard transports. Used
+		 * for testing purpose only. eg: Unix sockets
+		 */
+		imtu = ATT_DEFAULT_LE_MTU;
 	}
 
 	attrib = g_try_new0(struct _GAttrib, 1);
-- 
1.8.3.1


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

* [PATCH BlueZ v4 10/18] gatt: Register ATT command/event handler
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (8 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
                       ` (8 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers the ATT channel handler to manage incoming ATT
commands and events.
---
 src/gatt.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 82 insertions(+), 2 deletions(-)

diff --git a/src/gatt.c b/src/gatt.c
index 2f0466a..04186b6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -98,10 +98,85 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static int send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
+{
+	uint8_t pdu[ATT_DEFAULT_LE_MTU];
+	size_t plen;
+
+	plen = enc_error_resp(opcode, handle, ecode, pdu, sizeof(pdu));
+	return write(sk, pdu, plen);
+}
+
+static bool channel_handler_cb(struct io *io, void *user_data)
+{
+	uint8_t ipdu[ATT_DEFAULT_LE_MTU];
+	ssize_t len;
+	int sk = io_get_fd(io);
+
+	len = read(sk, ipdu, sizeof(ipdu));
+	if (len < 0) {
+		int err = errno;
+		DBG("ATT channel read: %s(%d)", strerror(err), err);
+		return false;
+	}
+
+	switch (ipdu[0]) {
+	case ATT_OP_ERROR:
+		break;
+
+	/* Requests */
+	case ATT_OP_WRITE_CMD:
+	case ATT_OP_WRITE_REQ:
+	case ATT_OP_READ_REQ:
+	case ATT_OP_READ_BY_TYPE_REQ:
+	case ATT_OP_MTU_REQ:
+	case ATT_OP_FIND_INFO_REQ:
+	case ATT_OP_FIND_BY_TYPE_REQ:
+	case ATT_OP_READ_BLOB_REQ:
+	case ATT_OP_READ_MULTI_REQ:
+	case ATT_OP_PREP_WRITE_REQ:
+	case ATT_OP_EXEC_WRITE_REQ:
+	case ATT_OP_READ_BY_GROUP_REQ:
+	case ATT_OP_SIGNED_WRITE_CMD:
+		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
+		break;
+
+	/* Responses */
+	case ATT_OP_MTU_RESP:
+	case ATT_OP_FIND_INFO_RESP:
+	case ATT_OP_FIND_BY_TYPE_RESP:
+	case ATT_OP_READ_BY_TYPE_RESP:
+	case ATT_OP_READ_RESP:
+	case ATT_OP_READ_BLOB_RESP:
+	case ATT_OP_READ_MULTI_RESP:
+	case ATT_OP_READ_BY_GROUP_RESP:
+	case ATT_OP_WRITE_RESP:
+	case ATT_OP_PREP_WRITE_RESP:
+	case ATT_OP_EXEC_WRITE_RESP:
+	case ATT_OP_HANDLE_CNF:
+		break;
+
+	/* Notification & Indication */
+	case ATT_OP_HANDLE_NOTIFY:
+	case ATT_OP_HANDLE_IND:
+		break;
+	}
+
+	return true;
+}
+
+static void channel_watch_destroy(void *user_data)
+{
+	struct io *io = user_data;
+
+	io_destroy(io);
+}
+
 static bool unix_accept_cb(struct io *io, void *user_data)
 {
 	struct sockaddr_un uaddr;
 	socklen_t len = sizeof(uaddr);
+	struct io *nio;
 	int err, nsk, sk;
 
 	sk = io_get_fd(io);
@@ -110,12 +185,17 @@ static bool unix_accept_cb(struct io *io, void *user_data)
 	if (nsk < 0) {
 		err = errno;
 		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
-		return TRUE;
+		return true;
 	}
 
 	DBG("ATT UNIX socket: %d", nsk);
+	nio = io_new(nsk);
+
+	io_set_close_on_destroy(nio, true);
+	io_set_read_handler(nio, channel_handler_cb, nio,
+						channel_watch_destroy);
 
-	return TRUE;
+	return true;
 }
 
 static void accept_watch_destroy(void *user_data)
-- 
1.8.3.1


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

* [PATCH BlueZ v4 11/18] gatt: Add Discover All Primary Services
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (9 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 10/18] gatt: Register ATT command/event handler Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 12/18] test: Add external service GATT skeleton Claudio Takahasi
                       ` (7 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch adds ATT Read By Group request handling to the attribute
server. It is the primitive to implement Discover All Primary Services
procedure.
---
 src/gatt.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 131 insertions(+), 4 deletions(-)

diff --git a/src/gatt.c b/src/gatt.c
index 04186b6..42d2440 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -107,14 +107,138 @@ static int send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
 	return write(sk, pdu, plen);
 }
 
+static void read_by_group_resp(int sk, uint16_t start,
+					uint16_t end, bt_uuid_t *pattern)
+{
+	uint8_t opdu[ATT_DEFAULT_LE_MTU];
+	GList *list;
+	struct btd_attribute *last = NULL;
+	uint8_t *group_start, *group_end = NULL, *group_uuid;
+	unsigned int uuid_type = BT_UUID_UNSPEC;
+	size_t group_len = 0, plen = 0;
+
+	/*
+	 * Read By Group Type Response format:
+	 *    Attribute Opcode: 1 byte
+	 *    Length: 1 byte (size of each group)
+	 *    Group: start | end | <<UUID>>
+	 */
+
+	opdu[0] = ATT_OP_READ_BY_GROUP_RESP;
+	group_start = &opdu[2];
+	group_uuid = &opdu[6];
+
+	for (list = local_attribute_db; list;
+			last = list->data, list = g_list_next(list)) {
+		struct btd_attribute *attr = list->data;
+
+		if (attr->handle < start)
+			continue;
+
+		if (attr->handle > end)
+			break;
+
+		if (bt_uuid_cmp(&attr->type, pattern) != 0)
+			continue;
+
+		if (uuid_type != BT_UUID_UNSPEC &&
+						uuid_type != attr->type.type) {
+			/*
+			 * Groups should contain the same length: UUID16 and
+			 * UUID128 should be sent on different ATT PDUs
+			 */
+			break;
+		}
+
+		/*
+		 * MTU checking should not be shifted up, otherwise the
+		 * handle of last end group will not be set properly.
+		 */
+		if ((plen + group_len) >= ATT_DEFAULT_LE_MTU)
+			break;
+
+		/* Start Grouping handle */
+		att_put_u16(attr->handle, group_start);
+
+		/* Grouping <<UUID>>: Value is little endian */
+		memcpy(group_uuid, attr->value, attr->value_len);
+
+		if (last && group_end) {
+			att_put_u16(last->handle, group_end);
+			group_end += group_len;
+			plen += group_len;
+		}
+
+		/* Grouping initial settings: First grouping */
+		if (uuid_type == BT_UUID_UNSPEC) {
+			uuid_type = attr->type.type;
+
+			/* start(0xXXXX) | end(0xXXXX) | <<UUID>> */
+			group_len = 2 + 2 + bt_uuid_len(&attr->type);
+
+			/* 2: ATT Opcode and Length */
+			plen = 2 + group_len;
+
+			/* Size of each Attribute Data */
+			opdu[1] = group_len;
+
+			group_end = &opdu[4];
+		}
+
+		group_start += group_len;
+		group_uuid += group_len;
+	}
+
+	if (plen == 0) {
+		send_error(sk, ATT_OP_READ_BY_GROUP_REQ, start,
+						ATT_ECODE_ATTR_NOT_FOUND);
+		return;
+	}
+
+	if (group_end)
+		att_put_u16(last->handle, group_end);
+
+	write(sk, opdu, plen);
+}
+
+static void read_by_group(int sk, const uint8_t *ipdu, ssize_t ilen)
+{
+	uint16_t decoded, start, end;
+	bt_uuid_t pattern;
+
+	decoded = dec_read_by_grp_req(ipdu, ilen, &start, &end, &pattern);
+	if (decoded == 0) {
+		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_INVALID_PDU);
+		return;
+	}
+
+	if (start > end || start == 0x0000) {
+		send_error(sk, ipdu[0], start, ATT_ECODE_INVALID_HANDLE);
+		return;
+	}
+
+	 /*
+	  * Restricting Read By Group Type to <<Primary>>.
+	  * Removing the checking below requires changes to support
+	  * dynamic values(defined in the upper layer) and additional
+	  * security verification.
+	  */
+	if (bt_uuid_cmp(&pattern, &primary_uuid) != 0) {
+		send_error(sk, ipdu[0], start, ATT_ECODE_UNSUPP_GRP_TYPE);
+		return;
+	}
+
+	read_by_group_resp(sk, start, end, &pattern);
+}
+
 static bool channel_handler_cb(struct io *io, void *user_data)
 {
 	uint8_t ipdu[ATT_DEFAULT_LE_MTU];
-	ssize_t len;
+	ssize_t ilen;
 	int sk = io_get_fd(io);
 
-	len = read(sk, ipdu, sizeof(ipdu));
-	if (len < 0) {
+	ilen = read(sk, ipdu, sizeof(ipdu));
+	if (ilen < 0) {
 		int err = errno;
 		DBG("ATT channel read: %s(%d)", strerror(err), err);
 		return false;
@@ -136,11 +260,14 @@ static bool channel_handler_cb(struct io *io, void *user_data)
 	case ATT_OP_READ_MULTI_REQ:
 	case ATT_OP_PREP_WRITE_REQ:
 	case ATT_OP_EXEC_WRITE_REQ:
-	case ATT_OP_READ_BY_GROUP_REQ:
 	case ATT_OP_SIGNED_WRITE_CMD:
 		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
 		break;
 
+	case ATT_OP_READ_BY_GROUP_REQ:
+		read_by_group(sk, ipdu, ilen);
+		break;
+
 	/* Responses */
 	case ATT_OP_MTU_RESP:
 	case ATT_OP_FIND_INFO_RESP:
-- 
1.8.3.1


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

* [PATCH BlueZ v4 12/18] test: Add external service GATT skeleton
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (10 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 13/18] gitignore: Add test/gatt-service Claudio Takahasi
                       ` (6 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial code for an external GATT service example.
It implements the API defined at doc/gatt-api.txt
---
 Makefile.tools      |   5 ++
 test/gatt-service.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 test/gatt-service.c

diff --git a/Makefile.tools b/Makefile.tools
index 9199222..a468272 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -374,3 +374,8 @@ test_scripts += test/sap_client.py test/bluezutils.py \
 		test/test-heartrate test/test-alert test/test-hfp \
 		test/test-cyclingspeed test/opp-client test/ftp-client \
 		test/pbap-client test/map-client
+
+noinst_PROGRAMS += test/gatt-service
+
+test_gatt_service_SOURCES = test/gatt-service.c
+test_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la
diff --git a/test/gatt-service.c b/test/gatt-service.c
new file mode 100644
index 0000000..1cb0913
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,136 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+/* Immediate Alert Service UUID */
+#define IAS_UUID			"00001802-0000-1000-8000-00805f9b34fb"
+
+static GMainLoop *main_loop;
+static GSList *services;
+
+static gboolean service_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	const char *uuid = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+	return TRUE;
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	return TRUE;
+}
+
+static gboolean service_exist_includes(const GDBusPropertyTable *property,
+							void *user_data)
+{
+	return FALSE;
+}
+
+static DBusMessage *service_release(DBusConnection *conn,
+				DBusMessage *msg, void *user_data)
+{
+	printf("Terminating...\n");
+
+	g_main_loop_quit(main_loop);
+
+	return NULL;
+}
+
+static const GDBusMethodTable service_methods[] = {
+	{ GDBUS_NOREPLY_METHOD("Release", NULL, NULL, service_release) },
+	{ }
+};
+
+static const GDBusPropertyTable service_properties[] = {
+	{ "UUID", "s", service_get_uuid },
+	{ "Includes", "ao", service_get_includes, NULL,
+					service_exist_includes },
+	{ }
+};
+
+static char *register_service(DBusConnection *conn, const char *uuid)
+{
+	static int id = 1;
+	char *path;
+
+	path = g_strdup_printf("/service%d", id++);
+	if (g_dbus_register_interface(conn, path, SERVICE_IFACE,
+				service_methods, NULL, service_properties,
+				g_strdup(uuid), g_free) == FALSE) {
+		printf("Couldn't register service interface\n");
+		g_free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+static void create_services(DBusConnection *conn)
+{
+	char *service_path;
+
+	service_path = register_service(conn, IAS_UUID);
+
+	services = g_slist_prepend(services, service_path);
+
+	printf("Registered service: %s\n", service_path);
+}
+
+int main(int argc, char *argv[])
+{
+	DBusConnection *dbus_conn;
+
+	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+
+	main_loop = g_main_loop_new(NULL, FALSE);
+
+	g_dbus_attach_object_manager(dbus_conn);
+
+	printf("gatt-service unique name: %s\n",
+				dbus_bus_get_unique_name(dbus_conn));
+
+	create_services(dbus_conn);
+
+	g_main_loop_run(main_loop);
+
+	g_slist_free_full(services, g_free);
+	dbus_connection_unref(dbus_conn);
+
+	return 0;
+}
-- 
1.8.3.1


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

* [PATCH BlueZ v4 13/18] gitignore: Add test/gatt-service
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (11 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 12/18] test: Add external service GATT skeleton Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 14/18] test: Add signal handling for gatt-service Claudio Takahasi
                       ` (5 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index e2b23fc..5e5880f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ test/sap_client.pyc
 test/bluezutils.pyc
 unit/test-ringbuf
 unit/test-queue
+test/gatt-service
 unit/test-eir
 unit/test-uuid
 unit/test-crc
-- 
1.8.3.1


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

* [PATCH BlueZ v4 14/18] test: Add signal handling for gatt-service
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (12 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 13/18] gitignore: Add test/gatt-service Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 15/18] test: Add registering external service Claudio Takahasi
                       ` (4 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch implements signal handling to run cleanup tasks before
exiting.
---
 test/gatt-service.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 1cb0913..5452599 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,6 +27,9 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/signalfd.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -112,9 +115,83 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	static bool __terminated = false;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	switch (si.ssi_signo) {
+	case SIGINT:
+	case SIGTERM:
+		if (!__terminated) {
+			printf("Terminating\n");
+			g_main_loop_quit(main_loop);
+		}
+
+		__terminated = true;
+		break;
+	}
+
+	return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int main(int argc, char *argv[])
 {
 	DBusConnection *dbus_conn;
+	guint signal;
+
+	signal = setup_signalfd();
+	if (signal == 0)
+		return -errno;
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
 
@@ -129,6 +206,8 @@ int main(int argc, char *argv[])
 
 	g_main_loop_run(main_loop);
 
+	g_source_remove(signal);
+
 	g_slist_free_full(services, g_free);
 	dbus_connection_unref(dbus_conn);
 
-- 
1.8.3.1


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

* [PATCH BlueZ v4 15/18] test: Add registering external service
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (13 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 14/18] test: Add signal handling for gatt-service Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 16/18] gatttool: Add unix socket connect Claudio Takahasi
                       ` (3 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch extends gatt-service to call RegisterService() when org.bluez
service gets connected to the system bus.
---
 test/gatt-service.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 5452599..acecf2a 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -35,6 +35,7 @@
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
 #define SERVICE_IFACE			"org.bluez.GattService1"
 
 /* Immediate Alert Service UUID */
@@ -115,6 +116,65 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static void register_external_service_reply(DBusPendingCall *call,
+							void *user_data)
+{
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	dbus_set_error_from_message(&derr, reply);
+
+	if (dbus_error_is_set(&derr))
+		printf("RegisterService: %s\n", derr.message);
+	else
+		printf("RegisterService: OK\n");
+
+	dbus_message_unref(reply);
+	dbus_error_free(&derr);
+}
+
+static void register_external_service(gpointer a, gpointer b)
+{
+	DBusConnection *conn = b;
+	const char *path = a;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	DBusMessageIter iter, dict;
+
+	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+					GATT_MGR_IFACE, "RegisterService");
+	if (msg == NULL) {
+		printf("Couldn't allocate D-Bus message\n");
+		return;
+	}
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	/* TODO: Add options dictionary */
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
+		dbus_message_unref(msg);
+		return;
+	}
+
+	dbus_pending_call_set_notify(call, register_external_service_reply,
+								NULL, NULL);
+
+	dbus_pending_call_unref(call);
+}
+
+static void connect_handler(DBusConnection *conn, void *user_data)
+{
+	g_slist_foreach(services, register_external_service, conn);
+}
+
 static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
 							gpointer user_data)
 {
@@ -186,6 +246,7 @@ static guint setup_signalfd(void)
 
 int main(int argc, char *argv[])
 {
+	GDBusClient *client;
 	DBusConnection *dbus_conn;
 	guint signal;
 
@@ -204,8 +265,14 @@ int main(int argc, char *argv[])
 
 	create_services(dbus_conn);
 
+	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+	g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+
 	g_main_loop_run(main_loop);
 
+	g_dbus_client_unref(client);
+
 	g_source_remove(signal);
 
 	g_slist_free_full(services, g_free);
-- 
1.8.3.1


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

* [PATCH BlueZ v4 16/18] gatttool: Add unix socket connect
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (14 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 15/18] test: Add registering external service Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
                       ` (2 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial support for GATT procedures over unix
socket transport on command line mode (one-shot command). Temporary
solution to allow local GATT procedures testing.
---
 attrib/gatttool.c | 27 ++++++++++++++++++++-------
 attrib/gatttool.h |  1 +
 attrib/utils.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 9f2ead9..cf106de 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <glib.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
@@ -53,6 +52,7 @@ static int opt_end = 0xffff;
 static int opt_handle = -1;
 static int opt_mtu = 0;
 static int opt_psm = 0;
+static gboolean opt_local = FALSE;
 static gboolean opt_primary = FALSE;
 static gboolean opt_characteristics = FALSE;
 static gboolean opt_char_read = FALSE;
@@ -511,6 +511,8 @@ static GOptionEntry options[] = {
 		"Specify local adapter interface", "hciX" },
 	{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
 		"Specify remote Bluetooth address", "MAC" },
+	{ "local", 'L', 0, G_OPTION_ARG_NONE, &opt_local,
+		"Use unix socket transport (local communication)", NULL },
 	{ "addr-type", 't', 0, G_OPTION_ARG_STRING, &opt_dst_type,
 		"Set LE address type. Default: public", "[public | random]"},
 	{ "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu,
@@ -563,6 +565,11 @@ int main(int argc, char *argv[])
 		g_clear_error(&gerr);
 	}
 
+	if (opt_local) {
+		opt_src = NULL;
+		opt_dst = NULL;
+	}
+
 	if (opt_interactive) {
 		interactive(opt_src, opt_dst, opt_dst_type, opt_psm);
 		goto done;
@@ -588,14 +595,20 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
-	if (opt_dst == NULL) {
-		g_print("Remote Bluetooth address required\n");
-		got_error = TRUE;
-		goto done;
+	if (opt_local)
+		chan = unix_connect(connect_cb, &gerr);
+	else {
+		if (opt_dst == NULL) {
+			g_print("Remote Bluetooth address required\n");
+			got_error = TRUE;
+			goto done;
+		}
+
+		chan = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
 	}
 
-	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
 		g_printerr("%s\n", gerr->message);
 		g_clear_error(&gerr);
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 8f0913c..be8e236 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -27,4 +27,5 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 			const char *dst_type, const char *sec_level,
 			int psm, int mtu, BtIOConnect connect_cb,
 			GError **gerr);
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/utils.c b/attrib/utils.c
index 17f02be..7d2966f 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -25,7 +25,12 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include <bluetooth/bluetooth.h>
@@ -101,6 +106,55 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 	return chan;
 }
 
+static gboolean unix_connect_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	BtIOConnect connect_cb = user_data;
+	GError *gerr;
+
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		gerr = g_error_new_literal(G_IO_CHANNEL_ERROR,
+						G_IO_CHANNEL_ERROR_FAILED,
+						"connection attempt failed");
+		connect_cb(io, gerr, user_data);
+		g_clear_error(&gerr);
+	} else {
+		connect_cb(io, NULL, user_data);
+	}
+
+	return FALSE;
+}
+
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr)
+{
+	GIOChannel *io;
+	struct sockaddr_un uaddr  = {
+		.sun_family	= AF_UNIX,
+		.sun_path	= "\0/bluetooth/unix_att",
+	};
+	int sk;
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		return NULL;
+	}
+
+	if (connect(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		close(sk);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+						unix_connect_cb, connect_cb);
+
+	return io;
+}
+
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data)
 {
 	char tmp[3];
-- 
1.8.3.1


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

* [PATCH BlueZ v4 17/18] gatttool: Add unix socket support for interactive mode
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (15 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 16/18] gatttool: Add unix socket connect Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 18:00     ` [PATCH BlueZ v4 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch allows running GATT operations over unix socket on
interactive mode.
---
 attrib/interactive.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 70c091c..67e060e 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -84,7 +84,7 @@ static char *get_prompt(void)
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
-		g_string_append_printf(prompt, "[%17s]", "");
+		g_string_append_printf(prompt, "[LOCAL]");
 
 	if (conn_state == STATE_CONNECTED)
 		g_string_append(prompt, COLOR_OFF);
@@ -405,15 +405,18 @@ static void cmd_connect(int argcp, char **argvp)
 			opt_dst_type = g_strdup("public");
 	}
 
-	if (opt_dst == NULL) {
-		error("Remote Bluetooth address required\n");
-		return;
+	if (opt_dst) {
+
+		rl_printf("Attempting to connect to %s\n", opt_dst);
+		set_state(STATE_CONNECTING);
+		iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
+	} else {
+		rl_printf("Local connection\n");
+		iochannel = unix_connect(connect_cb, &gerr);
 	}
 
-	rl_printf("Attempting to connect to %s\n", opt_dst);
-	set_state(STATE_CONNECTING);
-	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
 		set_state(STATE_DISCONNECTED);
 		error("%s\n", gerr->message);
-- 
1.8.3.1


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

* [PATCH BlueZ v4 18/18] bluetooth.conf: Add ObjectManager interface
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (16 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
@ 2014-01-27 18:00     ` Claudio Takahasi
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 src/bluetooth.conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..ad8891a 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -18,6 +18,7 @@
     <allow send_interface="org.bluez.Profile1"/>
     <allow send_interface="org.bluez.HeartRateWatcher1"/>
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
+    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
   </policy>
 
   <policy at_console="true">
-- 
1.8.3.1


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

* Re: [PATCH BlueZ v4 01/18] doc: Add GATT API
  2014-01-27 18:00     ` [PATCH BlueZ v4 01/18] doc: Add GATT API Claudio Takahasi
@ 2014-01-27 18:15       ` Marcel Holtmann
  2014-01-27 18:54         ` Claudio Takahasi
  0 siblings, 1 reply; 123+ messages in thread
From: Marcel Holtmann @ 2014-01-27 18:15 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: BlueZ development

Hi Claudio,

> This patch proposes an unified GATT API for local and remote services.
> ---
> doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 145 insertions(+)
> create mode 100644 doc/gatt-api.txt
> 
> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
> new file mode 100644
> index 0000000..2d92f03
> --- /dev/null
> +++ b/doc/gatt-api.txt
> @@ -0,0 +1,145 @@
> +BlueZ D-Bus GATT API description
> +********************************
> +
> +GATT local and remote services share the same high-level D-Bus API. Local
> +refers to GATT based service exported by a BlueZ plugin or an external
> +application. Remote refers to GATT services exported by the peer.
> +
> +BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
> +Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
> +external services to allow seamless GATT declarations (Service, Characteristic
> +and Descriptors) discovery.
> +
> +Service hierarchy
> +=================
> +
> +GATT remote and local service representation. Object path for local services
> +is freely definable.
> +
> +External applications implementing local services must register the services
> +using GattManager1 registration method and must implement the methods and
> +properties defined in GattService1 interface.
> +
> +Service		org.bluez
> +Interface	org.bluez.GattService1 [Experimental]
> +Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
> +
> +Methods		void Release()
> +
> +			Release this service. At this point, it will not be
> +			used by BlueZ anymore and can be destroyed by the
> +			owner. Method applicable to external GATT services
> +			implementations only (GATT servers).

so this is the part I do not like that much. We should not define an interface that has a method that is valid and used only when this is a GATT server.

What I am thinking right now (and might need to discuss this a bit further), we leave GattService1 without any methods and use it for both GATT client and server.

Then we create some GattServiceAgent1 or GattServiceCollection1 or maybe even GattServer1 that we can register with GattManager1 for the purpose of providing a Release method so that bluetoothd stays in control and can inform applications if it decided to remove a service.

I am even fine with allowing to provide multiple services in a collection/server registration. Thoughts?

Regards

Marcel


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

* Re: [PATCH BlueZ v4 01/18] doc: Add GATT API
  2014-01-27 18:15       ` Marcel Holtmann
@ 2014-01-27 18:54         ` Claudio Takahasi
  2014-01-27 19:08           ` Marcel Holtmann
  0 siblings, 1 reply; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 18:54 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: BlueZ development

Hi Marcel:

On Mon, Jan 27, 2014 at 3:15 PM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
> Hi Claudio,
>
>> This patch proposes an unified GATT API for local and remote services.
>> ---
>> doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++=
++++++
>> 1 file changed, 145 insertions(+)
>> create mode 100644 doc/gatt-api.txt
>>
>> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
>> new file mode 100644
>> index 0000000..2d92f03
>> --- /dev/null
>> +++ b/doc/gatt-api.txt
>> @@ -0,0 +1,145 @@
>> +BlueZ D-Bus GATT API description
>> +********************************
>> +
>> +GATT local and remote services share the same high-level D-Bus API. Loc=
al
>> +refers to GATT based service exported by a BlueZ plugin or an external
>> +application. Remote refers to GATT services exported by the peer.
>> +
>> +BlueZ acts as a proxy, translating ATT operations to D-Bus method calls=
 and
>> +Properties (or the opposite). Support for D-Bus Object Manager is manda=
tory for
>> +external services to allow seamless GATT declarations (Service, Charact=
eristic
>> +and Descriptors) discovery.
>> +
>> +Service hierarchy
>> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>> +
>> +GATT remote and local service representation. Object path for local ser=
vices
>> +is freely definable.
>> +
>> +External applications implementing local services must register the ser=
vices
>> +using GattManager1 registration method and must implement the methods a=
nd
>> +properties defined in GattService1 interface.
>> +
>> +Service              org.bluez
>> +Interface    org.bluez.GattService1 [Experimental]
>> +Object path  [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/se=
rviceXX
>> +
>> +Methods              void Release()
>> +
>> +                     Release this service. At this point, it will not b=
e
>> +                     used by BlueZ anymore and can be destroyed by the
>> +                     owner. Method applicable to external GATT services
>> +                     implementations only (GATT servers).
>
> so this is the part I do not like that much. We should not define an inte=
rface that has a method that is valid and used only when this is a GATT ser=
ver.
>
> What I am thinking right now (and might need to discuss this a bit furthe=
r), we leave GattService1 without any methods and use it for both GATT clie=
nt and server.
>
> Then we create some GattServiceAgent1 or GattServiceCollection1 or maybe =
even GattServer1 that we can register with GattManager1 for the purpose of =
providing a Release method so that bluetoothd stays in control and can info=
rm applications if it decided to remove a service.
>
> I am even fine with allowing to provide multiple services in a collection=
/server registration. Thoughts?
>
> Regards
>
> Marcel

The "Service Agent" approach was suggested in beginning of our
discussion. I don't remember anymore why we decided to change it.

Unless you think that it is essential, we could implement the
Release() method later. When we start the client implementation we
will have a better understanding of our needs.
Can I remove the Release() and re-send the patchset?

Regards,
Claudio.

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

* Re: [PATCH BlueZ v4 01/18] doc: Add GATT API
  2014-01-27 18:54         ` Claudio Takahasi
@ 2014-01-27 19:08           ` Marcel Holtmann
  0 siblings, 0 replies; 123+ messages in thread
From: Marcel Holtmann @ 2014-01-27 19:08 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: BlueZ development

Hi Claudio,

>>> This patch proposes an unified GATT API for local and remote services.
>>> ---
>>> doc/gatt-api.txt | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 145 insertions(+)
>>> create mode 100644 doc/gatt-api.txt
>>> 
>>> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
>>> new file mode 100644
>>> index 0000000..2d92f03
>>> --- /dev/null
>>> +++ b/doc/gatt-api.txt
>>> @@ -0,0 +1,145 @@
>>> +BlueZ D-Bus GATT API description
>>> +********************************
>>> +
>>> +GATT local and remote services share the same high-level D-Bus API. Local
>>> +refers to GATT based service exported by a BlueZ plugin or an external
>>> +application. Remote refers to GATT services exported by the peer.
>>> +
>>> +BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
>>> +Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
>>> +external services to allow seamless GATT declarations (Service, Characteristic
>>> +and Descriptors) discovery.
>>> +
>>> +Service hierarchy
>>> +=================
>>> +
>>> +GATT remote and local service representation. Object path for local services
>>> +is freely definable.
>>> +
>>> +External applications implementing local services must register the services
>>> +using GattManager1 registration method and must implement the methods and
>>> +properties defined in GattService1 interface.
>>> +
>>> +Service              org.bluez
>>> +Interface    org.bluez.GattService1 [Experimental]
>>> +Object path  [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
>>> +
>>> +Methods              void Release()
>>> +
>>> +                     Release this service. At this point, it will not be
>>> +                     used by BlueZ anymore and can be destroyed by the
>>> +                     owner. Method applicable to external GATT services
>>> +                     implementations only (GATT servers).
>> 
>> so this is the part I do not like that much. We should not define an interface that has a method that is valid and used only when this is a GATT server.
>> 
>> What I am thinking right now (and might need to discuss this a bit further), we leave GattService1 without any methods and use it for both GATT client and server.
>> 
>> Then we create some GattServiceAgent1 or GattServiceCollection1 or maybe even GattServer1 that we can register with GattManager1 for the purpose of providing a Release method so that bluetoothd stays in control and can inform applications if it decided to remove a service.
>> 
>> I am even fine with allowing to provide multiple services in a collection/server registration. Thoughts?
> 
> The "Service Agent" approach was suggested in beginning of our
> discussion. I don't remember anymore why we decided to change it.
> 
> Unless you think that it is essential, we could implement the
> Release() method later. When we start the client implementation we
> will have a better understanding of our needs.
> Can I remove the Release() and re-send the patch set?

as long as this is clearly hidden behind our experimental switch, we can get this started without release method.

I want to be cautious since any change would break the GattManager1 interface once we figure out how this should be done best.

Regards

Marcel


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

* [PATCH BlueZ v5 00/18] GATT API: External Services
  2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
                       ` (17 preceding siblings ...)
  2014-01-27 18:00     ` [PATCH BlueZ v4 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
@ 2014-01-27 20:35     ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 01/18] doc: Add experimental GATT API Claudio Takahasi
                         ` (18 more replies)
  18 siblings, 19 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patchset implements the minimal support for adding local services
declarations.

Limitation: Remove services and multiple services exported by the same
remote will be implemented the next series.

Changes from PATCH v4 to PATCH v5:
* Removed Release() method of GattService1 interface

Changes from PATCH v3 to PATCH v4:
* Rebase
* src/gatt.c: Replaced GIOChannel/GAttrib by "io".

Changes from PATCH v2 to PATCH v3:
* Rebase
* Interfaces renamed: s/GattServiceManager1/GattManager1,
  s/Characteristic1/GattCharacteristic1, s/Descriptor/GattDescriptor1
* test/gatt-service.c: s/fprintf/printf

Changes from PATCH v1 to PATCH v2:
* Rebase
* Included patch "doc: Add GATT API"
* Interfaces renamed: s/Service1/GattService1, and
  s/ServiceManager1/GattServiceManager1
* Removed patch "gatt: Implement UnregisterService" from this patchset

Changes from PATCH v0 to PATCH v1:
* Rebase

Changes from RFC v0 to PATCH v0:
* Changed copyright year : s/2013/2014
* Fixed coding style
* Added gatt-service binary to gitignore
* Added extra comment in the source code

Features:
* API for internal and external services declaration
* Unix socket for testing purpose: services are exported through unix
  sockets to avoid breaking the current attribute server.

How to test:
Run bluetoothd with EXPERIMENTAL flag (-E)
Replace /etc/dbus-1/system.d/bluetooth.conf and reload DBus settings
$gatttool -L --primary (or interactive mode)

Roughly upstreaming plan (steps):
* GATT Server: External Services -> pathset GATT API: External Services
* GATT Server: External Characteristics (Server)
* GATT Server: External Descriptors (Server)
* Replacement for GAttrib: use "io"
* Replace attribute server
* Remove ATTIO and automatic connection mechanism from userspace
* Fix all GATT internal plugins
* GATT Client: Remote Services

Alvaro Silva (6):
  gatt: Add stub for gatt.{c, h} files
  gatt: Register Manager D-Bus Interface
  gatt: Add registering external service
  gatt: Add external services tracking
  gatt: Register ATT command/event handler
  gatt: Add Discover All Primary Services

Andre Guedes (1):
  gatt: Add helper for creating GATT services

Claudio Takahasi (11):
  doc: Add experimental GATT API
  lib: Move GATT UUID to uuid.h
  gatt: Add server unix socket
  gattrib: Use default ATT LE MTU for non-standard sockets
  test: Add external service GATT skeleton
  gitignore: Add test/gatt-service
  test: Add signal handling for gatt-service
  test: Add registering external service
  gatttool: Add unix socket connect
  gatttool: Add unix socket support for interactive mode
  bluetooth.conf: Add ObjectManager interface

 .gitignore           |   1 +
 Makefile.am          |   2 +
 Makefile.tools       |   5 +
 attrib/gatt.h        |  25 ----
 attrib/gattrib.c     |  16 +--
 attrib/gatttool.c    |  27 +++-
 attrib/gatttool.h    |   1 +
 attrib/interactive.c |  19 +--
 attrib/utils.c       |  54 ++++++++
 doc/gatt-api.txt     | 142 ++++++++++++++++++++
 lib/uuid.h           |  30 +++++
 src/bluetooth.conf   |   1 +
 src/gatt-dbus.c      | 271 +++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h      |  25 ++++
 src/gatt.c           | 372 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h           |  36 +++++
 src/main.c           |   4 +
 test/gatt-service.c  | 267 ++++++++++++++++++++++++++++++++++++
 18 files changed, 1250 insertions(+), 48 deletions(-)
 create mode 100644 doc/gatt-api.txt
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h
 create mode 100644 test/gatt-service.c

-- 
1.8.3.1


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

* [PATCH BlueZ v5 01/18] doc: Add experimental GATT API
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
                         ` (17 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch proposes an unified GATT API for local and remote services.
---
 doc/gatt-api.txt | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)
 create mode 100644 doc/gatt-api.txt

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
new file mode 100644
index 0000000..0f6b084
--- /dev/null
+++ b/doc/gatt-api.txt
@@ -0,0 +1,142 @@
+BlueZ D-Bus GATT API description
+********************************
+
+GATT local and remote services share the same high-level D-Bus API. Local
+refers to GATT based service exported by a BlueZ plugin or an external
+application. Remote refers to GATT services exported by the peer.
+
+BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
+Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
+external services to allow seamless GATT declarations (Service, Characteristic
+and Descriptors) discovery.
+
+Releasing a registered GATT service is not defined yet. Any API extension
+should avoid breaking the defined API, and if possible keep an unified GATT
+remote and local services representation.
+
+Service hierarchy
+=================
+
+GATT remote and local service representation. Object path for local services
+is freely definable.
+
+External applications implementing local services must register the services
+using GattManager1 registration method and must implement the methods and
+properties defined in GattService1 interface.
+
+Service		org.bluez
+Interface	org.bluez.GattService1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+
+Properties	string UUID [read-only]
+
+			128-bit service UUID.
+
+		array{object} Includes [read-only]: Not implemented
+
+			Array of object paths representing the included
+			services of this service.
+
+
+Characteristic hierarchy
+========================
+
+For local GATT defined services, the object paths need to follow the service
+path hierarchy and are freely definable.
+
+Service		org.bluez
+Interface	org.bluez.GattCharacteristic1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+
+Properties	string UUID [read-only]
+
+			128-bit characteristic UUID.
+
+		object Service [read-only]
+
+			Object path of the GATT service the characteristc
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Value read from the remote Bluetooth device or from
+			the external application implementing GATT services.
+
+		array{string} Flags [read-only, optional]
+
+			Defines how the characteristic value can be used. See
+			Core spec page 1898, "Table 3.5: Characteristic
+			Properties bit field" and page 1900, "Table 3.8:
+			Characteristic Extended Properties bit field". Allowed
+			values: "broadcast", "read", "write-without-response",
+			"write", "notify", "indicate",
+			"authenticated-signed-writes", "reliable-write", and
+			"writable-auxiliaries".
+
+
+Characteristic Descriptors hierarchy
+====================================
+
+Local or remote GATT characteristic descriptors hierarchy.
+
+Service		org.bluez
+Interface	org.bluez.GattDescriptor1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+
+Properties	string UUID [read-only]
+
+			128-bit descriptor UUID.
+
+		object Characteristic [read-only]
+
+			Object path of the GATT characteristc the descriptor
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Raw characteristic descriptor value read from the
+			remote Bluetooth device or from the external
+			application implementing GATT services.
+
+		string Permissions [read-only]: To be defined
+
+			Defines read/write authentication and authorization
+			requirements.
+
+Service Manager hierarchy
+=============================
+
+Service Manager allows external applications to register GATT based
+services. Services must follow the API for Service and Characteristic
+described above.
+
+Local GATT services, characteristics and characteristic descriptors are
+discovered automatically using the D-Bus Object Manager interface.
+
+Service		org.bluez
+Interface	org.bluez.GattManager1 [Experimental]
+Object path	/org/bluez
+
+Methods		RegisterService(object service, dict options)
+
+			Registers remote application service exported under
+			interface GattService1. Characteristic objects must
+			be hierarchical to their service and must use the
+			interface GattCharacteristic1. D-Bus Object Manager
+			is used to fetch the exported objects.
+
+			"service" object path together with the D-Bus system
+			bus connection ID define the identification of the
+			application registering a GATT based service.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		UnregisterService(object service)
+
+			This unregisters the service that has been
+			previously registered. The object path parameter
+			must match the same value that has been used
+			on registration.
+
+			Possible errors: org.bluez.Error.DoesNotExist
-- 
1.8.3.1


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

* [PATCH BlueZ v5 02/18] gatt: Add stub for gatt.{c, h} files
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 01/18] doc: Add experimental GATT API Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
                         ` (16 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

These files implement functions to handle ATT transactions, and expose
functions to allow other entities to manage GATT based services. It
is a replacement for src/attrib-server.c.
---
 Makefile.am |  1 +
 src/gatt.c  | 38 ++++++++++++++++++++++++++++++++++++++
 src/gatt.h  | 26 ++++++++++++++++++++++++++
 src/main.c  |  4 ++++
 4 files changed, 69 insertions(+)
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h

diff --git a/Makefile.am b/Makefile.am
index 3a1e6dc..101d5de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
 			src/eir.h src/eir.c \
diff --git a/src/gatt.c b/src/gatt.c
new file mode 100644
index 0000000..06619f0
--- /dev/null
+++ b/src/gatt.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 "gatt.h"
+
+void gatt_init(void)
+{
+
+}
+
+void gatt_cleanup(void)
+{
+
+}
diff --git a/src/gatt.h b/src/gatt.h
new file mode 100644
index 0000000..3a320b4
--- /dev/null
+++ b/src/gatt.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 gatt_init(void);
+
+void gatt_cleanup(void);
diff --git a/src/main.c b/src/main.c
index 91d90b4..fccc838 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,6 +55,7 @@
 #include "dbus-common.h"
 #include "agent.h"
 #include "profile.h"
+#include "gatt.h"
 #include "systemd.h"
 
 #define BLUEZ_NAME "org.bluez"
@@ -545,6 +546,8 @@ int main(int argc, char *argv[])
 
 	g_dbus_set_flags(gdbus_flags);
 
+	gatt_init();
+
 	if (option_compat == TRUE)
 		sdp_flags |= SDP_SERVER_COMPAT;
 
@@ -595,6 +598,7 @@ int main(int argc, char *argv[])
 	btd_profile_cleanup();
 	btd_agent_cleanup();
 	btd_device_cleanup();
+	gatt_cleanup();
 
 	adapter_cleanup();
 
-- 
1.8.3.1


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

* [PATCH BlueZ v5 03/18] gatt: Register Manager D-Bus Interface
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 01/18] doc: Add experimental GATT API Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 04/18] gatt: Add registering external service Claudio Takahasi
                         ` (15 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers GATT Service Manager D-Bus Interface. This
interface implements the methods to allow external application register
and unregister GATT Services.
---
 Makefile.am     |  1 +
 src/gatt-dbus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h | 25 +++++++++++++++++++
 src/gatt.c      |  9 +++++++
 4 files changed, 110 insertions(+)
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h

diff --git a/Makefile.am b/Makefile.am
index 101d5de..fbae2c8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt-dbus.h src/gatt-dbus.c \
 			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
new file mode 100644
index 0000000..183c611
--- /dev/null
+++ b/src/gatt-dbus.c
@@ -0,0 +1,75 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include "dbus-common.h"
+#include "log.h"
+
+#include "gatt-dbus.h"
+
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
+
+static DBusMessage *register_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable methods[] = {
+	{ GDBUS_EXPERIMENTAL_METHOD("RegisterService",
+				GDBUS_ARGS({ "service", "o"},
+						{ "options", "a{sv}"}),
+				NULL, register_service) },
+	{ GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
+				GDBUS_ARGS({"service", "o"}),
+				NULL, unregister_service) },
+	{ }
+};
+
+gboolean gatt_dbus_manager_register(void)
+{
+	return g_dbus_register_interface(btd_get_dbus_connection(),
+					"/org/bluez", GATT_MGR_IFACE,
+					methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+							GATT_MGR_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
new file mode 100644
index 0000000..310cfa9
--- /dev/null
+++ b/src/gatt-dbus.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *
+ */
+
+gboolean gatt_dbus_manager_register(void);
+void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 06619f0..e8b691a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,14 +25,23 @@
 #include <config.h>
 #endif
 
+#include <glib.h>
+
+#include "log.h"
+
+#include "gatt-dbus.h"
 #include "gatt.h"
 
 void gatt_init(void)
 {
+	DBG("Starting GATT server");
 
+	gatt_dbus_manager_register();
 }
 
 void gatt_cleanup(void)
 {
+	DBG("Stopping GATT server");
 
+	gatt_dbus_manager_unregister();
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v5 04/18] gatt: Add registering external service
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (2 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
                         ` (14 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch allows external applications register a given service on
Bluez. Applications must provide an object path and a dictionary of
options. Options dictionary will be used later to provide additional
service information.
---
 src/gatt-dbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 183c611..fd614f9 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -26,22 +26,109 @@
 #endif
 
 #include <stdint.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#include "adapter.h"
+#include "device.h"
+#include "lib/uuid.h"
 #include "dbus-common.h"
 #include "log.h"
 
+#include "error.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
 
+struct external_app {
+	char *owner;
+	char *path;
+	GDBusClient *client;
+	unsigned int watch;
+};
+
+static GSList *external_apps;
+
+static int external_app_path_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct external_app *eapp = a;
+	const char *path = b;
+
+	return g_strcmp0(eapp->path, path);
+}
+
+static void external_app_watch_destroy(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+
+	/* TODO: Remove from the database */
+
+	external_apps = g_slist_remove(external_apps, eapp);
+
+	g_dbus_client_unref(eapp->client);
+
+	g_free(eapp->owner);
+	g_free(eapp->path);
+	g_free(eapp);
+}
+
+static struct external_app *new_external_app(DBusConnection *conn,
+					const char *sender, const char *path)
+{
+	struct external_app *eapp;
+	GDBusClient *client;
+
+	client = g_dbus_client_new(conn, sender, "/");
+	if (client == NULL)
+		return NULL;
+
+	eapp = g_new0(struct external_app, 1);
+
+	eapp->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
+			sender, NULL, eapp, external_app_watch_destroy);
+	if (eapp->watch == 0) {
+		g_dbus_client_unref(client);
+		g_free(eapp);
+		return NULL;
+	}
+
+	eapp->owner = g_strdup(sender);
+	eapp->client = client;
+	eapp->path = g_strdup(path);
+
+	return eapp;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
-	return dbus_message_new_method_return(msg);
+	struct external_app *eapp;
+	DBusMessageIter iter;
+	const char *path;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &path);
+
+	if (g_slist_find_custom(external_apps, path, external_app_path_cmp))
+		return btd_error_already_exists(msg);
+
+	eapp = new_external_app(conn, dbus_message_get_sender(msg), path);
+	if (eapp == NULL)
+		return btd_error_failed(msg, "Not enough resources");
+
+	external_apps = g_slist_prepend(external_apps, eapp);
+
+	DBG("New app %p: %s", eapp, path);
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
 static DBusMessage *unregister_service(DBusConnection *conn,
-- 
1.8.3.1


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

* [PATCH BlueZ v5 05/18] lib: Move GATT UUID to uuid.h
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (3 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 04/18] gatt: Add registering external service Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
                         ` (13 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch moves GATT UUIDs definitions to a common header. uuid.h contains
helper functions to manipulate Bluetooth UUIDs and some common BR/EDR services
UUIDs.
---
 attrib/gatt.h | 25 -------------------------
 lib/uuid.h    | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0f113e7..4fea3eb 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,31 +24,6 @@
 
 #include <bluetooth/sdp.h>
 
-/* GATT Profile Attribute types */
-#define GATT_PRIM_SVC_UUID		0x2800
-#define GATT_SND_SVC_UUID		0x2801
-#define GATT_INCLUDE_UUID		0x2802
-#define GATT_CHARAC_UUID		0x2803
-
-/* GATT Characteristic Types */
-#define GATT_CHARAC_DEVICE_NAME			0x2A00
-#define GATT_CHARAC_APPEARANCE			0x2A01
-#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG	0x2A02
-#define GATT_CHARAC_RECONNECTION_ADDRESS	0x2A03
-#define GATT_CHARAC_PERIPHERAL_PREF_CONN	0x2A04
-#define GATT_CHARAC_SERVICE_CHANGED		0x2A05
-
-/* GATT Characteristic Descriptors */
-#define GATT_CHARAC_EXT_PROPER_UUID	0x2900
-#define GATT_CHARAC_USER_DESC_UUID	0x2901
-#define GATT_CLIENT_CHARAC_CFG_UUID	0x2902
-#define GATT_SERVER_CHARAC_CFG_UUID	0x2903
-#define GATT_CHARAC_FMT_UUID		0x2904
-#define GATT_CHARAC_AGREG_FMT_UUID	0x2905
-#define GATT_CHARAC_VALID_RANGE_UUID	0x2906
-#define GATT_EXTERNAL_REPORT_REFERENCE	0x2907
-#define GATT_REPORT_REFERENCE		0x2908
-
 /* Client Characteristic Configuration bit field */
 #define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT	0x0001
 #define GATT_CLIENT_CHARAC_CFG_IND_BIT		0x0002
diff --git a/lib/uuid.h b/lib/uuid.h
index 95e5a9a..c24cee5 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -105,6 +105,31 @@ extern "C" {
 #define OBEX_MNS_UUID		"00001133-0000-1000-8000-00805f9b34fb"
 #define OBEX_MAP_UUID		"00001134-0000-1000-8000-00805f9b34fb"
 
+/* GATT UUIDs section */
+#define GATT_PRIM_SVC_UUID				0x2800
+#define GATT_SND_SVC_UUID				0x2801
+#define GATT_INCLUDE_UUID				0x2802
+#define GATT_CHARAC_UUID				0x2803
+
+/* GATT Characteristic Types */
+#define GATT_CHARAC_DEVICE_NAME				0x2A00
+#define GATT_CHARAC_APPEARANCE				0x2A01
+#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG		0x2A02
+#define GATT_CHARAC_RECONNECTION_ADDRESS		0x2A03
+#define GATT_CHARAC_PERIPHERAL_PREF_CONN		0x2A04
+#define GATT_CHARAC_SERVICE_CHANGED			0x2A05
+
+/* GATT Characteristic Descriptors */
+#define GATT_CHARAC_EXT_PROPER_UUID			0x2900
+#define GATT_CHARAC_USER_DESC_UUID			0x2901
+#define GATT_CLIENT_CHARAC_CFG_UUID			0x2902
+#define GATT_SERVER_CHARAC_CFG_UUID			0x2903
+#define GATT_CHARAC_FMT_UUID				0x2904
+#define GATT_CHARAC_AGREG_FMT_UUID			0x2905
+#define GATT_CHARAC_VALID_RANGE_UUID			0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE			0x2907
+#define GATT_REPORT_REFERENCE				0x2908
+
 typedef struct {
 	enum {
 		BT_UUID_UNSPEC = 0,
-- 
1.8.3.1


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

* [PATCH BlueZ v5 06/18] gatt: Add helper for creating GATT services
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (4 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 07/18] gatt: Add external services tracking Claudio Takahasi
                         ` (12 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes

From: Andre Guedes <andre.guedes@openbossa.org>

This patch adds the btd_gatt_add_service() helper which adds a
GATT Service declaration to the local attribute database.
---
 lib/uuid.h |  5 +++++
 src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h | 10 ++++++++++
 3 files changed, 74 insertions(+)

diff --git a/lib/uuid.h b/lib/uuid.h
index c24cee5..237145b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -158,6 +158,11 @@ void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
 int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
 int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
 
+static inline int bt_uuid_len(const bt_uuid_t *uuid)
+{
+	return uuid->type / 8;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gatt.c b/src/gatt.c
index e8b691a..f7b74d6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -28,10 +28,69 @@
 #include <glib.h>
 
 #include "log.h"
+#include "lib/uuid.h"
+#include "attrib/att.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
 
+/* Common GATT UUIDs */
+static const bt_uuid_t primary_uuid  = { .type = BT_UUID16,
+					.value.u16 = GATT_PRIM_SVC_UUID };
+
+struct btd_attribute {
+	uint16_t handle;
+	bt_uuid_t type;
+	uint16_t value_len;
+	uint8_t value[0];
+};
+
+static GList *local_attribute_db;
+static uint16_t next_handle = 0x0001;
+
+static int local_database_add(uint16_t handle, struct btd_attribute *attr)
+{
+	attr->handle = handle;
+
+	local_attribute_db = g_list_append(local_attribute_db, attr);
+
+	return 0;
+}
+
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
+{
+	uint16_t len = bt_uuid_len(uuid);
+	struct btd_attribute *attr = g_malloc0(sizeof(struct btd_attribute) +
+									len);
+
+	/*
+	 * Service DECLARATION
+	 *
+	 *   TYPE         ATTRIBUTE VALUE
+	 * +-------+---------------------------------+
+	 * |0x2800 | 0xYYYY...                       |
+	 * | (1)   | (2)                             |
+	 * +------+----------------------------------+
+	 * (1) - 2 octets: Primary/Secondary Service UUID
+	 * (2) - 2 or 16 octets: Service UUID
+	 */
+
+	attr->type = primary_uuid;
+
+	att_put_uuid(*uuid, attr->value);
+	attr->value_len = len;
+
+	if (local_database_add(next_handle, attr) < 0) {
+		g_free(attr);
+		return NULL;
+	}
+
+	/* TODO: missing overflow checking */
+	next_handle = next_handle + 1;
+
+	return attr;
+}
+
 void gatt_init(void)
 {
 	DBG("Starting GATT server");
diff --git a/src/gatt.h b/src/gatt.h
index 3a320b4..8dd1312 100644
--- a/src/gatt.h
+++ b/src/gatt.h
@@ -21,6 +21,16 @@
  *
  */
 
+struct btd_attribute;
+
 void gatt_init(void);
 
 void gatt_cleanup(void);
+
+/* btd_gatt_add_service - Add a service declaration to local attribute database.
+ * @uuid:	Service UUID.
+ *
+ * Returns a reference to service declaration attribute. In case of error,
+ * NULL is returned.
+ */
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
-- 
1.8.3.1


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

* [PATCH BlueZ v5 07/18] gatt: Add external services tracking
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (5 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 08/18] gatt: Add server unix socket Claudio Takahasi
                         ` (11 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

All primary services declarations provided by an external application
will be automatically inserted in the attribute database.
---
 src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index fd614f9..000d7ae 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -39,15 +39,21 @@
 #include "log.h"
 
 #include "error.h"
+#include "gatt.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+#define REGISTER_TIMER         1
 
 struct external_app {
 	char *owner;
 	char *path;
 	GDBusClient *client;
+	GSList *proxies;
 	unsigned int watch;
+	guint register_timer;
 };
 
 static GSList *external_apps;
@@ -60,6 +66,36 @@ static int external_app_path_cmp(gconstpointer a, gconstpointer b)
 	return g_strcmp0(eapp->path, path);
 }
 
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	if (g_strcmp0(interface, SERVICE_IFACE) != 0)
+		return;
+
+	eapp->proxies = g_slist_append(eapp->proxies, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	eapp->proxies = g_slist_remove(eapp->proxies, proxy);
+}
+
+
 static void external_app_watch_destroy(gpointer user_data)
 {
 	struct external_app *eapp = user_data;
@@ -70,6 +106,9 @@ static void external_app_watch_destroy(gpointer user_data)
 
 	g_dbus_client_unref(eapp->client);
 
+	if (eapp->register_timer)
+		g_source_remove(eapp->register_timer);
+
 	g_free(eapp->owner);
 	g_free(eapp->path);
 	g_free(eapp);
@@ -99,9 +138,75 @@ static struct external_app *new_external_app(DBusConnection *conn,
 	eapp->client = client;
 	eapp->path = g_strdup(path);
 
+	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+								NULL, eapp);
+
 	return eapp;
 }
 
+static int register_external_service(GDBusProxy *proxy)
+{
+	DBusMessageIter iter;
+	const char *uuid;
+	bt_uuid_t btuuid;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return -EINVAL;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return -EINVAL;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (bt_string_to_uuid(&btuuid, uuid) < 0)
+		return -EINVAL;
+
+	if (btd_gatt_add_service(&btuuid) == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static gboolean finish_register(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+	GSList *list;
+
+	/*
+	 * It is not possible to detect when the last proxy object
+	 * was reported. "Proxy added" handler reports objects
+	 * added on demand or returned by GetManagedObjects().
+	 * This timer helps to register all the GATT declarations
+	 * (services, characteristics and descriptors) after fetching
+	 * all the D-Bus objects.
+	 */
+
+	eapp->register_timer = 0;
+
+	for (list = eapp->proxies; list; list = g_slist_next(list)) {
+		const char *interface, *path;
+		GDBusProxy *proxy = list->data;
+
+		interface = g_dbus_proxy_get_interface(proxy);
+		path = g_dbus_proxy_get_path(proxy);
+
+		if (g_strcmp0(SERVICE_IFACE, interface) != 0)
+			continue;
+
+		if (g_strcmp0(path, eapp->path) != 0)
+			continue;
+
+		if (register_external_service(proxy) < 0) {
+			DBG("Inconsistent external service: %s", path);
+			continue;
+		}
+
+		DBG("External service: %s", path);
+	}
+
+	return FALSE;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -109,6 +214,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	DBusMessageIter iter;
 	const char *path;
 
+	DBG("Registering GATT Service");
+
 	if (!dbus_message_iter_init(msg, &iter))
 		return btd_error_invalid_args(msg);
 
@@ -127,6 +234,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	external_apps = g_slist_prepend(external_apps, eapp);
 
 	DBG("New app %p: %s", eapp, path);
+	eapp->register_timer = g_timeout_add_seconds(REGISTER_TIMER,
+							finish_register, eapp);
 
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v5 08/18] gatt: Add server unix socket
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (6 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 07/18] gatt: Add external services tracking Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
                         ` (10 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds a server unix socket to handle local ATT traffic. This
is a development purpose feature used to allow local testing without
breaking the current attribute server.
---
 src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/src/gatt.c b/src/gatt.c
index f7b74d6..7a595c6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,11 +25,17 @@
 #include <config.h>
 #endif
 
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include "log.h"
 #include "lib/uuid.h"
 #include "attrib/att.h"
+#include "src/shared/io.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
@@ -45,6 +51,7 @@ struct btd_attribute {
 	uint8_t value[0];
 };
 
+static struct io *server_io;
 static GList *local_attribute_db;
 static uint16_t next_handle = 0x0001;
 
@@ -91,11 +98,62 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static bool unix_accept_cb(struct io *io, void *user_data)
+{
+	struct sockaddr_un uaddr;
+	socklen_t len = sizeof(uaddr);
+	int err, nsk, sk;
+
+	sk = io_get_fd(io);
+
+	nsk = accept(sk, (struct sockaddr *) &uaddr, &len);
+	if (nsk < 0) {
+		err = errno;
+		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
+		return TRUE;
+	}
+
+	DBG("ATT UNIX socket: %d", nsk);
+
+	return TRUE;
+}
+
 void gatt_init(void)
 {
+	struct sockaddr_un uaddr  = {
+		.sun_family     = AF_UNIX,
+		.sun_path       = "\0/bluetooth/unix_att",
+	};
+	int sk, err;
+
 	DBG("Starting GATT server");
 
 	gatt_dbus_manager_register();
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		err = errno;
+		error("ATT UNIX socket: %s(%d)", strerror(err), err);
+		return;
+	}
+
+	if (bind(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		err = errno;
+		error("binding ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	if (listen(sk, 5) < 0) {
+		err = errno;
+		error("listen ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	server_io = io_new(sk);
+	io_set_close_on_destroy(server_io, true);
+	io_set_read_handler(server_io, unix_accept_cb, NULL, NULL);
 }
 
 void gatt_cleanup(void)
@@ -103,4 +161,5 @@ void gatt_cleanup(void)
 	DBG("Stopping GATT server");
 
 	gatt_dbus_manager_unregister();
+	io_destroy(server_io);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v5 09/18] gattrib: Use default ATT LE MTU for non-standard sockets
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (7 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 08/18] gatt: Add server unix socket Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 10/18] gatt: Register ATT command/event handler Claudio Takahasi
                         ` (9 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch forces the MTU to 23 (default ATT MTU) if the transport
is not Bluetooth. This is a development purpose change to allow
testing GATT procedures over non-Bluetooth sockets.
---
 attrib/gattrib.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index daf6312..b5b8529 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -468,18 +468,18 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	struct _GAttrib *attrib;
 	uint16_t imtu;
 	uint16_t att_mtu;
-	uint16_t cid;
-	GError *gerr = NULL;
+	uint16_t cid = 0;
 
 	g_io_channel_set_encoding(io, NULL, NULL);
 	g_io_channel_set_buffered(io, FALSE);
 
-	bt_io_get(io, &gerr, BT_IO_OPT_IMTU, &imtu,
-				BT_IO_OPT_CID, &cid, BT_IO_OPT_INVALID);
-	if (gerr) {
-		error("%s", gerr->message);
-		g_error_free(gerr);
-		return NULL;
+	if (bt_io_get(io, NULL, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_CID, &cid,
+						BT_IO_OPT_INVALID) == FALSE) {
+		/*
+		 * Use default ATT LE MTU for non-standard transports. Used
+		 * for testing purpose only. eg: Unix sockets
+		 */
+		imtu = ATT_DEFAULT_LE_MTU;
 	}
 
 	attrib = g_try_new0(struct _GAttrib, 1);
-- 
1.8.3.1


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

* [PATCH BlueZ v5 10/18] gatt: Register ATT command/event handler
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (8 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
                         ` (8 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers the ATT channel handler to manage incoming ATT
commands and events.
---
 src/gatt.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 82 insertions(+), 2 deletions(-)

diff --git a/src/gatt.c b/src/gatt.c
index 7a595c6..f5c1df7 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -98,10 +98,85 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static int send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
+{
+	uint8_t pdu[ATT_DEFAULT_LE_MTU];
+	size_t plen;
+
+	plen = enc_error_resp(opcode, handle, ecode, pdu, sizeof(pdu));
+	return write(sk, pdu, plen);
+}
+
+static bool channel_handler_cb(struct io *io, void *user_data)
+{
+	uint8_t ipdu[ATT_DEFAULT_LE_MTU];
+	ssize_t ilen;
+	int sk = io_get_fd(io);
+
+	ilen = read(sk, ipdu, sizeof(ipdu));
+	if (ilen < 0) {
+		int err = errno;
+		DBG("ATT channel read: %s(%d)", strerror(err), err);
+		return false;
+	}
+
+	switch (ipdu[0]) {
+	case ATT_OP_ERROR:
+		break;
+
+	/* Requests */
+	case ATT_OP_WRITE_CMD:
+	case ATT_OP_WRITE_REQ:
+	case ATT_OP_READ_REQ:
+	case ATT_OP_READ_BY_TYPE_REQ:
+	case ATT_OP_MTU_REQ:
+	case ATT_OP_FIND_INFO_REQ:
+	case ATT_OP_FIND_BY_TYPE_REQ:
+	case ATT_OP_READ_BLOB_REQ:
+	case ATT_OP_READ_MULTI_REQ:
+	case ATT_OP_PREP_WRITE_REQ:
+	case ATT_OP_EXEC_WRITE_REQ:
+	case ATT_OP_READ_BY_GROUP_REQ:
+	case ATT_OP_SIGNED_WRITE_CMD:
+		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
+		break;
+
+	/* Responses */
+	case ATT_OP_MTU_RESP:
+	case ATT_OP_FIND_INFO_RESP:
+	case ATT_OP_FIND_BY_TYPE_RESP:
+	case ATT_OP_READ_BY_TYPE_RESP:
+	case ATT_OP_READ_RESP:
+	case ATT_OP_READ_BLOB_RESP:
+	case ATT_OP_READ_MULTI_RESP:
+	case ATT_OP_READ_BY_GROUP_RESP:
+	case ATT_OP_WRITE_RESP:
+	case ATT_OP_PREP_WRITE_RESP:
+	case ATT_OP_EXEC_WRITE_RESP:
+	case ATT_OP_HANDLE_CNF:
+		break;
+
+	/* Notification & Indication */
+	case ATT_OP_HANDLE_NOTIFY:
+	case ATT_OP_HANDLE_IND:
+		break;
+	}
+
+	return true;
+}
+
+static void channel_watch_destroy(void *user_data)
+{
+	struct io *io = user_data;
+
+	io_destroy(io);
+}
+
 static bool unix_accept_cb(struct io *io, void *user_data)
 {
 	struct sockaddr_un uaddr;
 	socklen_t len = sizeof(uaddr);
+	struct io *nio;
 	int err, nsk, sk;
 
 	sk = io_get_fd(io);
@@ -110,12 +185,17 @@ static bool unix_accept_cb(struct io *io, void *user_data)
 	if (nsk < 0) {
 		err = errno;
 		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
-		return TRUE;
+		return true;
 	}
 
 	DBG("ATT UNIX socket: %d", nsk);
+	nio = io_new(nsk);
+
+	io_set_close_on_destroy(nio, true);
+	io_set_read_handler(nio, channel_handler_cb, nio,
+						channel_watch_destroy);
 
-	return TRUE;
+	return true;
 }
 
 void gatt_init(void)
-- 
1.8.3.1


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

* [PATCH BlueZ v5 11/18] gatt: Add Discover All Primary Services
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (9 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 10/18] gatt: Register ATT command/event handler Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 12/18] test: Add external service GATT skeleton Claudio Takahasi
                         ` (7 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch adds ATT Read By Group request handling to the attribute
server. It is the primitive to implement Discover All Primary Services
procedure.
---
 src/gatt.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 1 deletion(-)

diff --git a/src/gatt.c b/src/gatt.c
index f5c1df7..dce5c02 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -107,6 +107,130 @@ static int send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
 	return write(sk, pdu, plen);
 }
 
+static void read_by_group_resp(int sk, uint16_t start,
+					uint16_t end, bt_uuid_t *pattern)
+{
+	uint8_t opdu[ATT_DEFAULT_LE_MTU];
+	GList *list;
+	struct btd_attribute *last = NULL;
+	uint8_t *group_start, *group_end = NULL, *group_uuid;
+	unsigned int uuid_type = BT_UUID_UNSPEC;
+	size_t group_len = 0, plen = 0;
+
+	/*
+	 * Read By Group Type Response format:
+	 *    Attribute Opcode: 1 byte
+	 *    Length: 1 byte (size of each group)
+	 *    Group: start | end | <<UUID>>
+	 */
+
+	opdu[0] = ATT_OP_READ_BY_GROUP_RESP;
+	group_start = &opdu[2];
+	group_uuid = &opdu[6];
+
+	for (list = local_attribute_db; list;
+			last = list->data, list = g_list_next(list)) {
+		struct btd_attribute *attr = list->data;
+
+		if (attr->handle < start)
+			continue;
+
+		if (attr->handle > end)
+			break;
+
+		if (bt_uuid_cmp(&attr->type, pattern) != 0)
+			continue;
+
+		if (uuid_type != BT_UUID_UNSPEC &&
+						uuid_type != attr->type.type) {
+			/*
+			 * Groups should contain the same length: UUID16 and
+			 * UUID128 should be sent on different ATT PDUs
+			 */
+			break;
+		}
+
+		/*
+		 * MTU checking should not be shifted up, otherwise the
+		 * handle of last end group will not be set properly.
+		 */
+		if ((plen + group_len) >= ATT_DEFAULT_LE_MTU)
+			break;
+
+		/* Start Grouping handle */
+		att_put_u16(attr->handle, group_start);
+
+		/* Grouping <<UUID>>: Value is little endian */
+		memcpy(group_uuid, attr->value, attr->value_len);
+
+		if (last && group_end) {
+			att_put_u16(last->handle, group_end);
+			group_end += group_len;
+			plen += group_len;
+		}
+
+		/* Grouping initial settings: First grouping */
+		if (uuid_type == BT_UUID_UNSPEC) {
+			uuid_type = attr->type.type;
+
+			/* start(0xXXXX) | end(0xXXXX) | <<UUID>> */
+			group_len = 2 + 2 + bt_uuid_len(&attr->type);
+
+			/* 2: ATT Opcode and Length */
+			plen = 2 + group_len;
+
+			/* Size of each Attribute Data */
+			opdu[1] = group_len;
+
+			group_end = &opdu[4];
+		}
+
+		group_start += group_len;
+		group_uuid += group_len;
+	}
+
+	if (plen == 0) {
+		send_error(sk, ATT_OP_READ_BY_GROUP_REQ, start,
+						ATT_ECODE_ATTR_NOT_FOUND);
+		return;
+	}
+
+	if (group_end)
+		att_put_u16(last->handle, group_end);
+
+	write(sk, opdu, plen);
+}
+
+static void read_by_group(int sk, const uint8_t *ipdu, ssize_t ilen)
+{
+	uint16_t decoded, start, end;
+	bt_uuid_t pattern;
+
+	decoded = dec_read_by_grp_req(ipdu, ilen, &start, &end, &pattern);
+	if (decoded == 0) {
+		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_INVALID_PDU);
+		return;
+	}
+
+	if (start > end || start == 0x0000) {
+		send_error(sk, ipdu[0], start, ATT_ECODE_INVALID_HANDLE);
+		return;
+	}
+
+	 /*
+	  * Restricting Read By Group Type to <<Primary>>.
+	  * Removing the checking below requires changes to support
+	  * dynamic values(defined in the upper layer) and additional
+	  * security verification.
+	  */
+	if (bt_uuid_cmp(&pattern, &primary_uuid) != 0) {
+		send_error(sk, ipdu[0], start, ATT_ECODE_UNSUPP_GRP_TYPE);
+		return;
+	}
+
+	read_by_group_resp(sk, start, end, &pattern);
+}
+
 static bool channel_handler_cb(struct io *io, void *user_data)
 {
 	uint8_t ipdu[ATT_DEFAULT_LE_MTU];
@@ -136,11 +260,14 @@ static bool channel_handler_cb(struct io *io, void *user_data)
 	case ATT_OP_READ_MULTI_REQ:
 	case ATT_OP_PREP_WRITE_REQ:
 	case ATT_OP_EXEC_WRITE_REQ:
-	case ATT_OP_READ_BY_GROUP_REQ:
 	case ATT_OP_SIGNED_WRITE_CMD:
 		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
 		break;
 
+	case ATT_OP_READ_BY_GROUP_REQ:
+		read_by_group(sk, ipdu, ilen);
+		break;
+
 	/* Responses */
 	case ATT_OP_MTU_RESP:
 	case ATT_OP_FIND_INFO_RESP:
-- 
1.8.3.1


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

* [PATCH BlueZ v5 12/18] test: Add external service GATT skeleton
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (10 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 13/18] gitignore: Add test/gatt-service Claudio Takahasi
                         ` (6 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial code for an external GATT service example.
It implements the API defined at doc/gatt-api.txt
---
 Makefile.tools      |   5 +++
 test/gatt-service.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 test/gatt-service.c

diff --git a/Makefile.tools b/Makefile.tools
index 9199222..a468272 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -374,3 +374,8 @@ test_scripts += test/sap_client.py test/bluezutils.py \
 		test/test-heartrate test/test-alert test/test-hfp \
 		test/test-cyclingspeed test/opp-client test/ftp-client \
 		test/pbap-client test/map-client
+
+noinst_PROGRAMS += test/gatt-service
+
+test_gatt_service_SOURCES = test/gatt-service.c
+test_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la
diff --git a/test/gatt-service.c b/test/gatt-service.c
new file mode 100644
index 0000000..769fd37
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,121 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+/* Immediate Alert Service UUID */
+#define IAS_UUID			"00001802-0000-1000-8000-00805f9b34fb"
+
+static GMainLoop *main_loop;
+static GSList *services;
+
+static gboolean service_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	const char *uuid = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+	return TRUE;
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	return TRUE;
+}
+
+static gboolean service_exist_includes(const GDBusPropertyTable *property,
+							void *user_data)
+{
+	return FALSE;
+}
+
+static const GDBusPropertyTable service_properties[] = {
+	{ "UUID", "s", service_get_uuid },
+	{ "Includes", "ao", service_get_includes, NULL,
+					service_exist_includes },
+	{ }
+};
+
+static char *register_service(DBusConnection *conn, const char *uuid)
+{
+	static int id = 1;
+	char *path;
+
+	path = g_strdup_printf("/service%d", id++);
+	if (g_dbus_register_interface(conn, path, SERVICE_IFACE,
+				NULL, NULL, service_properties,
+				g_strdup(uuid), g_free) == FALSE) {
+		printf("Couldn't register service interface\n");
+		g_free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+static void create_services(DBusConnection *conn)
+{
+	char *service_path;
+
+	service_path = register_service(conn, IAS_UUID);
+
+	services = g_slist_prepend(services, service_path);
+
+	printf("Registered service: %s\n", service_path);
+}
+
+int main(int argc, char *argv[])
+{
+	DBusConnection *dbus_conn;
+
+	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+
+	main_loop = g_main_loop_new(NULL, FALSE);
+
+	g_dbus_attach_object_manager(dbus_conn);
+
+	printf("gatt-service unique name: %s\n",
+				dbus_bus_get_unique_name(dbus_conn));
+
+	create_services(dbus_conn);
+
+	g_main_loop_run(main_loop);
+
+	g_slist_free_full(services, g_free);
+	dbus_connection_unref(dbus_conn);
+
+	return 0;
+}
-- 
1.8.3.1


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

* [PATCH BlueZ v5 13/18] gitignore: Add test/gatt-service
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (11 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 12/18] test: Add external service GATT skeleton Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 14/18] test: Add signal handling for gatt-service Claudio Takahasi
                         ` (5 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index e2b23fc..5e5880f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ test/sap_client.pyc
 test/bluezutils.pyc
 unit/test-ringbuf
 unit/test-queue
+test/gatt-service
 unit/test-eir
 unit/test-uuid
 unit/test-crc
-- 
1.8.3.1


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

* [PATCH BlueZ v5 14/18] test: Add signal handling for gatt-service
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (12 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 13/18] gitignore: Add test/gatt-service Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 15/18] test: Add registering external service Claudio Takahasi
                         ` (4 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch implements signal handling to run cleanup tasks before
exiting.
---
 test/gatt-service.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 769fd37..4059336 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,6 +27,9 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/signalfd.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -97,9 +100,83 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	static bool __terminated = false;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	switch (si.ssi_signo) {
+	case SIGINT:
+	case SIGTERM:
+		if (!__terminated) {
+			printf("Terminating\n");
+			g_main_loop_quit(main_loop);
+		}
+
+		__terminated = true;
+		break;
+	}
+
+	return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int main(int argc, char *argv[])
 {
 	DBusConnection *dbus_conn;
+	guint signal;
+
+	signal = setup_signalfd();
+	if (signal == 0)
+		return -errno;
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
 
@@ -114,6 +191,8 @@ int main(int argc, char *argv[])
 
 	g_main_loop_run(main_loop);
 
+	g_source_remove(signal);
+
 	g_slist_free_full(services, g_free);
 	dbus_connection_unref(dbus_conn);
 
-- 
1.8.3.1


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

* [PATCH BlueZ v5 15/18] test: Add registering external service
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (13 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 14/18] test: Add signal handling for gatt-service Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 16/18] gatttool: Add unix socket connect Claudio Takahasi
                         ` (3 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch extends gatt-service to call RegisterService() when org.bluez
service gets connected to the system bus.
---
 test/gatt-service.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 4059336..b656ef3 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -35,6 +35,7 @@
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
 #define SERVICE_IFACE			"org.bluez.GattService1"
 
 /* Immediate Alert Service UUID */
@@ -100,6 +101,65 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static void register_external_service_reply(DBusPendingCall *call,
+							void *user_data)
+{
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	dbus_set_error_from_message(&derr, reply);
+
+	if (dbus_error_is_set(&derr))
+		printf("RegisterService: %s\n", derr.message);
+	else
+		printf("RegisterService: OK\n");
+
+	dbus_message_unref(reply);
+	dbus_error_free(&derr);
+}
+
+static void register_external_service(gpointer a, gpointer b)
+{
+	DBusConnection *conn = b;
+	const char *path = a;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	DBusMessageIter iter, dict;
+
+	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+					GATT_MGR_IFACE, "RegisterService");
+	if (msg == NULL) {
+		printf("Couldn't allocate D-Bus message\n");
+		return;
+	}
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	/* TODO: Add options dictionary */
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
+		dbus_message_unref(msg);
+		return;
+	}
+
+	dbus_pending_call_set_notify(call, register_external_service_reply,
+								NULL, NULL);
+
+	dbus_pending_call_unref(call);
+}
+
+static void connect_handler(DBusConnection *conn, void *user_data)
+{
+	g_slist_foreach(services, register_external_service, conn);
+}
+
 static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
 							gpointer user_data)
 {
@@ -171,6 +231,7 @@ static guint setup_signalfd(void)
 
 int main(int argc, char *argv[])
 {
+	GDBusClient *client;
 	DBusConnection *dbus_conn;
 	guint signal;
 
@@ -189,8 +250,14 @@ int main(int argc, char *argv[])
 
 	create_services(dbus_conn);
 
+	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+	g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+
 	g_main_loop_run(main_loop);
 
+	g_dbus_client_unref(client);
+
 	g_source_remove(signal);
 
 	g_slist_free_full(services, g_free);
-- 
1.8.3.1


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

* [PATCH BlueZ v5 16/18] gatttool: Add unix socket connect
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (14 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 15/18] test: Add registering external service Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
                         ` (2 subsequent siblings)
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial support for GATT procedures over unix
socket transport on command line mode (one-shot command). Temporary
solution to allow local GATT procedures testing.
---
 attrib/gatttool.c | 27 ++++++++++++++++++++-------
 attrib/gatttool.h |  1 +
 attrib/utils.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 9f2ead9..cf106de 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <glib.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
@@ -53,6 +52,7 @@ static int opt_end = 0xffff;
 static int opt_handle = -1;
 static int opt_mtu = 0;
 static int opt_psm = 0;
+static gboolean opt_local = FALSE;
 static gboolean opt_primary = FALSE;
 static gboolean opt_characteristics = FALSE;
 static gboolean opt_char_read = FALSE;
@@ -511,6 +511,8 @@ static GOptionEntry options[] = {
 		"Specify local adapter interface", "hciX" },
 	{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
 		"Specify remote Bluetooth address", "MAC" },
+	{ "local", 'L', 0, G_OPTION_ARG_NONE, &opt_local,
+		"Use unix socket transport (local communication)", NULL },
 	{ "addr-type", 't', 0, G_OPTION_ARG_STRING, &opt_dst_type,
 		"Set LE address type. Default: public", "[public | random]"},
 	{ "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu,
@@ -563,6 +565,11 @@ int main(int argc, char *argv[])
 		g_clear_error(&gerr);
 	}
 
+	if (opt_local) {
+		opt_src = NULL;
+		opt_dst = NULL;
+	}
+
 	if (opt_interactive) {
 		interactive(opt_src, opt_dst, opt_dst_type, opt_psm);
 		goto done;
@@ -588,14 +595,20 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
-	if (opt_dst == NULL) {
-		g_print("Remote Bluetooth address required\n");
-		got_error = TRUE;
-		goto done;
+	if (opt_local)
+		chan = unix_connect(connect_cb, &gerr);
+	else {
+		if (opt_dst == NULL) {
+			g_print("Remote Bluetooth address required\n");
+			got_error = TRUE;
+			goto done;
+		}
+
+		chan = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
 	}
 
-	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
 		g_printerr("%s\n", gerr->message);
 		g_clear_error(&gerr);
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 8f0913c..be8e236 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -27,4 +27,5 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 			const char *dst_type, const char *sec_level,
 			int psm, int mtu, BtIOConnect connect_cb,
 			GError **gerr);
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/utils.c b/attrib/utils.c
index 17f02be..7d2966f 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -25,7 +25,12 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include <bluetooth/bluetooth.h>
@@ -101,6 +106,55 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 	return chan;
 }
 
+static gboolean unix_connect_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	BtIOConnect connect_cb = user_data;
+	GError *gerr;
+
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		gerr = g_error_new_literal(G_IO_CHANNEL_ERROR,
+						G_IO_CHANNEL_ERROR_FAILED,
+						"connection attempt failed");
+		connect_cb(io, gerr, user_data);
+		g_clear_error(&gerr);
+	} else {
+		connect_cb(io, NULL, user_data);
+	}
+
+	return FALSE;
+}
+
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr)
+{
+	GIOChannel *io;
+	struct sockaddr_un uaddr  = {
+		.sun_family	= AF_UNIX,
+		.sun_path	= "\0/bluetooth/unix_att",
+	};
+	int sk;
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		return NULL;
+	}
+
+	if (connect(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		close(sk);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+						unix_connect_cb, connect_cb);
+
+	return io;
+}
+
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data)
 {
 	char tmp[3];
-- 
1.8.3.1


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

* [PATCH BlueZ v5 17/18] gatttool: Add unix socket support for interactive mode
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (15 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 16/18] gatttool: Add unix socket connect Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-01-27 20:35       ` [PATCH BlueZ v5 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch allows running GATT operations over unix socket on
interactive mode.
---
 attrib/interactive.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 70c091c..67e060e 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -84,7 +84,7 @@ static char *get_prompt(void)
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
-		g_string_append_printf(prompt, "[%17s]", "");
+		g_string_append_printf(prompt, "[LOCAL]");
 
 	if (conn_state == STATE_CONNECTED)
 		g_string_append(prompt, COLOR_OFF);
@@ -405,15 +405,18 @@ static void cmd_connect(int argcp, char **argvp)
 			opt_dst_type = g_strdup("public");
 	}
 
-	if (opt_dst == NULL) {
-		error("Remote Bluetooth address required\n");
-		return;
+	if (opt_dst) {
+
+		rl_printf("Attempting to connect to %s\n", opt_dst);
+		set_state(STATE_CONNECTING);
+		iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
+	} else {
+		rl_printf("Local connection\n");
+		iochannel = unix_connect(connect_cb, &gerr);
 	}
 
-	rl_printf("Attempting to connect to %s\n", opt_dst);
-	set_state(STATE_CONNECTING);
-	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
 		set_state(STATE_DISCONNECTED);
 		error("%s\n", gerr->message);
-- 
1.8.3.1


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

* [PATCH BlueZ v5 18/18] bluetooth.conf: Add ObjectManager interface
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (16 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
@ 2014-01-27 20:35       ` Claudio Takahasi
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
  18 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 src/bluetooth.conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..ad8891a 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -18,6 +18,7 @@
     <allow send_interface="org.bluez.Profile1"/>
     <allow send_interface="org.bluez.HeartRateWatcher1"/>
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
+    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
   </policy>
 
   <policy at_console="true">
-- 
1.8.3.1


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

* [PATCH BlueZ v6 00/18] GATT API: External Services
  2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
                         ` (17 preceding siblings ...)
  2014-01-27 20:35       ` [PATCH BlueZ v5 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
@ 2014-02-04 17:53       ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 01/18] doc: Add experimental GATT API Claudio Takahasi
                           ` (19 more replies)
  18 siblings, 20 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patchset implements the minimal support for adding local services
declarations.

Limitation: Remove services and multiple services exported by the same
remote will be implemented the next series.

Changes from PATCH v6 to PATCH v5:
* Rebase
* Fixed warning (gcc 4.6.3/32-bits): "ignoring return value of ‘write’"

Changes from PATCH v4 to PATCH v5:
* Removed Release() method of GattService1 interface

Changes from PATCH v3 to PATCH v4:
* Rebase
* src/gatt.c: Replaced GIOChannel/GAttrib by "io".

Changes from PATCH v2 to PATCH v3:
* Rebase
* Interfaces renamed: s/GattServiceManager1/GattManager1,
  s/Characteristic1/GattCharacteristic1, s/Descriptor/GattDescriptor1
* test/gatt-service.c: s/fprintf/printf

Changes from PATCH v1 to PATCH v2:
* Rebase
* Included patch "doc: Add GATT API"
* Interfaces renamed: s/Service1/GattService1, and
  s/ServiceManager1/GattServiceManager1
* Removed patch "gatt: Implement UnregisterService" from this patchset

Changes from PATCH v0 to PATCH v1:
* Rebase

Changes from RFC v0 to PATCH v0:
* Changed copyright year : s/2013/2014
* Fixed coding style
* Added gatt-service binary to gitignore
* Added extra comment in the source code

Features:
* API for internal and external services declaration
* Unix socket for testing purpose: services are exported through unix
  sockets to avoid breaking the current attribute server.

How to test:
  Run bluetoothd with EXPERIMENTAL flag (-E)
  Replace /etc/dbus-1/system.d/bluetooth.conf and reload DBus settings
  $gatttool -L --primary (or interactive mode)

Roughly upstreaming plan (steps):
 * GATT Server: External Services -> pathset GATT API: External Services
 * GATT Server: External Characteristics (Server)
 * GATT Server: External Descriptors (Server)
 * Replacement for GAttrib: use "io"
 * Replace attribute server
 * Remove ATTIO and automatic connection mechanism from userspace
 * Fix all GATT internal plugins
 * GATT Client: Remote Services

Alvaro Silva (6):
  gatt: Add stub for gatt.{c, h} files
  gatt: Register Manager D-Bus Interface
  gatt: Add registering external service
  gatt: Add external services tracking
  gatt: Register ATT command/event handler
  gatt: Add Discover All Primary Services

Andre Guedes (1):
  gatt: Add helper for creating GATT services

Claudio Takahasi (11):
  doc: Add experimental GATT API
  lib: Move GATT UUID to uuid.h
  gatt: Add server unix socket
  gattrib: Use default ATT LE MTU for non-standard sockets
  test: Add external service GATT skeleton
  gitignore: Add test/gatt-service
  test: Add signal handling for gatt-service
  test: Add registering external service
  gatttool: Add unix socket connect
  gatttool: Add unix socket support for interactive mode
  bluetooth.conf: Add ObjectManager interface

 .gitignore           |   1 +
 Makefile.am          |   2 +
 Makefile.tools       |   5 +
 attrib/gatt.h        |  25 ----
 attrib/gattrib.c     |  16 +--
 attrib/gatttool.c    |  27 +++-
 attrib/gatttool.h    |   1 +
 attrib/interactive.c |  19 +--
 attrib/utils.c       |  54 ++++++++
 doc/gatt-api.txt     | 142 +++++++++++++++++++
 lib/uuid.h           |  30 ++++
 src/bluetooth.conf   |   1 +
 src/gatt-dbus.c      | 271 ++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h      |  25 ++++
 src/gatt.c           | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h           |  36 +++++
 src/main.c           |   4 +
 test/gatt-service.c  | 267 ++++++++++++++++++++++++++++++++++++
 18 files changed, 1257 insertions(+), 48 deletions(-)
 create mode 100644 doc/gatt-api.txt
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h
 create mode 100644 test/gatt-service.c

-- 
1.8.3.1


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

* [PATCH BlueZ v6 01/18] doc: Add experimental GATT API
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
                           ` (18 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch proposes an unified GATT API for local and remote services.
---
 doc/gatt-api.txt | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)
 create mode 100644 doc/gatt-api.txt

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
new file mode 100644
index 0000000..0f6b084
--- /dev/null
+++ b/doc/gatt-api.txt
@@ -0,0 +1,142 @@
+BlueZ D-Bus GATT API description
+********************************
+
+GATT local and remote services share the same high-level D-Bus API. Local
+refers to GATT based service exported by a BlueZ plugin or an external
+application. Remote refers to GATT services exported by the peer.
+
+BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
+Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
+external services to allow seamless GATT declarations (Service, Characteristic
+and Descriptors) discovery.
+
+Releasing a registered GATT service is not defined yet. Any API extension
+should avoid breaking the defined API, and if possible keep an unified GATT
+remote and local services representation.
+
+Service hierarchy
+=================
+
+GATT remote and local service representation. Object path for local services
+is freely definable.
+
+External applications implementing local services must register the services
+using GattManager1 registration method and must implement the methods and
+properties defined in GattService1 interface.
+
+Service		org.bluez
+Interface	org.bluez.GattService1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+
+Properties	string UUID [read-only]
+
+			128-bit service UUID.
+
+		array{object} Includes [read-only]: Not implemented
+
+			Array of object paths representing the included
+			services of this service.
+
+
+Characteristic hierarchy
+========================
+
+For local GATT defined services, the object paths need to follow the service
+path hierarchy and are freely definable.
+
+Service		org.bluez
+Interface	org.bluez.GattCharacteristic1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+
+Properties	string UUID [read-only]
+
+			128-bit characteristic UUID.
+
+		object Service [read-only]
+
+			Object path of the GATT service the characteristc
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Value read from the remote Bluetooth device or from
+			the external application implementing GATT services.
+
+		array{string} Flags [read-only, optional]
+
+			Defines how the characteristic value can be used. See
+			Core spec page 1898, "Table 3.5: Characteristic
+			Properties bit field" and page 1900, "Table 3.8:
+			Characteristic Extended Properties bit field". Allowed
+			values: "broadcast", "read", "write-without-response",
+			"write", "notify", "indicate",
+			"authenticated-signed-writes", "reliable-write", and
+			"writable-auxiliaries".
+
+
+Characteristic Descriptors hierarchy
+====================================
+
+Local or remote GATT characteristic descriptors hierarchy.
+
+Service		org.bluez
+Interface	org.bluez.GattDescriptor1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+
+Properties	string UUID [read-only]
+
+			128-bit descriptor UUID.
+
+		object Characteristic [read-only]
+
+			Object path of the GATT characteristc the descriptor
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Raw characteristic descriptor value read from the
+			remote Bluetooth device or from the external
+			application implementing GATT services.
+
+		string Permissions [read-only]: To be defined
+
+			Defines read/write authentication and authorization
+			requirements.
+
+Service Manager hierarchy
+=============================
+
+Service Manager allows external applications to register GATT based
+services. Services must follow the API for Service and Characteristic
+described above.
+
+Local GATT services, characteristics and characteristic descriptors are
+discovered automatically using the D-Bus Object Manager interface.
+
+Service		org.bluez
+Interface	org.bluez.GattManager1 [Experimental]
+Object path	/org/bluez
+
+Methods		RegisterService(object service, dict options)
+
+			Registers remote application service exported under
+			interface GattService1. Characteristic objects must
+			be hierarchical to their service and must use the
+			interface GattCharacteristic1. D-Bus Object Manager
+			is used to fetch the exported objects.
+
+			"service" object path together with the D-Bus system
+			bus connection ID define the identification of the
+			application registering a GATT based service.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		UnregisterService(object service)
+
+			This unregisters the service that has been
+			previously registered. The object path parameter
+			must match the same value that has been used
+			on registration.
+
+			Possible errors: org.bluez.Error.DoesNotExist
-- 
1.8.3.1


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

* [PATCH BlueZ v6 02/18] gatt: Add stub for gatt.{c, h} files
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 01/18] doc: Add experimental GATT API Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
                           ` (17 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

These files implement functions to handle ATT transactions, and expose
functions to allow other entities to manage GATT based services. It
is a replacement for src/attrib-server.c.
---
 Makefile.am |  1 +
 src/gatt.c  | 38 ++++++++++++++++++++++++++++++++++++++
 src/gatt.h  | 26 ++++++++++++++++++++++++++
 src/main.c  |  4 ++++
 4 files changed, 69 insertions(+)
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h

diff --git a/Makefile.am b/Makefile.am
index 1a44a9f..5f61d50 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
 			src/eir.h src/eir.c \
diff --git a/src/gatt.c b/src/gatt.c
new file mode 100644
index 0000000..06619f0
--- /dev/null
+++ b/src/gatt.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 "gatt.h"
+
+void gatt_init(void)
+{
+
+}
+
+void gatt_cleanup(void)
+{
+
+}
diff --git a/src/gatt.h b/src/gatt.h
new file mode 100644
index 0000000..3a320b4
--- /dev/null
+++ b/src/gatt.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 gatt_init(void);
+
+void gatt_cleanup(void);
diff --git a/src/main.c b/src/main.c
index 91d90b4..fccc838 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,6 +55,7 @@
 #include "dbus-common.h"
 #include "agent.h"
 #include "profile.h"
+#include "gatt.h"
 #include "systemd.h"
 
 #define BLUEZ_NAME "org.bluez"
@@ -545,6 +546,8 @@ int main(int argc, char *argv[])
 
 	g_dbus_set_flags(gdbus_flags);
 
+	gatt_init();
+
 	if (option_compat == TRUE)
 		sdp_flags |= SDP_SERVER_COMPAT;
 
@@ -595,6 +598,7 @@ int main(int argc, char *argv[])
 	btd_profile_cleanup();
 	btd_agent_cleanup();
 	btd_device_cleanup();
+	gatt_cleanup();
 
 	adapter_cleanup();
 
-- 
1.8.3.1


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

* [PATCH BlueZ v6 03/18] gatt: Register Manager D-Bus Interface
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 01/18] doc: Add experimental GATT API Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 04/18] gatt: Add registering external service Claudio Takahasi
                           ` (16 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers GATT Service Manager D-Bus Interface. This
interface implements the methods to allow external application register
and unregister GATT Services.
---
 Makefile.am     |  1 +
 src/gatt-dbus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h | 25 +++++++++++++++++++
 src/gatt.c      |  9 +++++++
 4 files changed, 110 insertions(+)
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h

diff --git a/Makefile.am b/Makefile.am
index 5f61d50..e630fcb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt-dbus.h src/gatt-dbus.c \
 			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
new file mode 100644
index 0000000..183c611
--- /dev/null
+++ b/src/gatt-dbus.c
@@ -0,0 +1,75 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include "dbus-common.h"
+#include "log.h"
+
+#include "gatt-dbus.h"
+
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
+
+static DBusMessage *register_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable methods[] = {
+	{ GDBUS_EXPERIMENTAL_METHOD("RegisterService",
+				GDBUS_ARGS({ "service", "o"},
+						{ "options", "a{sv}"}),
+				NULL, register_service) },
+	{ GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
+				GDBUS_ARGS({"service", "o"}),
+				NULL, unregister_service) },
+	{ }
+};
+
+gboolean gatt_dbus_manager_register(void)
+{
+	return g_dbus_register_interface(btd_get_dbus_connection(),
+					"/org/bluez", GATT_MGR_IFACE,
+					methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+							GATT_MGR_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
new file mode 100644
index 0000000..310cfa9
--- /dev/null
+++ b/src/gatt-dbus.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *
+ */
+
+gboolean gatt_dbus_manager_register(void);
+void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 06619f0..e8b691a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,14 +25,23 @@
 #include <config.h>
 #endif
 
+#include <glib.h>
+
+#include "log.h"
+
+#include "gatt-dbus.h"
 #include "gatt.h"
 
 void gatt_init(void)
 {
+	DBG("Starting GATT server");
 
+	gatt_dbus_manager_register();
 }
 
 void gatt_cleanup(void)
 {
+	DBG("Stopping GATT server");
 
+	gatt_dbus_manager_unregister();
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v6 04/18] gatt: Add registering external service
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (2 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
                           ` (15 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch allows external applications register a given service on
Bluez. Applications must provide an object path and a dictionary of
options. Options dictionary will be used later to provide additional
service information.
---
 src/gatt-dbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 183c611..fd614f9 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -26,22 +26,109 @@
 #endif
 
 #include <stdint.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#include "adapter.h"
+#include "device.h"
+#include "lib/uuid.h"
 #include "dbus-common.h"
 #include "log.h"
 
+#include "error.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
 
+struct external_app {
+	char *owner;
+	char *path;
+	GDBusClient *client;
+	unsigned int watch;
+};
+
+static GSList *external_apps;
+
+static int external_app_path_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct external_app *eapp = a;
+	const char *path = b;
+
+	return g_strcmp0(eapp->path, path);
+}
+
+static void external_app_watch_destroy(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+
+	/* TODO: Remove from the database */
+
+	external_apps = g_slist_remove(external_apps, eapp);
+
+	g_dbus_client_unref(eapp->client);
+
+	g_free(eapp->owner);
+	g_free(eapp->path);
+	g_free(eapp);
+}
+
+static struct external_app *new_external_app(DBusConnection *conn,
+					const char *sender, const char *path)
+{
+	struct external_app *eapp;
+	GDBusClient *client;
+
+	client = g_dbus_client_new(conn, sender, "/");
+	if (client == NULL)
+		return NULL;
+
+	eapp = g_new0(struct external_app, 1);
+
+	eapp->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
+			sender, NULL, eapp, external_app_watch_destroy);
+	if (eapp->watch == 0) {
+		g_dbus_client_unref(client);
+		g_free(eapp);
+		return NULL;
+	}
+
+	eapp->owner = g_strdup(sender);
+	eapp->client = client;
+	eapp->path = g_strdup(path);
+
+	return eapp;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
-	return dbus_message_new_method_return(msg);
+	struct external_app *eapp;
+	DBusMessageIter iter;
+	const char *path;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &path);
+
+	if (g_slist_find_custom(external_apps, path, external_app_path_cmp))
+		return btd_error_already_exists(msg);
+
+	eapp = new_external_app(conn, dbus_message_get_sender(msg), path);
+	if (eapp == NULL)
+		return btd_error_failed(msg, "Not enough resources");
+
+	external_apps = g_slist_prepend(external_apps, eapp);
+
+	DBG("New app %p: %s", eapp, path);
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
 static DBusMessage *unregister_service(DBusConnection *conn,
-- 
1.8.3.1


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

* [PATCH BlueZ v6 05/18] lib: Move GATT UUID to uuid.h
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (3 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 04/18] gatt: Add registering external service Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
                           ` (14 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch moves GATT UUIDs definitions to a common header. uuid.h contains
helper functions to manipulate Bluetooth UUIDs and some common BR/EDR services
UUIDs.
---
 attrib/gatt.h | 25 -------------------------
 lib/uuid.h    | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0f113e7..4fea3eb 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,31 +24,6 @@
 
 #include <bluetooth/sdp.h>
 
-/* GATT Profile Attribute types */
-#define GATT_PRIM_SVC_UUID		0x2800
-#define GATT_SND_SVC_UUID		0x2801
-#define GATT_INCLUDE_UUID		0x2802
-#define GATT_CHARAC_UUID		0x2803
-
-/* GATT Characteristic Types */
-#define GATT_CHARAC_DEVICE_NAME			0x2A00
-#define GATT_CHARAC_APPEARANCE			0x2A01
-#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG	0x2A02
-#define GATT_CHARAC_RECONNECTION_ADDRESS	0x2A03
-#define GATT_CHARAC_PERIPHERAL_PREF_CONN	0x2A04
-#define GATT_CHARAC_SERVICE_CHANGED		0x2A05
-
-/* GATT Characteristic Descriptors */
-#define GATT_CHARAC_EXT_PROPER_UUID	0x2900
-#define GATT_CHARAC_USER_DESC_UUID	0x2901
-#define GATT_CLIENT_CHARAC_CFG_UUID	0x2902
-#define GATT_SERVER_CHARAC_CFG_UUID	0x2903
-#define GATT_CHARAC_FMT_UUID		0x2904
-#define GATT_CHARAC_AGREG_FMT_UUID	0x2905
-#define GATT_CHARAC_VALID_RANGE_UUID	0x2906
-#define GATT_EXTERNAL_REPORT_REFERENCE	0x2907
-#define GATT_REPORT_REFERENCE		0x2908
-
 /* Client Characteristic Configuration bit field */
 #define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT	0x0001
 #define GATT_CLIENT_CHARAC_CFG_IND_BIT		0x0002
diff --git a/lib/uuid.h b/lib/uuid.h
index 95e5a9a..c24cee5 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -105,6 +105,31 @@ extern "C" {
 #define OBEX_MNS_UUID		"00001133-0000-1000-8000-00805f9b34fb"
 #define OBEX_MAP_UUID		"00001134-0000-1000-8000-00805f9b34fb"
 
+/* GATT UUIDs section */
+#define GATT_PRIM_SVC_UUID				0x2800
+#define GATT_SND_SVC_UUID				0x2801
+#define GATT_INCLUDE_UUID				0x2802
+#define GATT_CHARAC_UUID				0x2803
+
+/* GATT Characteristic Types */
+#define GATT_CHARAC_DEVICE_NAME				0x2A00
+#define GATT_CHARAC_APPEARANCE				0x2A01
+#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG		0x2A02
+#define GATT_CHARAC_RECONNECTION_ADDRESS		0x2A03
+#define GATT_CHARAC_PERIPHERAL_PREF_CONN		0x2A04
+#define GATT_CHARAC_SERVICE_CHANGED			0x2A05
+
+/* GATT Characteristic Descriptors */
+#define GATT_CHARAC_EXT_PROPER_UUID			0x2900
+#define GATT_CHARAC_USER_DESC_UUID			0x2901
+#define GATT_CLIENT_CHARAC_CFG_UUID			0x2902
+#define GATT_SERVER_CHARAC_CFG_UUID			0x2903
+#define GATT_CHARAC_FMT_UUID				0x2904
+#define GATT_CHARAC_AGREG_FMT_UUID			0x2905
+#define GATT_CHARAC_VALID_RANGE_UUID			0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE			0x2907
+#define GATT_REPORT_REFERENCE				0x2908
+
 typedef struct {
 	enum {
 		BT_UUID_UNSPEC = 0,
-- 
1.8.3.1


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

* [PATCH BlueZ v6 06/18] gatt: Add helper for creating GATT services
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (4 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 07/18] gatt: Add external services tracking Claudio Takahasi
                           ` (13 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes

From: Andre Guedes <andre.guedes@openbossa.org>

This patch adds the btd_gatt_add_service() helper which adds a
GATT Service declaration to the local attribute database.
---
 lib/uuid.h |  5 +++++
 src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h | 10 ++++++++++
 3 files changed, 74 insertions(+)

diff --git a/lib/uuid.h b/lib/uuid.h
index c24cee5..237145b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -158,6 +158,11 @@ void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
 int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
 int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
 
+static inline int bt_uuid_len(const bt_uuid_t *uuid)
+{
+	return uuid->type / 8;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gatt.c b/src/gatt.c
index e8b691a..f7b74d6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -28,10 +28,69 @@
 #include <glib.h>
 
 #include "log.h"
+#include "lib/uuid.h"
+#include "attrib/att.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
 
+/* Common GATT UUIDs */
+static const bt_uuid_t primary_uuid  = { .type = BT_UUID16,
+					.value.u16 = GATT_PRIM_SVC_UUID };
+
+struct btd_attribute {
+	uint16_t handle;
+	bt_uuid_t type;
+	uint16_t value_len;
+	uint8_t value[0];
+};
+
+static GList *local_attribute_db;
+static uint16_t next_handle = 0x0001;
+
+static int local_database_add(uint16_t handle, struct btd_attribute *attr)
+{
+	attr->handle = handle;
+
+	local_attribute_db = g_list_append(local_attribute_db, attr);
+
+	return 0;
+}
+
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
+{
+	uint16_t len = bt_uuid_len(uuid);
+	struct btd_attribute *attr = g_malloc0(sizeof(struct btd_attribute) +
+									len);
+
+	/*
+	 * Service DECLARATION
+	 *
+	 *   TYPE         ATTRIBUTE VALUE
+	 * +-------+---------------------------------+
+	 * |0x2800 | 0xYYYY...                       |
+	 * | (1)   | (2)                             |
+	 * +------+----------------------------------+
+	 * (1) - 2 octets: Primary/Secondary Service UUID
+	 * (2) - 2 or 16 octets: Service UUID
+	 */
+
+	attr->type = primary_uuid;
+
+	att_put_uuid(*uuid, attr->value);
+	attr->value_len = len;
+
+	if (local_database_add(next_handle, attr) < 0) {
+		g_free(attr);
+		return NULL;
+	}
+
+	/* TODO: missing overflow checking */
+	next_handle = next_handle + 1;
+
+	return attr;
+}
+
 void gatt_init(void)
 {
 	DBG("Starting GATT server");
diff --git a/src/gatt.h b/src/gatt.h
index 3a320b4..8dd1312 100644
--- a/src/gatt.h
+++ b/src/gatt.h
@@ -21,6 +21,16 @@
  *
  */
 
+struct btd_attribute;
+
 void gatt_init(void);
 
 void gatt_cleanup(void);
+
+/* btd_gatt_add_service - Add a service declaration to local attribute database.
+ * @uuid:	Service UUID.
+ *
+ * Returns a reference to service declaration attribute. In case of error,
+ * NULL is returned.
+ */
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
-- 
1.8.3.1


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

* [PATCH BlueZ v6 07/18] gatt: Add external services tracking
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (5 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 08/18] gatt: Add server unix socket Claudio Takahasi
                           ` (12 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

All primary services declarations provided by an external application
will be automatically inserted in the attribute database.
---
 src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index fd614f9..000d7ae 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -39,15 +39,21 @@
 #include "log.h"
 
 #include "error.h"
+#include "gatt.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+#define REGISTER_TIMER         1
 
 struct external_app {
 	char *owner;
 	char *path;
 	GDBusClient *client;
+	GSList *proxies;
 	unsigned int watch;
+	guint register_timer;
 };
 
 static GSList *external_apps;
@@ -60,6 +66,36 @@ static int external_app_path_cmp(gconstpointer a, gconstpointer b)
 	return g_strcmp0(eapp->path, path);
 }
 
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	if (g_strcmp0(interface, SERVICE_IFACE) != 0)
+		return;
+
+	eapp->proxies = g_slist_append(eapp->proxies, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	eapp->proxies = g_slist_remove(eapp->proxies, proxy);
+}
+
+
 static void external_app_watch_destroy(gpointer user_data)
 {
 	struct external_app *eapp = user_data;
@@ -70,6 +106,9 @@ static void external_app_watch_destroy(gpointer user_data)
 
 	g_dbus_client_unref(eapp->client);
 
+	if (eapp->register_timer)
+		g_source_remove(eapp->register_timer);
+
 	g_free(eapp->owner);
 	g_free(eapp->path);
 	g_free(eapp);
@@ -99,9 +138,75 @@ static struct external_app *new_external_app(DBusConnection *conn,
 	eapp->client = client;
 	eapp->path = g_strdup(path);
 
+	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+								NULL, eapp);
+
 	return eapp;
 }
 
+static int register_external_service(GDBusProxy *proxy)
+{
+	DBusMessageIter iter;
+	const char *uuid;
+	bt_uuid_t btuuid;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return -EINVAL;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return -EINVAL;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (bt_string_to_uuid(&btuuid, uuid) < 0)
+		return -EINVAL;
+
+	if (btd_gatt_add_service(&btuuid) == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static gboolean finish_register(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+	GSList *list;
+
+	/*
+	 * It is not possible to detect when the last proxy object
+	 * was reported. "Proxy added" handler reports objects
+	 * added on demand or returned by GetManagedObjects().
+	 * This timer helps to register all the GATT declarations
+	 * (services, characteristics and descriptors) after fetching
+	 * all the D-Bus objects.
+	 */
+
+	eapp->register_timer = 0;
+
+	for (list = eapp->proxies; list; list = g_slist_next(list)) {
+		const char *interface, *path;
+		GDBusProxy *proxy = list->data;
+
+		interface = g_dbus_proxy_get_interface(proxy);
+		path = g_dbus_proxy_get_path(proxy);
+
+		if (g_strcmp0(SERVICE_IFACE, interface) != 0)
+			continue;
+
+		if (g_strcmp0(path, eapp->path) != 0)
+			continue;
+
+		if (register_external_service(proxy) < 0) {
+			DBG("Inconsistent external service: %s", path);
+			continue;
+		}
+
+		DBG("External service: %s", path);
+	}
+
+	return FALSE;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -109,6 +214,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	DBusMessageIter iter;
 	const char *path;
 
+	DBG("Registering GATT Service");
+
 	if (!dbus_message_iter_init(msg, &iter))
 		return btd_error_invalid_args(msg);
 
@@ -127,6 +234,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	external_apps = g_slist_prepend(external_apps, eapp);
 
 	DBG("New app %p: %s", eapp, path);
+	eapp->register_timer = g_timeout_add_seconds(REGISTER_TIMER,
+							finish_register, eapp);
 
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v6 08/18] gatt: Add server unix socket
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (6 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 07/18] gatt: Add external services tracking Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
                           ` (11 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds a server unix socket to handle local ATT traffic. This
is a development purpose feature used to allow local testing without
breaking the current attribute server.
---
 src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/src/gatt.c b/src/gatt.c
index f7b74d6..7a595c6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,11 +25,17 @@
 #include <config.h>
 #endif
 
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include "log.h"
 #include "lib/uuid.h"
 #include "attrib/att.h"
+#include "src/shared/io.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
@@ -45,6 +51,7 @@ struct btd_attribute {
 	uint8_t value[0];
 };
 
+static struct io *server_io;
 static GList *local_attribute_db;
 static uint16_t next_handle = 0x0001;
 
@@ -91,11 +98,62 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static bool unix_accept_cb(struct io *io, void *user_data)
+{
+	struct sockaddr_un uaddr;
+	socklen_t len = sizeof(uaddr);
+	int err, nsk, sk;
+
+	sk = io_get_fd(io);
+
+	nsk = accept(sk, (struct sockaddr *) &uaddr, &len);
+	if (nsk < 0) {
+		err = errno;
+		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
+		return TRUE;
+	}
+
+	DBG("ATT UNIX socket: %d", nsk);
+
+	return TRUE;
+}
+
 void gatt_init(void)
 {
+	struct sockaddr_un uaddr  = {
+		.sun_family     = AF_UNIX,
+		.sun_path       = "\0/bluetooth/unix_att",
+	};
+	int sk, err;
+
 	DBG("Starting GATT server");
 
 	gatt_dbus_manager_register();
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		err = errno;
+		error("ATT UNIX socket: %s(%d)", strerror(err), err);
+		return;
+	}
+
+	if (bind(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		err = errno;
+		error("binding ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	if (listen(sk, 5) < 0) {
+		err = errno;
+		error("listen ATT UNIX socket: %s(%d)", strerror(err), err);
+		close(sk);
+		return;
+	}
+
+	server_io = io_new(sk);
+	io_set_close_on_destroy(server_io, true);
+	io_set_read_handler(server_io, unix_accept_cb, NULL, NULL);
 }
 
 void gatt_cleanup(void)
@@ -103,4 +161,5 @@ void gatt_cleanup(void)
 	DBG("Stopping GATT server");
 
 	gatt_dbus_manager_unregister();
+	io_destroy(server_io);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v6 09/18] gattrib: Use default ATT LE MTU for non-standard sockets
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (7 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 08/18] gatt: Add server unix socket Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 10/18] gatt: Register ATT command/event handler Claudio Takahasi
                           ` (10 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch forces the MTU to 23 (default ATT MTU) if the transport
is not Bluetooth. This is a development purpose change to allow
testing GATT procedures over non-Bluetooth sockets.
---
 attrib/gattrib.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index daf6312..b5b8529 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -468,18 +468,18 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	struct _GAttrib *attrib;
 	uint16_t imtu;
 	uint16_t att_mtu;
-	uint16_t cid;
-	GError *gerr = NULL;
+	uint16_t cid = 0;
 
 	g_io_channel_set_encoding(io, NULL, NULL);
 	g_io_channel_set_buffered(io, FALSE);
 
-	bt_io_get(io, &gerr, BT_IO_OPT_IMTU, &imtu,
-				BT_IO_OPT_CID, &cid, BT_IO_OPT_INVALID);
-	if (gerr) {
-		error("%s", gerr->message);
-		g_error_free(gerr);
-		return NULL;
+	if (bt_io_get(io, NULL, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_CID, &cid,
+						BT_IO_OPT_INVALID) == FALSE) {
+		/*
+		 * Use default ATT LE MTU for non-standard transports. Used
+		 * for testing purpose only. eg: Unix sockets
+		 */
+		imtu = ATT_DEFAULT_LE_MTU;
 	}
 
 	attrib = g_try_new0(struct _GAttrib, 1);
-- 
1.8.3.1


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

* [PATCH BlueZ v6 10/18] gatt: Register ATT command/event handler
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (8 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
                           ` (9 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers the ATT channel handler to manage incoming ATT
commands and events.
---
 src/gatt.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 89 insertions(+), 2 deletions(-)

diff --git a/src/gatt.c b/src/gatt.c
index 7a595c6..ec8f381 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -55,6 +55,13 @@ static struct io *server_io;
 static GList *local_attribute_db;
 static uint16_t next_handle = 0x0001;
 
+static void write_pdu(int sk, const uint8_t *pdu, size_t plen)
+{
+	if (write(sk, pdu, plen) < 0)
+		error("Error sending ATT PDU (0x%02X): %s (%d)", pdu[0],
+						strerror(errno), errno);
+}
+
 static int local_database_add(uint16_t handle, struct btd_attribute *attr)
 {
 	attr->handle = handle;
@@ -98,10 +105,85 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
 	return attr;
 }
 
+static void send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
+{
+	uint8_t pdu[ATT_DEFAULT_LE_MTU];
+	size_t plen;
+
+	plen = enc_error_resp(opcode, handle, ecode, pdu, sizeof(pdu));
+	write_pdu(sk, pdu, plen);
+}
+
+static bool channel_handler_cb(struct io *io, void *user_data)
+{
+	uint8_t ipdu[ATT_DEFAULT_LE_MTU];
+	ssize_t ilen;
+	int sk = io_get_fd(io);
+
+	ilen = read(sk, ipdu, sizeof(ipdu));
+	if (ilen < 0) {
+		int err = errno;
+		DBG("ATT channel read: %s(%d)", strerror(err), err);
+		return false;
+	}
+
+	switch (ipdu[0]) {
+	case ATT_OP_ERROR:
+		break;
+
+	/* Requests */
+	case ATT_OP_WRITE_CMD:
+	case ATT_OP_WRITE_REQ:
+	case ATT_OP_READ_REQ:
+	case ATT_OP_READ_BY_TYPE_REQ:
+	case ATT_OP_MTU_REQ:
+	case ATT_OP_FIND_INFO_REQ:
+	case ATT_OP_FIND_BY_TYPE_REQ:
+	case ATT_OP_READ_BLOB_REQ:
+	case ATT_OP_READ_MULTI_REQ:
+	case ATT_OP_PREP_WRITE_REQ:
+	case ATT_OP_EXEC_WRITE_REQ:
+	case ATT_OP_READ_BY_GROUP_REQ:
+	case ATT_OP_SIGNED_WRITE_CMD:
+		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
+		break;
+
+	/* Responses */
+	case ATT_OP_MTU_RESP:
+	case ATT_OP_FIND_INFO_RESP:
+	case ATT_OP_FIND_BY_TYPE_RESP:
+	case ATT_OP_READ_BY_TYPE_RESP:
+	case ATT_OP_READ_RESP:
+	case ATT_OP_READ_BLOB_RESP:
+	case ATT_OP_READ_MULTI_RESP:
+	case ATT_OP_READ_BY_GROUP_RESP:
+	case ATT_OP_WRITE_RESP:
+	case ATT_OP_PREP_WRITE_RESP:
+	case ATT_OP_EXEC_WRITE_RESP:
+	case ATT_OP_HANDLE_CNF:
+		break;
+
+	/* Notification & Indication */
+	case ATT_OP_HANDLE_NOTIFY:
+	case ATT_OP_HANDLE_IND:
+		break;
+	}
+
+	return true;
+}
+
+static void channel_watch_destroy(void *user_data)
+{
+	struct io *io = user_data;
+
+	io_destroy(io);
+}
+
 static bool unix_accept_cb(struct io *io, void *user_data)
 {
 	struct sockaddr_un uaddr;
 	socklen_t len = sizeof(uaddr);
+	struct io *nio;
 	int err, nsk, sk;
 
 	sk = io_get_fd(io);
@@ -110,12 +192,17 @@ static bool unix_accept_cb(struct io *io, void *user_data)
 	if (nsk < 0) {
 		err = errno;
 		error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
-		return TRUE;
+		return true;
 	}
 
 	DBG("ATT UNIX socket: %d", nsk);
+	nio = io_new(nsk);
+
+	io_set_close_on_destroy(nio, true);
+	io_set_read_handler(nio, channel_handler_cb, nio,
+						channel_watch_destroy);
 
-	return TRUE;
+	return true;
 }
 
 void gatt_init(void)
-- 
1.8.3.1


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

* [PATCH BlueZ v6 11/18] gatt: Add Discover All Primary Services
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (9 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 10/18] gatt: Register ATT command/event handler Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 12/18] test: Add external service GATT skeleton Claudio Takahasi
                           ` (8 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch adds ATT Read By Group request handling to the attribute
server. It is the primitive to implement Discover All Primary Services
procedure.
---
 src/gatt.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 1 deletion(-)

diff --git a/src/gatt.c b/src/gatt.c
index ec8f381..f00f52a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -114,6 +114,130 @@ static void send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
 	write_pdu(sk, pdu, plen);
 }
 
+static void read_by_group_resp(int sk, uint16_t start,
+					uint16_t end, bt_uuid_t *pattern)
+{
+	uint8_t opdu[ATT_DEFAULT_LE_MTU];
+	GList *list;
+	struct btd_attribute *last = NULL;
+	uint8_t *group_start, *group_end = NULL, *group_uuid;
+	unsigned int uuid_type = BT_UUID_UNSPEC;
+	size_t group_len = 0, plen = 0;
+
+	/*
+	 * Read By Group Type Response format:
+	 *    Attribute Opcode: 1 byte
+	 *    Length: 1 byte (size of each group)
+	 *    Group: start | end | <<UUID>>
+	 */
+
+	opdu[0] = ATT_OP_READ_BY_GROUP_RESP;
+	group_start = &opdu[2];
+	group_uuid = &opdu[6];
+
+	for (list = local_attribute_db; list;
+			last = list->data, list = g_list_next(list)) {
+		struct btd_attribute *attr = list->data;
+
+		if (attr->handle < start)
+			continue;
+
+		if (attr->handle > end)
+			break;
+
+		if (bt_uuid_cmp(&attr->type, pattern) != 0)
+			continue;
+
+		if (uuid_type != BT_UUID_UNSPEC &&
+						uuid_type != attr->type.type) {
+			/*
+			 * Groups should contain the same length: UUID16 and
+			 * UUID128 should be sent on different ATT PDUs
+			 */
+			break;
+		}
+
+		/*
+		 * MTU checking should not be shifted up, otherwise the
+		 * handle of last end group will not be set properly.
+		 */
+		if ((plen + group_len) >= ATT_DEFAULT_LE_MTU)
+			break;
+
+		/* Start Grouping handle */
+		att_put_u16(attr->handle, group_start);
+
+		/* Grouping <<UUID>>: Value is little endian */
+		memcpy(group_uuid, attr->value, attr->value_len);
+
+		if (last && group_end) {
+			att_put_u16(last->handle, group_end);
+			group_end += group_len;
+			plen += group_len;
+		}
+
+		/* Grouping initial settings: First grouping */
+		if (uuid_type == BT_UUID_UNSPEC) {
+			uuid_type = attr->type.type;
+
+			/* start(0xXXXX) | end(0xXXXX) | <<UUID>> */
+			group_len = 2 + 2 + bt_uuid_len(&attr->type);
+
+			/* 2: ATT Opcode and Length */
+			plen = 2 + group_len;
+
+			/* Size of each Attribute Data */
+			opdu[1] = group_len;
+
+			group_end = &opdu[4];
+		}
+
+		group_start += group_len;
+		group_uuid += group_len;
+	}
+
+	if (plen == 0) {
+		send_error(sk, ATT_OP_READ_BY_GROUP_REQ, start,
+						ATT_ECODE_ATTR_NOT_FOUND);
+		return;
+	}
+
+	if (group_end)
+		att_put_u16(last->handle, group_end);
+
+	write_pdu(sk, opdu, plen);
+}
+
+static void read_by_group(int sk, const uint8_t *ipdu, ssize_t ilen)
+{
+	uint16_t decoded, start, end;
+	bt_uuid_t pattern;
+
+	decoded = dec_read_by_grp_req(ipdu, ilen, &start, &end, &pattern);
+	if (decoded == 0) {
+		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_INVALID_PDU);
+		return;
+	}
+
+	if (start > end || start == 0x0000) {
+		send_error(sk, ipdu[0], start, ATT_ECODE_INVALID_HANDLE);
+		return;
+	}
+
+	 /*
+	  * Restricting Read By Group Type to <<Primary>>.
+	  * Removing the checking below requires changes to support
+	  * dynamic values(defined in the upper layer) and additional
+	  * security verification.
+	  */
+	if (bt_uuid_cmp(&pattern, &primary_uuid) != 0) {
+		send_error(sk, ipdu[0], start, ATT_ECODE_UNSUPP_GRP_TYPE);
+		return;
+	}
+
+	read_by_group_resp(sk, start, end, &pattern);
+}
+
 static bool channel_handler_cb(struct io *io, void *user_data)
 {
 	uint8_t ipdu[ATT_DEFAULT_LE_MTU];
@@ -143,11 +267,14 @@ static bool channel_handler_cb(struct io *io, void *user_data)
 	case ATT_OP_READ_MULTI_REQ:
 	case ATT_OP_PREP_WRITE_REQ:
 	case ATT_OP_EXEC_WRITE_REQ:
-	case ATT_OP_READ_BY_GROUP_REQ:
 	case ATT_OP_SIGNED_WRITE_CMD:
 		send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
 		break;
 
+	case ATT_OP_READ_BY_GROUP_REQ:
+		read_by_group(sk, ipdu, ilen);
+		break;
+
 	/* Responses */
 	case ATT_OP_MTU_RESP:
 	case ATT_OP_FIND_INFO_RESP:
-- 
1.8.3.1


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

* [PATCH BlueZ v6 12/18] test: Add external service GATT skeleton
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (10 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 13/18] gitignore: Add test/gatt-service Claudio Takahasi
                           ` (7 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial code for an external GATT service example.
It implements the API defined at doc/gatt-api.txt
---
 Makefile.tools      |   5 +++
 test/gatt-service.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 test/gatt-service.c

diff --git a/Makefile.tools b/Makefile.tools
index 9199222..a468272 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -374,3 +374,8 @@ test_scripts += test/sap_client.py test/bluezutils.py \
 		test/test-heartrate test/test-alert test/test-hfp \
 		test/test-cyclingspeed test/opp-client test/ftp-client \
 		test/pbap-client test/map-client
+
+noinst_PROGRAMS += test/gatt-service
+
+test_gatt_service_SOURCES = test/gatt-service.c
+test_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la
diff --git a/test/gatt-service.c b/test/gatt-service.c
new file mode 100644
index 0000000..769fd37
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,121 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+/* Immediate Alert Service UUID */
+#define IAS_UUID			"00001802-0000-1000-8000-00805f9b34fb"
+
+static GMainLoop *main_loop;
+static GSList *services;
+
+static gboolean service_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	const char *uuid = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+	return TRUE;
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	return TRUE;
+}
+
+static gboolean service_exist_includes(const GDBusPropertyTable *property,
+							void *user_data)
+{
+	return FALSE;
+}
+
+static const GDBusPropertyTable service_properties[] = {
+	{ "UUID", "s", service_get_uuid },
+	{ "Includes", "ao", service_get_includes, NULL,
+					service_exist_includes },
+	{ }
+};
+
+static char *register_service(DBusConnection *conn, const char *uuid)
+{
+	static int id = 1;
+	char *path;
+
+	path = g_strdup_printf("/service%d", id++);
+	if (g_dbus_register_interface(conn, path, SERVICE_IFACE,
+				NULL, NULL, service_properties,
+				g_strdup(uuid), g_free) == FALSE) {
+		printf("Couldn't register service interface\n");
+		g_free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+static void create_services(DBusConnection *conn)
+{
+	char *service_path;
+
+	service_path = register_service(conn, IAS_UUID);
+
+	services = g_slist_prepend(services, service_path);
+
+	printf("Registered service: %s\n", service_path);
+}
+
+int main(int argc, char *argv[])
+{
+	DBusConnection *dbus_conn;
+
+	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+
+	main_loop = g_main_loop_new(NULL, FALSE);
+
+	g_dbus_attach_object_manager(dbus_conn);
+
+	printf("gatt-service unique name: %s\n",
+				dbus_bus_get_unique_name(dbus_conn));
+
+	create_services(dbus_conn);
+
+	g_main_loop_run(main_loop);
+
+	g_slist_free_full(services, g_free);
+	dbus_connection_unref(dbus_conn);
+
+	return 0;
+}
-- 
1.8.3.1


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

* [PATCH BlueZ v6 13/18] gitignore: Add test/gatt-service
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (11 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 12/18] test: Add external service GATT skeleton Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 14/18] test: Add signal handling for gatt-service Claudio Takahasi
                           ` (6 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index b86deae..3f3c7d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ test/sap_client.pyc
 test/bluezutils.pyc
 unit/test-ringbuf
 unit/test-queue
+test/gatt-service
 unit/test-eir
 unit/test-uuid
 unit/test-crc
-- 
1.8.3.1


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

* [PATCH BlueZ v6 14/18] test: Add signal handling for gatt-service
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (12 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 13/18] gitignore: Add test/gatt-service Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 15/18] test: Add registering external service Claudio Takahasi
                           ` (5 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch implements signal handling to run cleanup tasks before
exiting.
---
 test/gatt-service.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 769fd37..4059336 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,6 +27,9 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/signalfd.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -97,9 +100,83 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	static bool __terminated = false;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	switch (si.ssi_signo) {
+	case SIGINT:
+	case SIGTERM:
+		if (!__terminated) {
+			printf("Terminating\n");
+			g_main_loop_quit(main_loop);
+		}
+
+		__terminated = true;
+		break;
+	}
+
+	return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int main(int argc, char *argv[])
 {
 	DBusConnection *dbus_conn;
+	guint signal;
+
+	signal = setup_signalfd();
+	if (signal == 0)
+		return -errno;
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
 
@@ -114,6 +191,8 @@ int main(int argc, char *argv[])
 
 	g_main_loop_run(main_loop);
 
+	g_source_remove(signal);
+
 	g_slist_free_full(services, g_free);
 	dbus_connection_unref(dbus_conn);
 
-- 
1.8.3.1


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

* [PATCH BlueZ v6 15/18] test: Add registering external service
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (13 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 14/18] test: Add signal handling for gatt-service Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 16/18] gatttool: Add unix socket connect Claudio Takahasi
                           ` (4 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch extends gatt-service to call RegisterService() when org.bluez
service gets connected to the system bus.
---
 test/gatt-service.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 4059336..b656ef3 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -35,6 +35,7 @@
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
 #define SERVICE_IFACE			"org.bluez.GattService1"
 
 /* Immediate Alert Service UUID */
@@ -100,6 +101,65 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static void register_external_service_reply(DBusPendingCall *call,
+							void *user_data)
+{
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	dbus_set_error_from_message(&derr, reply);
+
+	if (dbus_error_is_set(&derr))
+		printf("RegisterService: %s\n", derr.message);
+	else
+		printf("RegisterService: OK\n");
+
+	dbus_message_unref(reply);
+	dbus_error_free(&derr);
+}
+
+static void register_external_service(gpointer a, gpointer b)
+{
+	DBusConnection *conn = b;
+	const char *path = a;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	DBusMessageIter iter, dict;
+
+	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+					GATT_MGR_IFACE, "RegisterService");
+	if (msg == NULL) {
+		printf("Couldn't allocate D-Bus message\n");
+		return;
+	}
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	/* TODO: Add options dictionary */
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
+		dbus_message_unref(msg);
+		return;
+	}
+
+	dbus_pending_call_set_notify(call, register_external_service_reply,
+								NULL, NULL);
+
+	dbus_pending_call_unref(call);
+}
+
+static void connect_handler(DBusConnection *conn, void *user_data)
+{
+	g_slist_foreach(services, register_external_service, conn);
+}
+
 static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
 							gpointer user_data)
 {
@@ -171,6 +231,7 @@ static guint setup_signalfd(void)
 
 int main(int argc, char *argv[])
 {
+	GDBusClient *client;
 	DBusConnection *dbus_conn;
 	guint signal;
 
@@ -189,8 +250,14 @@ int main(int argc, char *argv[])
 
 	create_services(dbus_conn);
 
+	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+	g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+
 	g_main_loop_run(main_loop);
 
+	g_dbus_client_unref(client);
+
 	g_source_remove(signal);
 
 	g_slist_free_full(services, g_free);
-- 
1.8.3.1


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

* [PATCH BlueZ v6 16/18] gatttool: Add unix socket connect
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (14 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 15/18] test: Add registering external service Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
                           ` (3 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial support for GATT procedures over unix
socket transport on command line mode (one-shot command). Temporary
solution to allow local GATT procedures testing.
---
 attrib/gatttool.c | 27 ++++++++++++++++++++-------
 attrib/gatttool.h |  1 +
 attrib/utils.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 9f2ead9..cf106de 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <glib.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
@@ -53,6 +52,7 @@ static int opt_end = 0xffff;
 static int opt_handle = -1;
 static int opt_mtu = 0;
 static int opt_psm = 0;
+static gboolean opt_local = FALSE;
 static gboolean opt_primary = FALSE;
 static gboolean opt_characteristics = FALSE;
 static gboolean opt_char_read = FALSE;
@@ -511,6 +511,8 @@ static GOptionEntry options[] = {
 		"Specify local adapter interface", "hciX" },
 	{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
 		"Specify remote Bluetooth address", "MAC" },
+	{ "local", 'L', 0, G_OPTION_ARG_NONE, &opt_local,
+		"Use unix socket transport (local communication)", NULL },
 	{ "addr-type", 't', 0, G_OPTION_ARG_STRING, &opt_dst_type,
 		"Set LE address type. Default: public", "[public | random]"},
 	{ "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu,
@@ -563,6 +565,11 @@ int main(int argc, char *argv[])
 		g_clear_error(&gerr);
 	}
 
+	if (opt_local) {
+		opt_src = NULL;
+		opt_dst = NULL;
+	}
+
 	if (opt_interactive) {
 		interactive(opt_src, opt_dst, opt_dst_type, opt_psm);
 		goto done;
@@ -588,14 +595,20 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
-	if (opt_dst == NULL) {
-		g_print("Remote Bluetooth address required\n");
-		got_error = TRUE;
-		goto done;
+	if (opt_local)
+		chan = unix_connect(connect_cb, &gerr);
+	else {
+		if (opt_dst == NULL) {
+			g_print("Remote Bluetooth address required\n");
+			got_error = TRUE;
+			goto done;
+		}
+
+		chan = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
 	}
 
-	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
 		g_printerr("%s\n", gerr->message);
 		g_clear_error(&gerr);
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 8f0913c..be8e236 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -27,4 +27,5 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 			const char *dst_type, const char *sec_level,
 			int psm, int mtu, BtIOConnect connect_cb,
 			GError **gerr);
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/utils.c b/attrib/utils.c
index 17f02be..7d2966f 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -25,7 +25,12 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
 #include <glib.h>
 
 #include <bluetooth/bluetooth.h>
@@ -101,6 +106,55 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
 	return chan;
 }
 
+static gboolean unix_connect_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	BtIOConnect connect_cb = user_data;
+	GError *gerr;
+
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		gerr = g_error_new_literal(G_IO_CHANNEL_ERROR,
+						G_IO_CHANNEL_ERROR_FAILED,
+						"connection attempt failed");
+		connect_cb(io, gerr, user_data);
+		g_clear_error(&gerr);
+	} else {
+		connect_cb(io, NULL, user_data);
+	}
+
+	return FALSE;
+}
+
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr)
+{
+	GIOChannel *io;
+	struct sockaddr_un uaddr  = {
+		.sun_family	= AF_UNIX,
+		.sun_path	= "\0/bluetooth/unix_att",
+	};
+	int sk;
+
+	sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC , 0);
+	if (sk < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		return NULL;
+	}
+
+	if (connect(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+		g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+				G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+		close(sk);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+						unix_connect_cb, connect_cb);
+
+	return io;
+}
+
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data)
 {
 	char tmp[3];
-- 
1.8.3.1


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

* [PATCH BlueZ v6 17/18] gatttool: Add unix socket support for interactive mode
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (15 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 16/18] gatttool: Add unix socket connect Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-04 17:53         ` [PATCH BlueZ v6 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
                           ` (2 subsequent siblings)
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch allows running GATT operations over unix socket on
interactive mode.
---
 attrib/interactive.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 70c091c..67e060e 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -84,7 +84,7 @@ static char *get_prompt(void)
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
-		g_string_append_printf(prompt, "[%17s]", "");
+		g_string_append_printf(prompt, "[LOCAL]");
 
 	if (conn_state == STATE_CONNECTED)
 		g_string_append(prompt, COLOR_OFF);
@@ -405,15 +405,18 @@ static void cmd_connect(int argcp, char **argvp)
 			opt_dst_type = g_strdup("public");
 	}
 
-	if (opt_dst == NULL) {
-		error("Remote Bluetooth address required\n");
-		return;
+	if (opt_dst) {
+
+		rl_printf("Attempting to connect to %s\n", opt_dst);
+		set_state(STATE_CONNECTING);
+		iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type,
+					opt_sec_level, opt_psm, opt_mtu,
+					connect_cb, &gerr);
+	} else {
+		rl_printf("Local connection\n");
+		iochannel = unix_connect(connect_cb, &gerr);
 	}
 
-	rl_printf("Attempting to connect to %s\n", opt_dst);
-	set_state(STATE_CONNECTING);
-	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
 		set_state(STATE_DISCONNECTED);
 		error("%s\n", gerr->message);
-- 
1.8.3.1


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

* [PATCH BlueZ v6 18/18] bluetooth.conf: Add ObjectManager interface
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (16 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
@ 2014-02-04 17:53         ` Claudio Takahasi
  2014-02-18 13:41         ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
  2014-02-18 17:44         ` Marcel Holtmann
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-04 17:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 src/bluetooth.conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..ad8891a 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -18,6 +18,7 @@
     <allow send_interface="org.bluez.Profile1"/>
     <allow send_interface="org.bluez.HeartRateWatcher1"/>
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
+    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
   </policy>
 
   <policy at_console="true">
-- 
1.8.3.1


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

* Re: [PATCH BlueZ v6 00/18] GATT API: External Services
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (17 preceding siblings ...)
  2014-02-04 17:53         ` [PATCH BlueZ v6 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
@ 2014-02-18 13:41         ` Claudio Takahasi
  2014-02-18 17:44         ` Marcel Holtmann
  19 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-18 13:41 UTC (permalink / raw)
  To: BlueZ development, Johan Hedberg; +Cc: Claudio Takahasi

Hi Johan:

On Tue, Feb 4, 2014 at 2:53 PM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> This patchset implements the minimal support for adding local services
> declarations.
>
> Limitation: Remove services and multiple services exported by the same
> remote will be implemented the next series.
>
> Changes from PATCH v6 to PATCH v5:
> * Rebase
> * Fixed warning (gcc 4.6.3/32-bits): "ignoring return value of ‘write’"
>
> Changes from PATCH v4 to PATCH v5:
> * Removed Release() method of GattService1 interface
>
> Changes from PATCH v3 to PATCH v4:
> * Rebase
> * src/gatt.c: Replaced GIOChannel/GAttrib by "io".
>
> Changes from PATCH v2 to PATCH v3:
> * Rebase
> * Interfaces renamed: s/GattServiceManager1/GattManager1,
>   s/Characteristic1/GattCharacteristic1, s/Descriptor/GattDescriptor1
> * test/gatt-service.c: s/fprintf/printf
>
> Changes from PATCH v1 to PATCH v2:
> * Rebase
> * Included patch "doc: Add GATT API"
> * Interfaces renamed: s/Service1/GattService1, and
>   s/ServiceManager1/GattServiceManager1
> * Removed patch "gatt: Implement UnregisterService" from this patchset
>
> Changes from PATCH v0 to PATCH v1:
> * Rebase
>
> Changes from RFC v0 to PATCH v0:
> * Changed copyright year : s/2013/2014
> * Fixed coding style
> * Added gatt-service binary to gitignore
> * Added extra comment in the source code
>
> Features:
> * API for internal and external services declaration
> * Unix socket for testing purpose: services are exported through unix
>   sockets to avoid breaking the current attribute server.
>
> How to test:
>   Run bluetoothd with EXPERIMENTAL flag (-E)
>   Replace /etc/dbus-1/system.d/bluetooth.conf and reload DBus settings
>   $gatttool -L --primary (or interactive mode)
>
> Roughly upstreaming plan (steps):
>  * GATT Server: External Services -> pathset GATT API: External Services
>  * GATT Server: External Characteristics (Server)
>  * GATT Server: External Descriptors (Server)
>  * Replacement for GAttrib: use "io"
>  * Replace attribute server
>  * Remove ATTIO and automatic connection mechanism from userspace
>  * Fix all GATT internal plugins
>  * GATT Client: Remote Services
>
> Alvaro Silva (6):
>   gatt: Add stub for gatt.{c, h} files
>   gatt: Register Manager D-Bus Interface
>   gatt: Add registering external service
>   gatt: Add external services tracking
>   gatt: Register ATT command/event handler
>   gatt: Add Discover All Primary Services
>
> Andre Guedes (1):
>   gatt: Add helper for creating GATT services
>
> Claudio Takahasi (11):
>   doc: Add experimental GATT API
>   lib: Move GATT UUID to uuid.h
>   gatt: Add server unix socket
>   gattrib: Use default ATT LE MTU for non-standard sockets
>   test: Add external service GATT skeleton
>   gitignore: Add test/gatt-service
>   test: Add signal handling for gatt-service
>   test: Add registering external service
>   gatttool: Add unix socket connect
>   gatttool: Add unix socket support for interactive mode
>   bluetooth.conf: Add ObjectManager interface
>
>  .gitignore           |   1 +
>  Makefile.am          |   2 +
>  Makefile.tools       |   5 +
>  attrib/gatt.h        |  25 ----
>  attrib/gattrib.c     |  16 +--
>  attrib/gatttool.c    |  27 +++-
>  attrib/gatttool.h    |   1 +
>  attrib/interactive.c |  19 +--
>  attrib/utils.c       |  54 ++++++++
>  doc/gatt-api.txt     | 142 +++++++++++++++++++
>  lib/uuid.h           |  30 ++++
>  src/bluetooth.conf   |   1 +
>  src/gatt-dbus.c      | 271 ++++++++++++++++++++++++++++++++++++
>  src/gatt-dbus.h      |  25 ++++
>  src/gatt.c           | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/gatt.h           |  36 +++++
>  src/main.c           |   4 +
>  test/gatt-service.c  | 267 ++++++++++++++++++++++++++++++++++++
>  18 files changed, 1257 insertions(+), 48 deletions(-)
>  create mode 100644 doc/gatt-api.txt
>  create mode 100644 src/gatt-dbus.c
>  create mode 100644 src/gatt-dbus.h
>  create mode 100644 src/gatt.c
>  create mode 100644 src/gatt.h
>  create mode 100644 test/gatt-service.c
>
> --
> 1.8.3.1
>

ping...

Claudio.

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

* Re: [PATCH BlueZ v6 00/18] GATT API: External Services
  2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
                           ` (18 preceding siblings ...)
  2014-02-18 13:41         ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
@ 2014-02-18 17:44         ` Marcel Holtmann
  2014-02-18 18:08           ` Claudio Takahasi
  19 siblings, 1 reply; 123+ messages in thread
From: Marcel Holtmann @ 2014-02-18 17:44 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Claudio,

> This patchset implements the minimal support for adding local services
> declarations.
> 
> Limitation: Remove services and multiple services exported by the same
> remote will be implemented the next series.

what is the deal with this unix socket you are using for local access? I think we should remove that functionality and keep it simple in the beginning.

Regards

Marcel


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

* Re: [PATCH BlueZ v6 00/18] GATT API: External Services
  2014-02-18 17:44         ` Marcel Holtmann
@ 2014-02-18 18:08           ` Claudio Takahasi
  2014-02-18 18:17             ` Marcel Holtmann
  0 siblings, 1 reply; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-18 18:08 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Marcel,

On Tue, Feb 18, 2014 at 2:44 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Claudio,
>
>> This patchset implements the minimal support for adding local services
>> declarations.
>>
>> Limitation: Remove services and multiple services exported by the same
>> remote will be implemented the next series.
>
> what is the deal with this unix socket you are using for local access? I think we should remove that functionality and keep it simple in the beginning.
>
> Regards
>
> Marcel

Testing purpose only to avoid breaking the current attribute server.
The fact is, the current attribute server "architecture" is not
flexible enough to support external services properly.
The idea is to get rid of the "old" attribute server when we finish
the new implementation.

Lizardo has some patches allowing compatibility between the two
versions. We will send new patchsets to remove the unix socket, and
introduce this compatibility.

Regards,
Claudio

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

* Re: [PATCH BlueZ v6 00/18] GATT API: External Services
  2014-02-18 18:08           ` Claudio Takahasi
@ 2014-02-18 18:17             ` Marcel Holtmann
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
  0 siblings, 1 reply; 123+ messages in thread
From: Marcel Holtmann @ 2014-02-18 18:17 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Claudio,

>>> This patchset implements the minimal support for adding local services
>>> declarations.
>>> 
>>> Limitation: Remove services and multiple services exported by the same
>>> remote will be implemented the next series.
>> 
>> what is the deal with this unix socket you are using for local access? I think we should remove that functionality and keep it simple in the beginning.
> 
> Testing purpose only to avoid breaking the current attribute server.
> The fact is, the current attribute server "architecture" is not
> flexible enough to support external services properly.
> The idea is to get rid of the "old" attribute server when we finish
> the new implementation.
> 
> Lizardo has some patches allowing compatibility between the two
> versions. We will send new patchsets to remove the unix socket, and
> introduce this compatibility.

that sounds better. I rather not have an extra unix socket based API around. We are still having a heard time to get rid of the SDP unix socket.

Regards

Marcel


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

* [PATCH BlueZ v7 00/11] GATT API: External Services
  2014-02-18 18:17             ` Marcel Holtmann
@ 2014-02-19 18:51               ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 01/11] doc: Add experimental GATT API Claudio Takahasi
                                   ` (10 more replies)
  0 siblings, 11 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patchset implements the minimal support for adding local services
declarations.

Limitation: Remove services and multiple services exported by the same
remote will be implemented the next series. Created services are not
integrated in the attribute server. A new patchset will be sent later
allowing access the services through the LE, BR/EDR sockets.

Changes from PATCH v6 to v7:
* Rebase
* Remove testing interface (Unix socket)

Changes from PATCH v5 to v6:
* Rebase
* Fixed warning (gcc 4.6.3/32-bits): "ignoring return value of 'write'"

Changes from PATCH v4 to v5:
* Removed Release() method of GattService1 interface

Changes from PATCH v3 to v4:
* Rebase
* src/gatt.c: Replaced GIOChannel/GAttrib by "io".

Changes from PATCH v2 to v3:
* Rebase
* Interfaces renamed: s/GattServiceManager1/GattManager1,
  s/Characteristic1/GattCharacteristic1, s/Descriptor/GattDescriptor1
* test/gatt-service.c: s/fprintf/printf

Changes from PATCH v1 to v2:
* Rebase
* Included patch "doc: Add GATT API"
* Interfaces renamed: s/Service1/GattService1, and
  s/ServiceManager1/GattServiceManager1
* Removed patch "gatt: Implement UnregisterService" from this patchset

Changes from PATCH v0 to v1:
* Rebase

Changes from RFC v0 to PATCH v0:
* Changed copyright year : s/2013/2014
* Fixed coding style
* Added gatt-service binary to gitignore
* Added extra comment in the source code

Roughly upstreaming plan (steps):
 * GATT Server: External Services -> pathset GATT API: External Services
 * GATT Server: Export new database over BR/EDR and LE
 * GATT Server: External Characteristics (Server)
 * GATT Server: External Descriptors (Server)
 * Replacement for GAttrib: use "io"
 * Replace attribute server
 * Remove ATTIO and automatic connection mechanism from userspace
 * Fix all GATT internal plugins
 * GATT Client: Remote Services

Alvaro Silva (4):
  gatt: Add stub for gatt.{c, h} files
  gatt: Register Manager D-Bus Interface
  gatt: Add registering external service
  gatt: Add external services tracking

Andre Guedes (1):
  gatt: Add helper for creating GATT services

Claudio Takahasi (6):
  doc: Add experimental GATT API
  lib: Move GATT UUID to uuid.h
  test: Add external service GATT skeleton
  test: Add signal handling for gatt-service
  test: Add registering external service
  bluetooth.conf: Add ObjectManager interface

 .gitignore          |   1 +
 Makefile.am         |   2 +
 Makefile.tools      |   5 +
 attrib/gatt.h       |  25 -----
 doc/gatt-api.txt    | 142 +++++++++++++++++++++++++++
 lib/uuid.h          |  30 ++++++
 src/bluetooth.conf  |   1 +
 src/gatt-dbus.c     | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h     |  25 +++++
 src/gatt.c          | 106 ++++++++++++++++++++
 src/gatt.h          |  36 +++++++
 src/main.c          |  15 ++-
 test/gatt-service.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++
 13 files changed, 896 insertions(+), 30 deletions(-)
 create mode 100644 doc/gatt-api.txt
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h
 create mode 100644 test/gatt-service.c

-- 
1.8.3.1


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

* [PATCH BlueZ v7 01/11] doc: Add experimental GATT API
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 02/11] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
                                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch proposes an unified GATT API for local and remote services.
---
 doc/gatt-api.txt | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)
 create mode 100644 doc/gatt-api.txt

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
new file mode 100644
index 0000000..0f6b084
--- /dev/null
+++ b/doc/gatt-api.txt
@@ -0,0 +1,142 @@
+BlueZ D-Bus GATT API description
+********************************
+
+GATT local and remote services share the same high-level D-Bus API. Local
+refers to GATT based service exported by a BlueZ plugin or an external
+application. Remote refers to GATT services exported by the peer.
+
+BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and
+Properties (or the opposite). Support for D-Bus Object Manager is mandatory for
+external services to allow seamless GATT declarations (Service, Characteristic
+and Descriptors) discovery.
+
+Releasing a registered GATT service is not defined yet. Any API extension
+should avoid breaking the defined API, and if possible keep an unified GATT
+remote and local services representation.
+
+Service hierarchy
+=================
+
+GATT remote and local service representation. Object path for local services
+is freely definable.
+
+External applications implementing local services must register the services
+using GattManager1 registration method and must implement the methods and
+properties defined in GattService1 interface.
+
+Service		org.bluez
+Interface	org.bluez.GattService1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX
+
+Properties	string UUID [read-only]
+
+			128-bit service UUID.
+
+		array{object} Includes [read-only]: Not implemented
+
+			Array of object paths representing the included
+			services of this service.
+
+
+Characteristic hierarchy
+========================
+
+For local GATT defined services, the object paths need to follow the service
+path hierarchy and are freely definable.
+
+Service		org.bluez
+Interface	org.bluez.GattCharacteristic1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
+
+Properties	string UUID [read-only]
+
+			128-bit characteristic UUID.
+
+		object Service [read-only]
+
+			Object path of the GATT service the characteristc
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Value read from the remote Bluetooth device or from
+			the external application implementing GATT services.
+
+		array{string} Flags [read-only, optional]
+
+			Defines how the characteristic value can be used. See
+			Core spec page 1898, "Table 3.5: Characteristic
+			Properties bit field" and page 1900, "Table 3.8:
+			Characteristic Extended Properties bit field". Allowed
+			values: "broadcast", "read", "write-without-response",
+			"write", "notify", "indicate",
+			"authenticated-signed-writes", "reliable-write", and
+			"writable-auxiliaries".
+
+
+Characteristic Descriptors hierarchy
+====================================
+
+Local or remote GATT characteristic descriptors hierarchy.
+
+Service		org.bluez
+Interface	org.bluez.GattDescriptor1 [Experimental]
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
+
+Properties	string UUID [read-only]
+
+			128-bit descriptor UUID.
+
+		object Characteristic [read-only]
+
+			Object path of the GATT characteristc the descriptor
+			belongs to.
+
+		array{byte} Value [read-write]
+
+			Raw characteristic descriptor value read from the
+			remote Bluetooth device or from the external
+			application implementing GATT services.
+
+		string Permissions [read-only]: To be defined
+
+			Defines read/write authentication and authorization
+			requirements.
+
+Service Manager hierarchy
+=============================
+
+Service Manager allows external applications to register GATT based
+services. Services must follow the API for Service and Characteristic
+described above.
+
+Local GATT services, characteristics and characteristic descriptors are
+discovered automatically using the D-Bus Object Manager interface.
+
+Service		org.bluez
+Interface	org.bluez.GattManager1 [Experimental]
+Object path	/org/bluez
+
+Methods		RegisterService(object service, dict options)
+
+			Registers remote application service exported under
+			interface GattService1. Characteristic objects must
+			be hierarchical to their service and must use the
+			interface GattCharacteristic1. D-Bus Object Manager
+			is used to fetch the exported objects.
+
+			"service" object path together with the D-Bus system
+			bus connection ID define the identification of the
+			application registering a GATT based service.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		UnregisterService(object service)
+
+			This unregisters the service that has been
+			previously registered. The object path parameter
+			must match the same value that has been used
+			on registration.
+
+			Possible errors: org.bluez.Error.DoesNotExist
-- 
1.8.3.1


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

* [PATCH BlueZ v7 02/11] gatt: Add stub for gatt.{c, h} files
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 01/11] doc: Add experimental GATT API Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 03/11] gatt: Register Manager D-Bus Interface Claudio Takahasi
                                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

These files implement functions to handle ATT transactions, and expose
functions to allow other entities to manage GATT based services. It
is a replacement for src/attrib-server.c.
---
 Makefile.am |  1 +
 src/gatt.c  | 38 ++++++++++++++++++++++++++++++++++++++
 src/gatt.h  | 26 ++++++++++++++++++++++++++
 src/main.c  | 15 ++++++++++-----
 4 files changed, 75 insertions(+), 5 deletions(-)
 create mode 100644 src/gatt.c
 create mode 100644 src/gatt.h

diff --git a/Makefile.am b/Makefile.am
index 11f2aa1..6bbf63b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
 			src/eir.h src/eir.c \
diff --git a/src/gatt.c b/src/gatt.c
new file mode 100644
index 0000000..06619f0
--- /dev/null
+++ b/src/gatt.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 "gatt.h"
+
+void gatt_init(void)
+{
+
+}
+
+void gatt_cleanup(void)
+{
+
+}
diff --git a/src/gatt.h b/src/gatt.h
new file mode 100644
index 0000000..3a320b4
--- /dev/null
+++ b/src/gatt.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 gatt_init(void);
+
+void gatt_cleanup(void);
diff --git a/src/main.c b/src/main.c
index 91d90b4..b3136fc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,6 +55,7 @@
 #include "dbus-common.h"
 #include "agent.h"
 #include "profile.h"
+#include "gatt.h"
 #include "systemd.h"
 
 #define BLUEZ_NAME "org.bluez"
@@ -531,6 +532,13 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
+	if (option_experimental)
+		gdbus_flags = G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
+
+	g_dbus_set_flags(gdbus_flags);
+
+	gatt_init();
+
 	if (adapter_init() < 0) {
 		error("Adapter handling initialization failed");
 		exit(1);
@@ -540,11 +548,6 @@ int main(int argc, char *argv[])
 	btd_agent_init();
 	btd_profile_init();
 
-	if (option_experimental)
-		gdbus_flags = G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
-
-	g_dbus_set_flags(gdbus_flags);
-
 	if (option_compat == TRUE)
 		sdp_flags |= SDP_SERVER_COMPAT;
 
@@ -598,6 +601,8 @@ int main(int argc, char *argv[])
 
 	adapter_cleanup();
 
+	gatt_cleanup();
+
 	rfkill_exit();
 
 	stop_sdp_server();
-- 
1.8.3.1


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

* [PATCH BlueZ v7 03/11] gatt: Register Manager D-Bus Interface
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 01/11] doc: Add experimental GATT API Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 02/11] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 04/11] gatt: Add registering external service Claudio Takahasi
                                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch registers GATT Service Manager D-Bus Interface. This
interface implements the methods to allow external application register
and unregister GATT Services.
---
 Makefile.am     |  1 +
 src/gatt-dbus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt-dbus.h | 25 +++++++++++++++++++
 src/gatt.c      |  9 +++++++
 4 files changed, 110 insertions(+)
 create mode 100644 src/gatt-dbus.c
 create mode 100644 src/gatt-dbus.h

diff --git a/Makefile.am b/Makefile.am
index 6bbf63b..2862bc4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/profile.h src/profile.c \
 			src/service.h src/service.c \
+			src/gatt-dbus.h src/gatt-dbus.c \
 			src/gatt.h src/gatt.c \
 			src/device.h src/device.c src/attio.h \
 			src/dbus-common.c src/dbus-common.h \
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
new file mode 100644
index 0000000..183c611
--- /dev/null
+++ b/src/gatt-dbus.c
@@ -0,0 +1,75 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include "dbus-common.h"
+#include "log.h"
+
+#include "gatt-dbus.h"
+
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
+
+static DBusMessage *register_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable methods[] = {
+	{ GDBUS_EXPERIMENTAL_METHOD("RegisterService",
+				GDBUS_ARGS({ "service", "o"},
+						{ "options", "a{sv}"}),
+				NULL, register_service) },
+	{ GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
+				GDBUS_ARGS({"service", "o"}),
+				NULL, unregister_service) },
+	{ }
+};
+
+gboolean gatt_dbus_manager_register(void)
+{
+	return g_dbus_register_interface(btd_get_dbus_connection(),
+					"/org/bluez", GATT_MGR_IFACE,
+					methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+							GATT_MGR_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
new file mode 100644
index 0000000..310cfa9
--- /dev/null
+++ b/src/gatt-dbus.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *
+ */
+
+gboolean gatt_dbus_manager_register(void);
+void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 06619f0..e8b691a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,14 +25,23 @@
 #include <config.h>
 #endif
 
+#include <glib.h>
+
+#include "log.h"
+
+#include "gatt-dbus.h"
 #include "gatt.h"
 
 void gatt_init(void)
 {
+	DBG("Starting GATT server");
 
+	gatt_dbus_manager_register();
 }
 
 void gatt_cleanup(void)
 {
+	DBG("Stopping GATT server");
 
+	gatt_dbus_manager_unregister();
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v7 04/11] gatt: Add registering external service
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (2 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 03/11] gatt: Register Manager D-Bus Interface Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 05/11] lib: Move GATT UUID to uuid.h Claudio Takahasi
                                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

This patch allows external applications register a given service on
Bluez. Applications must provide an object path and a dictionary of
options. Options dictionary will be used later to provide additional
service information.
---
 src/gatt-dbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 183c611..fd614f9 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -26,22 +26,109 @@
 #endif
 
 #include <stdint.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#include "adapter.h"
+#include "device.h"
+#include "lib/uuid.h"
 #include "dbus-common.h"
 #include "log.h"
 
+#include "error.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
 
+struct external_app {
+	char *owner;
+	char *path;
+	GDBusClient *client;
+	unsigned int watch;
+};
+
+static GSList *external_apps;
+
+static int external_app_path_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct external_app *eapp = a;
+	const char *path = b;
+
+	return g_strcmp0(eapp->path, path);
+}
+
+static void external_app_watch_destroy(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+
+	/* TODO: Remove from the database */
+
+	external_apps = g_slist_remove(external_apps, eapp);
+
+	g_dbus_client_unref(eapp->client);
+
+	g_free(eapp->owner);
+	g_free(eapp->path);
+	g_free(eapp);
+}
+
+static struct external_app *new_external_app(DBusConnection *conn,
+					const char *sender, const char *path)
+{
+	struct external_app *eapp;
+	GDBusClient *client;
+
+	client = g_dbus_client_new(conn, sender, "/");
+	if (client == NULL)
+		return NULL;
+
+	eapp = g_new0(struct external_app, 1);
+
+	eapp->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
+			sender, NULL, eapp, external_app_watch_destroy);
+	if (eapp->watch == 0) {
+		g_dbus_client_unref(client);
+		g_free(eapp);
+		return NULL;
+	}
+
+	eapp->owner = g_strdup(sender);
+	eapp->client = client;
+	eapp->path = g_strdup(path);
+
+	return eapp;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
-	return dbus_message_new_method_return(msg);
+	struct external_app *eapp;
+	DBusMessageIter iter;
+	const char *path;
+
+	if (!dbus_message_iter_init(msg, &iter))
+		return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &path);
+
+	if (g_slist_find_custom(external_apps, path, external_app_path_cmp))
+		return btd_error_already_exists(msg);
+
+	eapp = new_external_app(conn, dbus_message_get_sender(msg), path);
+	if (eapp == NULL)
+		return btd_error_failed(msg, "Not enough resources");
+
+	external_apps = g_slist_prepend(external_apps, eapp);
+
+	DBG("New app %p: %s", eapp, path);
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
 static DBusMessage *unregister_service(DBusConnection *conn,
-- 
1.8.3.1


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

* [PATCH BlueZ v7 05/11] lib: Move GATT UUID to uuid.h
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (3 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 04/11] gatt: Add registering external service Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 06/11] gatt: Add helper for creating GATT services Claudio Takahasi
                                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch moves GATT UUIDs definitions to a common header. uuid.h contains
helper functions to manipulate Bluetooth UUIDs and some common BR/EDR services
UUIDs.
---
 attrib/gatt.h | 25 -------------------------
 lib/uuid.h    | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0f113e7..4fea3eb 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,31 +24,6 @@
 
 #include <bluetooth/sdp.h>
 
-/* GATT Profile Attribute types */
-#define GATT_PRIM_SVC_UUID		0x2800
-#define GATT_SND_SVC_UUID		0x2801
-#define GATT_INCLUDE_UUID		0x2802
-#define GATT_CHARAC_UUID		0x2803
-
-/* GATT Characteristic Types */
-#define GATT_CHARAC_DEVICE_NAME			0x2A00
-#define GATT_CHARAC_APPEARANCE			0x2A01
-#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG	0x2A02
-#define GATT_CHARAC_RECONNECTION_ADDRESS	0x2A03
-#define GATT_CHARAC_PERIPHERAL_PREF_CONN	0x2A04
-#define GATT_CHARAC_SERVICE_CHANGED		0x2A05
-
-/* GATT Characteristic Descriptors */
-#define GATT_CHARAC_EXT_PROPER_UUID	0x2900
-#define GATT_CHARAC_USER_DESC_UUID	0x2901
-#define GATT_CLIENT_CHARAC_CFG_UUID	0x2902
-#define GATT_SERVER_CHARAC_CFG_UUID	0x2903
-#define GATT_CHARAC_FMT_UUID		0x2904
-#define GATT_CHARAC_AGREG_FMT_UUID	0x2905
-#define GATT_CHARAC_VALID_RANGE_UUID	0x2906
-#define GATT_EXTERNAL_REPORT_REFERENCE	0x2907
-#define GATT_REPORT_REFERENCE		0x2908
-
 /* Client Characteristic Configuration bit field */
 #define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT	0x0001
 #define GATT_CLIENT_CHARAC_CFG_IND_BIT		0x0002
diff --git a/lib/uuid.h b/lib/uuid.h
index 95e5a9a..c24cee5 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -105,6 +105,31 @@ extern "C" {
 #define OBEX_MNS_UUID		"00001133-0000-1000-8000-00805f9b34fb"
 #define OBEX_MAP_UUID		"00001134-0000-1000-8000-00805f9b34fb"
 
+/* GATT UUIDs section */
+#define GATT_PRIM_SVC_UUID				0x2800
+#define GATT_SND_SVC_UUID				0x2801
+#define GATT_INCLUDE_UUID				0x2802
+#define GATT_CHARAC_UUID				0x2803
+
+/* GATT Characteristic Types */
+#define GATT_CHARAC_DEVICE_NAME				0x2A00
+#define GATT_CHARAC_APPEARANCE				0x2A01
+#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG		0x2A02
+#define GATT_CHARAC_RECONNECTION_ADDRESS		0x2A03
+#define GATT_CHARAC_PERIPHERAL_PREF_CONN		0x2A04
+#define GATT_CHARAC_SERVICE_CHANGED			0x2A05
+
+/* GATT Characteristic Descriptors */
+#define GATT_CHARAC_EXT_PROPER_UUID			0x2900
+#define GATT_CHARAC_USER_DESC_UUID			0x2901
+#define GATT_CLIENT_CHARAC_CFG_UUID			0x2902
+#define GATT_SERVER_CHARAC_CFG_UUID			0x2903
+#define GATT_CHARAC_FMT_UUID				0x2904
+#define GATT_CHARAC_AGREG_FMT_UUID			0x2905
+#define GATT_CHARAC_VALID_RANGE_UUID			0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE			0x2907
+#define GATT_REPORT_REFERENCE				0x2908
+
 typedef struct {
 	enum {
 		BT_UUID_UNSPEC = 0,
-- 
1.8.3.1


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

* [PATCH BlueZ v7 06/11] gatt: Add helper for creating GATT services
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (4 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 05/11] lib: Move GATT UUID to uuid.h Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 07/11] gatt: Add external services tracking Claudio Takahasi
                                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes

From: Andre Guedes <andre.guedes@openbossa.org>

This patch adds the btd_gatt_add_service() helper which adds a
GATT Service declaration to the local attribute database.
---
 lib/uuid.h |  5 +++++
 src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatt.h | 10 ++++++++++
 3 files changed, 74 insertions(+)

diff --git a/lib/uuid.h b/lib/uuid.h
index c24cee5..237145b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -158,6 +158,11 @@ void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
 int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
 int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
 
+static inline int bt_uuid_len(const bt_uuid_t *uuid)
+{
+	return uuid->type / 8;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gatt.c b/src/gatt.c
index e8b691a..f7b74d6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -28,10 +28,69 @@
 #include <glib.h>
 
 #include "log.h"
+#include "lib/uuid.h"
+#include "attrib/att.h"
 
 #include "gatt-dbus.h"
 #include "gatt.h"
 
+/* Common GATT UUIDs */
+static const bt_uuid_t primary_uuid  = { .type = BT_UUID16,
+					.value.u16 = GATT_PRIM_SVC_UUID };
+
+struct btd_attribute {
+	uint16_t handle;
+	bt_uuid_t type;
+	uint16_t value_len;
+	uint8_t value[0];
+};
+
+static GList *local_attribute_db;
+static uint16_t next_handle = 0x0001;
+
+static int local_database_add(uint16_t handle, struct btd_attribute *attr)
+{
+	attr->handle = handle;
+
+	local_attribute_db = g_list_append(local_attribute_db, attr);
+
+	return 0;
+}
+
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
+{
+	uint16_t len = bt_uuid_len(uuid);
+	struct btd_attribute *attr = g_malloc0(sizeof(struct btd_attribute) +
+									len);
+
+	/*
+	 * Service DECLARATION
+	 *
+	 *   TYPE         ATTRIBUTE VALUE
+	 * +-------+---------------------------------+
+	 * |0x2800 | 0xYYYY...                       |
+	 * | (1)   | (2)                             |
+	 * +------+----------------------------------+
+	 * (1) - 2 octets: Primary/Secondary Service UUID
+	 * (2) - 2 or 16 octets: Service UUID
+	 */
+
+	attr->type = primary_uuid;
+
+	att_put_uuid(*uuid, attr->value);
+	attr->value_len = len;
+
+	if (local_database_add(next_handle, attr) < 0) {
+		g_free(attr);
+		return NULL;
+	}
+
+	/* TODO: missing overflow checking */
+	next_handle = next_handle + 1;
+
+	return attr;
+}
+
 void gatt_init(void)
 {
 	DBG("Starting GATT server");
diff --git a/src/gatt.h b/src/gatt.h
index 3a320b4..8dd1312 100644
--- a/src/gatt.h
+++ b/src/gatt.h
@@ -21,6 +21,16 @@
  *
  */
 
+struct btd_attribute;
+
 void gatt_init(void);
 
 void gatt_cleanup(void);
+
+/* btd_gatt_add_service - Add a service declaration to local attribute database.
+ * @uuid:	Service UUID.
+ *
+ * Returns a reference to service declaration attribute. In case of error,
+ * NULL is returned.
+ */
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
-- 
1.8.3.1


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

* [PATCH BlueZ v7 07/11] gatt: Add external services tracking
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (5 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 06/11] gatt: Add helper for creating GATT services Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-24  8:33                   ` Johan Hedberg
  2014-02-19 18:51                 ` [PATCH BlueZ v7 08/11] test: Add external service GATT skeleton Claudio Takahasi
                                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva

From: Alvaro Silva <alvaro.silva@openbossa.org>

All primary services declarations provided by an external application
will be automatically inserted in the attribute database.
---
 src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index fd614f9..000d7ae 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -39,15 +39,21 @@
 #include "log.h"
 
 #include "error.h"
+#include "gatt.h"
 #include "gatt-dbus.h"
 
 #define GATT_MGR_IFACE			"org.bluez.GattManager1"
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+#define REGISTER_TIMER         1
 
 struct external_app {
 	char *owner;
 	char *path;
 	GDBusClient *client;
+	GSList *proxies;
 	unsigned int watch;
+	guint register_timer;
 };
 
 static GSList *external_apps;
@@ -60,6 +66,36 @@ static int external_app_path_cmp(gconstpointer a, gconstpointer b)
 	return g_strcmp0(eapp->path, path);
 }
 
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	if (g_strcmp0(interface, SERVICE_IFACE) != 0)
+		return;
+
+	eapp->proxies = g_slist_append(eapp->proxies, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+	struct external_app *eapp = user_data;
+	const char *interface, *path;
+
+	interface = g_dbus_proxy_get_interface(proxy);
+	path = g_dbus_proxy_get_path(proxy);
+
+	DBG("path %s iface %s", path, interface);
+
+	eapp->proxies = g_slist_remove(eapp->proxies, proxy);
+}
+
+
 static void external_app_watch_destroy(gpointer user_data)
 {
 	struct external_app *eapp = user_data;
@@ -70,6 +106,9 @@ static void external_app_watch_destroy(gpointer user_data)
 
 	g_dbus_client_unref(eapp->client);
 
+	if (eapp->register_timer)
+		g_source_remove(eapp->register_timer);
+
 	g_free(eapp->owner);
 	g_free(eapp->path);
 	g_free(eapp);
@@ -99,9 +138,75 @@ static struct external_app *new_external_app(DBusConnection *conn,
 	eapp->client = client;
 	eapp->path = g_strdup(path);
 
+	g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+								NULL, eapp);
+
 	return eapp;
 }
 
+static int register_external_service(GDBusProxy *proxy)
+{
+	DBusMessageIter iter;
+	const char *uuid;
+	bt_uuid_t btuuid;
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return -EINVAL;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return -EINVAL;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	if (bt_string_to_uuid(&btuuid, uuid) < 0)
+		return -EINVAL;
+
+	if (btd_gatt_add_service(&btuuid) == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static gboolean finish_register(gpointer user_data)
+{
+	struct external_app *eapp = user_data;
+	GSList *list;
+
+	/*
+	 * It is not possible to detect when the last proxy object
+	 * was reported. "Proxy added" handler reports objects
+	 * added on demand or returned by GetManagedObjects().
+	 * This timer helps to register all the GATT declarations
+	 * (services, characteristics and descriptors) after fetching
+	 * all the D-Bus objects.
+	 */
+
+	eapp->register_timer = 0;
+
+	for (list = eapp->proxies; list; list = g_slist_next(list)) {
+		const char *interface, *path;
+		GDBusProxy *proxy = list->data;
+
+		interface = g_dbus_proxy_get_interface(proxy);
+		path = g_dbus_proxy_get_path(proxy);
+
+		if (g_strcmp0(SERVICE_IFACE, interface) != 0)
+			continue;
+
+		if (g_strcmp0(path, eapp->path) != 0)
+			continue;
+
+		if (register_external_service(proxy) < 0) {
+			DBG("Inconsistent external service: %s", path);
+			continue;
+		}
+
+		DBG("External service: %s", path);
+	}
+
+	return FALSE;
+}
+
 static DBusMessage *register_service(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -109,6 +214,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	DBusMessageIter iter;
 	const char *path;
 
+	DBG("Registering GATT Service");
+
 	if (!dbus_message_iter_init(msg, &iter))
 		return btd_error_invalid_args(msg);
 
@@ -127,6 +234,8 @@ static DBusMessage *register_service(DBusConnection *conn,
 	external_apps = g_slist_prepend(external_apps, eapp);
 
 	DBG("New app %p: %s", eapp, path);
+	eapp->register_timer = g_timeout_add_seconds(REGISTER_TIMER,
+							finish_register, eapp);
 
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
-- 
1.8.3.1


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

* [PATCH BlueZ v7 08/11] test: Add external service GATT skeleton
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (6 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 07/11] gatt: Add external services tracking Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 09/11] test: Add signal handling for gatt-service Claudio Takahasi
                                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch adds the initial code for an external GATT service example.
It implements the API defined at doc/gatt-api.txt
---
 .gitignore          |   1 +
 Makefile.tools      |   5 +++
 test/gatt-service.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 127 insertions(+)
 create mode 100644 test/gatt-service.c

diff --git a/.gitignore b/.gitignore
index b86deae..3f3c7d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ test/sap_client.pyc
 test/bluezutils.pyc
 unit/test-ringbuf
 unit/test-queue
+test/gatt-service
 unit/test-eir
 unit/test-uuid
 unit/test-crc
diff --git a/Makefile.tools b/Makefile.tools
index 012dd70..92f31a2 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -378,3 +378,8 @@ test_scripts += test/sap_client.py test/bluezutils.py \
 		test/test-heartrate test/test-alert test/test-hfp \
 		test/test-cyclingspeed test/opp-client test/ftp-client \
 		test/pbap-client test/map-client
+
+noinst_PROGRAMS += test/gatt-service
+
+test_gatt_service_SOURCES = test/gatt-service.c
+test_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la
diff --git a/test/gatt-service.c b/test/gatt-service.c
new file mode 100644
index 0000000..769fd37
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,121 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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 <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#define SERVICE_IFACE			"org.bluez.GattService1"
+
+/* Immediate Alert Service UUID */
+#define IAS_UUID			"00001802-0000-1000-8000-00805f9b34fb"
+
+static GMainLoop *main_loop;
+static GSList *services;
+
+static gboolean service_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	const char *uuid = user_data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+	return TRUE;
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	return TRUE;
+}
+
+static gboolean service_exist_includes(const GDBusPropertyTable *property,
+							void *user_data)
+{
+	return FALSE;
+}
+
+static const GDBusPropertyTable service_properties[] = {
+	{ "UUID", "s", service_get_uuid },
+	{ "Includes", "ao", service_get_includes, NULL,
+					service_exist_includes },
+	{ }
+};
+
+static char *register_service(DBusConnection *conn, const char *uuid)
+{
+	static int id = 1;
+	char *path;
+
+	path = g_strdup_printf("/service%d", id++);
+	if (g_dbus_register_interface(conn, path, SERVICE_IFACE,
+				NULL, NULL, service_properties,
+				g_strdup(uuid), g_free) == FALSE) {
+		printf("Couldn't register service interface\n");
+		g_free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+static void create_services(DBusConnection *conn)
+{
+	char *service_path;
+
+	service_path = register_service(conn, IAS_UUID);
+
+	services = g_slist_prepend(services, service_path);
+
+	printf("Registered service: %s\n", service_path);
+}
+
+int main(int argc, char *argv[])
+{
+	DBusConnection *dbus_conn;
+
+	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+
+	main_loop = g_main_loop_new(NULL, FALSE);
+
+	g_dbus_attach_object_manager(dbus_conn);
+
+	printf("gatt-service unique name: %s\n",
+				dbus_bus_get_unique_name(dbus_conn));
+
+	create_services(dbus_conn);
+
+	g_main_loop_run(main_loop);
+
+	g_slist_free_full(services, g_free);
+	dbus_connection_unref(dbus_conn);
+
+	return 0;
+}
-- 
1.8.3.1


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

* [PATCH BlueZ v7 09/11] test: Add signal handling for gatt-service
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (7 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 08/11] test: Add external service GATT skeleton Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 10/11] test: Add registering external service Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 11/11] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch implements signal handling to run cleanup tasks before
exiting.
---
 test/gatt-service.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 769fd37..4059336 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,6 +27,9 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/signalfd.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -97,9 +100,83 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	static bool __terminated = false;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	switch (si.ssi_signo) {
+	case SIGINT:
+	case SIGTERM:
+		if (!__terminated) {
+			printf("Terminating\n");
+			g_main_loop_quit(main_loop);
+		}
+
+		__terminated = true;
+		break;
+	}
+
+	return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int main(int argc, char *argv[])
 {
 	DBusConnection *dbus_conn;
+	guint signal;
+
+	signal = setup_signalfd();
+	if (signal == 0)
+		return -errno;
 
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
 
@@ -114,6 +191,8 @@ int main(int argc, char *argv[])
 
 	g_main_loop_run(main_loop);
 
+	g_source_remove(signal);
+
 	g_slist_free_full(services, g_free);
 	dbus_connection_unref(dbus_conn);
 
-- 
1.8.3.1


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

* [PATCH BlueZ v7 10/11] test: Add registering external service
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (8 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 09/11] test: Add signal handling for gatt-service Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  2014-02-19 18:51                 ` [PATCH BlueZ v7 11/11] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

This patch extends gatt-service to call RegisterService() when org.bluez
service gets connected to the system bus.
---
 test/gatt-service.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/test/gatt-service.c b/test/gatt-service.c
index 4059336..b656ef3 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -35,6 +35,7 @@
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
 
+#define GATT_MGR_IFACE			"org.bluez.GattManager1"
 #define SERVICE_IFACE			"org.bluez.GattService1"
 
 /* Immediate Alert Service UUID */
@@ -100,6 +101,65 @@ static void create_services(DBusConnection *conn)
 	printf("Registered service: %s\n", service_path);
 }
 
+static void register_external_service_reply(DBusPendingCall *call,
+							void *user_data)
+{
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	dbus_set_error_from_message(&derr, reply);
+
+	if (dbus_error_is_set(&derr))
+		printf("RegisterService: %s\n", derr.message);
+	else
+		printf("RegisterService: OK\n");
+
+	dbus_message_unref(reply);
+	dbus_error_free(&derr);
+}
+
+static void register_external_service(gpointer a, gpointer b)
+{
+	DBusConnection *conn = b;
+	const char *path = a;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	DBusMessageIter iter, dict;
+
+	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+					GATT_MGR_IFACE, "RegisterService");
+	if (msg == NULL) {
+		printf("Couldn't allocate D-Bus message\n");
+		return;
+	}
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+	/* TODO: Add options dictionary */
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
+		dbus_message_unref(msg);
+		return;
+	}
+
+	dbus_pending_call_set_notify(call, register_external_service_reply,
+								NULL, NULL);
+
+	dbus_pending_call_unref(call);
+}
+
+static void connect_handler(DBusConnection *conn, void *user_data)
+{
+	g_slist_foreach(services, register_external_service, conn);
+}
+
 static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
 							gpointer user_data)
 {
@@ -171,6 +231,7 @@ static guint setup_signalfd(void)
 
 int main(int argc, char *argv[])
 {
+	GDBusClient *client;
 	DBusConnection *dbus_conn;
 	guint signal;
 
@@ -189,8 +250,14 @@ int main(int argc, char *argv[])
 
 	create_services(dbus_conn);
 
+	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+	g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+
 	g_main_loop_run(main_loop);
 
+	g_dbus_client_unref(client);
+
 	g_source_remove(signal);
 
 	g_slist_free_full(services, g_free);
-- 
1.8.3.1


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

* [PATCH BlueZ v7 11/11] bluetooth.conf: Add ObjectManager interface
  2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
                                   ` (9 preceding siblings ...)
  2014-02-19 18:51                 ` [PATCH BlueZ v7 10/11] test: Add registering external service Claudio Takahasi
@ 2014-02-19 18:51                 ` Claudio Takahasi
  10 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-19 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: claudio.takahasi

---
 src/bluetooth.conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..ad8891a 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -18,6 +18,7 @@
     <allow send_interface="org.bluez.Profile1"/>
     <allow send_interface="org.bluez.HeartRateWatcher1"/>
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
+    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
   </policy>
 
   <policy at_console="true">
-- 
1.8.3.1


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

* Re: [PATCH BlueZ v7 07/11] gatt: Add external services tracking
  2014-02-19 18:51                 ` [PATCH BlueZ v7 07/11] gatt: Add external services tracking Claudio Takahasi
@ 2014-02-24  8:33                   ` Johan Hedberg
  2014-02-24 12:49                     ` Anderson Lizardo
  0 siblings, 1 reply; 123+ messages in thread
From: Johan Hedberg @ 2014-02-24  8:33 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth, Alvaro Silva

Hi Claudio,

On Wed, Feb 19, 2014, Claudio Takahasi wrote:
> From: Alvaro Silva <alvaro.silva@openbossa.org>
> 
> All primary services declarations provided by an external application
> will be automatically inserted in the attribute database.
> ---
>  src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 109 insertions(+)

I've applied patches 1-6 but this one seems a bit strange.

> +static void proxy_added(GDBusProxy *proxy, void *user_data)
> +{
> +	struct external_app *eapp = user_data;
> +	const char *interface, *path;
> +
> +	interface = g_dbus_proxy_get_interface(proxy);
> +	path = g_dbus_proxy_get_path(proxy);
> +
> +	DBG("path %s iface %s", path, interface);
> +
> +	if (g_strcmp0(interface, SERVICE_IFACE) != 0)
> +		return;
> +
> +	eapp->proxies = g_slist_append(eapp->proxies, proxy);
> +}
> +
> +static void proxy_removed(GDBusProxy *proxy, void *user_data)
> +{
> +	struct external_app *eapp = user_data;
> +	const char *interface, *path;
> +
> +	interface = g_dbus_proxy_get_interface(proxy);
> +	path = g_dbus_proxy_get_path(proxy);
> +
> +	DBG("path %s iface %s", path, interface);
> +
> +	eapp->proxies = g_slist_remove(eapp->proxies, proxy);
> +}
> +
> +

Double empty line above - please fix (not related to my main issue with
this patch though)

> +static gboolean finish_register(gpointer user_data)
> +{
> +	struct external_app *eapp = user_data;
> +	GSList *list;
> +
> +	/*
> +	 * It is not possible to detect when the last proxy object
> +	 * was reported. "Proxy added" handler reports objects
> +	 * added on demand or returned by GetManagedObjects().
> +	 * This timer helps to register all the GATT declarations
> +	 * (services, characteristics and descriptors) after fetching
> +	 * all the D-Bus objects.
> +	 */
> +
> +	eapp->register_timer = 0;
> +
> +	for (list = eapp->proxies; list; list = g_slist_next(list)) {
> +		const char *interface, *path;
> +		GDBusProxy *proxy = list->data;
> +
> +		interface = g_dbus_proxy_get_interface(proxy);
> +		path = g_dbus_proxy_get_path(proxy);
> +
> +		if (g_strcmp0(SERVICE_IFACE, interface) != 0)
> +			continue;
> +
> +		if (g_strcmp0(path, eapp->path) != 0)
> +			continue;
> +
> +		if (register_external_service(proxy) < 0) {
> +			DBG("Inconsistent external service: %s", path);
> +			continue;
> +		}
> +
> +		DBG("External service: %s", path);
> +	}
> +
> +	return FALSE;
> +}

This whole timer thing seems too hackish to me.

A better way to fix this might be to have something like
g_dbus_client_set_proxies_complete_watch (or some better name) to let
the code wait until GetManagedObjects has returned and the initial
proxies added. Do you agree?

Johan

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

* Re: [PATCH BlueZ v7 07/11] gatt: Add external services tracking
  2014-02-24  8:33                   ` Johan Hedberg
@ 2014-02-24 12:49                     ` Anderson Lizardo
  2014-02-24 12:51                       ` Anderson Lizardo
  0 siblings, 1 reply; 123+ messages in thread
From: Anderson Lizardo @ 2014-02-24 12:49 UTC (permalink / raw)
  To: Claudio Takahasi, BlueZ development, Alvaro Silva

Hi Johan,

On Mon, Feb 24, 2014 at 4:33 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> This whole timer thing seems too hackish to me.
>
> A better way to fix this might be to have something like
> g_dbus_client_set_proxies_complete_watch (or some better name) to let
> the code wait until GetManagedObjects has returned and the initial
> proxies added. Do you agree?

We came up with this workaround during development, but we forgot to
highlight on the cover letter. Indeed a function like the one you
propose should be enough.

Regarding the name for the function, I was thinking as
"g_dbus_client_proxies_ready_watch()". What do you think?


BTW, thanks for looking into these patches and beginning to apply them.

Best Regards,
-- 
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil

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

* Re: [PATCH BlueZ v7 07/11] gatt: Add external services tracking
  2014-02-24 12:49                     ` Anderson Lizardo
@ 2014-02-24 12:51                       ` Anderson Lizardo
  2014-02-25  6:26                         ` Johan Hedberg
  0 siblings, 1 reply; 123+ messages in thread
From: Anderson Lizardo @ 2014-02-24 12:51 UTC (permalink / raw)
  To: Claudio Takahasi, BlueZ development, Alvaro Silva

Hi,

On Mon, Feb 24, 2014 at 8:49 AM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Hi Johan,
>
> On Mon, Feb 24, 2014 at 4:33 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> This whole timer thing seems too hackish to me.
>>
>> A better way to fix this might be to have something like
>> g_dbus_client_set_proxies_complete_watch (or some better name) to let
>> the code wait until GetManagedObjects has returned and the initial
>> proxies added. Do you agree?
>
> We came up with this workaround during development, but we forgot to
> highlight on the cover letter. Indeed a function like the one you
> propose should be enough.
>
> Regarding the name for the function, I was thinking as
> "g_dbus_client_proxies_ready_watch()". What do you think?

Or "g_dbus_client_set_proxies_ready_watch()" to be consistent.

-- 
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil

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

* Re: [PATCH BlueZ v7 07/11] gatt: Add external services tracking
  2014-02-24 12:51                       ` Anderson Lizardo
@ 2014-02-25  6:26                         ` Johan Hedberg
  2014-02-27 21:47                           ` Claudio Takahasi
  0 siblings, 1 reply; 123+ messages in thread
From: Johan Hedberg @ 2014-02-25  6:26 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: Claudio Takahasi, BlueZ development, Alvaro Silva

Hi Lizardo,

On Mon, Feb 24, 2014, Anderson Lizardo wrote:
> On Mon, Feb 24, 2014 at 8:49 AM, Anderson Lizardo
> <anderson.lizardo@openbossa.org> wrote:
> > Hi Johan,
> >
> > On Mon, Feb 24, 2014 at 4:33 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> >> This whole timer thing seems too hackish to me.
> >>
> >> A better way to fix this might be to have something like
> >> g_dbus_client_set_proxies_complete_watch (or some better name) to let
> >> the code wait until GetManagedObjects has returned and the initial
> >> proxies added. Do you agree?
> >
> > We came up with this workaround during development, but we forgot to
> > highlight on the cover letter. Indeed a function like the one you
> > propose should be enough.
> >
> > Regarding the name for the function, I was thinking as
> > "g_dbus_client_proxies_ready_watch()". What do you think?
> 
> Or "g_dbus_client_set_proxies_ready_watch()" to be consistent.

That sounds good enough to me.

Johan

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

* Re: [PATCH BlueZ v7 07/11] gatt: Add external services tracking
  2014-02-25  6:26                         ` Johan Hedberg
@ 2014-02-27 21:47                           ` Claudio Takahasi
  0 siblings, 0 replies; 123+ messages in thread
From: Claudio Takahasi @ 2014-02-27 21:47 UTC (permalink / raw)
  To: Anderson Lizardo, Johan Hedberg; +Cc: BlueZ development, Claudio Takahasi

Hi Johan/Lizardo:

On Tue, Feb 25, 2014 at 3:26 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Lizardo,
>
> On Mon, Feb 24, 2014, Anderson Lizardo wrote:
>> On Mon, Feb 24, 2014 at 8:49 AM, Anderson Lizardo
>> <anderson.lizardo@openbossa.org> wrote:
>> > Hi Johan,
>> >
>> > On Mon, Feb 24, 2014 at 4:33 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> >> This whole timer thing seems too hackish to me.
>> >>
>> >> A better way to fix this might be to have something like
>> >> g_dbus_client_set_proxies_complete_watch (or some better name) to let
>> >> the code wait until GetManagedObjects has returned and the initial
>> >> proxies added. Do you agree?
>> >
>> > We came up with this workaround during development, but we forgot to
>> > highlight on the cover letter. Indeed a function like the one you
>> > propose should be enough.
>> >
>> > Regarding the name for the function, I was thinking as
>> > "g_dbus_client_proxies_ready_watch()". What do you think?
>>
>> Or "g_dbus_client_set_proxies_ready_watch()" to be consistent.
>
> That sounds good enough to me.
>
> Johan

I spent some time investigating (and prototyping) alternatives to
avoid inserting a new gdbus helper, but all of them have drawbacks.

Even using DBus properties (without object manager) extending the
RegisterService() method to include an array of the object paths in
the options doesn't help. New proxies/properties are reported
individually through callbacks, consequently extra logic is required
in the "gdbus user" to detect when all objects are "received" and to
validate each object. Another issue of using property "watch" is to
manage when it first appeared and when it is property changed.
*Maybe* foreach helper plus the "ready" callback is another acceptable approach.

Keeping the object manager approach, what we need is way to figure out
if proxy_added is reporting the "last" proxy, otherwise timer is still
needed.
So, the proposed ready callback should be called after reporting the
last proxy. I will implement the suggested helper
(g_dbus_client_set_proxies_ready_watch) and see how far we go.

Regards,
Claudio.

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

end of thread, other threads:[~2014-02-27 21:47 UTC | newest]

Thread overview: 123+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-21 13:26 [PATCH BlueZ v2 00/18] GATT API: External Services Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 01/18] doc: Add GATT API Claudio Takahasi
2014-01-21 16:50   ` Marcel Holtmann
2014-01-21 19:40     ` Claudio Takahasi
2014-01-21 19:48       ` Johan Hedberg
2014-01-21 19:51         ` Marcel Holtmann
2014-01-21 13:26 ` [PATCH BlueZ v2 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 04/18] gatt: Add registering external service Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 07/18] gatt: Add external services tracking Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 08/18] gatt: Add server unix socket Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 10/18] gatt: Register ATT command/event handler Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 12/18] test: Add external service GATT skeleton Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 13/18] gitignore: Add test/gatt-service Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 14/18] test: Add signal handling for gatt-service Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 15/18] test: Add registering external service Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 16/18] gatttool: Add unix socket connect Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
2014-01-21 13:26 ` [PATCH BlueZ v2 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
2014-01-22 13:40 ` [PATCH BlueZ v3 00/18] GATT API: External Services Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 01/18] doc: Add GATT API Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 04/18] gatt: Add registering external service Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 07/18] gatt: Add external services tracking Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 08/18] gatt: Add server unix socket Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 10/18] gatt: Register ATT command/event handler Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 12/18] test: Add external service GATT skeleton Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 13/18] gitignore: Add test/gatt-service Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 14/18] test: Add signal handling for gatt-service Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 15/18] test: Add registering external service Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 16/18] gatttool: Add unix socket connect Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
2014-01-22 13:40   ` [PATCH BlueZ v3 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
2014-01-27 18:00   ` [PATCH BlueZ v4 00/18] GATT API: External Services Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 01/18] doc: Add GATT API Claudio Takahasi
2014-01-27 18:15       ` Marcel Holtmann
2014-01-27 18:54         ` Claudio Takahasi
2014-01-27 19:08           ` Marcel Holtmann
2014-01-27 18:00     ` [PATCH BlueZ v4 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 04/18] gatt: Add registering external service Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 07/18] gatt: Add external services tracking Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 08/18] gatt: Add server unix socket Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 10/18] gatt: Register ATT command/event handler Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 12/18] test: Add external service GATT skeleton Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 13/18] gitignore: Add test/gatt-service Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 14/18] test: Add signal handling for gatt-service Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 15/18] test: Add registering external service Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 16/18] gatttool: Add unix socket connect Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
2014-01-27 18:00     ` [PATCH BlueZ v4 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
2014-01-27 20:35     ` [PATCH BlueZ v5 00/18] GATT API: External Services Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 01/18] doc: Add experimental GATT API Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 04/18] gatt: Add registering external service Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 07/18] gatt: Add external services tracking Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 08/18] gatt: Add server unix socket Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 10/18] gatt: Register ATT command/event handler Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 12/18] test: Add external service GATT skeleton Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 13/18] gitignore: Add test/gatt-service Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 14/18] test: Add signal handling for gatt-service Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 15/18] test: Add registering external service Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 16/18] gatttool: Add unix socket connect Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
2014-01-27 20:35       ` [PATCH BlueZ v5 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
2014-02-04 17:53       ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 01/18] doc: Add experimental GATT API Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 02/18] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 03/18] gatt: Register Manager D-Bus Interface Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 04/18] gatt: Add registering external service Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 05/18] lib: Move GATT UUID to uuid.h Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 06/18] gatt: Add helper for creating GATT services Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 07/18] gatt: Add external services tracking Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 08/18] gatt: Add server unix socket Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 09/18] gattrib: Use default ATT LE MTU for non-standard sockets Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 10/18] gatt: Register ATT command/event handler Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 11/18] gatt: Add Discover All Primary Services Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 12/18] test: Add external service GATT skeleton Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 13/18] gitignore: Add test/gatt-service Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 14/18] test: Add signal handling for gatt-service Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 15/18] test: Add registering external service Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 16/18] gatttool: Add unix socket connect Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 17/18] gatttool: Add unix socket support for interactive mode Claudio Takahasi
2014-02-04 17:53         ` [PATCH BlueZ v6 18/18] bluetooth.conf: Add ObjectManager interface Claudio Takahasi
2014-02-18 13:41         ` [PATCH BlueZ v6 00/18] GATT API: External Services Claudio Takahasi
2014-02-18 17:44         ` Marcel Holtmann
2014-02-18 18:08           ` Claudio Takahasi
2014-02-18 18:17             ` Marcel Holtmann
2014-02-19 18:51               ` [PATCH BlueZ v7 00/11] " Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 01/11] doc: Add experimental GATT API Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 02/11] gatt: Add stub for gatt.{c, h} files Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 03/11] gatt: Register Manager D-Bus Interface Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 04/11] gatt: Add registering external service Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 05/11] lib: Move GATT UUID to uuid.h Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 06/11] gatt: Add helper for creating GATT services Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 07/11] gatt: Add external services tracking Claudio Takahasi
2014-02-24  8:33                   ` Johan Hedberg
2014-02-24 12:49                     ` Anderson Lizardo
2014-02-24 12:51                       ` Anderson Lizardo
2014-02-25  6:26                         ` Johan Hedberg
2014-02-27 21:47                           ` Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 08/11] test: Add external service GATT skeleton Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 09/11] test: Add signal handling for gatt-service Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 10/11] test: Add registering external service Claudio Takahasi
2014-02-19 18:51                 ` [PATCH BlueZ v7 11/11] bluetooth.conf: Add ObjectManager interface Claudio Takahasi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.