Diff between 2da5bbf7fca7e6a17d3861d9ea75c23e71d487eb and 8f902ac3b122dc68270d244af34bbc1f1974ad3a

Changed Files

File Additions Deletions Status
android/hog.c +53 -34 modified

Full Patch

diff --git a/android/hog.c b/android/hog.c
index 09a16d5..51c7c64 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -382,12 +382,47 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
 					external_service_char_cb, hog);
 }
 
-static int report_type_cmp(gconstpointer a, gconstpointer b)
+
+static int report_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct report *ra = a, *rb = b;
+
+	/* sort by type first.. */
+	if (ra->type != rb->type)
+		return ra->type - rb->type;
+
+	/* skip id check in case of report id 0 */
+	if (!rb->id)
+		return 0;
+
+	/* ..then by id */
+	return ra->id - rb->id;
+}
+
+static struct report *find_report(struct bt_hog *hog, uint8_t type, uint8_t id)
 {
-	const struct report *report = a;
-	uint8_t type = GPOINTER_TO_UINT(b);
+	struct report cmp;
+	GSList *l;
+
+	switch (type) {
+	case UHID_FEATURE_REPORT:
+		cmp.type = HOG_REPORT_TYPE_FEATURE;
+		break;
+	case UHID_OUTPUT_REPORT:
+		cmp.type = HOG_REPORT_TYPE_OUTPUT;
+		break;
+	case UHID_INPUT_REPORT:
+		cmp.type = HOG_REPORT_TYPE_INPUT;
+		break;
+	default:
+		return NULL;
+	}
+
+	cmp.id = hog->has_report_id ? id : 0;
 
-	return report->type - type;
+	l = g_slist_find_custom(hog->reports, &cmp, report_cmp);
+
+	return l ? l->data : NULL;
 }
 
 static void output_written_cb(guint8 status, const guint8 *pdu,
@@ -403,30 +438,22 @@ static void forward_report(struct uhid_event *ev, void *user_data)
 {
 	struct bt_hog *hog = user_data;
 	struct report *report;
-	GSList *l;
 	void *data;
 	int size;
-	guint type;
-
-	if (hog->has_report_id) {
-		data = ev->u.output.data + 1;
-		size = ev->u.output.size - 1;
-	} else {
-		data = ev->u.output.data;
-		size = ev->u.output.size;
-	}
 
-	type = HOG_REPORT_TYPE_OUTPUT;
-
-	l = g_slist_find_custom(hog->reports, GUINT_TO_POINTER(type),
-							report_type_cmp);
-	if (!l)
+	report = find_report(hog, ev->u.output.rtype, ev->u.output.data[0]);
+	if (!report)
 		return;
 
-	report = l->data;
+	data = ev->u.output.data;
+	size = ev->u.output.size;
+	if (hog->has_report_id && size > 0) {
+		data++;
+		--size;
+	}
 
-	DBG("Sending report type %d to handle 0x%X", type,
-						report->decl->value_handle);
+	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
+				report->id, report->decl->value_handle);
 
 	if (hog->attrib == NULL)
 		return;
@@ -443,7 +470,6 @@ static void get_report(struct uhid_event *ev, void *user_data)
 {
 	struct bt_hog *hog = user_data;
 	struct report *report;
-	GSList *l;
 	struct uhid_event rsp;
 	int err;
 
@@ -451,16 +477,12 @@ static void get_report(struct uhid_event *ev, void *user_data)
 	rsp.type = UHID_FEATURE_ANSWER;
 	rsp.u.feature_answer.id = ev->u.feature.id;
 
-	l = g_slist_find_custom(hog->reports,
-				GUINT_TO_POINTER(ev->u.feature.rtype),
-				report_type_cmp);
-	if (!l) {
+	report = find_report(hog, ev->u.feature.rtype, ev->u.feature.rnum);
+	if (!report) {
 		rsp.u.feature_answer.err = ENOTSUP;
 		goto done;
 	}
 
-	report = l->data;
-
 	if (!report->value) {
 		rsp.u.feature_answer.err = EIO;
 		goto done;
@@ -1090,13 +1112,10 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
 	if (!hog->attrib)
 		return -ENOTCONN;
 
-	l = g_slist_find_custom(hog->reports, GUINT_TO_POINTER(type),
-							report_type_cmp);
-	if (!l)
+	report = find_report(hog, type, 0);
+	if (!report)
 		return -ENOTSUP;
 
-	report = l->data;
-
 	DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
 
 	if (report->decl->properties & GATT_CHR_PROP_WRITE)