aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Paulo Rechi Vita <jprvita@openbossa.org>2012-04-24 14:33:29 -0300
committerJoão Paulo Rechi Vita <jprvita@openbossa.org>2012-06-21 18:00:14 -0300
commitfb020e7bf59c647fc70248bd042913fb1b448c3c (patch)
treea75cddf6eaa6f77701d31bd6d0ab80f9b98fabc5
parent55f84a0a52f1fc6a6c9980bbf5939c2deb6d7663 (diff)
downloadbluez-fb020e7bf59c647fc70248bd042913fb1b448c3c.tar.gz
bluez-fb020e7bf59c647fc70248bd042913fb1b448c3c.tar.xz
bluez-fb020e7bf59c647fc70248bd042913fb1b448c3c.zip
hog: Handle output reports
This patch writes the output reports coming from the HID host on the device's Output Report characteristic.
-rw-r--r--input/hog_device.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/input/hog_device.c b/input/hog_device.c
index cd5d1bfb..50394e72 100644
--- a/input/hog_device.c
+++ b/input/hog_device.c
@@ -54,6 +54,9 @@
#define HOG_REPORT_MAP_UUID 0x2A4B
#define HOG_REPORT_UUID 0x2A4D
+#define HOG_REPORT_TYPE_INPUT 1
+#define HOG_REPORT_TYPE_OUTPUT 2
+
#define UHID_DEVICE_FILE "/dev/uhid"
#define HOG_REPORT_MAP_MAX_SIZE 512
@@ -337,6 +340,54 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
}
}
+static void output_written_cb(guint8 status, const guint8 *pdu,
+ guint16 plen, gpointer user_data)
+{
+ if (status != 0) {
+ error("Write output report failed: %s", att_ecode2str(status));
+ return;
+ }
+}
+
+static gint report_type_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct report *report = a;
+ uint8_t type = GPOINTER_TO_UINT(b);
+
+ return report->type - type;
+}
+
+static void forward_report(struct hog_device *hogdev,
+ struct uhid_event *ev)
+{
+ struct report *report;
+ GSList *l;
+ void *data;
+ int size;
+ guint type;
+
+ type = HOG_REPORT_TYPE_OUTPUT;
+ data = ev->u.output.data;
+ size = ev->u.output.size;
+
+ l = g_slist_find_custom(hogdev->reports, GUINT_TO_POINTER(type),
+ report_type_cmp);
+ if (!l)
+ return;
+
+ report = l->data;
+
+ DBG("Sending report type %d to device %s handle 0x%X", type,
+ hogdev->path, report->decl->value_handle);
+
+ if (report->decl->properties & ATT_CHAR_PROPER_WRITE)
+ gatt_write_char(hogdev->attrib, report->decl->value_handle,
+ data, size, output_written_cb, hogdev);
+ else if (report->decl->properties & ATT_CHAR_PROPER_WRITE_WITHOUT_RESP)
+ gatt_write_char(hogdev->attrib, report->decl->value_handle,
+ data, size, NULL, NULL);
+}
+
static gboolean uhid_event_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
@@ -360,6 +411,15 @@ static gboolean uhid_event_cb(GIOChannel *io, GIOCondition cond,
DBG("uHID event type %d received", ev.type);
+ switch (ev.type) {
+ case UHID_OUTPUT:
+ forward_report(hogdev, &ev);
+ break;
+ default:
+ warn("unexpected uHID event");
+ break;
+ }
+
return TRUE;
failed: