xref: /freebsd/lib/libusbhid/parse.c (revision 9e2046dfecbbdda2ba5060c92f583d78cca04bcb)
19e2046dfSNick Hibma /*	$NetBSD: parse.c,v 1.9 2000/03/17 18:09:17 augustss Exp $	*/
29e2046dfSNick Hibma 
39e2046dfSNick Hibma /*
49e2046dfSNick Hibma  * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org>
59e2046dfSNick Hibma  * All rights reserved.
69e2046dfSNick Hibma  *
79e2046dfSNick Hibma  * Redistribution and use in source and binary forms, with or without
89e2046dfSNick Hibma  * modification, are permitted provided that the following conditions
99e2046dfSNick Hibma  * are met:
109e2046dfSNick Hibma  * 1. Redistributions of source code must retain the above copyright
119e2046dfSNick Hibma  *    notice, this list of conditions and the following disclaimer.
129e2046dfSNick Hibma  * 2. Redistributions in binary form must reproduce the above copyright
139e2046dfSNick Hibma  *    notice, this list of conditions and the following disclaimer in the
149e2046dfSNick Hibma  *    documentation and/or other materials provided with the distribution.
159e2046dfSNick Hibma  *
169e2046dfSNick Hibma  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
179e2046dfSNick Hibma  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189e2046dfSNick Hibma  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199e2046dfSNick Hibma  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209e2046dfSNick Hibma  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
219e2046dfSNick Hibma  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
229e2046dfSNick Hibma  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
239e2046dfSNick Hibma  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
249e2046dfSNick Hibma  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
259e2046dfSNick Hibma  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269e2046dfSNick Hibma  * SUCH DAMAGE.
279e2046dfSNick Hibma  *
289e2046dfSNick Hibma  * $FreeBSD$
299e2046dfSNick Hibma  *
309e2046dfSNick Hibma  */
319e2046dfSNick Hibma 
329e2046dfSNick Hibma #include <assert.h>
339e2046dfSNick Hibma #include <stdlib.h>
349e2046dfSNick Hibma #include <string.h>
359e2046dfSNick Hibma #include <sys/time.h>
369e2046dfSNick Hibma 
379e2046dfSNick Hibma #include <dev/usb/usb.h>
389e2046dfSNick Hibma #include <dev/usb/usbhid.h>
399e2046dfSNick Hibma 
409e2046dfSNick Hibma #include "libusb.h"
419e2046dfSNick Hibma #include "usbvar.h"
429e2046dfSNick Hibma 
439e2046dfSNick Hibma #define MAXUSAGE 100
449e2046dfSNick Hibma struct hid_data {
459e2046dfSNick Hibma 	u_char *start;
469e2046dfSNick Hibma 	u_char *end;
479e2046dfSNick Hibma 	u_char *p;
489e2046dfSNick Hibma 	hid_item_t cur;
499e2046dfSNick Hibma 	unsigned int usages[MAXUSAGE];
509e2046dfSNick Hibma 	int nusage;
519e2046dfSNick Hibma 	int minset;
529e2046dfSNick Hibma 	int multi;
539e2046dfSNick Hibma 	int multimax;
549e2046dfSNick Hibma 	int kindset;
559e2046dfSNick Hibma };
569e2046dfSNick Hibma 
579e2046dfSNick Hibma static int min(int x, int y) { return x < y ? x : y; }
589e2046dfSNick Hibma 
599e2046dfSNick Hibma static void
609e2046dfSNick Hibma hid_clear_local(hid_item_t *c)
619e2046dfSNick Hibma {
629e2046dfSNick Hibma 
639e2046dfSNick Hibma 	_DIAGASSERT(c != NULL);
649e2046dfSNick Hibma 
659e2046dfSNick Hibma 	c->usage = 0;
669e2046dfSNick Hibma 	c->usage_minimum = 0;
679e2046dfSNick Hibma 	c->usage_maximum = 0;
689e2046dfSNick Hibma 	c->designator_index = 0;
699e2046dfSNick Hibma 	c->designator_minimum = 0;
709e2046dfSNick Hibma 	c->designator_maximum = 0;
719e2046dfSNick Hibma 	c->string_index = 0;
729e2046dfSNick Hibma 	c->string_minimum = 0;
739e2046dfSNick Hibma 	c->string_maximum = 0;
749e2046dfSNick Hibma 	c->set_delimiter = 0;
759e2046dfSNick Hibma }
769e2046dfSNick Hibma 
779e2046dfSNick Hibma hid_data_t
789e2046dfSNick Hibma hid_start_parse(report_desc_t d, int kindset)
799e2046dfSNick Hibma {
809e2046dfSNick Hibma 	struct hid_data *s;
819e2046dfSNick Hibma 
829e2046dfSNick Hibma 	_DIAGASSERT(d != NULL);
839e2046dfSNick Hibma 
849e2046dfSNick Hibma 	s = malloc(sizeof *s);
859e2046dfSNick Hibma 	memset(s, 0, sizeof *s);
869e2046dfSNick Hibma 	s->start = s->p = d->data;
879e2046dfSNick Hibma 	s->end = d->data + d->size;
889e2046dfSNick Hibma 	s->kindset = kindset;
899e2046dfSNick Hibma 	return (s);
909e2046dfSNick Hibma }
919e2046dfSNick Hibma 
929e2046dfSNick Hibma void
939e2046dfSNick Hibma hid_end_parse(hid_data_t s)
949e2046dfSNick Hibma {
959e2046dfSNick Hibma 
969e2046dfSNick Hibma 	_DIAGASSERT(s != NULL);
979e2046dfSNick Hibma 
989e2046dfSNick Hibma 	while (s->cur.next) {
999e2046dfSNick Hibma 		hid_item_t *hi = s->cur.next->next;
1009e2046dfSNick Hibma 		free(s->cur.next);
1019e2046dfSNick Hibma 		s->cur.next = hi;
1029e2046dfSNick Hibma 	}
1039e2046dfSNick Hibma 	free(s);
1049e2046dfSNick Hibma }
1059e2046dfSNick Hibma 
1069e2046dfSNick Hibma int
1079e2046dfSNick Hibma hid_get_item(hid_data_t s, hid_item_t *h)
1089e2046dfSNick Hibma {
1099e2046dfSNick Hibma 	hid_item_t *c;
1109e2046dfSNick Hibma 	unsigned int bTag = 0, bType = 0, bSize, oldpos;
1119e2046dfSNick Hibma 	unsigned char *data;
1129e2046dfSNick Hibma 	int dval;
1139e2046dfSNick Hibma 	unsigned char *p;
1149e2046dfSNick Hibma 	hid_item_t *hi;
1159e2046dfSNick Hibma 	int i;
1169e2046dfSNick Hibma 
1179e2046dfSNick Hibma 	_DIAGASSERT(s != NULL);
1189e2046dfSNick Hibma 	_DIAGASSERT(h != NULL);
1199e2046dfSNick Hibma 
1209e2046dfSNick Hibma 	c = &s->cur;
1219e2046dfSNick Hibma 
1229e2046dfSNick Hibma  top:
1239e2046dfSNick Hibma 	if (s->multimax) {
1249e2046dfSNick Hibma 		if (s->multi < s->multimax) {
1259e2046dfSNick Hibma 			c->usage = s->usages[min(s->multi, s->nusage-1)];
1269e2046dfSNick Hibma 			s->multi++;
1279e2046dfSNick Hibma 			*h = *c;
1289e2046dfSNick Hibma 			c->pos += c->report_size;
1299e2046dfSNick Hibma 			h->next = 0;
1309e2046dfSNick Hibma 			return (1);
1319e2046dfSNick Hibma 		} else {
1329e2046dfSNick Hibma 			c->report_count = s->multimax;
1339e2046dfSNick Hibma 			s->multimax = 0;
1349e2046dfSNick Hibma 			s->nusage = 0;
1359e2046dfSNick Hibma 			hid_clear_local(c);
1369e2046dfSNick Hibma 		}
1379e2046dfSNick Hibma 	}
1389e2046dfSNick Hibma 	for (;;) {
1399e2046dfSNick Hibma 		p = s->p;
1409e2046dfSNick Hibma 		if (p >= s->end)
1419e2046dfSNick Hibma 			return (0);
1429e2046dfSNick Hibma 
1439e2046dfSNick Hibma 		bSize = *p++;
1449e2046dfSNick Hibma 		if (bSize == 0xfe) {
1459e2046dfSNick Hibma 			/* long item */
1469e2046dfSNick Hibma 			bSize = *p++;
1479e2046dfSNick Hibma 			bSize |= *p++ << 8;
1489e2046dfSNick Hibma 			bTag = *p++;
1499e2046dfSNick Hibma 			data = p;
1509e2046dfSNick Hibma 			p += bSize;
1519e2046dfSNick Hibma 		} else {
1529e2046dfSNick Hibma 			/* short item */
1539e2046dfSNick Hibma 			bTag = bSize >> 4;
1549e2046dfSNick Hibma 			bType = (bSize >> 2) & 3;
1559e2046dfSNick Hibma 			bSize &= 3;
1569e2046dfSNick Hibma 			if (bSize == 3) bSize = 4;
1579e2046dfSNick Hibma 			data = p;
1589e2046dfSNick Hibma 			p += bSize;
1599e2046dfSNick Hibma 		}
1609e2046dfSNick Hibma 		s->p = p;
1619e2046dfSNick Hibma 		/*
1629e2046dfSNick Hibma 		 * The spec is unclear if the data is signed or unsigned.
1639e2046dfSNick Hibma 		 */
1649e2046dfSNick Hibma 		switch(bSize) {
1659e2046dfSNick Hibma 		case 0:
1669e2046dfSNick Hibma 			dval = 0;
1679e2046dfSNick Hibma 			break;
1689e2046dfSNick Hibma 		case 1:
1699e2046dfSNick Hibma 			dval = (int8_t)*data++;
1709e2046dfSNick Hibma 			break;
1719e2046dfSNick Hibma 		case 2:
1729e2046dfSNick Hibma 			dval = *data++;
1739e2046dfSNick Hibma 			dval |= *data++ << 8;
1749e2046dfSNick Hibma 			dval = (int16_t)dval;
1759e2046dfSNick Hibma 			break;
1769e2046dfSNick Hibma 		case 4:
1779e2046dfSNick Hibma 			dval = *data++;
1789e2046dfSNick Hibma 			dval |= *data++ << 8;
1799e2046dfSNick Hibma 			dval |= *data++ << 16;
1809e2046dfSNick Hibma 			dval |= *data++ << 24;
1819e2046dfSNick Hibma 			break;
1829e2046dfSNick Hibma 		default:
1839e2046dfSNick Hibma 			return (-1);
1849e2046dfSNick Hibma 		}
1859e2046dfSNick Hibma 
1869e2046dfSNick Hibma 		switch (bType) {
1879e2046dfSNick Hibma 		case 0:			/* Main */
1889e2046dfSNick Hibma 			switch (bTag) {
1899e2046dfSNick Hibma 			case 8:		/* Input */
1909e2046dfSNick Hibma 				if (!(s->kindset & (1 << hid_input)))
1919e2046dfSNick Hibma 					continue;
1929e2046dfSNick Hibma 				c->kind = hid_input;
1939e2046dfSNick Hibma 				c->flags = dval;
1949e2046dfSNick Hibma 			ret:
1959e2046dfSNick Hibma 				if (c->flags & HIO_VARIABLE) {
1969e2046dfSNick Hibma 					s->multimax = c->report_count;
1979e2046dfSNick Hibma 					s->multi = 0;
1989e2046dfSNick Hibma 					c->report_count = 1;
1999e2046dfSNick Hibma 					if (s->minset) {
2009e2046dfSNick Hibma 						for (i = c->usage_minimum;
2019e2046dfSNick Hibma 						     i <= c->usage_maximum;
2029e2046dfSNick Hibma 						     i++) {
2039e2046dfSNick Hibma 							s->usages[s->nusage] = i;
2049e2046dfSNick Hibma 							if (s->nusage < MAXUSAGE-1)
2059e2046dfSNick Hibma 								s->nusage++;
2069e2046dfSNick Hibma 						}
2079e2046dfSNick Hibma 						s->minset = 0;
2089e2046dfSNick Hibma 					}
2099e2046dfSNick Hibma 					goto top;
2109e2046dfSNick Hibma 				} else {
2119e2046dfSNick Hibma 					if (s->minset)
2129e2046dfSNick Hibma 						c->usage = c->usage_minimum;
2139e2046dfSNick Hibma 					*h = *c;
2149e2046dfSNick Hibma 					h->next = 0;
2159e2046dfSNick Hibma 					c->pos += c->report_size * c->report_count;
2169e2046dfSNick Hibma 					hid_clear_local(c);
2179e2046dfSNick Hibma 					s->minset = 0;
2189e2046dfSNick Hibma 					return (1);
2199e2046dfSNick Hibma 				}
2209e2046dfSNick Hibma 			case 9:		/* Output */
2219e2046dfSNick Hibma 				if (!(s->kindset & (1 << hid_output)))
2229e2046dfSNick Hibma 					continue;
2239e2046dfSNick Hibma 				c->kind = hid_output;
2249e2046dfSNick Hibma 				c->flags = dval;
2259e2046dfSNick Hibma 				goto ret;
2269e2046dfSNick Hibma 			case 10:	/* Collection */
2279e2046dfSNick Hibma 				c->kind = hid_collection;
2289e2046dfSNick Hibma 				c->collection = dval;
2299e2046dfSNick Hibma 				c->collevel++;
2309e2046dfSNick Hibma 				*h = *c;
2319e2046dfSNick Hibma 				hid_clear_local(c);
2329e2046dfSNick Hibma 				c->report_ID = NO_REPORT_ID;
2339e2046dfSNick Hibma 				s->nusage = 0;
2349e2046dfSNick Hibma 				return (1);
2359e2046dfSNick Hibma 			case 11:	/* Feature */
2369e2046dfSNick Hibma 				if (!(s->kindset & (1 << hid_feature)))
2379e2046dfSNick Hibma 					continue;
2389e2046dfSNick Hibma 				c->kind = hid_feature;
2399e2046dfSNick Hibma 				c->flags = dval;
2409e2046dfSNick Hibma 				goto ret;
2419e2046dfSNick Hibma 			case 12:	/* End collection */
2429e2046dfSNick Hibma 				c->kind = hid_endcollection;
2439e2046dfSNick Hibma 				c->collevel--;
2449e2046dfSNick Hibma 				*h = *c;
2459e2046dfSNick Hibma 				/*hid_clear_local(c);*/
2469e2046dfSNick Hibma 				s->nusage = 0;
2479e2046dfSNick Hibma 				return (1);
2489e2046dfSNick Hibma 			default:
2499e2046dfSNick Hibma 				return (-2);
2509e2046dfSNick Hibma 			}
2519e2046dfSNick Hibma 
2529e2046dfSNick Hibma 		case 1:		/* Global */
2539e2046dfSNick Hibma 			switch (bTag) {
2549e2046dfSNick Hibma 			case 0:
2559e2046dfSNick Hibma 				c->_usage_page = dval << 16;
2569e2046dfSNick Hibma 				break;
2579e2046dfSNick Hibma 			case 1:
2589e2046dfSNick Hibma 				c->logical_minimum = dval;
2599e2046dfSNick Hibma 				break;
2609e2046dfSNick Hibma 			case 2:
2619e2046dfSNick Hibma 				c->logical_maximum = dval;
2629e2046dfSNick Hibma 				break;
2639e2046dfSNick Hibma 			case 3:
2649e2046dfSNick Hibma 				c->physical_maximum = dval;
2659e2046dfSNick Hibma 				break;
2669e2046dfSNick Hibma 			case 4:
2679e2046dfSNick Hibma 				c->physical_maximum = dval;
2689e2046dfSNick Hibma 				break;
2699e2046dfSNick Hibma 			case 5:
2709e2046dfSNick Hibma 				c->unit_exponent = dval;
2719e2046dfSNick Hibma 				break;
2729e2046dfSNick Hibma 			case 6:
2739e2046dfSNick Hibma 				c->unit = dval;
2749e2046dfSNick Hibma 				break;
2759e2046dfSNick Hibma 			case 7:
2769e2046dfSNick Hibma 				c->report_size = dval;
2779e2046dfSNick Hibma 				break;
2789e2046dfSNick Hibma 			case 8:
2799e2046dfSNick Hibma 				c->report_ID = dval;
2809e2046dfSNick Hibma 				break;
2819e2046dfSNick Hibma 			case 9:
2829e2046dfSNick Hibma 				c->report_count = dval;
2839e2046dfSNick Hibma 				break;
2849e2046dfSNick Hibma 			case 10: /* Push */
2859e2046dfSNick Hibma 				hi = malloc(sizeof *hi);
2869e2046dfSNick Hibma 				*hi = s->cur;
2879e2046dfSNick Hibma 				c->next = hi;
2889e2046dfSNick Hibma 				break;
2899e2046dfSNick Hibma 			case 11: /* Pop */
2909e2046dfSNick Hibma 				hi = c->next;
2919e2046dfSNick Hibma 				oldpos = c->pos;
2929e2046dfSNick Hibma 				s->cur = *hi;
2939e2046dfSNick Hibma 				c->pos = oldpos;
2949e2046dfSNick Hibma 				free(hi);
2959e2046dfSNick Hibma 				break;
2969e2046dfSNick Hibma 			default:
2979e2046dfSNick Hibma 				return (-3);
2989e2046dfSNick Hibma 			}
2999e2046dfSNick Hibma 			break;
3009e2046dfSNick Hibma 		case 2:		/* Local */
3019e2046dfSNick Hibma 			switch (bTag) {
3029e2046dfSNick Hibma 			case 0:
3039e2046dfSNick Hibma 				if (bSize == 1)
3049e2046dfSNick Hibma 					dval = c->_usage_page | (dval&0xff);
3059e2046dfSNick Hibma 				else if (bSize == 2)
3069e2046dfSNick Hibma 					dval = c->_usage_page | (dval&0xffff);
3079e2046dfSNick Hibma 				c->usage = dval;
3089e2046dfSNick Hibma 				if (s->nusage < MAXUSAGE)
3099e2046dfSNick Hibma 					s->usages[s->nusage++] = dval;
3109e2046dfSNick Hibma 				/* else XXX */
3119e2046dfSNick Hibma 				break;
3129e2046dfSNick Hibma 			case 1:
3139e2046dfSNick Hibma 				s->minset = 1;
3149e2046dfSNick Hibma 				if (bSize == 1)
3159e2046dfSNick Hibma 					dval = c->_usage_page | (dval&0xff);
3169e2046dfSNick Hibma 				else if (bSize == 2)
3179e2046dfSNick Hibma 					dval = c->_usage_page | (dval&0xffff);
3189e2046dfSNick Hibma 				c->usage_minimum = dval;
3199e2046dfSNick Hibma 				break;
3209e2046dfSNick Hibma 			case 2:
3219e2046dfSNick Hibma 				if (bSize == 1)
3229e2046dfSNick Hibma 					dval = c->_usage_page | (dval&0xff);
3239e2046dfSNick Hibma 				else if (bSize == 2)
3249e2046dfSNick Hibma 					dval = c->_usage_page | (dval&0xffff);
3259e2046dfSNick Hibma 				c->usage_maximum = dval;
3269e2046dfSNick Hibma 				break;
3279e2046dfSNick Hibma 			case 3:
3289e2046dfSNick Hibma 				c->designator_index = dval;
3299e2046dfSNick Hibma 				break;
3309e2046dfSNick Hibma 			case 4:
3319e2046dfSNick Hibma 				c->designator_minimum = dval;
3329e2046dfSNick Hibma 				break;
3339e2046dfSNick Hibma 			case 5:
3349e2046dfSNick Hibma 				c->designator_maximum = dval;
3359e2046dfSNick Hibma 				break;
3369e2046dfSNick Hibma 			case 7:
3379e2046dfSNick Hibma 				c->string_index = dval;
3389e2046dfSNick Hibma 				break;
3399e2046dfSNick Hibma 			case 8:
3409e2046dfSNick Hibma 				c->string_minimum = dval;
3419e2046dfSNick Hibma 				break;
3429e2046dfSNick Hibma 			case 9:
3439e2046dfSNick Hibma 				c->string_maximum = dval;
3449e2046dfSNick Hibma 				break;
3459e2046dfSNick Hibma 			case 10:
3469e2046dfSNick Hibma 				c->set_delimiter = dval;
3479e2046dfSNick Hibma 				break;
3489e2046dfSNick Hibma 			default:
3499e2046dfSNick Hibma 				return (-4);
3509e2046dfSNick Hibma 			}
3519e2046dfSNick Hibma 			break;
3529e2046dfSNick Hibma 		default:
3539e2046dfSNick Hibma 			return (-5);
3549e2046dfSNick Hibma 		}
3559e2046dfSNick Hibma 	}
3569e2046dfSNick Hibma }
3579e2046dfSNick Hibma 
3589e2046dfSNick Hibma int
3599e2046dfSNick Hibma hid_report_size(report_desc_t r, enum hid_kind k, int *idp)
3609e2046dfSNick Hibma {
3619e2046dfSNick Hibma 	struct hid_data *d;
3629e2046dfSNick Hibma 	hid_item_t h;
3639e2046dfSNick Hibma 	int size, id;
3649e2046dfSNick Hibma 
3659e2046dfSNick Hibma 	_DIAGASSERT(r != NULL);
3669e2046dfSNick Hibma 	/* idp may be NULL */
3679e2046dfSNick Hibma 
3689e2046dfSNick Hibma 	id = 0;
3699e2046dfSNick Hibma 	if (idp)
3709e2046dfSNick Hibma 		*idp = 0;
3719e2046dfSNick Hibma 	memset(&h, 0, sizeof h);
3729e2046dfSNick Hibma 	for (d = hid_start_parse(r, 1<<k); hid_get_item(d, &h); ) {
3739e2046dfSNick Hibma 		if (h.report_ID != NO_REPORT_ID) {
3749e2046dfSNick Hibma 			if (idp)
3759e2046dfSNick Hibma 				*idp = h.report_ID;
3769e2046dfSNick Hibma 			id = 8;
3779e2046dfSNick Hibma 		}
3789e2046dfSNick Hibma 	}
3799e2046dfSNick Hibma 	hid_end_parse(d);
3809e2046dfSNick Hibma 	size = h.pos + id;
3819e2046dfSNick Hibma 	return ((size + 7) / 8);
3829e2046dfSNick Hibma }
3839e2046dfSNick Hibma 
3849e2046dfSNick Hibma int
3859e2046dfSNick Hibma hid_locate(desc, u, k, h)
3869e2046dfSNick Hibma 	report_desc_t desc;
3879e2046dfSNick Hibma 	unsigned int u;
3889e2046dfSNick Hibma 	enum hid_kind k;
3899e2046dfSNick Hibma 	hid_item_t *h;
3909e2046dfSNick Hibma {
3919e2046dfSNick Hibma 	hid_data_t d;
3929e2046dfSNick Hibma 
3939e2046dfSNick Hibma 	_DIAGASSERT(desc != NULL);
3949e2046dfSNick Hibma 	_DIAGASSERT(h != NULL);
3959e2046dfSNick Hibma 
3969e2046dfSNick Hibma 	for (d = hid_start_parse(desc, 1<<k); hid_get_item(d, h); ) {
3979e2046dfSNick Hibma 		if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) {
3989e2046dfSNick Hibma 			hid_end_parse(d);
3999e2046dfSNick Hibma 			return (1);
4009e2046dfSNick Hibma 		}
4019e2046dfSNick Hibma 	}
4029e2046dfSNick Hibma 	hid_end_parse(d);
4039e2046dfSNick Hibma 	h->report_size = 0;
4049e2046dfSNick Hibma 	return (0);
4059e2046dfSNick Hibma }
406