The HID protocol support encapsulating non-HID service data as reports. This
patches adds support for this feature for HoG devices.
João Paulo Rechi Vita (3):
gatt: Add a new descriptor UUID
hog: discover External Report Reference descriptor
hog: discover the non-HID service characteristic
attrib/gatt.h | 1 +
profiles/input/hog_device.c | 96 ++++++++++++++++++++++++++++++++++++++-------
2 files changed, 83 insertions(+), 14 deletions(-)
--
1.7.11.2
Hi Jo?o Paulo,
On Mon, Aug 13, 2012, Jo?o Paulo Rechi Vita wrote:
> The HID protocol support encapsulating non-HID service data as reports. This
> patches adds support for this feature for HoG devices.
>
> Jo?o Paulo Rechi Vita (3):
> gatt: Add a new descriptor UUID
> hog: discover External Report Reference descriptor
> hog: discover the non-HID service characteristic
>
> attrib/gatt.h | 1 +
> profiles/input/hog_device.c | 96 ++++++++++++++++++++++++++++++++++++++-------
> 2 files changed, 83 insertions(+), 14 deletions(-)
All three patches have been applied. Thanks.
Johan
Find the characteristic by the UUID provided on the External Report
Reference descriptor and enable notifications for it. The characteristic
will be handled as a HID report and it's data processed through the uhid
device.
---
profiles/input/hog_device.c | 76 +++++++++++++++++++++++++++++++++++----------
1 file changed, 59 insertions(+), 17 deletions(-)
diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index f4cf596..5a1de12 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -170,23 +170,6 @@ static void write_ccc(uint16_t handle, gpointer user_data)
report_ccc_written_cb, hogdev);
}
-static void external_report_reference_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
-{
- if (status != 0) {
- error("Read External Report Reference descriptor failed: %s",
- att_ecode2str(status));
- return;
- }
-
- if (plen != 3) {
- error("Malformed ATT read response");
- return;
- }
-
- DBG("External Report Reference read: 0x%02x 0x%02x", pdu[1], pdu[2]);
-}
-
static void report_reference_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
@@ -208,6 +191,9 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
DBG("Report ID: 0x%02x Report type: 0x%02x", pdu[1], pdu[2]);
}
+static void external_report_reference_cb(guint8 status, const guint8 *pdu,
+ guint16 plen, gpointer user_data);
+
static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data)
{
@@ -274,6 +260,62 @@ static void discover_descriptor(GAttrib *attrib, struct gatt_char *chr,
gatt_find_info(attrib, start, end, discover_descriptor_cb, user_data);
}
+static void external_service_char_cb(GSList *chars, guint8 status,
+ gpointer user_data)
+{
+ struct hog_device *hogdev = user_data;
+ struct report *report;
+ GSList *l;
+
+ if (status != 0) {
+ const char *str = att_ecode2str(status);
+ DBG("Discover external service characteristic failed: %s", str);
+ return;
+ }
+
+ for (l = chars; l; l = g_slist_next(l)) {
+ struct gatt_char *chr, *next;
+
+ chr = l->data;
+ next = l->next ? l->next->data : NULL;
+
+ DBG("0x%04x UUID: %s properties: %02x",
+ chr->handle, chr->uuid, chr->properties);
+
+ report = g_new0(struct report, 1);
+ report->hogdev = hogdev;
+ report->decl = g_memdup(chr, sizeof(*chr));
+ hogdev->reports = g_slist_append(hogdev->reports, report);
+ discover_descriptor(hogdev->attrib, chr, next, report);
+ }
+}
+
+static void external_report_reference_cb(guint8 status, const guint8 *pdu,
+ guint16 plen, gpointer user_data)
+{
+ struct hog_device *hogdev = user_data;
+ uint16_t uuid16;
+ bt_uuid_t uuid;
+
+ if (status != 0) {
+ error("Read External Report Reference descriptor failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ if (plen != 3) {
+ error("Malformed ATT read response");
+ return;
+ }
+
+ uuid16 = att_get_u16(&pdu[1]);
+ DBG("External report reference read, external report characteristic "
+ "UUID: 0x%04x", uuid16);
+ bt_uuid16_create(&uuid, uuid16);
+ gatt_discover_char(hogdev->attrib, 0x00, 0xff, &uuid,
+ external_service_char_cb, hogdev);
+}
+
static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
gpointer user_data)
{
--
1.7.11.2
Non-HID service data may be encapsulated on the HID protocol and
transfered as a HID Report. This descriptor is used to map a report
on the USB-HID descriptor that transports non-HID data to the
characteristic on a external service that will actually transport the
data on GATT devices.
---
profiles/input/hog_device.c | 54 +++++++++++++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 14 deletions(-)
diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index ffd7139..f4cf596 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -170,6 +170,23 @@ static void write_ccc(uint16_t handle, gpointer user_data)
report_ccc_written_cb, hogdev);
}
+static void external_report_reference_cb(guint8 status, const guint8 *pdu,
+ guint16 plen, gpointer user_data)
+{
+ if (status != 0) {
+ error("Read External Report Reference descriptor failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ if (plen != 3) {
+ error("Malformed ATT read response");
+ return;
+ }
+
+ DBG("External Report Reference read: 0x%02x 0x%02x", pdu[1], pdu[2]);
+}
+
static void report_reference_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
@@ -194,8 +211,8 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data)
{
- struct report *report = user_data;
- struct hog_device *hogdev = report->hogdev;
+ struct report *report;
+ struct hog_device *hogdev;
struct att_data_list *list;
uint8_t format;
int i;
@@ -221,11 +238,22 @@ static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
handle = att_get_u16(value);
uuid16 = att_get_u16(&value[2]);
- if (uuid16 == GATT_CLIENT_CHARAC_CFG_UUID)
- write_ccc(handle, hogdev);
- else if (uuid16 == GATT_REPORT_REFERENCE)
+ switch (uuid16) {
+ case GATT_CLIENT_CHARAC_CFG_UUID:
+ report = user_data;
+ write_ccc(handle, report->hogdev);
+ break;
+ case GATT_REPORT_REFERENCE:
+ report = user_data;
+ gatt_read_char(report->hogdev->attrib, handle, 0,
+ report_reference_cb, report);
+ break;
+ case GATT_EXTERNAL_REPORT_REFERENCE:
+ hogdev = user_data;
gatt_read_char(hogdev->attrib, handle, 0,
- report_reference_cb, report);
+ external_report_reference_cb, hogdev);
+ break;
+ }
}
done:
@@ -372,7 +400,7 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid;
struct report *report;
GSList *l;
- uint16_t map_handle = 0, info_handle = 0, proto_mode_handle = 0;
+ uint16_t info_handle = 0, proto_mode_handle = 0;
if (status != 0) {
const char *str = att_ecode2str(status);
@@ -404,9 +432,11 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
hogdev->reports = g_slist_append(hogdev->reports,
report);
discover_descriptor(hogdev->attrib, chr, next, report);
- } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0)
- map_handle = chr->value_handle;
- else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
+ } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
+ gatt_read_char(hogdev->attrib, chr->value_handle, 0,
+ report_map_read_cb, hogdev);
+ discover_descriptor(hogdev->attrib, chr, next, NULL);
+ } else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
info_handle = chr->value_handle;
else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
proto_mode_handle = chr->value_handle;
@@ -421,10 +451,6 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
if (info_handle)
gatt_read_char(hogdev->attrib, info_handle, 0,
info_read_cb, hogdev);
-
- if (map_handle)
- gatt_read_char(hogdev->attrib, map_handle, 0,
- report_map_read_cb, hogdev);
}
static void output_written_cb(guint8 status, const guint8 *pdu,
--
1.7.11.2
Add the UUID of the External Report Reference descriptor.
---
attrib/gatt.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/attrib/gatt.h b/attrib/gatt.h
index c7e79ab..aab93b6 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -46,6 +46,7 @@
#define GATT_CHARAC_FMT_UUID 0x2904
#define GATT_CHARAC_AGREG_FMT_UUID 0x2905
#define GATT_CHARAC_VALID_RANGE_UUID 0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE 0x2907
#define GATT_REPORT_REFERENCE 0x2908
/* Client Characteristic Configuration bit field */
--
1.7.11.2