OSDN Git Service

hog: Use the per handle GATT event notifier
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>
Wed, 10 Oct 2012 23:55:55 +0000 (20:55 -0300)
committerJohan Hedberg <johan.hedberg@intel.com>
Thu, 11 Oct 2012 06:56:16 +0000 (08:56 +0200)
profiles/input/hog_device.c

index 52ebd95..9ac7bd7 100644 (file)
@@ -76,7 +76,6 @@ struct hog_device {
        struct btd_device       *device;
        GAttrib                 *attrib;
        guint                   attioid;
-       guint                   report_cb_id;
        struct gatt_primary     *hog_primary;
        GSList                  *reports;
        int                     uhid_fd;
@@ -92,27 +91,18 @@ struct hog_device {
 struct report {
        uint8_t                 id;
        uint8_t                 type;
+       guint                   notifyid;
        struct gatt_char        *decl;
        struct hog_device       *hogdev;
 };
 
-static gint report_handle_cmp(gconstpointer a, gconstpointer b)
-{
-       const struct report *report = a;
-       uint16_t handle = GPOINTER_TO_UINT(b);
-
-       return report->decl->value_handle - handle;
-}
-
 static void report_value_cb(const uint8_t *pdu, uint16_t len,
                                                        gpointer user_data)
 {
-       struct hog_device *hogdev = user_data;
+       struct report *report = user_data;
+       struct hog_device *hogdev = report->hogdev;
        struct uhid_event ev;
        uint16_t report_size = len - 3;
-       guint handle;
-       GSList *l;
-       struct report *report;
        uint8_t *buf;
 
        if (len < 3) { /* 1-byte opcode + 2-byte handle */
@@ -120,17 +110,6 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len,
                return;
        }
 
-       handle = att_get_u16(&pdu[1]);
-
-       l = g_slist_find_custom(hogdev->reports, GUINT_TO_POINTER(handle),
-                                                       report_handle_cmp);
-       if (!l) {
-               error("Invalid report");
-               return;
-       }
-
-       report = l->data;
-
        memset(&ev, 0, sizeof(ev));
        ev.type = UHID_INPUT;
        ev.u.input.size = MIN(report_size, UHID_DATA_MAX);
@@ -154,22 +133,31 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len,
 static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
                                        guint16 plen, gpointer user_data)
 {
+       struct report *report = user_data;
+       struct hog_device *hogdev = report->hogdev;
+
        if (status != 0) {
                error("Write report characteristic descriptor failed: %s",
                                                        att_ecode2str(status));
                return;
        }
 
+       report->notifyid = g_attrib_register(hogdev->attrib,
+                                       ATT_OP_HANDLE_NOTIFY,
+                                       report->decl->value_handle,
+                                       report_value_cb, report, NULL);
+
        DBG("Report characteristic descriptor written: notifications enabled");
 }
 
 static void write_ccc(uint16_t handle, gpointer user_data)
 {
-       struct hog_device *hogdev = user_data;
+       struct report *report = user_data;
+       struct hog_device *hogdev = report->hogdev;
        uint8_t value[] = { 0x01, 0x00 };
 
        gatt_write_char(hogdev->attrib, handle, value, sizeof(value),
-                                       report_ccc_written_cb, hogdev);
+                                       report_ccc_written_cb, report);
 }
 
 static void report_reference_cb(guint8 status, const guint8 *pdu,
@@ -196,6 +184,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
 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)
 {
@@ -229,7 +218,7 @@ static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
                switch (uuid16) {
                case GATT_CLIENT_CHARAC_CFG_UUID:
                        report = user_data;
-                       write_ccc(handle, report->hogdev);
+                       write_ccc(handle, report);
                        break;
                case GATT_REPORT_REFERENCE:
                        report = user_data;
@@ -608,27 +597,37 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
        struct hog_device *hogdev = user_data;
        struct gatt_primary *prim = hogdev->hog_primary;
+       GSList *l;
 
        hogdev->attrib = g_attrib_ref(attrib);
 
-       hogdev->report_cb_id = g_attrib_register(hogdev->attrib,
-                                       ATT_OP_HANDLE_NOTIFY,
-                                       GATTRIB_ALL_HANDLES,
-                                       report_value_cb, hogdev, NULL);
-
        if (hogdev->reports == NULL) {
                gatt_discover_char(hogdev->attrib, prim->range.start,
                                                prim->range.end, NULL,
                                                char_discovered_cb, hogdev);
+               return;
+       }
+
+       for (l = hogdev->reports; l; l = l->next) {
+               struct report *r = l->data;
+
+               r->notifyid = g_attrib_register(hogdev->attrib,
+                                       ATT_OP_HANDLE_NOTIFY,
+                                       r->decl->value_handle,
+                                       report_value_cb, r, NULL);
        }
 }
 
 static void attio_disconnected_cb(gpointer user_data)
 {
        struct hog_device *hogdev = user_data;
+       GSList *l;
+
+       for (l = hogdev->reports; l; l = l->next) {
+               struct report *r = l->data;
 
-       g_attrib_unregister(hogdev->attrib, hogdev->report_cb_id);
-       hogdev->report_cb_id = 0;
+               g_attrib_unregister(hogdev->attrib, r->notifyid);
+       }
 
        g_attrib_unref(hogdev->attrib);
        hogdev->attrib = NULL;
@@ -652,6 +651,9 @@ static struct hog_device *hog_device_new(struct btd_device *device,
 static void report_free(void *data)
 {
        struct report *report = data;
+       struct hog_device *hogdev = report->hogdev;
+
+       g_attrib_unregister(hogdev->attrib, report->notifyid);
        g_free(report->decl);
        g_free(report);
 }