summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-02-04 00:43:46 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-02-04 00:43:46 +0000
commit2078ecaa8d52c74bc1d8d945d28755b6c2833d2d (patch)
treecc2b424832101ce844bdc2668488c759c20cc00a /lib
parent942604bcc1f7004ea0b087d5142798289b519797 (diff)
Return the correct report ID when hitting a "collection" item.
Collection are reported before their corresponding report ID, so bring back the trick from old parser and do not return them until we find a report ID or another start or end of collection. Fix a regression introduced by last parser backport from FreeBSD reported by Benjamin Baier, thanks!
Diffstat (limited to 'lib')
-rw-r--r--lib/libusbhid/parse.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/lib/libusbhid/parse.c b/lib/libusbhid/parse.c
index 06624eccd77..98f9e196015 100644
--- a/lib/libusbhid/parse.c
+++ b/lib/libusbhid/parse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.c,v 1.10 2015/01/18 17:16:06 mpi Exp $ */
+/* $OpenBSD: parse.c,v 1.11 2015/02/04 00:43:45 mpi Exp $ */
/* $NetBSD: parse.c,v 1.2 2001/12/29 20:44:22 augustss Exp $ */
/*
@@ -67,6 +67,8 @@ struct hid_data {
uint8_t ousage; /* current "usages_min/max" offset */
uint8_t susage; /* usage set flags */
int32_t reportid; /* requested report ID */
+ struct hid_item savedcoll; /* save coll until we know the ID */
+ uint8_t hassavedcoll;
};
static void
@@ -151,6 +153,7 @@ hid_start_parse(report_desc_t d, int kindset, int id)
s->end = d->data + d->size;
s->kindset = kindset;
s->reportid = id;
+ s->hassavedcoll = 0;
return (s);
}
@@ -191,10 +194,20 @@ hid_get_byte(struct hid_data *s, const uint16_t wSize)
return (retval);
}
+#define REPORT_SAVED_COLL \
+ do { \
+ if (s->hassavedcoll) { \
+ *h = s->savedcoll; \
+ h->report_ID = c->report_ID; \
+ s->hassavedcoll = 0; \
+ return (1); \
+ } \
+ } while(0)
+
static int
hid_get_item_raw(hid_data_t s, hid_item_t *h)
{
- hid_item_t *c;
+ hid_item_t nc, *c;
unsigned int bTag, bType, bSize;
int32_t mask;
int32_t dval;
@@ -207,6 +220,7 @@ hid_get_item_raw(hid_data_t s, hid_item_t *h)
top:
/* check if there is an array of items */
if (s->icount < s->ncount) {
+ REPORT_SAVED_COLL;
/* get current usage */
if (s->iusage < s->nusage) {
dval = s->usages_min[s->iusage] + s->ousage;
@@ -328,13 +342,23 @@ hid_get_item_raw(hid_data_t s, hid_item_t *h)
c->collection = dval;
c->collevel++;
c->usage = s->usage_last;
- *h = *c;
- return (1);
+ nc = *c;
+ if (s->hassavedcoll) {
+ *h = s->savedcoll;
+ h->report_ID = nc.report_ID;
+ s->savedcoll = nc;
+ return (1);
+ } else {
+ s->hassavedcoll = 1;
+ s->savedcoll = nc;
+ }
+ goto top;
case 11: /* Feature */
c->kind = hid_feature;
c->flags = dval;
goto ret;
case 12: /* End collection */
+ REPORT_SAVED_COLL;
c->kind = hid_endcollection;
if (c->collevel == 0) {
/* Invalid end collection. */