summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2014-06-27 21:08:58 +0300
committerSzymon Janc <szymon.janc@tieto.com>2014-06-29 14:52:36 +0200
commit47a337152d342a37e3021dab0b18487b185e8b76 (patch)
tree41cbbddf9af999549109c3fca29c672d3d68d036 /android
parent831b17ae4d559ae8bc2c0b83e2320f0d6893f971 (diff)
downloadbluez-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.c80
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)