All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db
@ 2016-12-27 12:40 Luiz Augusto von Dentz
  2016-12-27 12:40 ` [PATCH BlueZ 2/3] dis: " Luiz Augusto von Dentz
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2016-12-27 12:40 UTC (permalink / raw
  To: linux-bluetooth

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

This add support of passing a gatt-db to avoid having to discover the
services again, this should also make it easier to port to bt_gatt_client
once Android code support it.
---
 android/hidhost.c        |   4 +
 profiles/input/hog-lib.c | 247 +++++++++++++++++++++++++++++++++++++++++------
 profiles/input/hog-lib.h |   4 +-
 profiles/input/hog.c     |  61 ++++++------
 unit/test-hog.c          |   6 ++
 5 files changed, 255 insertions(+), 67 deletions(-)

diff --git a/android/hidhost.c b/android/hidhost.c
index 591ca95..fe0ea2f 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -38,9 +38,13 @@
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
+#include "lib/uuid.h"
 #include "src/shared/mgmt.h"
 #include "src/shared/util.h"
 #include "src/shared/uhid.h"
+#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
 #include "src/sdp-client.h"
 #include "src/uuid-helper.h"
 #include "src/log.h"
diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index e376c2b..ed38916 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -45,6 +45,8 @@
 #include "src/shared/util.h"
 #include "src/shared/uhid.h"
 #include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
 #include "src/log.h"
 
 #include "attrib/att.h"
@@ -59,6 +61,7 @@
 #include "profiles/input/hog-lib.h"
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
+#define HOG_UUID16		0x1812
 
 #define HOG_INFO_UUID		0x2A4A
 #define HOG_REPORT_MAP_UUID	0x2A4B
@@ -83,6 +86,7 @@ struct bt_hog {
 	uint16_t		vendor;
 	uint16_t		product;
 	uint16_t		version;
+	struct gatt_db_attribute *attr;
 	struct gatt_primary	*primary;
 	GAttrib			*attrib;
 	GSList			*reports;
@@ -110,9 +114,11 @@ struct report {
 	struct bt_hog		*hog;
 	uint8_t			id;
 	uint8_t			type;
+	uint16_t		handle;
+	uint16_t		value_handle;
+	uint8_t			properties;
 	uint16_t		ccc_handle;
 	guint			notifyid;
-	struct gatt_char	*decl;
 	uint16_t		len;
 	uint8_t			*value;
 };
@@ -181,6 +187,10 @@ static void read_char(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
 	struct gatt_request *req;
 	unsigned int id;
 
+	/* Ignore if not connected */
+	if (!attrib)
+		return;
+
 	req = create_request(hog, user_data);
 	if (!req)
 		return;
@@ -334,7 +344,7 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
 
 	report->notifyid = g_attrib_register(hog->attrib,
 					ATT_OP_HANDLE_NOTIFY,
-					report->decl->value_handle,
+					report->value_handle,
 					report_value_cb, report, NULL);
 
 	DBG("Report characteristic descriptor written: notifications enabled");
@@ -403,7 +413,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
 	report->id = pdu[1];
 	report->type = pdu[2];
 
-	DBG("Report 0x%04x: id 0x%02x type %s", report->decl->value_handle,
+	DBG("Report 0x%04x: id 0x%02x type %s", report->value_handle,
 				report->id, type_to_string(report->type));
 
 	/* Enable notifications only for Input Reports */
@@ -516,7 +526,7 @@ static int report_chrc_cmp(const void *data, const void *user_data)
 	const struct report *report = data;
 	const struct gatt_char *decl = user_data;
 
-	return report->decl->handle - decl->handle;
+	return report->handle - decl->handle;
 }
 
 static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
@@ -531,7 +541,9 @@ static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
 
 	report = g_new0(struct report, 1);
 	report->hog = hog;
-	report->decl = g_memdup(chr, sizeof(*chr));
+	report->handle = chr->handle;
+	report->value_handle = chr->value_handle;
+	report->properties = chr->properties;
 	hog->reports = g_slist_append(hog->reports, report);
 
 	read_char(hog, hog->attrib, chr->value_handle, report_read_cb, report);
@@ -691,16 +703,16 @@ static void forward_report(struct uhid_event *ev, void *user_data)
 	}
 
 	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
-				report->id, report->decl->value_handle);
+				report->id, report->value_handle);
 
 	if (hog->attrib == NULL)
 		return;
 
-	if (report->decl->properties & GATT_CHR_PROP_WRITE)
-		write_char(hog, hog->attrib, report->decl->value_handle,
+	if (report->properties & GATT_CHR_PROP_WRITE)
+		write_char(hog, hog->attrib, report->value_handle,
 				data, size, output_written_cb, hog);
-	else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
-		gatt_write_cmd(hog->attrib, report->decl->value_handle,
+	else if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
+		gatt_write_cmd(hog->attrib, report->value_handle,
 						data, size, NULL, NULL);
 }
 
@@ -789,13 +801,13 @@ static void set_report(struct uhid_event *ev, void *user_data)
 	}
 
 	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
-				report->id, report->decl->value_handle);
+				report->id, report->value_handle);
 
 	if (hog->attrib == NULL)
 		return;
 
 	hog->setrep_att = gatt_write_char(hog->attrib,
-						report->decl->value_handle,
+						report->value_handle,
 						data, size, set_report_cb,
 						hog);
 	if (!hog->setrep_att) {
@@ -878,7 +890,7 @@ static void get_report(struct uhid_event *ev, void *user_data)
 	}
 
 	hog->getrep_att = gatt_read_char(hog->attrib,
-						report->decl->value_handle,
+						report->value_handle,
 						get_report_cb, hog);
 	if (!hog->getrep_att) {
 		err = ENOMEM;
@@ -1180,7 +1192,6 @@ static void report_free(void *data)
 	struct report *report = data;
 
 	g_free(report->value);
-	g_free(report->decl);
 	g_free(report);
 }
 
@@ -1211,14 +1222,132 @@ static void hog_free(void *data)
 
 struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					void *primary)
+					struct gatt_db *db)
 {
-	return bt_hog_new(-1, name, vendor, product, version, primary);
+	return bt_hog_new(-1, name, vendor, product, version, db);
 }
 
-struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
+static void foreach_hog_report(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct report *report = user_data;
+	struct bt_hog *hog = report->hog;
+	const bt_uuid_t *uuid;
+	bt_uuid_t ref_uuid, ccc_uuid;
+	uint16_t handle;
+
+	handle = gatt_db_attribute_get_handle(attr);
+	uuid = gatt_db_attribute_get_type(attr);
+
+	bt_uuid16_create(&ref_uuid, GATT_REPORT_REFERENCE);
+	if (!bt_uuid_cmp(&ref_uuid, uuid)) {
+		read_char(hog, hog->attrib, handle, report_reference_cb,
+								report);
+		return;
+	}
+
+	bt_uuid16_create(&ccc_uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	if (!bt_uuid_cmp(&ccc_uuid, uuid))
+		report->ccc_handle = handle;
+}
+
+static int report_attr_cmp(const void *data, const void *user_data)
+{
+	const struct report *report = data;
+	const struct gatt_db_attribute *attr = user_data;
+
+	return report->handle - gatt_db_attribute_get_handle(attr);
+}
+
+static struct report *report_add(struct bt_hog *hog,
+					struct gatt_db_attribute *attr)
+{
+	struct report *report;
+	GSList *l;
+
+	/* Skip if report already exists */
+	l = g_slist_find_custom(hog->reports, attr, report_attr_cmp);
+	if (l)
+		return l->data;
+
+	report = g_new0(struct report, 1);
+	report->hog = hog;
+
+	gatt_db_attribute_get_char_data(attr, &report->handle,
+					&report->value_handle,
+					&report->properties,
+					NULL, NULL);
+
+	hog->reports = g_slist_append(hog->reports, report);
+
+	read_char(hog, hog->attrib, report->value_handle, report_read_cb,
+								report);
+
+	return report;
+}
+
+static void foreach_hog_external(struct gatt_db_attribute *attr,
+							void *user_data)
+{
+	struct bt_hog *hog = user_data;
+	const bt_uuid_t *uuid;
+	bt_uuid_t ext_uuid;
+	uint16_t handle;
+
+	handle = gatt_db_attribute_get_handle(attr);
+	uuid = gatt_db_attribute_get_type(attr);
+
+	bt_uuid16_create(&ext_uuid, GATT_EXTERNAL_REPORT_REFERENCE);
+	if (!bt_uuid_cmp(&ext_uuid, uuid))
+		read_char(hog, hog->attrib, handle,
+					external_report_reference_cb, hog);
+}
+
+static void foreach_hog_chrc(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_hog *hog = user_data;
+	bt_uuid_t uuid, report_uuid, report_map_uuid, info_uuid;
+	bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
+	uint16_t handle, value_handle;
+
+	gatt_db_attribute_get_char_data(attr, &handle, &value_handle, NULL,
+					NULL, &uuid);
+
+	bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
+	if (!bt_uuid_cmp(&report_uuid, &uuid)) {
+		struct report *report = report_add(hog, attr);
+		gatt_db_service_foreach_desc(attr, foreach_hog_report, report);
+		return;
+	}
+
+	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
+	if (!bt_uuid_cmp(&report_map_uuid, &uuid)) {
+		read_char(hog, hog->attrib, value_handle, report_map_read_cb,
+									hog);
+		gatt_db_service_foreach_desc(attr, foreach_hog_external, hog);
+		return;
+	}
+
+	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
+	if (!bt_uuid_cmp(&info_uuid, &uuid)) {
+		read_char(hog, hog->attrib, value_handle, info_read_cb, hog);
+		return;
+	}
+
+	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
+	if (!bt_uuid_cmp(&proto_mode_uuid, &uuid)) {
+		hog->proto_mode_handle = value_handle;
+		read_char(hog, hog->attrib, value_handle, proto_mode_read_cb,
+									hog);
+	}
+
+	bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
+	if (!bt_uuid_cmp(&ctrlpt_uuid, &uuid))
+		hog->ctrlpt_handle = value_handle;
+}
+
+static struct bt_hog *hog_new(int fd, const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					void *primary)
+					struct gatt_db_attribute *attr)
 {
 	struct bt_hog *hog;
 
@@ -1245,9 +1374,58 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
 	hog->vendor = vendor;
 	hog->product = product;
 	hog->version = version;
+	hog->attr = attr;
 
-	if (primary)
-		hog->primary = g_memdup(primary, sizeof(*hog->primary));
+	return hog;
+}
+
+static void hog_attach_instace(struct bt_hog *hog,
+				struct gatt_db_attribute *attr)
+{
+	struct bt_hog *instance;
+
+	if (!hog->attr) {
+		hog->attr = attr;
+		gatt_db_service_foreach_char(hog->attr, foreach_hog_chrc, hog);
+		return;
+	}
+
+	instance = hog_new(hog->uhid_fd, hog->name, hog->vendor,
+					hog->product, hog->version, attr);
+	if (!instance)
+		return;
+
+	hog->instances = g_slist_append(hog->instances, instance);
+}
+
+static void foreach_hog_service(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_hog *hog = user_data;
+
+	hog_attach_instace(hog, attr);
+}
+
+struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
+					uint16_t product, uint16_t version,
+					struct gatt_db *db)
+{
+	struct bt_hog *hog;
+
+	hog = hog_new(fd, name, vendor, product, version, NULL);
+	if (!hog)
+		return NULL;
+
+	if (db) {
+		bt_uuid_t uuid;
+
+		/* Handle the HID services */
+		bt_uuid16_create(&uuid, HOG_UUID16);
+		gatt_db_foreach_service(db, &uuid, foreach_hog_service, hog);
+		if (!hog->attr) {
+			hog_free(hog);
+			return NULL;
+		}
+	}
 
 	return bt_hog_ref(hog);
 }
@@ -1357,10 +1535,11 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
 	}
 
 	instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
-					hog->product, hog->version, primary);
+					hog->product, hog->version, NULL);
 	if (!instance)
 		return;
 
+	instance->primary = g_memdup(primary, sizeof(*primary));
 	find_included(instance, hog->attrib, primary->range.start,
 			primary->range.end, find_included_cb, instance);
 
@@ -1415,7 +1594,6 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
 
 bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 {
-	struct gatt_primary *primary = hog->primary;
 	GSList *l;
 
 	if (hog->attrib)
@@ -1423,7 +1601,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 
 	hog->attrib = g_attrib_ref(gatt);
 
-	if (!primary) {
+	if (!hog->attr && !hog->primary) {
 		discover_primary(hog, hog->attrib, NULL, primary_cb, hog);
 		return true;
 	}
@@ -1444,9 +1622,14 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 
 	if (!hog->uhid_created) {
 		DBG("HoG discovering characteristics");
-		discover_char(hog, hog->attrib, primary->range.start,
-						primary->range.end, NULL,
-						char_discovered_cb, hog);
+		if (hog->attr)
+			gatt_db_service_foreach_char(hog->attr,
+							foreach_hog_chrc, hog);
+		else
+			discover_char(hog, hog->attrib,
+					hog->primary->range.start,
+					hog->primary->range.end, NULL,
+					char_discovered_cb, hog);
 		return true;
 	}
 
@@ -1455,7 +1638,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 
 		r->notifyid = g_attrib_register(hog->attrib,
 					ATT_OP_HANDLE_NOTIFY,
-					r->decl->value_handle,
+					r->value_handle,
 					report_value_cb, r, NULL);
 	}
 
@@ -1528,14 +1711,14 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
 	if (!report)
 		return -ENOTSUP;
 
-	DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
+	DBG("hog: Write report, handle 0x%X", report->value_handle);
 
-	if (report->decl->properties & GATT_CHR_PROP_WRITE)
-		write_char(hog, hog->attrib, report->decl->value_handle,
+	if (report->properties & GATT_CHR_PROP_WRITE)
+		write_char(hog, hog->attrib, report->value_handle,
 				data, size, output_written_cb, hog);
 
-	if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
-		gatt_write_cmd(hog->attrib, report->decl->value_handle,
+	if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
+		gatt_write_cmd(hog->attrib, report->value_handle,
 						data, size, NULL, NULL);
 
 	for (l = hog->instances; l; l = l->next) {
diff --git a/profiles/input/hog-lib.h b/profiles/input/hog-lib.h
index 2a9b899..415dc63 100644
--- a/profiles/input/hog-lib.h
+++ b/profiles/input/hog-lib.h
@@ -25,11 +25,11 @@ struct bt_hog;
 
 struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					void *primary);
+					struct gatt_db *db);
 
 struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
 					uint16_t product, uint16_t version,
-					void *primary);
+					struct gatt_db *db);
 
 struct bt_hog *bt_hog_ref(struct bt_hog *hog);
 void bt_hog_unref(struct bt_hog *hog);
diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index 7d318cd..23c9c15 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -67,32 +67,34 @@ struct hog_device {
 static gboolean suspend_supported = FALSE;
 static struct queue *devices = NULL;
 
-static struct hog_device *hog_device_new(struct btd_device *device,
-						struct gatt_primary *prim)
+static void hog_device_accept(struct hog_device *dev, struct gatt_db *db)
 {
-	struct hog_device *dev;
 	char name[248];
 	uint16_t vendor, product, version;
 
-	if (device_name_known(device))
-		device_get_name(device, name, sizeof(name));
+	if (dev->hog)
+		return;
+
+	if (device_name_known(dev->device))
+		device_get_name(dev->device, name, sizeof(name));
 	else
 		strcpy(name, "bluez-hog-device");
 
-	vendor = btd_device_get_vendor(device);
-	product = btd_device_get_product(device);
-	version = btd_device_get_version(device);
+	vendor = btd_device_get_vendor(dev->device);
+	product = btd_device_get_product(dev->device);
+	version = btd_device_get_version(dev->device);
 
 	DBG("name=%s vendor=0x%X, product=0x%X, version=0x%X", name, vendor,
 							product, version);
 
-	dev = new0(struct hog_device, 1);
-	dev->hog = bt_hog_new_default(name, vendor, product, version, prim);
-	if (!dev->hog) {
-		free(dev);
-		return NULL;
-	}
+	dev->hog = bt_hog_new_default(name, vendor, product, version, db);
+}
 
+static struct hog_device *hog_device_new(struct btd_device *device)
+{
+	struct hog_device *dev;
+
+	dev = new0(struct hog_device, 1);
 	dev->device = btd_device_ref(device);
 
 	if (!devices)
@@ -148,30 +150,16 @@ static int hog_probe(struct btd_service *service)
 {
 	struct btd_device *device = btd_service_get_device(service);
 	const char *path = device_get_path(device);
-	GSList *primaries, *l;
+	struct hog_device *dev;
 
 	DBG("path %s", path);
 
-	primaries = btd_device_get_primaries(device);
-	if (primaries == NULL)
+	dev = hog_device_new(device);
+	if (!dev)
 		return -EINVAL;
 
-	for (l = primaries; l; l = g_slist_next(l)) {
-		struct gatt_primary *prim = l->data;
-		struct hog_device *dev;
-
-		if (strcmp(prim->uuid, HOG_UUID) != 0)
-			continue;
-
-		dev = hog_device_new(device, prim);
-		if (!dev)
-			break;
-
-		btd_service_set_user_data(service, dev);
-		return 0;
-	}
-
-	return -EINVAL;
+	btd_service_set_user_data(service, dev);
+	return 0;
 }
 
 static void hog_remove(struct btd_service *service)
@@ -189,8 +177,15 @@ static int hog_accept(struct btd_service *service)
 {
 	struct hog_device *dev = btd_service_get_user_data(service);
 	struct btd_device *device = btd_service_get_device(service);
+	struct gatt_db *db = btd_device_get_gatt_db(device);
 	GAttrib *attrib = btd_device_get_attrib(device);
 
+	if (!dev->hog) {
+		hog_device_accept(dev, db);
+		if (!dev->hog)
+			return -EINVAL;
+	}
+
 	/* TODO: Replace GAttrib with bt_gatt_client */
 	bt_hog_attach(dev->hog, attrib);
 
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 9f026e5..d117968 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -32,8 +32,14 @@
 
 #include <glib.h>
 
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+
 #include "src/shared/util.h"
 #include "src/shared/tester.h"
+#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
 
 #include "attrib/gattrib.h"
 
-- 
2.9.3


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

* [PATCH BlueZ 2/3] dis: Add support to gatt-db
  2016-12-27 12:40 [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
@ 2016-12-27 12:40 ` Luiz Augusto von Dentz
  2016-12-27 12:40 ` [PATCH BlueZ 3/3] input/hog-lib: Attempt to read PNP values if not set Luiz Augusto von Dentz
  2016-12-29 13:23 ` [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
  2 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2016-12-27 12:40 UTC (permalink / raw
  To: linux-bluetooth

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

This add support of passing a gatt-db to avoid having to discover the
services again, this should also make it easier to port to bt_gatt_client
once Android code support it.
---
 profiles/deviceinfo/dis.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
 profiles/deviceinfo/dis.h |  3 ++-
 profiles/input/hog-lib.c  |  2 +-
 3 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/profiles/deviceinfo/dis.c b/profiles/deviceinfo/dis.c
index 91c5d39..91ce26b 100644
--- a/profiles/deviceinfo/dis.c
+++ b/profiles/deviceinfo/dis.c
@@ -37,6 +37,8 @@
 
 #include "src/shared/util.h"
 #include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
 
 #include "attrib/gattrib.h"
 #include "attrib/att.h"
@@ -44,6 +46,7 @@
 
 #include "profiles/deviceinfo/dis.h"
 
+#define DIS_UUID16	0x180a
 #define PNP_ID_SIZE	7
 
 struct bt_dis {
@@ -87,7 +90,43 @@ static void dis_free(struct bt_dis *dis)
 	g_free(dis);
 }
 
-struct bt_dis *bt_dis_new(void *primary)
+static void foreach_dis_service(struct gatt_db_attribute *attr, void *user_data)
+{
+	struct bt_dis *dis = user_data;
+
+	/* Ignore if there are multiple instances */
+	if (dis->handle)
+		return;
+
+	dis->handle = gatt_db_attribute_get_handle(attr);
+}
+
+struct bt_dis *bt_dis_new(struct gatt_db *db)
+{
+	struct bt_dis *dis;
+
+	dis = g_try_new0(struct bt_dis, 1);
+	if (!dis)
+		return NULL;
+
+	dis->gatt_op = queue_new();
+
+	if (db) {
+		bt_uuid_t uuid;
+
+		/* Handle the DIS service */
+		bt_uuid16_create(&uuid, DIS_UUID16);
+		gatt_db_foreach_service(db, &uuid, foreach_dis_service, dis);
+		if (!dis->handle) {
+			dis_free(dis);
+			return NULL;
+		}
+	}
+
+	return bt_dis_ref(dis);
+}
+
+struct bt_dis *bt_dis_new_primary(void *primary)
 {
 	struct bt_dis *dis;
 
@@ -251,7 +290,7 @@ bool bt_dis_attach(struct bt_dis *dis, void *attrib)
 {
 	struct gatt_primary *primary = dis->primary;
 
-	if (dis->attrib || !primary)
+	if (dis->attrib)
 		return false;
 
 	dis->attrib = g_attrib_ref(attrib);
@@ -260,6 +299,8 @@ bool bt_dis_attach(struct bt_dis *dis, void *attrib)
 		discover_char(dis, dis->attrib, primary->range.start,
 						primary->range.end, NULL,
 						configure_deviceinfo_cb, dis);
+	else
+		read_char(dis, attrib, dis->handle, read_pnpid_cb, dis);
 
 	return true;
 }
diff --git a/profiles/deviceinfo/dis.h b/profiles/deviceinfo/dis.h
index faf27b3..305ba1a 100644
--- a/profiles/deviceinfo/dis.h
+++ b/profiles/deviceinfo/dis.h
@@ -23,7 +23,8 @@
 
 struct bt_dis;
 
-struct bt_dis *bt_dis_new(void *primary);
+struct bt_dis *bt_dis_new(struct gatt_db *db);
+struct bt_dis *bt_dis_new_primary(void *primary);
 
 struct bt_dis *bt_dis_ref(struct bt_dis *dis);
 void bt_dis_unref(struct bt_dis *dis);
diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index ed38916..0f2f394 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -1503,7 +1503,7 @@ static void hog_attach_dis(struct bt_hog *hog, struct gatt_primary *primary)
 		return;
 	}
 
-	hog->dis = bt_dis_new(primary);
+	hog->dis = bt_dis_new_primary(primary);
 	if (hog->dis) {
 		bt_dis_set_notification(hog->dis, dis_notify, hog);
 		bt_dis_attach(hog->dis, hog->attrib);
-- 
2.9.3


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

* [PATCH BlueZ 3/3] input/hog-lib: Attempt to read PNP values if not set
  2016-12-27 12:40 [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
  2016-12-27 12:40 ` [PATCH BlueZ 2/3] dis: " Luiz Augusto von Dentz
@ 2016-12-27 12:40 ` Luiz Augusto von Dentz
  2016-12-29 13:23 ` [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
  2 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2016-12-27 12:40 UTC (permalink / raw
  To: linux-bluetooth

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

---
 profiles/input/hog-lib.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index 0f2f394..a159b17 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -1425,6 +1425,11 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
 			hog_free(hog);
 			return NULL;
 		}
+
+		/* Try creating a DIS instance in case pid/vid are not set */
+		if (!vendor && !product) {
+			hog->dis = bt_dis_new(db);
+		}
 	}
 
 	return bt_hog_ref(hog);
-- 
2.9.3


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

* Re: [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db
  2016-12-27 12:40 [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
  2016-12-27 12:40 ` [PATCH BlueZ 2/3] dis: " Luiz Augusto von Dentz
  2016-12-27 12:40 ` [PATCH BlueZ 3/3] input/hog-lib: Attempt to read PNP values if not set Luiz Augusto von Dentz
@ 2016-12-29 13:23 ` Luiz Augusto von Dentz
  2016-12-30  0:47   ` Petri Gynther
  2 siblings, 1 reply; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2016-12-29 13:23 UTC (permalink / raw
  To: linux-bluetooth@vger.kernel.org

Hi,

On Tue, Dec 27, 2016 at 2:40 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This add support of passing a gatt-db to avoid having to discover the
> services again, this should also make it easier to port to bt_gatt_client
> once Android code support it.
> ---
>  android/hidhost.c        |   4 +
>  profiles/input/hog-lib.c | 247 +++++++++++++++++++++++++++++++++++++++++------
>  profiles/input/hog-lib.h |   4 +-
>  profiles/input/hog.c     |  61 ++++++------
>  unit/test-hog.c          |   6 ++
>  5 files changed, 255 insertions(+), 67 deletions(-)
>
> diff --git a/android/hidhost.c b/android/hidhost.c
> index 591ca95..fe0ea2f 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -38,9 +38,13 @@
>  #include "lib/bluetooth.h"
>  #include "lib/sdp.h"
>  #include "lib/sdp_lib.h"
> +#include "lib/uuid.h"
>  #include "src/shared/mgmt.h"
>  #include "src/shared/util.h"
>  #include "src/shared/uhid.h"
> +#include "src/shared/queue.h"
> +#include "src/shared/att.h"
> +#include "src/shared/gatt-db.h"
>  #include "src/sdp-client.h"
>  #include "src/uuid-helper.h"
>  #include "src/log.h"
> diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
> index e376c2b..ed38916 100644
> --- a/profiles/input/hog-lib.c
> +++ b/profiles/input/hog-lib.c
> @@ -45,6 +45,8 @@
>  #include "src/shared/util.h"
>  #include "src/shared/uhid.h"
>  #include "src/shared/queue.h"
> +#include "src/shared/att.h"
> +#include "src/shared/gatt-db.h"
>  #include "src/log.h"
>
>  #include "attrib/att.h"
> @@ -59,6 +61,7 @@
>  #include "profiles/input/hog-lib.h"
>
>  #define HOG_UUID               "00001812-0000-1000-8000-00805f9b34fb"
> +#define HOG_UUID16             0x1812
>
>  #define HOG_INFO_UUID          0x2A4A
>  #define HOG_REPORT_MAP_UUID    0x2A4B
> @@ -83,6 +86,7 @@ struct bt_hog {
>         uint16_t                vendor;
>         uint16_t                product;
>         uint16_t                version;
> +       struct gatt_db_attribute *attr;
>         struct gatt_primary     *primary;
>         GAttrib                 *attrib;
>         GSList                  *reports;
> @@ -110,9 +114,11 @@ struct report {
>         struct bt_hog           *hog;
>         uint8_t                 id;
>         uint8_t                 type;
> +       uint16_t                handle;
> +       uint16_t                value_handle;
> +       uint8_t                 properties;
>         uint16_t                ccc_handle;
>         guint                   notifyid;
> -       struct gatt_char        *decl;
>         uint16_t                len;
>         uint8_t                 *value;
>  };
> @@ -181,6 +187,10 @@ static void read_char(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
>         struct gatt_request *req;
>         unsigned int id;
>
> +       /* Ignore if not connected */
> +       if (!attrib)
> +               return;
> +
>         req = create_request(hog, user_data);
>         if (!req)
>                 return;
> @@ -334,7 +344,7 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
>
>         report->notifyid = g_attrib_register(hog->attrib,
>                                         ATT_OP_HANDLE_NOTIFY,
> -                                       report->decl->value_handle,
> +                                       report->value_handle,
>                                         report_value_cb, report, NULL);
>
>         DBG("Report characteristic descriptor written: notifications enabled");
> @@ -403,7 +413,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
>         report->id = pdu[1];
>         report->type = pdu[2];
>
> -       DBG("Report 0x%04x: id 0x%02x type %s", report->decl->value_handle,
> +       DBG("Report 0x%04x: id 0x%02x type %s", report->value_handle,
>                                 report->id, type_to_string(report->type));
>
>         /* Enable notifications only for Input Reports */
> @@ -516,7 +526,7 @@ static int report_chrc_cmp(const void *data, const void *user_data)
>         const struct report *report = data;
>         const struct gatt_char *decl = user_data;
>
> -       return report->decl->handle - decl->handle;
> +       return report->handle - decl->handle;
>  }
>
>  static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
> @@ -531,7 +541,9 @@ static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
>
>         report = g_new0(struct report, 1);
>         report->hog = hog;
> -       report->decl = g_memdup(chr, sizeof(*chr));
> +       report->handle = chr->handle;
> +       report->value_handle = chr->value_handle;
> +       report->properties = chr->properties;
>         hog->reports = g_slist_append(hog->reports, report);
>
>         read_char(hog, hog->attrib, chr->value_handle, report_read_cb, report);
> @@ -691,16 +703,16 @@ static void forward_report(struct uhid_event *ev, void *user_data)
>         }
>
>         DBG("Sending report type %d ID %d to handle 0x%X", report->type,
> -                               report->id, report->decl->value_handle);
> +                               report->id, report->value_handle);
>
>         if (hog->attrib == NULL)
>                 return;
>
> -       if (report->decl->properties & GATT_CHR_PROP_WRITE)
> -               write_char(hog, hog->attrib, report->decl->value_handle,
> +       if (report->properties & GATT_CHR_PROP_WRITE)
> +               write_char(hog, hog->attrib, report->value_handle,
>                                 data, size, output_written_cb, hog);
> -       else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
> -               gatt_write_cmd(hog->attrib, report->decl->value_handle,
> +       else if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
> +               gatt_write_cmd(hog->attrib, report->value_handle,
>                                                 data, size, NULL, NULL);
>  }
>
> @@ -789,13 +801,13 @@ static void set_report(struct uhid_event *ev, void *user_data)
>         }
>
>         DBG("Sending report type %d ID %d to handle 0x%X", report->type,
> -                               report->id, report->decl->value_handle);
> +                               report->id, report->value_handle);
>
>         if (hog->attrib == NULL)
>                 return;
>
>         hog->setrep_att = gatt_write_char(hog->attrib,
> -                                               report->decl->value_handle,
> +                                               report->value_handle,
>                                                 data, size, set_report_cb,
>                                                 hog);
>         if (!hog->setrep_att) {
> @@ -878,7 +890,7 @@ static void get_report(struct uhid_event *ev, void *user_data)
>         }
>
>         hog->getrep_att = gatt_read_char(hog->attrib,
> -                                               report->decl->value_handle,
> +                                               report->value_handle,
>                                                 get_report_cb, hog);
>         if (!hog->getrep_att) {
>                 err = ENOMEM;
> @@ -1180,7 +1192,6 @@ static void report_free(void *data)
>         struct report *report = data;
>
>         g_free(report->value);
> -       g_free(report->decl);
>         g_free(report);
>  }
>
> @@ -1211,14 +1222,132 @@ static void hog_free(void *data)
>
>  struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
>                                         uint16_t product, uint16_t version,
> -                                       void *primary)
> +                                       struct gatt_db *db)
>  {
> -       return bt_hog_new(-1, name, vendor, product, version, primary);
> +       return bt_hog_new(-1, name, vendor, product, version, db);
>  }
>
> -struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> +static void foreach_hog_report(struct gatt_db_attribute *attr, void *user_data)
> +{
> +       struct report *report = user_data;
> +       struct bt_hog *hog = report->hog;
> +       const bt_uuid_t *uuid;
> +       bt_uuid_t ref_uuid, ccc_uuid;
> +       uint16_t handle;
> +
> +       handle = gatt_db_attribute_get_handle(attr);
> +       uuid = gatt_db_attribute_get_type(attr);
> +
> +       bt_uuid16_create(&ref_uuid, GATT_REPORT_REFERENCE);
> +       if (!bt_uuid_cmp(&ref_uuid, uuid)) {
> +               read_char(hog, hog->attrib, handle, report_reference_cb,
> +                                                               report);
> +               return;
> +       }
> +
> +       bt_uuid16_create(&ccc_uuid, GATT_CLIENT_CHARAC_CFG_UUID);
> +       if (!bt_uuid_cmp(&ccc_uuid, uuid))
> +               report->ccc_handle = handle;
> +}
> +
> +static int report_attr_cmp(const void *data, const void *user_data)
> +{
> +       const struct report *report = data;
> +       const struct gatt_db_attribute *attr = user_data;
> +
> +       return report->handle - gatt_db_attribute_get_handle(attr);
> +}
> +
> +static struct report *report_add(struct bt_hog *hog,
> +                                       struct gatt_db_attribute *attr)
> +{
> +       struct report *report;
> +       GSList *l;
> +
> +       /* Skip if report already exists */
> +       l = g_slist_find_custom(hog->reports, attr, report_attr_cmp);
> +       if (l)
> +               return l->data;
> +
> +       report = g_new0(struct report, 1);
> +       report->hog = hog;
> +
> +       gatt_db_attribute_get_char_data(attr, &report->handle,
> +                                       &report->value_handle,
> +                                       &report->properties,
> +                                       NULL, NULL);
> +
> +       hog->reports = g_slist_append(hog->reports, report);
> +
> +       read_char(hog, hog->attrib, report->value_handle, report_read_cb,
> +                                                               report);
> +
> +       return report;
> +}
> +
> +static void foreach_hog_external(struct gatt_db_attribute *attr,
> +                                                       void *user_data)
> +{
> +       struct bt_hog *hog = user_data;
> +       const bt_uuid_t *uuid;
> +       bt_uuid_t ext_uuid;
> +       uint16_t handle;
> +
> +       handle = gatt_db_attribute_get_handle(attr);
> +       uuid = gatt_db_attribute_get_type(attr);
> +
> +       bt_uuid16_create(&ext_uuid, GATT_EXTERNAL_REPORT_REFERENCE);
> +       if (!bt_uuid_cmp(&ext_uuid, uuid))
> +               read_char(hog, hog->attrib, handle,
> +                                       external_report_reference_cb, hog);
> +}
> +
> +static void foreach_hog_chrc(struct gatt_db_attribute *attr, void *user_data)
> +{
> +       struct bt_hog *hog = user_data;
> +       bt_uuid_t uuid, report_uuid, report_map_uuid, info_uuid;
> +       bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
> +       uint16_t handle, value_handle;
> +
> +       gatt_db_attribute_get_char_data(attr, &handle, &value_handle, NULL,
> +                                       NULL, &uuid);
> +
> +       bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
> +       if (!bt_uuid_cmp(&report_uuid, &uuid)) {
> +               struct report *report = report_add(hog, attr);
> +               gatt_db_service_foreach_desc(attr, foreach_hog_report, report);
> +               return;
> +       }
> +
> +       bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
> +       if (!bt_uuid_cmp(&report_map_uuid, &uuid)) {
> +               read_char(hog, hog->attrib, value_handle, report_map_read_cb,
> +                                                                       hog);
> +               gatt_db_service_foreach_desc(attr, foreach_hog_external, hog);
> +               return;
> +       }
> +
> +       bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
> +       if (!bt_uuid_cmp(&info_uuid, &uuid)) {
> +               read_char(hog, hog->attrib, value_handle, info_read_cb, hog);
> +               return;
> +       }
> +
> +       bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
> +       if (!bt_uuid_cmp(&proto_mode_uuid, &uuid)) {
> +               hog->proto_mode_handle = value_handle;
> +               read_char(hog, hog->attrib, value_handle, proto_mode_read_cb,
> +                                                                       hog);
> +       }
> +
> +       bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
> +       if (!bt_uuid_cmp(&ctrlpt_uuid, &uuid))
> +               hog->ctrlpt_handle = value_handle;
> +}
> +
> +static struct bt_hog *hog_new(int fd, const char *name, uint16_t vendor,
>                                         uint16_t product, uint16_t version,
> -                                       void *primary)
> +                                       struct gatt_db_attribute *attr)
>  {
>         struct bt_hog *hog;
>
> @@ -1245,9 +1374,58 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>         hog->vendor = vendor;
>         hog->product = product;
>         hog->version = version;
> +       hog->attr = attr;
>
> -       if (primary)
> -               hog->primary = g_memdup(primary, sizeof(*hog->primary));
> +       return hog;
> +}
> +
> +static void hog_attach_instace(struct bt_hog *hog,
> +                               struct gatt_db_attribute *attr)
> +{
> +       struct bt_hog *instance;
> +
> +       if (!hog->attr) {
> +               hog->attr = attr;
> +               gatt_db_service_foreach_char(hog->attr, foreach_hog_chrc, hog);
> +               return;
> +       }
> +
> +       instance = hog_new(hog->uhid_fd, hog->name, hog->vendor,
> +                                       hog->product, hog->version, attr);
> +       if (!instance)
> +               return;
> +
> +       hog->instances = g_slist_append(hog->instances, instance);
> +}
> +
> +static void foreach_hog_service(struct gatt_db_attribute *attr, void *user_data)
> +{
> +       struct bt_hog *hog = user_data;
> +
> +       hog_attach_instace(hog, attr);
> +}
> +
> +struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> +                                       uint16_t product, uint16_t version,
> +                                       struct gatt_db *db)
> +{
> +       struct bt_hog *hog;
> +
> +       hog = hog_new(fd, name, vendor, product, version, NULL);
> +       if (!hog)
> +               return NULL;
> +
> +       if (db) {
> +               bt_uuid_t uuid;
> +
> +               /* Handle the HID services */
> +               bt_uuid16_create(&uuid, HOG_UUID16);
> +               gatt_db_foreach_service(db, &uuid, foreach_hog_service, hog);
> +               if (!hog->attr) {
> +                       hog_free(hog);
> +                       return NULL;
> +               }
> +       }
>
>         return bt_hog_ref(hog);
>  }
> @@ -1357,10 +1535,11 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
>         }
>
>         instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
> -                                       hog->product, hog->version, primary);
> +                                       hog->product, hog->version, NULL);
>         if (!instance)
>                 return;
>
> +       instance->primary = g_memdup(primary, sizeof(*primary));
>         find_included(instance, hog->attrib, primary->range.start,
>                         primary->range.end, find_included_cb, instance);
>
> @@ -1415,7 +1594,6 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
>
>  bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>  {
> -       struct gatt_primary *primary = hog->primary;
>         GSList *l;
>
>         if (hog->attrib)
> @@ -1423,7 +1601,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>
>         hog->attrib = g_attrib_ref(gatt);
>
> -       if (!primary) {
> +       if (!hog->attr && !hog->primary) {
>                 discover_primary(hog, hog->attrib, NULL, primary_cb, hog);
>                 return true;
>         }
> @@ -1444,9 +1622,14 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>
>         if (!hog->uhid_created) {
>                 DBG("HoG discovering characteristics");
> -               discover_char(hog, hog->attrib, primary->range.start,
> -                                               primary->range.end, NULL,
> -                                               char_discovered_cb, hog);
> +               if (hog->attr)
> +                       gatt_db_service_foreach_char(hog->attr,
> +                                                       foreach_hog_chrc, hog);
> +               else
> +                       discover_char(hog, hog->attrib,
> +                                       hog->primary->range.start,
> +                                       hog->primary->range.end, NULL,
> +                                       char_discovered_cb, hog);
>                 return true;
>         }
>
> @@ -1455,7 +1638,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>
>                 r->notifyid = g_attrib_register(hog->attrib,
>                                         ATT_OP_HANDLE_NOTIFY,
> -                                       r->decl->value_handle,
> +                                       r->value_handle,
>                                         report_value_cb, r, NULL);
>         }
>
> @@ -1528,14 +1711,14 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
>         if (!report)
>                 return -ENOTSUP;
>
> -       DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
> +       DBG("hog: Write report, handle 0x%X", report->value_handle);
>
> -       if (report->decl->properties & GATT_CHR_PROP_WRITE)
> -               write_char(hog, hog->attrib, report->decl->value_handle,
> +       if (report->properties & GATT_CHR_PROP_WRITE)
> +               write_char(hog, hog->attrib, report->value_handle,
>                                 data, size, output_written_cb, hog);
>
> -       if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
> -               gatt_write_cmd(hog->attrib, report->decl->value_handle,
> +       if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
> +               gatt_write_cmd(hog->attrib, report->value_handle,
>                                                 data, size, NULL, NULL);
>
>         for (l = hog->instances; l; l = l->next) {
> diff --git a/profiles/input/hog-lib.h b/profiles/input/hog-lib.h
> index 2a9b899..415dc63 100644
> --- a/profiles/input/hog-lib.h
> +++ b/profiles/input/hog-lib.h
> @@ -25,11 +25,11 @@ struct bt_hog;
>
>  struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
>                                         uint16_t product, uint16_t version,
> -                                       void *primary);
> +                                       struct gatt_db *db);
>
>  struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>                                         uint16_t product, uint16_t version,
> -                                       void *primary);
> +                                       struct gatt_db *db);
>
>  struct bt_hog *bt_hog_ref(struct bt_hog *hog);
>  void bt_hog_unref(struct bt_hog *hog);
> diff --git a/profiles/input/hog.c b/profiles/input/hog.c
> index 7d318cd..23c9c15 100644
> --- a/profiles/input/hog.c
> +++ b/profiles/input/hog.c
> @@ -67,32 +67,34 @@ struct hog_device {
>  static gboolean suspend_supported = FALSE;
>  static struct queue *devices = NULL;
>
> -static struct hog_device *hog_device_new(struct btd_device *device,
> -                                               struct gatt_primary *prim)
> +static void hog_device_accept(struct hog_device *dev, struct gatt_db *db)
>  {
> -       struct hog_device *dev;
>         char name[248];
>         uint16_t vendor, product, version;
>
> -       if (device_name_known(device))
> -               device_get_name(device, name, sizeof(name));
> +       if (dev->hog)
> +               return;
> +
> +       if (device_name_known(dev->device))
> +               device_get_name(dev->device, name, sizeof(name));
>         else
>                 strcpy(name, "bluez-hog-device");
>
> -       vendor = btd_device_get_vendor(device);
> -       product = btd_device_get_product(device);
> -       version = btd_device_get_version(device);
> +       vendor = btd_device_get_vendor(dev->device);
> +       product = btd_device_get_product(dev->device);
> +       version = btd_device_get_version(dev->device);
>
>         DBG("name=%s vendor=0x%X, product=0x%X, version=0x%X", name, vendor,
>                                                         product, version);
>
> -       dev = new0(struct hog_device, 1);
> -       dev->hog = bt_hog_new_default(name, vendor, product, version, prim);
> -       if (!dev->hog) {
> -               free(dev);
> -               return NULL;
> -       }
> +       dev->hog = bt_hog_new_default(name, vendor, product, version, db);
> +}
>
> +static struct hog_device *hog_device_new(struct btd_device *device)
> +{
> +       struct hog_device *dev;
> +
> +       dev = new0(struct hog_device, 1);
>         dev->device = btd_device_ref(device);
>
>         if (!devices)
> @@ -148,30 +150,16 @@ static int hog_probe(struct btd_service *service)
>  {
>         struct btd_device *device = btd_service_get_device(service);
>         const char *path = device_get_path(device);
> -       GSList *primaries, *l;
> +       struct hog_device *dev;
>
>         DBG("path %s", path);
>
> -       primaries = btd_device_get_primaries(device);
> -       if (primaries == NULL)
> +       dev = hog_device_new(device);
> +       if (!dev)
>                 return -EINVAL;
>
> -       for (l = primaries; l; l = g_slist_next(l)) {
> -               struct gatt_primary *prim = l->data;
> -               struct hog_device *dev;
> -
> -               if (strcmp(prim->uuid, HOG_UUID) != 0)
> -                       continue;
> -
> -               dev = hog_device_new(device, prim);
> -               if (!dev)
> -                       break;
> -
> -               btd_service_set_user_data(service, dev);
> -               return 0;
> -       }
> -
> -       return -EINVAL;
> +       btd_service_set_user_data(service, dev);
> +       return 0;
>  }
>
>  static void hog_remove(struct btd_service *service)
> @@ -189,8 +177,15 @@ static int hog_accept(struct btd_service *service)
>  {
>         struct hog_device *dev = btd_service_get_user_data(service);
>         struct btd_device *device = btd_service_get_device(service);
> +       struct gatt_db *db = btd_device_get_gatt_db(device);
>         GAttrib *attrib = btd_device_get_attrib(device);
>
> +       if (!dev->hog) {
> +               hog_device_accept(dev, db);
> +               if (!dev->hog)
> +                       return -EINVAL;
> +       }
> +
>         /* TODO: Replace GAttrib with bt_gatt_client */
>         bt_hog_attach(dev->hog, attrib);
>
> diff --git a/unit/test-hog.c b/unit/test-hog.c
> index 9f026e5..d117968 100644
> --- a/unit/test-hog.c
> +++ b/unit/test-hog.c
> @@ -32,8 +32,14 @@
>
>  #include <glib.h>
>
> +#include "lib/bluetooth.h"
> +#include "lib/uuid.h"
> +
>  #include "src/shared/util.h"
>  #include "src/shared/tester.h"
> +#include "src/shared/queue.h"
> +#include "src/shared/att.h"
> +#include "src/shared/gatt-db.h"
>
>  #include "attrib/gattrib.h"
>
> --
> 2.9.3

Applied.


-- 
Luiz Augusto von Dentz

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

* Re: [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db
  2016-12-29 13:23 ` [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
@ 2016-12-30  0:47   ` Petri Gynther
  2016-12-30  8:59     ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 6+ messages in thread
From: Petri Gynther @ 2016-12-30  0:47 UTC (permalink / raw
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org

Hi Luiz,

Are these 3 patches supposed to eliminate re-reading the HoG report
map from the device on reconnect? And get it from GATT DB instead?

I merged the tip of BlueZ and tried it with our HoG remote. But, I
still see Read Blob Requests & Responses being sent over air to
re-read the report map:

15,3601,88379000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
            [hci0] 00:35:56.596115
15,3602,88379000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
15,3603,88379000,-;btmon:         Handle: 0x0041
15,3604,88379000,-;btmon:         Offset: 0x0016
--
15,3609,88402000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
            [hci0] 00:35:56.624487
15,3610,88402000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
15,3611,88402000,-;btmon:         81 02 95 01 75 08 81 01 95 05 75 01
05 08 19 01  ....u.....u.....
15,3612,88402000,-;btmon:         29 05 91 02 95 01
            ).....
--
15,3704,88585000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
            [hci0] 00:35:56.805750
15,3705,88585000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
15,3706,88585000,-;btmon:         Handle: 0x0041
15,3707,88585000,-;btmon:         Offset: 0x002c
--
15,3712,88609000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
            [hci0] 00:35:56.831684
15,3713,88609000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
15,3714,88609000,-;btmon:         75 03 91 01 95 06 75 08 15 00 25 73
05 07 19 00  u.....u...%s....
15,3715,88610000,-;btmon:         29 73 81 00 c0 05
            )s....
--
15,3842,89855000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
            [hci0] 00:35:58.074749
15,3843,89855000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
15,3844,89855000,-;btmon:         Handle: 0x0041
15,3845,89855000,-;btmon:         Offset: 0x0042
--
15,3850,89882000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
            [hci0] 00:35:58.104341
15,3851,89882000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
15,3852,89882000,-;btmon:         0c 09 01 a1 01 85 03 05 0c a1 02 19
00 2a 3c 02  .............*<.
15,3853,89882000,-;btmon:         15 00 26 3c 02 95
            ..&<..
--
15,3984,90013000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
            [hci0] 00:35:58.235072
15,3985,90016000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
15,3986,90016000,-;btmon:         Handle: 0x0041
15,3987,90016000,-;btmon:         Offset: 0x0058
--
15,3992,90041000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
            [hci0] 00:35:58.263061
15,3993,90041000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
15,3994,90041000,-;btmon:         01 75 10 81 00 c0 c0 06 00 ff 09 07
a1 01 85 81  .u..............
15,3995,90041000,-;btmon:         19 00 2a ff 00 15
            ..*...
--
15,4062,90309000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
            [hci0] 00:35:58.529604
15,4063,90309000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
15,4064,90309000,-;btmon:         Handle: 0x0041
15,4065,90309000,-;btmon:         Offset: 0x006e
--
15,4073,90623000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 16
            [hci0] 00:35:58.843074
15,4074,90623000,-;btmon:       ATT: Read Blob Response (0x0d) len 11
15,4075,90623000,-;btmon:         00 26 ff 00 75 08 95 01 81 02 c0
            .&..u......
15,4076,90623000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb() HoG inspecting report
map
15,4077,90623000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb() Report MAP:
15,4078,90623000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          05 01
15,4079,90623000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          09 06
15,4080,90623000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          a1 01
15,4081,90623000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          85 02
15,4082,90623000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          05 07
15,4083,90624000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          19 e0
15,4084,90625000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          29 e7
15,4085,90625000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          15 00
15,4086,90627000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          25 01
15,4087,90627000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          75 01
15,4088,90629000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          95 08
15,4089,90630000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          81 02
15,4090,90633000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          95 01
15,4091,90634000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          75 08
15,4092,90637000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          81 01
15,4093,90638000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          95 05
15,4094,90641000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          75 01
15,4095,90641000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          05 08
15,4096,90642000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          19 01
15,4097,90642000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          29 05
15,4098,90645000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          91 02
15,4099,90646000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          95 01
15,4100,90647000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          75 03
15,4101,90649000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          91 01
15,4102,90650000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          95 06
15,4103,90650000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          75 08
15,4104,90656000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          15 00
15,4105,90658000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          25 73
15,4106,90658000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          05 07
15,4107,90661000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          19 00
15,4108,90662000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          29 73
15,4109,90669000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          81 00
15,4110,90669000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          c0
15,4111,90672000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          05 0c
15,4112,90672000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          09 01
15,4113,90673000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          a1 01
15,4114,90673000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          85 03
15,4115,90676000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          05 0c
15,4116,90676000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          a1 02
15,4117,90677000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          19 00
15,4118,90678000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          2a 3c 02
15,4119,90678000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          15 00
15,4120,90680000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          26 3c 02
15,4121,90681000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          95 01
15,4122,90683000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          75 10
15,4123,90684000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          81 00
15,4124,90686000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          c0
15,4125,90688000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          c0
15,4126,90689000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          06 00 ff
15,4127,90690000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          09 07
15,4128,90694000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          a1 01
15,4129,90694000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          85 81
15,4130,90695000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          19 00
15,4131,90696000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          2a ff 00
15,4132,90696000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          15 00
15,4133,90697000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          26 ff 00
15,4134,90697000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          75 08
15,4135,90698000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          95 01
15,4136,90698000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          81 02
15,4137,90699000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb()          c0
15,4140,90713000,-;bluez: bluetoothd[2345]:
profiles/input/hog-lib.c:report_map_read_cb() HoG created uHID device

On Thu, Dec 29, 2016 at 5:23 AM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi,
>
> On Tue, Dec 27, 2016 at 2:40 PM, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>>
>> This add support of passing a gatt-db to avoid having to discover the
>> services again, this should also make it easier to port to bt_gatt_client
>> once Android code support it.
>> ---
>>  android/hidhost.c        |   4 +
>>  profiles/input/hog-lib.c | 247 +++++++++++++++++++++++++++++++++++++++++------
>>  profiles/input/hog-lib.h |   4 +-
>>  profiles/input/hog.c     |  61 ++++++------
>>  unit/test-hog.c          |   6 ++
>>  5 files changed, 255 insertions(+), 67 deletions(-)
>>
>> diff --git a/android/hidhost.c b/android/hidhost.c
>> index 591ca95..fe0ea2f 100644
>> --- a/android/hidhost.c
>> +++ b/android/hidhost.c
>> @@ -38,9 +38,13 @@
>>  #include "lib/bluetooth.h"
>>  #include "lib/sdp.h"
>>  #include "lib/sdp_lib.h"
>> +#include "lib/uuid.h"
>>  #include "src/shared/mgmt.h"
>>  #include "src/shared/util.h"
>>  #include "src/shared/uhid.h"
>> +#include "src/shared/queue.h"
>> +#include "src/shared/att.h"
>> +#include "src/shared/gatt-db.h"
>>  #include "src/sdp-client.h"
>>  #include "src/uuid-helper.h"
>>  #include "src/log.h"
>> diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
>> index e376c2b..ed38916 100644
>> --- a/profiles/input/hog-lib.c
>> +++ b/profiles/input/hog-lib.c
>> @@ -45,6 +45,8 @@
>>  #include "src/shared/util.h"
>>  #include "src/shared/uhid.h"
>>  #include "src/shared/queue.h"
>> +#include "src/shared/att.h"
>> +#include "src/shared/gatt-db.h"
>>  #include "src/log.h"
>>
>>  #include "attrib/att.h"
>> @@ -59,6 +61,7 @@
>>  #include "profiles/input/hog-lib.h"
>>
>>  #define HOG_UUID               "00001812-0000-1000-8000-00805f9b34fb"
>> +#define HOG_UUID16             0x1812
>>
>>  #define HOG_INFO_UUID          0x2A4A
>>  #define HOG_REPORT_MAP_UUID    0x2A4B
>> @@ -83,6 +86,7 @@ struct bt_hog {
>>         uint16_t                vendor;
>>         uint16_t                product;
>>         uint16_t                version;
>> +       struct gatt_db_attribute *attr;
>>         struct gatt_primary     *primary;
>>         GAttrib                 *attrib;
>>         GSList                  *reports;
>> @@ -110,9 +114,11 @@ struct report {
>>         struct bt_hog           *hog;
>>         uint8_t                 id;
>>         uint8_t                 type;
>> +       uint16_t                handle;
>> +       uint16_t                value_handle;
>> +       uint8_t                 properties;
>>         uint16_t                ccc_handle;
>>         guint                   notifyid;
>> -       struct gatt_char        *decl;
>>         uint16_t                len;
>>         uint8_t                 *value;
>>  };
>> @@ -181,6 +187,10 @@ static void read_char(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
>>         struct gatt_request *req;
>>         unsigned int id;
>>
>> +       /* Ignore if not connected */
>> +       if (!attrib)
>> +               return;
>> +
>>         req = create_request(hog, user_data);
>>         if (!req)
>>                 return;
>> @@ -334,7 +344,7 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
>>
>>         report->notifyid = g_attrib_register(hog->attrib,
>>                                         ATT_OP_HANDLE_NOTIFY,
>> -                                       report->decl->value_handle,
>> +                                       report->value_handle,
>>                                         report_value_cb, report, NULL);
>>
>>         DBG("Report characteristic descriptor written: notifications enabled");
>> @@ -403,7 +413,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
>>         report->id = pdu[1];
>>         report->type = pdu[2];
>>
>> -       DBG("Report 0x%04x: id 0x%02x type %s", report->decl->value_handle,
>> +       DBG("Report 0x%04x: id 0x%02x type %s", report->value_handle,
>>                                 report->id, type_to_string(report->type));
>>
>>         /* Enable notifications only for Input Reports */
>> @@ -516,7 +526,7 @@ static int report_chrc_cmp(const void *data, const void *user_data)
>>         const struct report *report = data;
>>         const struct gatt_char *decl = user_data;
>>
>> -       return report->decl->handle - decl->handle;
>> +       return report->handle - decl->handle;
>>  }
>>
>>  static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
>> @@ -531,7 +541,9 @@ static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
>>
>>         report = g_new0(struct report, 1);
>>         report->hog = hog;
>> -       report->decl = g_memdup(chr, sizeof(*chr));
>> +       report->handle = chr->handle;
>> +       report->value_handle = chr->value_handle;
>> +       report->properties = chr->properties;
>>         hog->reports = g_slist_append(hog->reports, report);
>>
>>         read_char(hog, hog->attrib, chr->value_handle, report_read_cb, report);
>> @@ -691,16 +703,16 @@ static void forward_report(struct uhid_event *ev, void *user_data)
>>         }
>>
>>         DBG("Sending report type %d ID %d to handle 0x%X", report->type,
>> -                               report->id, report->decl->value_handle);
>> +                               report->id, report->value_handle);
>>
>>         if (hog->attrib == NULL)
>>                 return;
>>
>> -       if (report->decl->properties & GATT_CHR_PROP_WRITE)
>> -               write_char(hog, hog->attrib, report->decl->value_handle,
>> +       if (report->properties & GATT_CHR_PROP_WRITE)
>> +               write_char(hog, hog->attrib, report->value_handle,
>>                                 data, size, output_written_cb, hog);
>> -       else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>> -               gatt_write_cmd(hog->attrib, report->decl->value_handle,
>> +       else if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>> +               gatt_write_cmd(hog->attrib, report->value_handle,
>>                                                 data, size, NULL, NULL);
>>  }
>>
>> @@ -789,13 +801,13 @@ static void set_report(struct uhid_event *ev, void *user_data)
>>         }
>>
>>         DBG("Sending report type %d ID %d to handle 0x%X", report->type,
>> -                               report->id, report->decl->value_handle);
>> +                               report->id, report->value_handle);
>>
>>         if (hog->attrib == NULL)
>>                 return;
>>
>>         hog->setrep_att = gatt_write_char(hog->attrib,
>> -                                               report->decl->value_handle,
>> +                                               report->value_handle,
>>                                                 data, size, set_report_cb,
>>                                                 hog);
>>         if (!hog->setrep_att) {
>> @@ -878,7 +890,7 @@ static void get_report(struct uhid_event *ev, void *user_data)
>>         }
>>
>>         hog->getrep_att = gatt_read_char(hog->attrib,
>> -                                               report->decl->value_handle,
>> +                                               report->value_handle,
>>                                                 get_report_cb, hog);
>>         if (!hog->getrep_att) {
>>                 err = ENOMEM;
>> @@ -1180,7 +1192,6 @@ static void report_free(void *data)
>>         struct report *report = data;
>>
>>         g_free(report->value);
>> -       g_free(report->decl);
>>         g_free(report);
>>  }
>>
>> @@ -1211,14 +1222,132 @@ static void hog_free(void *data)
>>
>>  struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
>>                                         uint16_t product, uint16_t version,
>> -                                       void *primary)
>> +                                       struct gatt_db *db)
>>  {
>> -       return bt_hog_new(-1, name, vendor, product, version, primary);
>> +       return bt_hog_new(-1, name, vendor, product, version, db);
>>  }
>>
>> -struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>> +static void foreach_hog_report(struct gatt_db_attribute *attr, void *user_data)
>> +{
>> +       struct report *report = user_data;
>> +       struct bt_hog *hog = report->hog;
>> +       const bt_uuid_t *uuid;
>> +       bt_uuid_t ref_uuid, ccc_uuid;
>> +       uint16_t handle;
>> +
>> +       handle = gatt_db_attribute_get_handle(attr);
>> +       uuid = gatt_db_attribute_get_type(attr);
>> +
>> +       bt_uuid16_create(&ref_uuid, GATT_REPORT_REFERENCE);
>> +       if (!bt_uuid_cmp(&ref_uuid, uuid)) {
>> +               read_char(hog, hog->attrib, handle, report_reference_cb,
>> +                                                               report);
>> +               return;
>> +       }
>> +
>> +       bt_uuid16_create(&ccc_uuid, GATT_CLIENT_CHARAC_CFG_UUID);
>> +       if (!bt_uuid_cmp(&ccc_uuid, uuid))
>> +               report->ccc_handle = handle;
>> +}
>> +
>> +static int report_attr_cmp(const void *data, const void *user_data)
>> +{
>> +       const struct report *report = data;
>> +       const struct gatt_db_attribute *attr = user_data;
>> +
>> +       return report->handle - gatt_db_attribute_get_handle(attr);
>> +}
>> +
>> +static struct report *report_add(struct bt_hog *hog,
>> +                                       struct gatt_db_attribute *attr)
>> +{
>> +       struct report *report;
>> +       GSList *l;
>> +
>> +       /* Skip if report already exists */
>> +       l = g_slist_find_custom(hog->reports, attr, report_attr_cmp);
>> +       if (l)
>> +               return l->data;
>> +
>> +       report = g_new0(struct report, 1);
>> +       report->hog = hog;
>> +
>> +       gatt_db_attribute_get_char_data(attr, &report->handle,
>> +                                       &report->value_handle,
>> +                                       &report->properties,
>> +                                       NULL, NULL);
>> +
>> +       hog->reports = g_slist_append(hog->reports, report);
>> +
>> +       read_char(hog, hog->attrib, report->value_handle, report_read_cb,
>> +                                                               report);
>> +
>> +       return report;
>> +}
>> +
>> +static void foreach_hog_external(struct gatt_db_attribute *attr,
>> +                                                       void *user_data)
>> +{
>> +       struct bt_hog *hog = user_data;
>> +       const bt_uuid_t *uuid;
>> +       bt_uuid_t ext_uuid;
>> +       uint16_t handle;
>> +
>> +       handle = gatt_db_attribute_get_handle(attr);
>> +       uuid = gatt_db_attribute_get_type(attr);
>> +
>> +       bt_uuid16_create(&ext_uuid, GATT_EXTERNAL_REPORT_REFERENCE);
>> +       if (!bt_uuid_cmp(&ext_uuid, uuid))
>> +               read_char(hog, hog->attrib, handle,
>> +                                       external_report_reference_cb, hog);
>> +}
>> +
>> +static void foreach_hog_chrc(struct gatt_db_attribute *attr, void *user_data)
>> +{
>> +       struct bt_hog *hog = user_data;
>> +       bt_uuid_t uuid, report_uuid, report_map_uuid, info_uuid;
>> +       bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
>> +       uint16_t handle, value_handle;
>> +
>> +       gatt_db_attribute_get_char_data(attr, &handle, &value_handle, NULL,
>> +                                       NULL, &uuid);
>> +
>> +       bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
>> +       if (!bt_uuid_cmp(&report_uuid, &uuid)) {
>> +               struct report *report = report_add(hog, attr);
>> +               gatt_db_service_foreach_desc(attr, foreach_hog_report, report);
>> +               return;
>> +       }
>> +
>> +       bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
>> +       if (!bt_uuid_cmp(&report_map_uuid, &uuid)) {
>> +               read_char(hog, hog->attrib, value_handle, report_map_read_cb,
>> +                                                                       hog);
>> +               gatt_db_service_foreach_desc(attr, foreach_hog_external, hog);
>> +               return;
>> +       }
>> +
>> +       bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
>> +       if (!bt_uuid_cmp(&info_uuid, &uuid)) {
>> +               read_char(hog, hog->attrib, value_handle, info_read_cb, hog);
>> +               return;
>> +       }
>> +
>> +       bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
>> +       if (!bt_uuid_cmp(&proto_mode_uuid, &uuid)) {
>> +               hog->proto_mode_handle = value_handle;
>> +               read_char(hog, hog->attrib, value_handle, proto_mode_read_cb,
>> +                                                                       hog);
>> +       }
>> +
>> +       bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
>> +       if (!bt_uuid_cmp(&ctrlpt_uuid, &uuid))
>> +               hog->ctrlpt_handle = value_handle;
>> +}
>> +
>> +static struct bt_hog *hog_new(int fd, const char *name, uint16_t vendor,
>>                                         uint16_t product, uint16_t version,
>> -                                       void *primary)
>> +                                       struct gatt_db_attribute *attr)
>>  {
>>         struct bt_hog *hog;
>>
>> @@ -1245,9 +1374,58 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>>         hog->vendor = vendor;
>>         hog->product = product;
>>         hog->version = version;
>> +       hog->attr = attr;
>>
>> -       if (primary)
>> -               hog->primary = g_memdup(primary, sizeof(*hog->primary));
>> +       return hog;
>> +}
>> +
>> +static void hog_attach_instace(struct bt_hog *hog,
>> +                               struct gatt_db_attribute *attr)
>> +{
>> +       struct bt_hog *instance;
>> +
>> +       if (!hog->attr) {
>> +               hog->attr = attr;
>> +               gatt_db_service_foreach_char(hog->attr, foreach_hog_chrc, hog);
>> +               return;
>> +       }
>> +
>> +       instance = hog_new(hog->uhid_fd, hog->name, hog->vendor,
>> +                                       hog->product, hog->version, attr);
>> +       if (!instance)
>> +               return;
>> +
>> +       hog->instances = g_slist_append(hog->instances, instance);
>> +}
>> +
>> +static void foreach_hog_service(struct gatt_db_attribute *attr, void *user_data)
>> +{
>> +       struct bt_hog *hog = user_data;
>> +
>> +       hog_attach_instace(hog, attr);
>> +}
>> +
>> +struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>> +                                       uint16_t product, uint16_t version,
>> +                                       struct gatt_db *db)
>> +{
>> +       struct bt_hog *hog;
>> +
>> +       hog = hog_new(fd, name, vendor, product, version, NULL);
>> +       if (!hog)
>> +               return NULL;
>> +
>> +       if (db) {
>> +               bt_uuid_t uuid;
>> +
>> +               /* Handle the HID services */
>> +               bt_uuid16_create(&uuid, HOG_UUID16);
>> +               gatt_db_foreach_service(db, &uuid, foreach_hog_service, hog);
>> +               if (!hog->attr) {
>> +                       hog_free(hog);
>> +                       return NULL;
>> +               }
>> +       }
>>
>>         return bt_hog_ref(hog);
>>  }
>> @@ -1357,10 +1535,11 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
>>         }
>>
>>         instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
>> -                                       hog->product, hog->version, primary);
>> +                                       hog->product, hog->version, NULL);
>>         if (!instance)
>>                 return;
>>
>> +       instance->primary = g_memdup(primary, sizeof(*primary));
>>         find_included(instance, hog->attrib, primary->range.start,
>>                         primary->range.end, find_included_cb, instance);
>>
>> @@ -1415,7 +1594,6 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
>>
>>  bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>  {
>> -       struct gatt_primary *primary = hog->primary;
>>         GSList *l;
>>
>>         if (hog->attrib)
>> @@ -1423,7 +1601,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>
>>         hog->attrib = g_attrib_ref(gatt);
>>
>> -       if (!primary) {
>> +       if (!hog->attr && !hog->primary) {
>>                 discover_primary(hog, hog->attrib, NULL, primary_cb, hog);
>>                 return true;
>>         }
>> @@ -1444,9 +1622,14 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>
>>         if (!hog->uhid_created) {
>>                 DBG("HoG discovering characteristics");
>> -               discover_char(hog, hog->attrib, primary->range.start,
>> -                                               primary->range.end, NULL,
>> -                                               char_discovered_cb, hog);
>> +               if (hog->attr)
>> +                       gatt_db_service_foreach_char(hog->attr,
>> +                                                       foreach_hog_chrc, hog);
>> +               else
>> +                       discover_char(hog, hog->attrib,
>> +                                       hog->primary->range.start,
>> +                                       hog->primary->range.end, NULL,
>> +                                       char_discovered_cb, hog);
>>                 return true;
>>         }
>>
>> @@ -1455,7 +1638,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>
>>                 r->notifyid = g_attrib_register(hog->attrib,
>>                                         ATT_OP_HANDLE_NOTIFY,
>> -                                       r->decl->value_handle,
>> +                                       r->value_handle,
>>                                         report_value_cb, r, NULL);
>>         }
>>
>> @@ -1528,14 +1711,14 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
>>         if (!report)
>>                 return -ENOTSUP;
>>
>> -       DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
>> +       DBG("hog: Write report, handle 0x%X", report->value_handle);
>>
>> -       if (report->decl->properties & GATT_CHR_PROP_WRITE)
>> -               write_char(hog, hog->attrib, report->decl->value_handle,
>> +       if (report->properties & GATT_CHR_PROP_WRITE)
>> +               write_char(hog, hog->attrib, report->value_handle,
>>                                 data, size, output_written_cb, hog);
>>
>> -       if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>> -               gatt_write_cmd(hog->attrib, report->decl->value_handle,
>> +       if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>> +               gatt_write_cmd(hog->attrib, report->value_handle,
>>                                                 data, size, NULL, NULL);
>>
>>         for (l = hog->instances; l; l = l->next) {
>> diff --git a/profiles/input/hog-lib.h b/profiles/input/hog-lib.h
>> index 2a9b899..415dc63 100644
>> --- a/profiles/input/hog-lib.h
>> +++ b/profiles/input/hog-lib.h
>> @@ -25,11 +25,11 @@ struct bt_hog;
>>
>>  struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
>>                                         uint16_t product, uint16_t version,
>> -                                       void *primary);
>> +                                       struct gatt_db *db);
>>
>>  struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>>                                         uint16_t product, uint16_t version,
>> -                                       void *primary);
>> +                                       struct gatt_db *db);
>>
>>  struct bt_hog *bt_hog_ref(struct bt_hog *hog);
>>  void bt_hog_unref(struct bt_hog *hog);
>> diff --git a/profiles/input/hog.c b/profiles/input/hog.c
>> index 7d318cd..23c9c15 100644
>> --- a/profiles/input/hog.c
>> +++ b/profiles/input/hog.c
>> @@ -67,32 +67,34 @@ struct hog_device {
>>  static gboolean suspend_supported = FALSE;
>>  static struct queue *devices = NULL;
>>
>> -static struct hog_device *hog_device_new(struct btd_device *device,
>> -                                               struct gatt_primary *prim)
>> +static void hog_device_accept(struct hog_device *dev, struct gatt_db *db)
>>  {
>> -       struct hog_device *dev;
>>         char name[248];
>>         uint16_t vendor, product, version;
>>
>> -       if (device_name_known(device))
>> -               device_get_name(device, name, sizeof(name));
>> +       if (dev->hog)
>> +               return;
>> +
>> +       if (device_name_known(dev->device))
>> +               device_get_name(dev->device, name, sizeof(name));
>>         else
>>                 strcpy(name, "bluez-hog-device");
>>
>> -       vendor = btd_device_get_vendor(device);
>> -       product = btd_device_get_product(device);
>> -       version = btd_device_get_version(device);
>> +       vendor = btd_device_get_vendor(dev->device);
>> +       product = btd_device_get_product(dev->device);
>> +       version = btd_device_get_version(dev->device);
>>
>>         DBG("name=%s vendor=0x%X, product=0x%X, version=0x%X", name, vendor,
>>                                                         product, version);
>>
>> -       dev = new0(struct hog_device, 1);
>> -       dev->hog = bt_hog_new_default(name, vendor, product, version, prim);
>> -       if (!dev->hog) {
>> -               free(dev);
>> -               return NULL;
>> -       }
>> +       dev->hog = bt_hog_new_default(name, vendor, product, version, db);
>> +}
>>
>> +static struct hog_device *hog_device_new(struct btd_device *device)
>> +{
>> +       struct hog_device *dev;
>> +
>> +       dev = new0(struct hog_device, 1);
>>         dev->device = btd_device_ref(device);
>>
>>         if (!devices)
>> @@ -148,30 +150,16 @@ static int hog_probe(struct btd_service *service)
>>  {
>>         struct btd_device *device = btd_service_get_device(service);
>>         const char *path = device_get_path(device);
>> -       GSList *primaries, *l;
>> +       struct hog_device *dev;
>>
>>         DBG("path %s", path);
>>
>> -       primaries = btd_device_get_primaries(device);
>> -       if (primaries == NULL)
>> +       dev = hog_device_new(device);
>> +       if (!dev)
>>                 return -EINVAL;
>>
>> -       for (l = primaries; l; l = g_slist_next(l)) {
>> -               struct gatt_primary *prim = l->data;
>> -               struct hog_device *dev;
>> -
>> -               if (strcmp(prim->uuid, HOG_UUID) != 0)
>> -                       continue;
>> -
>> -               dev = hog_device_new(device, prim);
>> -               if (!dev)
>> -                       break;
>> -
>> -               btd_service_set_user_data(service, dev);
>> -               return 0;
>> -       }
>> -
>> -       return -EINVAL;
>> +       btd_service_set_user_data(service, dev);
>> +       return 0;
>>  }
>>
>>  static void hog_remove(struct btd_service *service)
>> @@ -189,8 +177,15 @@ static int hog_accept(struct btd_service *service)
>>  {
>>         struct hog_device *dev = btd_service_get_user_data(service);
>>         struct btd_device *device = btd_service_get_device(service);
>> +       struct gatt_db *db = btd_device_get_gatt_db(device);
>>         GAttrib *attrib = btd_device_get_attrib(device);
>>
>> +       if (!dev->hog) {
>> +               hog_device_accept(dev, db);
>> +               if (!dev->hog)
>> +                       return -EINVAL;
>> +       }
>> +
>>         /* TODO: Replace GAttrib with bt_gatt_client */
>>         bt_hog_attach(dev->hog, attrib);
>>
>> diff --git a/unit/test-hog.c b/unit/test-hog.c
>> index 9f026e5..d117968 100644
>> --- a/unit/test-hog.c
>> +++ b/unit/test-hog.c
>> @@ -32,8 +32,14 @@
>>
>>  #include <glib.h>
>>
>> +#include "lib/bluetooth.h"
>> +#include "lib/uuid.h"
>> +
>>  #include "src/shared/util.h"
>>  #include "src/shared/tester.h"
>> +#include "src/shared/queue.h"
>> +#include "src/shared/att.h"
>> +#include "src/shared/gatt-db.h"
>>
>>  #include "attrib/gattrib.h"
>>
>> --
>> 2.9.3
>
> Applied.
>
>
> --
> Luiz Augusto von Dentz
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db
  2016-12-30  0:47   ` Petri Gynther
@ 2016-12-30  8:59     ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2016-12-30  8:59 UTC (permalink / raw
  To: Petri Gynther; +Cc: linux-bluetooth@vger.kernel.org

Hi Petri,

On Fri, Dec 30, 2016 at 2:47 AM, Petri Gynther <pgynther@google.com> wrote:
> Hi Luiz,
>
> Are these 3 patches supposed to eliminate re-reading the HoG report
> map from the device on reconnect? And get it from GATT DB instead?

Nope, there is no caching for values only handles so this is working
as intended, though in the future we may allow the profile to store
the values directly in the db which should indicate the core to store
it on file but if we were strictly following the spec the values could
in fact change.

> I merged the tip of BlueZ and tried it with our HoG remote. But, I
> still see Read Blob Requests & Responses being sent over air to
> re-read the report map:
>
> 15,3601,88379000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
>             [hci0] 00:35:56.596115
> 15,3602,88379000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
> 15,3603,88379000,-;btmon:         Handle: 0x0041
> 15,3604,88379000,-;btmon:         Offset: 0x0016
> --
> 15,3609,88402000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
>             [hci0] 00:35:56.624487
> 15,3610,88402000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
> 15,3611,88402000,-;btmon:         81 02 95 01 75 08 81 01 95 05 75 01
> 05 08 19 01  ....u.....u.....
> 15,3612,88402000,-;btmon:         29 05 91 02 95 01
>             ).....
> --
> 15,3704,88585000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
>             [hci0] 00:35:56.805750
> 15,3705,88585000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
> 15,3706,88585000,-;btmon:         Handle: 0x0041
> 15,3707,88585000,-;btmon:         Offset: 0x002c
> --
> 15,3712,88609000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
>             [hci0] 00:35:56.831684
> 15,3713,88609000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
> 15,3714,88609000,-;btmon:         75 03 91 01 95 06 75 08 15 00 25 73
> 05 07 19 00  u.....u...%s....
> 15,3715,88610000,-;btmon:         29 73 81 00 c0 05
>             )s....
> --
> 15,3842,89855000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
>             [hci0] 00:35:58.074749
> 15,3843,89855000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
> 15,3844,89855000,-;btmon:         Handle: 0x0041
> 15,3845,89855000,-;btmon:         Offset: 0x0042
> --
> 15,3850,89882000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
>             [hci0] 00:35:58.104341
> 15,3851,89882000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
> 15,3852,89882000,-;btmon:         0c 09 01 a1 01 85 03 05 0c a1 02 19
> 00 2a 3c 02  .............*<.
> 15,3853,89882000,-;btmon:         15 00 26 3c 02 95
>             ..&<..
> --
> 15,3984,90013000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
>             [hci0] 00:35:58.235072
> 15,3985,90016000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
> 15,3986,90016000,-;btmon:         Handle: 0x0041
> 15,3987,90016000,-;btmon:         Offset: 0x0058
> --
> 15,3992,90041000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 27
>             [hci0] 00:35:58.263061
> 15,3993,90041000,-;btmon:       ATT: Read Blob Response (0x0d) len 22
> 15,3994,90041000,-;btmon:         01 75 10 81 00 c0 c0 06 00 ff 09 07
> a1 01 85 81  .u..............
> 15,3995,90041000,-;btmon:         19 00 2a ff 00 15
>             ..*...
> --
> 15,4062,90309000,-;btmon: < ACL Data TX: Handle 128 flags 0x00 dlen 9
>             [hci0] 00:35:58.529604
> 15,4063,90309000,-;btmon:       ATT: Read Blob Request (0x0c) len 4
> 15,4064,90309000,-;btmon:         Handle: 0x0041
> 15,4065,90309000,-;btmon:         Offset: 0x006e
> --
> 15,4073,90623000,-;btmon: > ACL Data RX: Handle 128 flags 0x02 dlen 16
>             [hci0] 00:35:58.843074
> 15,4074,90623000,-;btmon:       ATT: Read Blob Response (0x0d) len 11
> 15,4075,90623000,-;btmon:         00 26 ff 00 75 08 95 01 81 02 c0
>             .&..u......
> 15,4076,90623000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb() HoG inspecting report
> map
> 15,4077,90623000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb() Report MAP:
> 15,4078,90623000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          05 01
> 15,4079,90623000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          09 06
> 15,4080,90623000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          a1 01
> 15,4081,90623000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          85 02
> 15,4082,90623000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          05 07
> 15,4083,90624000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          19 e0
> 15,4084,90625000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          29 e7
> 15,4085,90625000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          15 00
> 15,4086,90627000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          25 01
> 15,4087,90627000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          75 01
> 15,4088,90629000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          95 08
> 15,4089,90630000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          81 02
> 15,4090,90633000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          95 01
> 15,4091,90634000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          75 08
> 15,4092,90637000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          81 01
> 15,4093,90638000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          95 05
> 15,4094,90641000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          75 01
> 15,4095,90641000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          05 08
> 15,4096,90642000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          19 01
> 15,4097,90642000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          29 05
> 15,4098,90645000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          91 02
> 15,4099,90646000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          95 01
> 15,4100,90647000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          75 03
> 15,4101,90649000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          91 01
> 15,4102,90650000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          95 06
> 15,4103,90650000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          75 08
> 15,4104,90656000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          15 00
> 15,4105,90658000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          25 73
> 15,4106,90658000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          05 07
> 15,4107,90661000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          19 00
> 15,4108,90662000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          29 73
> 15,4109,90669000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          81 00
> 15,4110,90669000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          c0
> 15,4111,90672000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          05 0c
> 15,4112,90672000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          09 01
> 15,4113,90673000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          a1 01
> 15,4114,90673000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          85 03
> 15,4115,90676000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          05 0c
> 15,4116,90676000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          a1 02
> 15,4117,90677000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          19 00
> 15,4118,90678000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          2a 3c 02
> 15,4119,90678000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          15 00
> 15,4120,90680000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          26 3c 02
> 15,4121,90681000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          95 01
> 15,4122,90683000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          75 10
> 15,4123,90684000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          81 00
> 15,4124,90686000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          c0
> 15,4125,90688000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          c0
> 15,4126,90689000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          06 00 ff
> 15,4127,90690000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          09 07
> 15,4128,90694000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          a1 01
> 15,4129,90694000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          85 81
> 15,4130,90695000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          19 00
> 15,4131,90696000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          2a ff 00
> 15,4132,90696000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          15 00
> 15,4133,90697000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          26 ff 00
> 15,4134,90697000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          75 08
> 15,4135,90698000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          95 01
> 15,4136,90698000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          81 02
> 15,4137,90699000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb()          c0
> 15,4140,90713000,-;bluez: bluetoothd[2345]:
> profiles/input/hog-lib.c:report_map_read_cb() HoG created uHID device
>
> On Thu, Dec 29, 2016 at 5:23 AM, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>> Hi,
>>
>> On Tue, Dec 27, 2016 at 2:40 PM, Luiz Augusto von Dentz
>> <luiz.dentz@gmail.com> wrote:
>>> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>>>
>>> This add support of passing a gatt-db to avoid having to discover the
>>> services again, this should also make it easier to port to bt_gatt_client
>>> once Android code support it.
>>> ---
>>>  android/hidhost.c        |   4 +
>>>  profiles/input/hog-lib.c | 247 +++++++++++++++++++++++++++++++++++++++++------
>>>  profiles/input/hog-lib.h |   4 +-
>>>  profiles/input/hog.c     |  61 ++++++------
>>>  unit/test-hog.c          |   6 ++
>>>  5 files changed, 255 insertions(+), 67 deletions(-)
>>>
>>> diff --git a/android/hidhost.c b/android/hidhost.c
>>> index 591ca95..fe0ea2f 100644
>>> --- a/android/hidhost.c
>>> +++ b/android/hidhost.c
>>> @@ -38,9 +38,13 @@
>>>  #include "lib/bluetooth.h"
>>>  #include "lib/sdp.h"
>>>  #include "lib/sdp_lib.h"
>>> +#include "lib/uuid.h"
>>>  #include "src/shared/mgmt.h"
>>>  #include "src/shared/util.h"
>>>  #include "src/shared/uhid.h"
>>> +#include "src/shared/queue.h"
>>> +#include "src/shared/att.h"
>>> +#include "src/shared/gatt-db.h"
>>>  #include "src/sdp-client.h"
>>>  #include "src/uuid-helper.h"
>>>  #include "src/log.h"
>>> diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
>>> index e376c2b..ed38916 100644
>>> --- a/profiles/input/hog-lib.c
>>> +++ b/profiles/input/hog-lib.c
>>> @@ -45,6 +45,8 @@
>>>  #include "src/shared/util.h"
>>>  #include "src/shared/uhid.h"
>>>  #include "src/shared/queue.h"
>>> +#include "src/shared/att.h"
>>> +#include "src/shared/gatt-db.h"
>>>  #include "src/log.h"
>>>
>>>  #include "attrib/att.h"
>>> @@ -59,6 +61,7 @@
>>>  #include "profiles/input/hog-lib.h"
>>>
>>>  #define HOG_UUID               "00001812-0000-1000-8000-00805f9b34fb"
>>> +#define HOG_UUID16             0x1812
>>>
>>>  #define HOG_INFO_UUID          0x2A4A
>>>  #define HOG_REPORT_MAP_UUID    0x2A4B
>>> @@ -83,6 +86,7 @@ struct bt_hog {
>>>         uint16_t                vendor;
>>>         uint16_t                product;
>>>         uint16_t                version;
>>> +       struct gatt_db_attribute *attr;
>>>         struct gatt_primary     *primary;
>>>         GAttrib                 *attrib;
>>>         GSList                  *reports;
>>> @@ -110,9 +114,11 @@ struct report {
>>>         struct bt_hog           *hog;
>>>         uint8_t                 id;
>>>         uint8_t                 type;
>>> +       uint16_t                handle;
>>> +       uint16_t                value_handle;
>>> +       uint8_t                 properties;
>>>         uint16_t                ccc_handle;
>>>         guint                   notifyid;
>>> -       struct gatt_char        *decl;
>>>         uint16_t                len;
>>>         uint8_t                 *value;
>>>  };
>>> @@ -181,6 +187,10 @@ static void read_char(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
>>>         struct gatt_request *req;
>>>         unsigned int id;
>>>
>>> +       /* Ignore if not connected */
>>> +       if (!attrib)
>>> +               return;
>>> +
>>>         req = create_request(hog, user_data);
>>>         if (!req)
>>>                 return;
>>> @@ -334,7 +344,7 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
>>>
>>>         report->notifyid = g_attrib_register(hog->attrib,
>>>                                         ATT_OP_HANDLE_NOTIFY,
>>> -                                       report->decl->value_handle,
>>> +                                       report->value_handle,
>>>                                         report_value_cb, report, NULL);
>>>
>>>         DBG("Report characteristic descriptor written: notifications enabled");
>>> @@ -403,7 +413,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
>>>         report->id = pdu[1];
>>>         report->type = pdu[2];
>>>
>>> -       DBG("Report 0x%04x: id 0x%02x type %s", report->decl->value_handle,
>>> +       DBG("Report 0x%04x: id 0x%02x type %s", report->value_handle,
>>>                                 report->id, type_to_string(report->type));
>>>
>>>         /* Enable notifications only for Input Reports */
>>> @@ -516,7 +526,7 @@ static int report_chrc_cmp(const void *data, const void *user_data)
>>>         const struct report *report = data;
>>>         const struct gatt_char *decl = user_data;
>>>
>>> -       return report->decl->handle - decl->handle;
>>> +       return report->handle - decl->handle;
>>>  }
>>>
>>>  static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
>>> @@ -531,7 +541,9 @@ static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
>>>
>>>         report = g_new0(struct report, 1);
>>>         report->hog = hog;
>>> -       report->decl = g_memdup(chr, sizeof(*chr));
>>> +       report->handle = chr->handle;
>>> +       report->value_handle = chr->value_handle;
>>> +       report->properties = chr->properties;
>>>         hog->reports = g_slist_append(hog->reports, report);
>>>
>>>         read_char(hog, hog->attrib, chr->value_handle, report_read_cb, report);
>>> @@ -691,16 +703,16 @@ static void forward_report(struct uhid_event *ev, void *user_data)
>>>         }
>>>
>>>         DBG("Sending report type %d ID %d to handle 0x%X", report->type,
>>> -                               report->id, report->decl->value_handle);
>>> +                               report->id, report->value_handle);
>>>
>>>         if (hog->attrib == NULL)
>>>                 return;
>>>
>>> -       if (report->decl->properties & GATT_CHR_PROP_WRITE)
>>> -               write_char(hog, hog->attrib, report->decl->value_handle,
>>> +       if (report->properties & GATT_CHR_PROP_WRITE)
>>> +               write_char(hog, hog->attrib, report->value_handle,
>>>                                 data, size, output_written_cb, hog);
>>> -       else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>>> -               gatt_write_cmd(hog->attrib, report->decl->value_handle,
>>> +       else if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>>> +               gatt_write_cmd(hog->attrib, report->value_handle,
>>>                                                 data, size, NULL, NULL);
>>>  }
>>>
>>> @@ -789,13 +801,13 @@ static void set_report(struct uhid_event *ev, void *user_data)
>>>         }
>>>
>>>         DBG("Sending report type %d ID %d to handle 0x%X", report->type,
>>> -                               report->id, report->decl->value_handle);
>>> +                               report->id, report->value_handle);
>>>
>>>         if (hog->attrib == NULL)
>>>                 return;
>>>
>>>         hog->setrep_att = gatt_write_char(hog->attrib,
>>> -                                               report->decl->value_handle,
>>> +                                               report->value_handle,
>>>                                                 data, size, set_report_cb,
>>>                                                 hog);
>>>         if (!hog->setrep_att) {
>>> @@ -878,7 +890,7 @@ static void get_report(struct uhid_event *ev, void *user_data)
>>>         }
>>>
>>>         hog->getrep_att = gatt_read_char(hog->attrib,
>>> -                                               report->decl->value_handle,
>>> +                                               report->value_handle,
>>>                                                 get_report_cb, hog);
>>>         if (!hog->getrep_att) {
>>>                 err = ENOMEM;
>>> @@ -1180,7 +1192,6 @@ static void report_free(void *data)
>>>         struct report *report = data;
>>>
>>>         g_free(report->value);
>>> -       g_free(report->decl);
>>>         g_free(report);
>>>  }
>>>
>>> @@ -1211,14 +1222,132 @@ static void hog_free(void *data)
>>>
>>>  struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
>>>                                         uint16_t product, uint16_t version,
>>> -                                       void *primary)
>>> +                                       struct gatt_db *db)
>>>  {
>>> -       return bt_hog_new(-1, name, vendor, product, version, primary);
>>> +       return bt_hog_new(-1, name, vendor, product, version, db);
>>>  }
>>>
>>> -struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>>> +static void foreach_hog_report(struct gatt_db_attribute *attr, void *user_data)
>>> +{
>>> +       struct report *report = user_data;
>>> +       struct bt_hog *hog = report->hog;
>>> +       const bt_uuid_t *uuid;
>>> +       bt_uuid_t ref_uuid, ccc_uuid;
>>> +       uint16_t handle;
>>> +
>>> +       handle = gatt_db_attribute_get_handle(attr);
>>> +       uuid = gatt_db_attribute_get_type(attr);
>>> +
>>> +       bt_uuid16_create(&ref_uuid, GATT_REPORT_REFERENCE);
>>> +       if (!bt_uuid_cmp(&ref_uuid, uuid)) {
>>> +               read_char(hog, hog->attrib, handle, report_reference_cb,
>>> +                                                               report);
>>> +               return;
>>> +       }
>>> +
>>> +       bt_uuid16_create(&ccc_uuid, GATT_CLIENT_CHARAC_CFG_UUID);
>>> +       if (!bt_uuid_cmp(&ccc_uuid, uuid))
>>> +               report->ccc_handle = handle;
>>> +}
>>> +
>>> +static int report_attr_cmp(const void *data, const void *user_data)
>>> +{
>>> +       const struct report *report = data;
>>> +       const struct gatt_db_attribute *attr = user_data;
>>> +
>>> +       return report->handle - gatt_db_attribute_get_handle(attr);
>>> +}
>>> +
>>> +static struct report *report_add(struct bt_hog *hog,
>>> +                                       struct gatt_db_attribute *attr)
>>> +{
>>> +       struct report *report;
>>> +       GSList *l;
>>> +
>>> +       /* Skip if report already exists */
>>> +       l = g_slist_find_custom(hog->reports, attr, report_attr_cmp);
>>> +       if (l)
>>> +               return l->data;
>>> +
>>> +       report = g_new0(struct report, 1);
>>> +       report->hog = hog;
>>> +
>>> +       gatt_db_attribute_get_char_data(attr, &report->handle,
>>> +                                       &report->value_handle,
>>> +                                       &report->properties,
>>> +                                       NULL, NULL);
>>> +
>>> +       hog->reports = g_slist_append(hog->reports, report);
>>> +
>>> +       read_char(hog, hog->attrib, report->value_handle, report_read_cb,
>>> +                                                               report);
>>> +
>>> +       return report;
>>> +}
>>> +
>>> +static void foreach_hog_external(struct gatt_db_attribute *attr,
>>> +                                                       void *user_data)
>>> +{
>>> +       struct bt_hog *hog = user_data;
>>> +       const bt_uuid_t *uuid;
>>> +       bt_uuid_t ext_uuid;
>>> +       uint16_t handle;
>>> +
>>> +       handle = gatt_db_attribute_get_handle(attr);
>>> +       uuid = gatt_db_attribute_get_type(attr);
>>> +
>>> +       bt_uuid16_create(&ext_uuid, GATT_EXTERNAL_REPORT_REFERENCE);
>>> +       if (!bt_uuid_cmp(&ext_uuid, uuid))
>>> +               read_char(hog, hog->attrib, handle,
>>> +                                       external_report_reference_cb, hog);
>>> +}
>>> +
>>> +static void foreach_hog_chrc(struct gatt_db_attribute *attr, void *user_data)
>>> +{
>>> +       struct bt_hog *hog = user_data;
>>> +       bt_uuid_t uuid, report_uuid, report_map_uuid, info_uuid;
>>> +       bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
>>> +       uint16_t handle, value_handle;
>>> +
>>> +       gatt_db_attribute_get_char_data(attr, &handle, &value_handle, NULL,
>>> +                                       NULL, &uuid);
>>> +
>>> +       bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
>>> +       if (!bt_uuid_cmp(&report_uuid, &uuid)) {
>>> +               struct report *report = report_add(hog, attr);
>>> +               gatt_db_service_foreach_desc(attr, foreach_hog_report, report);
>>> +               return;
>>> +       }
>>> +
>>> +       bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
>>> +       if (!bt_uuid_cmp(&report_map_uuid, &uuid)) {
>>> +               read_char(hog, hog->attrib, value_handle, report_map_read_cb,
>>> +                                                                       hog);
>>> +               gatt_db_service_foreach_desc(attr, foreach_hog_external, hog);
>>> +               return;
>>> +       }
>>> +
>>> +       bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
>>> +       if (!bt_uuid_cmp(&info_uuid, &uuid)) {
>>> +               read_char(hog, hog->attrib, value_handle, info_read_cb, hog);
>>> +               return;
>>> +       }
>>> +
>>> +       bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
>>> +       if (!bt_uuid_cmp(&proto_mode_uuid, &uuid)) {
>>> +               hog->proto_mode_handle = value_handle;
>>> +               read_char(hog, hog->attrib, value_handle, proto_mode_read_cb,
>>> +                                                                       hog);
>>> +       }
>>> +
>>> +       bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
>>> +       if (!bt_uuid_cmp(&ctrlpt_uuid, &uuid))
>>> +               hog->ctrlpt_handle = value_handle;
>>> +}
>>> +
>>> +static struct bt_hog *hog_new(int fd, const char *name, uint16_t vendor,
>>>                                         uint16_t product, uint16_t version,
>>> -                                       void *primary)
>>> +                                       struct gatt_db_attribute *attr)
>>>  {
>>>         struct bt_hog *hog;
>>>
>>> @@ -1245,9 +1374,58 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>>>         hog->vendor = vendor;
>>>         hog->product = product;
>>>         hog->version = version;
>>> +       hog->attr = attr;
>>>
>>> -       if (primary)
>>> -               hog->primary = g_memdup(primary, sizeof(*hog->primary));
>>> +       return hog;
>>> +}
>>> +
>>> +static void hog_attach_instace(struct bt_hog *hog,
>>> +                               struct gatt_db_attribute *attr)
>>> +{
>>> +       struct bt_hog *instance;
>>> +
>>> +       if (!hog->attr) {
>>> +               hog->attr = attr;
>>> +               gatt_db_service_foreach_char(hog->attr, foreach_hog_chrc, hog);
>>> +               return;
>>> +       }
>>> +
>>> +       instance = hog_new(hog->uhid_fd, hog->name, hog->vendor,
>>> +                                       hog->product, hog->version, attr);
>>> +       if (!instance)
>>> +               return;
>>> +
>>> +       hog->instances = g_slist_append(hog->instances, instance);
>>> +}
>>> +
>>> +static void foreach_hog_service(struct gatt_db_attribute *attr, void *user_data)
>>> +{
>>> +       struct bt_hog *hog = user_data;
>>> +
>>> +       hog_attach_instace(hog, attr);
>>> +}
>>> +
>>> +struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>>> +                                       uint16_t product, uint16_t version,
>>> +                                       struct gatt_db *db)
>>> +{
>>> +       struct bt_hog *hog;
>>> +
>>> +       hog = hog_new(fd, name, vendor, product, version, NULL);
>>> +       if (!hog)
>>> +               return NULL;
>>> +
>>> +       if (db) {
>>> +               bt_uuid_t uuid;
>>> +
>>> +               /* Handle the HID services */
>>> +               bt_uuid16_create(&uuid, HOG_UUID16);
>>> +               gatt_db_foreach_service(db, &uuid, foreach_hog_service, hog);
>>> +               if (!hog->attr) {
>>> +                       hog_free(hog);
>>> +                       return NULL;
>>> +               }
>>> +       }
>>>
>>>         return bt_hog_ref(hog);
>>>  }
>>> @@ -1357,10 +1535,11 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
>>>         }
>>>
>>>         instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
>>> -                                       hog->product, hog->version, primary);
>>> +                                       hog->product, hog->version, NULL);
>>>         if (!instance)
>>>                 return;
>>>
>>> +       instance->primary = g_memdup(primary, sizeof(*primary));
>>>         find_included(instance, hog->attrib, primary->range.start,
>>>                         primary->range.end, find_included_cb, instance);
>>>
>>> @@ -1415,7 +1594,6 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
>>>
>>>  bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>>  {
>>> -       struct gatt_primary *primary = hog->primary;
>>>         GSList *l;
>>>
>>>         if (hog->attrib)
>>> @@ -1423,7 +1601,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>>
>>>         hog->attrib = g_attrib_ref(gatt);
>>>
>>> -       if (!primary) {
>>> +       if (!hog->attr && !hog->primary) {
>>>                 discover_primary(hog, hog->attrib, NULL, primary_cb, hog);
>>>                 return true;
>>>         }
>>> @@ -1444,9 +1622,14 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>>
>>>         if (!hog->uhid_created) {
>>>                 DBG("HoG discovering characteristics");
>>> -               discover_char(hog, hog->attrib, primary->range.start,
>>> -                                               primary->range.end, NULL,
>>> -                                               char_discovered_cb, hog);
>>> +               if (hog->attr)
>>> +                       gatt_db_service_foreach_char(hog->attr,
>>> +                                                       foreach_hog_chrc, hog);
>>> +               else
>>> +                       discover_char(hog, hog->attrib,
>>> +                                       hog->primary->range.start,
>>> +                                       hog->primary->range.end, NULL,
>>> +                                       char_discovered_cb, hog);
>>>                 return true;
>>>         }
>>>
>>> @@ -1455,7 +1638,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>>>
>>>                 r->notifyid = g_attrib_register(hog->attrib,
>>>                                         ATT_OP_HANDLE_NOTIFY,
>>> -                                       r->decl->value_handle,
>>> +                                       r->value_handle,
>>>                                         report_value_cb, r, NULL);
>>>         }
>>>
>>> @@ -1528,14 +1711,14 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
>>>         if (!report)
>>>                 return -ENOTSUP;
>>>
>>> -       DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
>>> +       DBG("hog: Write report, handle 0x%X", report->value_handle);
>>>
>>> -       if (report->decl->properties & GATT_CHR_PROP_WRITE)
>>> -               write_char(hog, hog->attrib, report->decl->value_handle,
>>> +       if (report->properties & GATT_CHR_PROP_WRITE)
>>> +               write_char(hog, hog->attrib, report->value_handle,
>>>                                 data, size, output_written_cb, hog);
>>>
>>> -       if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>>> -               gatt_write_cmd(hog->attrib, report->decl->value_handle,
>>> +       if (report->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
>>> +               gatt_write_cmd(hog->attrib, report->value_handle,
>>>                                                 data, size, NULL, NULL);
>>>
>>>         for (l = hog->instances; l; l = l->next) {
>>> diff --git a/profiles/input/hog-lib.h b/profiles/input/hog-lib.h
>>> index 2a9b899..415dc63 100644
>>> --- a/profiles/input/hog-lib.h
>>> +++ b/profiles/input/hog-lib.h
>>> @@ -25,11 +25,11 @@ struct bt_hog;
>>>
>>>  struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
>>>                                         uint16_t product, uint16_t version,
>>> -                                       void *primary);
>>> +                                       struct gatt_db *db);
>>>
>>>  struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
>>>                                         uint16_t product, uint16_t version,
>>> -                                       void *primary);
>>> +                                       struct gatt_db *db);
>>>
>>>  struct bt_hog *bt_hog_ref(struct bt_hog *hog);
>>>  void bt_hog_unref(struct bt_hog *hog);
>>> diff --git a/profiles/input/hog.c b/profiles/input/hog.c
>>> index 7d318cd..23c9c15 100644
>>> --- a/profiles/input/hog.c
>>> +++ b/profiles/input/hog.c
>>> @@ -67,32 +67,34 @@ struct hog_device {
>>>  static gboolean suspend_supported = FALSE;
>>>  static struct queue *devices = NULL;
>>>
>>> -static struct hog_device *hog_device_new(struct btd_device *device,
>>> -                                               struct gatt_primary *prim)
>>> +static void hog_device_accept(struct hog_device *dev, struct gatt_db *db)
>>>  {
>>> -       struct hog_device *dev;
>>>         char name[248];
>>>         uint16_t vendor, product, version;
>>>
>>> -       if (device_name_known(device))
>>> -               device_get_name(device, name, sizeof(name));
>>> +       if (dev->hog)
>>> +               return;
>>> +
>>> +       if (device_name_known(dev->device))
>>> +               device_get_name(dev->device, name, sizeof(name));
>>>         else
>>>                 strcpy(name, "bluez-hog-device");
>>>
>>> -       vendor = btd_device_get_vendor(device);
>>> -       product = btd_device_get_product(device);
>>> -       version = btd_device_get_version(device);
>>> +       vendor = btd_device_get_vendor(dev->device);
>>> +       product = btd_device_get_product(dev->device);
>>> +       version = btd_device_get_version(dev->device);
>>>
>>>         DBG("name=%s vendor=0x%X, product=0x%X, version=0x%X", name, vendor,
>>>                                                         product, version);
>>>
>>> -       dev = new0(struct hog_device, 1);
>>> -       dev->hog = bt_hog_new_default(name, vendor, product, version, prim);
>>> -       if (!dev->hog) {
>>> -               free(dev);
>>> -               return NULL;
>>> -       }
>>> +       dev->hog = bt_hog_new_default(name, vendor, product, version, db);
>>> +}
>>>
>>> +static struct hog_device *hog_device_new(struct btd_device *device)
>>> +{
>>> +       struct hog_device *dev;
>>> +
>>> +       dev = new0(struct hog_device, 1);
>>>         dev->device = btd_device_ref(device);
>>>
>>>         if (!devices)
>>> @@ -148,30 +150,16 @@ static int hog_probe(struct btd_service *service)
>>>  {
>>>         struct btd_device *device = btd_service_get_device(service);
>>>         const char *path = device_get_path(device);
>>> -       GSList *primaries, *l;
>>> +       struct hog_device *dev;
>>>
>>>         DBG("path %s", path);
>>>
>>> -       primaries = btd_device_get_primaries(device);
>>> -       if (primaries == NULL)
>>> +       dev = hog_device_new(device);
>>> +       if (!dev)
>>>                 return -EINVAL;
>>>
>>> -       for (l = primaries; l; l = g_slist_next(l)) {
>>> -               struct gatt_primary *prim = l->data;
>>> -               struct hog_device *dev;
>>> -
>>> -               if (strcmp(prim->uuid, HOG_UUID) != 0)
>>> -                       continue;
>>> -
>>> -               dev = hog_device_new(device, prim);
>>> -               if (!dev)
>>> -                       break;
>>> -
>>> -               btd_service_set_user_data(service, dev);
>>> -               return 0;
>>> -       }
>>> -
>>> -       return -EINVAL;
>>> +       btd_service_set_user_data(service, dev);
>>> +       return 0;
>>>  }
>>>
>>>  static void hog_remove(struct btd_service *service)
>>> @@ -189,8 +177,15 @@ static int hog_accept(struct btd_service *service)
>>>  {
>>>         struct hog_device *dev = btd_service_get_user_data(service);
>>>         struct btd_device *device = btd_service_get_device(service);
>>> +       struct gatt_db *db = btd_device_get_gatt_db(device);
>>>         GAttrib *attrib = btd_device_get_attrib(device);
>>>
>>> +       if (!dev->hog) {
>>> +               hog_device_accept(dev, db);
>>> +               if (!dev->hog)
>>> +                       return -EINVAL;
>>> +       }
>>> +
>>>         /* TODO: Replace GAttrib with bt_gatt_client */
>>>         bt_hog_attach(dev->hog, attrib);
>>>
>>> diff --git a/unit/test-hog.c b/unit/test-hog.c
>>> index 9f026e5..d117968 100644
>>> --- a/unit/test-hog.c
>>> +++ b/unit/test-hog.c
>>> @@ -32,8 +32,14 @@
>>>
>>>  #include <glib.h>
>>>
>>> +#include "lib/bluetooth.h"
>>> +#include "lib/uuid.h"
>>> +
>>>  #include "src/shared/util.h"
>>>  #include "src/shared/tester.h"
>>> +#include "src/shared/queue.h"
>>> +#include "src/shared/att.h"
>>> +#include "src/shared/gatt-db.h"
>>>
>>>  #include "attrib/gattrib.h"
>>>
>>> --
>>> 2.9.3
>>
>> Applied.
>>
>>
>> --
>> Luiz Augusto von Dentz
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Luiz Augusto von Dentz

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

end of thread, other threads:[~2016-12-30  8:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-27 12:40 [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
2016-12-27 12:40 ` [PATCH BlueZ 2/3] dis: " Luiz Augusto von Dentz
2016-12-27 12:40 ` [PATCH BlueZ 3/3] input/hog-lib: Attempt to read PNP values if not set Luiz Augusto von Dentz
2016-12-29 13:23 ` [PATCH BlueZ 1/3] input/hog-lib: Add support to gatt-db Luiz Augusto von Dentz
2016-12-30  0:47   ` Petri Gynther
2016-12-30  8:59     ` Luiz Augusto von Dentz

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.