From: armansito@chromium.org
To: linux-bluetooth@vger.kernel.org
Cc: Arman Uguray <armansito@chromium.org>
Subject: [RFC BlueZ 1/2] gatt-dbus: Add remote GATT service objects.
Date: Tue, 11 Mar 2014 21:03:59 -0700 [thread overview]
Message-ID: <1394597040-4483-2-git-send-email-armansito@chromium.org> (raw)
In-Reply-To: <1394597040-4483-1-git-send-email-armansito@chromium.org>
From: Arman Uguray <armansito@chromium.org>
This CL adds the initial GATT client D-Bus API support for remote primary GATT
services. Characteristics, descriptors, and included services are not yet
handled.
---
src/device.c | 47 +++++++++++++++++++++++++++--
src/gatt-dbus.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
src/gatt-dbus.h | 25 ++++++++++++++++
3 files changed, 158 insertions(+), 6 deletions(-)
diff --git a/src/device.c b/src/device.c
index e624445..0623e4d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -65,6 +65,7 @@
#include "textfile.h"
#include "storage.h"
#include "attrib-server.h"
+#include "gatt.h"
#define IO_CAPABILITY_NOINPUTNOOUTPUT 0x03
@@ -186,6 +187,7 @@ struct btd_device {
GSList *uuids;
GSList *primaries; /* List of primary services */
GSList *services; /* List of btd_service */
+ GSList *gatt_services; /* List of GATT DBus Services */
GSList *pending; /* Pending services */
GSList *watches; /* List of disconnect_data */
gboolean temporary;
@@ -511,11 +513,18 @@ static void svc_dev_remove(gpointer user_data)
g_free(cb);
}
+static void gatt_dbus_service_free(gpointer user_data)
+{
+ struct btd_gatt_dbus_service *service = user_data;
+ btd_gatt_dbus_service_free(service);
+}
+
static void device_free(gpointer user_data)
{
struct btd_device *device = user_data;
g_slist_free_full(device->uuids, g_free);
+ g_slist_free_full(device->gatt_services, gatt_dbus_service_free);
g_slist_free_full(device->primaries, g_free);
g_slist_free_full(device->attios, g_free);
g_slist_free_full(device->attios_offline, g_free);
@@ -2287,6 +2296,7 @@ static struct btd_device *device_new(struct btd_adapter *adapter,
str2ba(address, &device->bdaddr);
device->adapter = adapter;
+ device->gatt_services = NULL;
return btd_device_ref(device);
}
@@ -3317,6 +3327,35 @@ done:
return FALSE;
}
+static void expose_btd_dbus_gatt_services(struct btd_device *device)
+{
+ GSList *l;
+
+ /* Clear current list of GATT services. */
+ g_slist_free_full(device->gatt_services, gatt_dbus_service_free);
+ device->gatt_services = NULL;
+ for (l = device->primaries; l; l = g_slist_next(l)) {
+ struct gatt_primary *prim = l->data;
+
+ /* Don't create objects for the GAP and GATT services. */
+ if (bt_uuid_strcmp(prim->uuid, GATT_UUID) == 0) {
+ DBG("Skipping GATT UUID for GATT service objects.");
+ continue;
+ }
+ if (bt_uuid_strcmp(prim->uuid, GAP_UUID) == 0) {
+ DBG("Skipping GAP UUID for GATT service objects.");
+ continue;
+ }
+
+ struct btd_gatt_dbus_service *service;
+ service = btd_gatt_dbus_service_create(device, prim);
+ if (service == NULL)
+ continue;
+ device->gatt_services = g_slist_append(device->gatt_services,
+ service);
+ }
+}
+
static void register_all_services(struct browse_req *req, GSList *services)
{
struct btd_device *device = req->device;
@@ -3329,6 +3368,8 @@ static void register_all_services(struct browse_req *req, GSList *services)
device_register_primaries(device, g_slist_copy(services), -1);
+ expose_btd_dbus_gatt_services(device);
+
device_probe_profiles(device, req->profiles_added);
if (device->attios == NULL && device->attios_offline == NULL)
@@ -3501,10 +3542,10 @@ done:
bonding_request_free(device->bonding);
}
- if (device->connect) {
- if (!device->le_state.svc_resolved)
- device_browse_primary(device, NULL);
+ if (!device->le_state.svc_resolved)
+ device_browse_primary(device, NULL);
+ if (device->connect) {
if (err < 0)
reply = btd_error_failed(device->connect,
strerror(-err));
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index c5f1597..60b87fa 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -37,6 +37,9 @@
#include "lib/uuid.h"
#include "dbus-common.h"
#include "log.h"
+#include "attrib/att.h"
+#include "attrib/gattrib.h"
+#include "attrib/gatt.h"
#include "error.h"
#include "gatt.h"
@@ -47,6 +50,12 @@
#define GATT_CHR_IFACE "org.bluez.GattCharacteristic1"
#define GATT_DESCRIPTOR_IFACE "org.bluez.GattDescriptor1"
+struct btd_gatt_dbus_service {
+ bt_uuid_t uuid;
+ struct btd_device *device;
+ char *path;
+};
+
struct external_app {
char *owner;
char *path;
@@ -436,7 +445,7 @@ static DBusMessage *unregister_service(DBusConnection *conn,
return dbus_message_new_method_return(msg);
}
-static const GDBusMethodTable methods[] = {
+static const GDBusMethodTable manager_methods[] = {
{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterService",
GDBUS_ARGS({ "service", "o"},
{ "options", "a{sv}"}),
@@ -450,8 +459,8 @@ static const GDBusMethodTable methods[] = {
gboolean gatt_dbus_manager_register(void)
{
if (g_dbus_register_interface(btd_get_dbus_connection(),
- "/org/bluez", GATT_MGR_IFACE,
- methods, NULL, NULL, NULL, NULL) == FALSE)
+ "/org/bluez", GATT_MGR_IFACE, manager_methods,
+ NULL, NULL, NULL, NULL) == FALSE)
return FALSE;
proxy_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
@@ -468,3 +477,80 @@ void gatt_dbus_manager_unregister(void)
g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
GATT_MGR_IFACE);
}
+
+static gboolean service_property_get_uuid(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ char uuid[MAX_LEN_UUID_STR + 1];
+ const char *ptr = uuid;
+ struct btd_gatt_dbus_service *service = data;
+
+ bt_uuid_to_string(&service->uuid, uuid, sizeof(uuid));
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
+
+ return TRUE;
+}
+
+static const GDBusPropertyTable service_properties[] = {
+ { "UUID", "s", service_property_get_uuid },
+ {}
+};
+
+static void service_free(gpointer user_data)
+{
+ struct btd_gatt_dbus_service *service = user_data;
+
+ g_free(service->path);
+ g_free(service);
+}
+
+struct btd_gatt_dbus_service *btd_gatt_dbus_service_create(
+ struct btd_device *device, struct gatt_primary *primary)
+{
+ struct btd_gatt_dbus_service *service;
+ bt_uuid_t uuid;
+ const char *device_path = device_get_path(device);
+
+ DBG("GATT service UUID: %s", primary->uuid);
+
+ service = g_try_malloc0(sizeof(struct btd_gatt_dbus_service));
+ if (service == NULL)
+ return NULL;
+
+ service->path = g_strdup_printf("%s/service%04X", device_path,
+ primary->range.start);
+
+ if (bt_string_to_uuid(&uuid, primary->uuid)) {
+ error("Primary has invalid UUID: %s", primary->uuid);
+ goto fail;
+ }
+
+ bt_uuid_to_uuid128(&uuid, &service->uuid);
+
+ DBG("Creating GATT service %s", service->path);
+
+ if (g_dbus_register_interface(btd_get_dbus_connection(),
+ service->path, GATT_SERVICE_IFACE,
+ NULL, NULL, service_properties,
+ service,
+ service_free) == FALSE) {
+ char device_addr[18];
+ ba2str(device_get_address(device), device_addr);
+ error("Unable to register GATT service: UUID: %s, device: %s",
+ primary->uuid, device_addr);
+ goto fail;
+ }
+
+ service->device = device;
+ return service;
+
+fail:
+ service_free(service);
+ return NULL;
+}
+
+void btd_gatt_dbus_service_free(struct btd_gatt_dbus_service* service)
+{
+ g_dbus_unregister_interface(btd_get_dbus_connection(),
+ service->path, GATT_SERVICE_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
index 310cfa9..08d3f11 100644
--- a/src/gatt-dbus.h
+++ b/src/gatt-dbus.h
@@ -21,5 +21,30 @@
*
*/
+struct btd_gatt_dbus_service;
+struct btd_device;
+struct gatt_primary;
+
gboolean gatt_dbus_manager_register(void);
void gatt_dbus_manager_unregister(void);
+
+/*
+ * btd_gatt_dbus_service_create - Create a GATT service that represents a remote
+ * primary GATT service and expose it via D-Bus.
+ *
+ * @device: The remote device that hosts the GATT service.
+ * @primary: The primary GATT service.
+ *
+ * Returns a reference to the GATT service object. In case of error, NULL is
+ * returned.
+ */
+struct btd_gatt_dbus_service *btd_gatt_dbus_service_create(
+ struct btd_device *device, struct gatt_primary *primary);
+
+/*
+ * btd_gatt_dbus_service_free - Unregister a GATT service as a D-Bus object and
+ * free up its memory.
+ *
+ * @service: The GATT service object to remove.
+ */
+void btd_gatt_dbus_service_free(struct btd_gatt_dbus_service* service);
--
1.8.3.2
next prev parent reply other threads:[~2014-03-12 4:03 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-12 4:03 [RFC BlueZ 0/2] Initial D-Bus GATT client API implementation armansito
2014-03-12 4:03 ` armansito [this message]
2014-03-14 14:24 ` [RFC BlueZ 1/2] gatt-dbus: Add remote GATT service objects Anderson Lizardo
2014-03-14 18:28 ` Arman Uguray
2014-03-12 4:04 ` [RFC BlueZ 2/2] gatt-dbus: Add remote GATT characteristic objects armansito
2014-03-14 15:56 ` Anderson Lizardo
2014-03-14 13:07 ` [RFC BlueZ 0/2] Initial D-Bus GATT client API implementation Anderson Lizardo
2014-03-14 17:48 ` Arman Uguray
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1394597040-4483-2-git-send-email-armansito@chromium.org \
--to=armansito@chromium.org \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox