diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2014-06-27 21:08:58 +0300 |
---|---|---|
committer | Szymon Janc <szymon.janc@tieto.com> | 2014-06-29 14:52:36 +0200 |
commit | 47a337152d342a37e3021dab0b18487b185e8b76 (patch) | |
tree | 41cbbddf9af999549109c3fca29c672d3d68d036 /android | |
parent | 831b17ae4d559ae8bc2c0b83e2320f0d6893f971 (diff) | |
download | bluez-47a337152d342a37e3021dab0b18487b185e8b76.tar.gz |
android/hog: Fix using the same callback for different descriptors
External Report and Report descriptors take different user_data so have
different callbacks to avoid possible crash if a discover happen to find
the descriptors of unexpect type.
Diffstat (limited to 'android')
-rw-r--r-- | android/hog.c | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/android/hog.c b/android/hog.c index 42b7d7379..ad4eee5a0 100644 --- a/android/hog.c +++ b/android/hog.c @@ -166,14 +166,14 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu, DBG("Report characteristic descriptor written: notifications enabled"); } -static void write_ccc(uint16_t handle, gpointer user_data) +static void write_ccc(GAttrib *attrib, uint16_t handle, void *user_data) { - struct report *report = user_data; - struct bt_hog *hog = report->hog; - uint8_t value[] = { 0x01, 0x00 }; + uint8_t value[2]; + + put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value); - gatt_write_char(hog->attrib, handle, value, sizeof(value), - report_ccc_written_cb, report); + gatt_write_char(attrib, handle, value, sizeof(value), + report_ccc_written_cb, user_data); } static void report_reference_cb(guint8 status, const guint8 *pdu, @@ -200,15 +200,45 @@ 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(uint8_t status, GSList *descs, - void *user_data) +static void discover_external_cb(uint8_t status, GSList *descs, void *user_data) { - struct report *report; - struct bt_hog *hog; - GAttrib *attrib = NULL; + struct bt_hog *hog = user_data; if (status != 0) { - error("Discover all descriptors failed: %s", + error("Discover external descriptors failed: %s", + att_ecode2str(status)); + return; + } + + for ( ; descs; descs = descs->next) { + struct gatt_desc *desc = descs->data; + + gatt_read_char(hog->attrib, desc->handle, + external_report_reference_cb, hog); + } +} + +static void discover_external(GAttrib *attrib, uint16_t start, uint16_t end, + gpointer user_data) +{ + bt_uuid_t uuid; + + if (start > end) + return; + + bt_uuid16_create(&uuid, GATT_EXTERNAL_REPORT_REFERENCE); + + gatt_discover_desc(attrib, start, end, NULL, discover_external_cb, + user_data); +} + +static void discover_report_cb(uint8_t status, GSList *descs, void *user_data) +{ + struct report *report = user_data; + struct bt_hog *hog = report->hog; + + if (status != 0) { + error("Discover report descriptors failed: %s", att_ecode2str(status)); return; } @@ -218,34 +248,24 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs, switch (desc->uuid16) { case GATT_CLIENT_CHARAC_CFG_UUID: - report = user_data; - attrib = report->hog->attrib; - write_ccc(desc->handle, report); + write_ccc(hog->attrib, desc->handle, report); break; case GATT_REPORT_REFERENCE: - report = user_data; - attrib = report->hog->attrib; - gatt_read_char(attrib, desc->handle, + gatt_read_char(hog->attrib, desc->handle, report_reference_cb, report); break; - case GATT_EXTERNAL_REPORT_REFERENCE: - hog = user_data; - attrib = hog->attrib; - gatt_read_char(attrib, desc->handle, - external_report_reference_cb, hog); - break; } } } -static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end, +static void discover_report(GAttrib *attrib, uint16_t start, uint16_t end, gpointer user_data) { if (start > end) return; - gatt_discover_desc(attrib, start, end, NULL, - discover_descriptor_cb, user_data); + gatt_discover_desc(attrib, start, end, NULL, discover_report_cb, + user_data); } static void external_service_char_cb(uint8_t status, GSList *chars, @@ -278,7 +298,7 @@ static void external_service_char_cb(uint8_t status, GSList *chars, hog->reports = g_slist_append(hog->reports, report); start = chr->value_handle + 1; end = (next ? next->handle - 1 : primary->range.end); - discover_descriptor(hog->attrib, start, end, report); + discover_report(hog->attrib, start, end, report); } } @@ -614,11 +634,11 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data) report->hog = hog; report->decl = g_memdup(chr, sizeof(*chr)); hog->reports = g_slist_append(hog->reports, report); - discover_descriptor(hog->attrib, start, end, report); + discover_report(hog->attrib, start, end, report); } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) { gatt_read_char(hog->attrib, chr->value_handle, report_map_read_cb, hog); - discover_descriptor(hog->attrib, start, end, hog); + discover_external(hog->attrib, start, end, hog); } else if (bt_uuid_cmp(&uuid, &info_uuid) == 0) info_handle = chr->value_handle; else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0) |