diff options
Diffstat (limited to 'lib/libusbhid')
-rw-r--r-- | lib/libusbhid/Makefile | 21 | ||||
-rw-r--r-- | lib/libusbhid/Makefile.depend | 15 | ||||
-rw-r--r-- | lib/libusbhid/data.c | 142 | ||||
-rw-r--r-- | lib/libusbhid/descr.c | 175 | ||||
-rw-r--r-- | lib/libusbhid/descr_compat.c | 78 | ||||
-rw-r--r-- | lib/libusbhid/parse.c | 583 | ||||
-rw-r--r-- | lib/libusbhid/usage.c | 238 | ||||
-rw-r--r-- | lib/libusbhid/usbhid.3 | 246 | ||||
-rw-r--r-- | lib/libusbhid/usbhid.h | 118 | ||||
-rw-r--r-- | lib/libusbhid/usbvar.h | 48 |
10 files changed, 1664 insertions, 0 deletions
diff --git a/lib/libusbhid/Makefile b/lib/libusbhid/Makefile new file mode 100644 index 000000000000..cb5de55883bb --- /dev/null +++ b/lib/libusbhid/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.5 1999/07/23 09:44:38 mrg Exp $ + +LIB= usbhid +MAN= usbhid.3 + +SHLIB_MAJOR= 4 + +MLINKS= usbhid.3 libusbhid.3 usbhid.3 hid_get_report_desc.3 \ + usbhid.3 hid_dispose_report_desc.3 \ + usbhid.3 hid_start_parse.3 usbhid.3 hid_end_parse.3 \ + usbhid.3 hid_get_item.3 usbhid.3 hid_report_size.3 \ + usbhid.3 hid_locate.3 \ + usbhid.3 hid_usage_page.3 usbhid.3 hid_usage_in_page.3 \ + usbhid.3 hid_init.3 \ + usbhid.3 hid_get_data.3 usbhid.3 hid_set_data.3 + +SRCS= descr.c descr_compat.c parse.c usage.c data.c + +INCS= usbhid.h + +.include <bsd.lib.mk> diff --git a/lib/libusbhid/Makefile.depend b/lib/libusbhid/Makefile.depend new file mode 100644 index 000000000000..6ef78fac5cbf --- /dev/null +++ b/lib/libusbhid/Makefile.depend @@ -0,0 +1,15 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/lib/libusbhid/data.c b/lib/libusbhid/data.c new file mode 100644 index 000000000000..0fc2f4e4d840 --- /dev/null +++ b/lib/libusbhid/data.c @@ -0,0 +1,142 @@ +/* $NetBSD: data.c,v 1.8 2000/04/02 11:10:53 augustss Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <dev/usb/usb_ioctl.h> +#include "usbhid.h" +#include "usbvar.h" + +int32_t +hid_get_data(const void *p, const hid_item_t *h) +{ + const uint8_t *buf; + uint32_t hpos; + uint32_t hsize; + uint32_t data; + int i, end, offs; + + buf = p; + + /* Skip report ID byte. */ + if (h->report_ID > 0) + buf++; + + hpos = h->pos; /* bit position of data */ + hsize = h->report_size; /* bit length of data */ + + /* Range check and limit */ + if (hsize == 0) + return (0); + if (hsize > 32) + hsize = 32; + + offs = hpos / 8; + end = (hpos + hsize) / 8 - offs; + data = 0; + for (i = 0; i <= end; i++) + data |= buf[offs + i] << (i*8); + + /* Correctly shift down data */ + data >>= hpos % 8; + hsize = 32 - hsize; + + /* Mask and sign extend in one */ + if ((h->logical_minimum < 0) || (h->logical_maximum < 0)) + data = (int32_t)((int32_t)data << hsize) >> hsize; + else + data = (uint32_t)((uint32_t)data << hsize) >> hsize; + + return (data); +} + +void +hid_set_data(void *p, const hid_item_t *h, int32_t data) +{ + uint8_t *buf; + uint32_t hpos; + uint32_t hsize; + uint32_t mask; + int i; + int end; + int offs; + + buf = p; + + /* Set report ID byte. */ + if (h->report_ID > 0) + *buf++ = h->report_ID & 0xff; + + hpos = h->pos; /* bit position of data */ + hsize = h->report_size; /* bit length of data */ + + if (hsize != 32) { + mask = (1 << hsize) - 1; + data &= mask; + } else + mask = ~0; + + data <<= (hpos % 8); + mask <<= (hpos % 8); + mask = ~mask; + + offs = hpos / 8; + end = (hpos + hsize) / 8 - offs; + + for (i = 0; i <= end; i++) + buf[offs + i] = (buf[offs + i] & (mask >> (i*8))) | + ((data >> (i*8)) & 0xff); +} + +int +hid_get_report(int fd, enum hid_kind k, unsigned char *data, unsigned int size) +{ + struct usb_gen_descriptor ugd; + + memset(&ugd, 0, sizeof(ugd)); + ugd.ugd_data = data; + ugd.ugd_maxlen = size; + ugd.ugd_report_type = k + 1; + return (ioctl(fd, USB_GET_REPORT, &ugd)); +} + +int +hid_set_report(int fd, enum hid_kind k, unsigned char *data, unsigned int size) +{ + struct usb_gen_descriptor ugd; + + memset(&ugd, 0, sizeof(ugd)); + ugd.ugd_data = data; + ugd.ugd_maxlen = size; + ugd.ugd_report_type = k + 1; + return (ioctl(fd, USB_SET_REPORT, &ugd)); +} diff --git a/lib/libusbhid/descr.c b/lib/libusbhid/descr.c new file mode 100644 index 000000000000..74491df53f6c --- /dev/null +++ b/lib/libusbhid/descr.c @@ -0,0 +1,175 @@ +/* $NetBSD: descr.c,v 1.9 2000/09/24 02:13:24 augustss Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <dev/usb/usb_ioctl.h> + +#include "usbhid.h" +#include "usbvar.h" + +int +hid_set_immed(int fd, int enable) +{ + int ret; + ret = ioctl(fd, USB_SET_IMMED, &enable); +#ifdef HID_COMPAT7 + if (ret < 0) + ret = hid_set_immed_compat7(fd, enable); +#endif + return (ret); +} + +int +hid_get_report_id(int fd) +{ + report_desc_t rep; + hid_data_t d; + hid_item_t h; + int kindset; + int temp = -1; + int ret; + + if ((rep = hid_get_report_desc(fd)) == NULL) + goto use_ioctl; + kindset = 1 << hid_input | 1 << hid_output | 1 << hid_feature; + for (d = hid_start_parse(rep, kindset, -1); hid_get_item(d, &h); ) { + /* Return the first report ID we met. */ + if (h.report_ID != 0) { + temp = h.report_ID; + break; + } + } + hid_end_parse(d); + hid_dispose_report_desc(rep); + + if (temp > 0) + return (temp); + +use_ioctl: + ret = ioctl(fd, USB_GET_REPORT_ID, &temp); +#ifdef HID_COMPAT7 + if (ret < 0) + ret = hid_get_report_id_compat7(fd); + else +#endif + ret = temp; + + return (ret); +} + +report_desc_t +hid_get_report_desc(int fd) +{ + struct usb_gen_descriptor ugd; + report_desc_t rep; + void *data; + + memset(&ugd, 0, sizeof(ugd)); + + /* get actual length first */ + ugd.ugd_data = NULL; + ugd.ugd_maxlen = 65535; + if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) { +#ifdef HID_COMPAT7 + /* could not read descriptor */ + /* try FreeBSD 7 compat code */ + return (hid_get_report_desc_compat7(fd)); +#else + return (NULL); +#endif + } + + /* + * NOTE: The kernel will return a failure if + * "ugd_actlen" is zero. + */ + data = malloc(ugd.ugd_actlen); + if (data == NULL) + return (NULL); + + /* fetch actual descriptor */ + ugd.ugd_data = data; + ugd.ugd_maxlen = ugd.ugd_actlen; + if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) { + /* could not read descriptor */ + free(data); + return (NULL); + } + + /* sanity check */ + if (ugd.ugd_actlen < 1) { + /* invalid report descriptor */ + free(data); + return (NULL); + } + + /* check END_COLLECTION */ + if (((unsigned char *)data)[ugd.ugd_actlen -1] != 0xC0) { + /* invalid end byte */ + free(data); + return (NULL); + } + + rep = hid_use_report_desc(data, ugd.ugd_actlen); + + free(data); + + return (rep); +} + +report_desc_t +hid_use_report_desc(unsigned char *data, unsigned int size) +{ + report_desc_t r; + + r = malloc(sizeof(*r) + size); + if (r == NULL) { + errno = ENOMEM; + return (NULL); + } + r->size = size; + memcpy(r->data, data, size); + return (r); +} + +void +hid_dispose_report_desc(report_desc_t r) +{ + + free(r); +} diff --git a/lib/libusbhid/descr_compat.c b/lib/libusbhid/descr_compat.c new file mode 100644 index 000000000000..c861d2f4d253 --- /dev/null +++ b/lib/libusbhid/descr_compat.c @@ -0,0 +1,78 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This file contains fallback-compatibility code for the old FreeBSD + * USB stack. + */ +#ifdef HID_COMPAT7 + +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +#include <dev/usb/usb.h> + +#include "usbhid.h" +#include "usbvar.h" + +int +hid_set_immed_compat7(int fd, int enable) +{ + return (ioctl(fd, USB_SET_IMMED, &enable)); +} + +int +hid_get_report_id_compat7(int fd) +{ + int temp = -1; + + if (ioctl(fd, USB_GET_REPORT_ID, &temp) < 0) + return (-1); + + return (temp); +} + +report_desc_t +hid_get_report_desc_compat7(int fd) +{ + struct usb_ctl_report_desc rep; + + rep.ucrd_size = 0; + if (ioctl(fd, USB_GET_REPORT_DESC, &rep) < 0) + return (NULL); + + return (hid_use_report_desc(rep.ucrd_data, (unsigned int)rep.ucrd_size)); +} +#endif /* HID_COMPAT7 */ diff --git a/lib/libusbhid/parse.c b/lib/libusbhid/parse.c new file mode 100644 index 000000000000..8eb94ab82fc8 --- /dev/null +++ b/lib/libusbhid/parse.c @@ -0,0 +1,583 @@ +/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999, 2001 Lennart Augustsson <augustss@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbhid.h> + +#include "usbhid.h" +#include "usbvar.h" + +#define MAXUSAGE 100 +#define MAXPUSH 4 +#define MAXID 64 +#define ITEMTYPES 3 + +struct hid_pos_data { + int32_t rid; + uint32_t pos[ITEMTYPES]; +}; + +struct hid_data { + const uint8_t *start; + const uint8_t *end; + const uint8_t *p; + struct hid_item cur[MAXPUSH]; + struct hid_pos_data last_pos[MAXID]; + uint32_t pos[ITEMTYPES]; + int32_t usages_min[MAXUSAGE]; + int32_t usages_max[MAXUSAGE]; + int32_t usage_last; /* last seen usage */ + uint32_t loc_size; /* last seen size */ + uint32_t loc_count; /* last seen count */ + uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ + uint8_t pushlevel; /* current pushlevel */ + uint8_t ncount; /* end usage item count */ + uint8_t icount; /* current usage item count */ + uint8_t nusage; /* end "usages_min/max" index */ + uint8_t iusage; /* current "usages_min/max" index */ + uint8_t ousage; /* current "usages_min/max" offset */ + uint8_t susage; /* usage set flags */ + int32_t reportid; /* requested report ID */ +}; + +/*------------------------------------------------------------------------* + * hid_clear_local + *------------------------------------------------------------------------*/ +static void +hid_clear_local(hid_item_t *c) +{ + + c->usage = 0; + c->usage_minimum = 0; + c->usage_maximum = 0; + c->designator_index = 0; + c->designator_minimum = 0; + c->designator_maximum = 0; + c->string_index = 0; + c->string_minimum = 0; + c->string_maximum = 0; + c->set_delimiter = 0; +} + +static void +hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) +{ + uint8_t i, j; + + /* check for same report ID - optimise */ + + if (c->report_ID == next_rID) + return; + + /* save current position for current rID */ + + if (c->report_ID == 0) { + i = 0; + } else { + for (i = 1; i != MAXID; i++) { + if (s->last_pos[i].rid == c->report_ID) + break; + if (s->last_pos[i].rid == 0) + break; + } + } + if (i != MAXID) { + s->last_pos[i].rid = c->report_ID; + for (j = 0; j < ITEMTYPES; j++) + s->last_pos[i].pos[j] = s->pos[j]; + } + + /* store next report ID */ + + c->report_ID = next_rID; + + /* lookup last position for next rID */ + + if (next_rID == 0) { + i = 0; + } else { + for (i = 1; i != MAXID; i++) { + if (s->last_pos[i].rid == next_rID) + break; + if (s->last_pos[i].rid == 0) + break; + } + } + if (i != MAXID) { + s->last_pos[i].rid = next_rID; + for (j = 0; j < ITEMTYPES; j++) + s->pos[j] = s->last_pos[i].pos[j]; + } else { + for (j = 0; j < ITEMTYPES; j++) + s->pos[j] = 0; /* Out of RID entries. */ + } +} + +/*------------------------------------------------------------------------* + * hid_start_parse + *------------------------------------------------------------------------*/ +hid_data_t +hid_start_parse(report_desc_t d, int kindset, int id) +{ + struct hid_data *s; + + s = malloc(sizeof *s); + memset(s, 0, sizeof *s); + s->start = s->p = d->data; + s->end = d->data + d->size; + s->kindset = kindset; + s->reportid = id; + return (s); +} + +/*------------------------------------------------------------------------* + * hid_end_parse + *------------------------------------------------------------------------*/ +void +hid_end_parse(hid_data_t s) +{ + + if (s == NULL) + return; + + free(s); +} + +/*------------------------------------------------------------------------* + * get byte from HID descriptor + *------------------------------------------------------------------------*/ +static uint8_t +hid_get_byte(struct hid_data *s, const uint16_t wSize) +{ + const uint8_t *ptr; + uint8_t retval; + + ptr = s->p; + + /* check if end is reached */ + if (ptr == s->end) + return (0); + + /* read out a byte */ + retval = *ptr; + + /* check if data pointer can be advanced by "wSize" bytes */ + if ((s->end - ptr) < wSize) + ptr = s->end; + else + ptr += wSize; + + /* update pointer */ + s->p = ptr; + + return (retval); +} + +/*------------------------------------------------------------------------* + * hid_get_item + *------------------------------------------------------------------------*/ +static int +hid_get_item_raw(hid_data_t s, hid_item_t *h) +{ + hid_item_t *c; + unsigned int bTag, bType, bSize; + int32_t mask; + int32_t dval; + + if (s == NULL) + return (0); + + c = &s->cur[s->pushlevel]; + + top: + /* check if there is an array of items */ + if (s->icount < s->ncount) { + /* get current usage */ + if (s->iusage < s->nusage) { + dval = s->usages_min[s->iusage] + s->ousage; + c->usage = dval; + s->usage_last = dval; + if (dval == s->usages_max[s->iusage]) { + s->iusage ++; + s->ousage = 0; + } else { + s->ousage ++; + } + } else { + /* Using last usage */ + dval = s->usage_last; + } + s->icount ++; + /* + * Only copy HID item, increment position and return + * if correct kindset! + */ + if (s->kindset & (1 << c->kind)) { + *h = *c; + h->pos = s->pos[c->kind]; + s->pos[c->kind] += c->report_size * c->report_count; + return (1); + } + } + + /* reset state variables */ + s->icount = 0; + s->ncount = 0; + s->iusage = 0; + s->nusage = 0; + s->susage = 0; + s->ousage = 0; + hid_clear_local(c); + + /* get next item */ + while (s->p != s->end) { + + bSize = hid_get_byte(s, 1); + if (bSize == 0xfe) { + /* long item */ + bSize = hid_get_byte(s, 1); + bSize |= hid_get_byte(s, 1) << 8; + bTag = hid_get_byte(s, 1); + bType = 0xff; /* XXX what should it be */ + } else { + /* short item */ + bTag = bSize >> 4; + bType = (bSize >> 2) & 3; + bSize &= 3; + if (bSize == 3) + bSize = 4; + } + + switch(bSize) { + case 0: + dval = 0; + mask = 0; + break; + case 1: + dval = (int8_t)hid_get_byte(s, 1); + mask = 0xFF; + break; + case 2: + dval = hid_get_byte(s, 1); + dval |= hid_get_byte(s, 1) << 8; + dval = (int16_t)dval; + mask = 0xFFFF; + break; + case 4: + dval = hid_get_byte(s, 1); + dval |= hid_get_byte(s, 1) << 8; + dval |= hid_get_byte(s, 1) << 16; + dval |= hid_get_byte(s, 1) << 24; + mask = 0xFFFFFFFF; + break; + default: + dval = hid_get_byte(s, bSize); + continue; + } + + switch (bType) { + case 0: /* Main */ + switch (bTag) { + case 8: /* Input */ + c->kind = hid_input; + c->flags = dval; + ret: + c->report_count = s->loc_count; + c->report_size = s->loc_size; + + if (c->flags & HIO_VARIABLE) { + /* range check usage count */ + if (c->report_count > 255) { + s->ncount = 255; + } else + s->ncount = c->report_count; + + /* + * The "top" loop will return + * one and one item: + */ + c->report_count = 1; + c->usage_minimum = 0; + c->usage_maximum = 0; + } else { + s->ncount = 1; + } + goto top; + + case 9: /* Output */ + c->kind = hid_output; + c->flags = dval; + goto ret; + case 10: /* Collection */ + c->kind = hid_collection; + c->collection = dval; + c->collevel++; + c->usage = s->usage_last; + *h = *c; + return (1); + case 11: /* Feature */ + c->kind = hid_feature; + c->flags = dval; + goto ret; + case 12: /* End collection */ + c->kind = hid_endcollection; + if (c->collevel == 0) { + /* Invalid end collection. */ + return (0); + } + c->collevel--; + *h = *c; + return (1); + default: + break; + } + break; + + case 1: /* Global */ + switch (bTag) { + case 0: + c->_usage_page = dval << 16; + break; + case 1: + c->logical_minimum = dval; + break; + case 2: + c->logical_maximum = dval; + break; + case 3: + c->physical_minimum = dval; + break; + case 4: + c->physical_maximum = dval; + break; + case 5: + c->unit_exponent = dval; + break; + case 6: + c->unit = dval; + break; + case 7: + /* mask because value is unsigned */ + s->loc_size = dval & mask; + break; + case 8: + hid_switch_rid(s, c, dval & mask); + break; + case 9: + /* mask because value is unsigned */ + s->loc_count = dval & mask; + break; + case 10: /* Push */ + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) + return (0); + s->pushlevel ++; + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->report_size = s->loc_size; + c->report_count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; + break; + case 11: /* Pop */ + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) + return (0); + s->pushlevel --; + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->report_size; + s->loc_count = c->report_count; + c->report_size = 0; + c->report_count = 0; + break; + default: + break; + } + break; + case 2: /* Local */ + switch (bTag) { + case 0: + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + + /* set last usage, in case of a collection */ + s->usage_last = dval; + + if (s->nusage < MAXUSAGE) { + s->usages_min[s->nusage] = dval; + s->usages_max[s->nusage] = dval; + s->nusage ++; + } + /* else XXX */ + + /* clear any pending usage sets */ + s->susage = 0; + break; + case 1: + s->susage |= 1; + + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + c->usage_minimum = dval; + + goto check_set; + case 2: + s->susage |= 2; + + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + c->usage_maximum = dval; + + check_set: + if (s->susage != 3) + break; + + /* sanity check */ + if ((s->nusage < MAXUSAGE) && + (c->usage_minimum <= c->usage_maximum)) { + /* add usage range */ + s->usages_min[s->nusage] = + c->usage_minimum; + s->usages_max[s->nusage] = + c->usage_maximum; + s->nusage ++; + } + /* else XXX */ + + s->susage = 0; + break; + case 3: + c->designator_index = dval; + break; + case 4: + c->designator_minimum = dval; + break; + case 5: + c->designator_maximum = dval; + break; + case 7: + c->string_index = dval; + break; + case 8: + c->string_minimum = dval; + break; + case 9: + c->string_maximum = dval; + break; + case 10: + c->set_delimiter = dval; + break; + default: + break; + } + break; + default: + break; + } + } + return (0); +} + +int +hid_get_item(hid_data_t s, hid_item_t *h) +{ + int r; + + for (;;) { + r = hid_get_item_raw(s, h); + if (r <= 0 || s->reportid == -1 || h->report_ID == s->reportid) + break; + } + return (r); +} + +int +hid_report_size(report_desc_t r, enum hid_kind k, int id) +{ + struct hid_data *d; + struct hid_item h; + uint32_t temp; + uint32_t hpos; + uint32_t lpos; + int report_id = 0; + + hpos = 0; + lpos = 0xFFFFFFFF; + + memset(&h, 0, sizeof h); + for (d = hid_start_parse(r, 1 << k, id); hid_get_item(d, &h); ) { + if (h.kind == k) { + /* compute minimum */ + if (lpos > h.pos) + lpos = h.pos; + /* compute end position */ + temp = h.pos + (h.report_size * h.report_count); + /* compute maximum */ + if (hpos < temp) + hpos = temp; + if (h.report_ID != 0) + report_id = 1; + } + } + hid_end_parse(d); + + /* safety check - can happen in case of currupt descriptors */ + if (lpos > hpos) + temp = 0; + else + temp = hpos - lpos; + + /* return length in bytes rounded up */ + return ((temp + 7) / 8 + report_id); +} + +int +hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, + hid_item_t *h, int id) +{ + struct hid_data *d; + + for (d = hid_start_parse(desc, 1 << k, id); hid_get_item(d, h); ) { + if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) { + hid_end_parse(d); + return (1); + } + } + hid_end_parse(d); + h->report_size = 0; + return (0); +} diff --git a/lib/libusbhid/usage.c b/lib/libusbhid/usage.c new file mode 100644 index 000000000000..3233044b5bff --- /dev/null +++ b/lib/libusbhid/usage.c @@ -0,0 +1,238 @@ +/* $NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <assert.h> +#include <ctype.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "usbhid.h" + +#define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages" + +struct usage_in_page { + const char *name; + int usage; +}; + +static struct usage_page { + const char *name; + int usage; + struct usage_in_page *page_contents; + int pagesize, pagesizemax; +} *pages; +static int npages, npagesmax; + +#ifdef DEBUG +void +dump_hid_table(void) +{ + int i, j; + + for (i = 0; i < npages; i++) { + printf("%d\t%s\n", pages[i].usage, pages[i].name); + for (j = 0; j < pages[i].pagesize; j++) { + printf("\t%d\t%s\n", pages[i].page_contents[j].usage, + pages[i].page_contents[j].name); + } + } +} +#endif + +void +hid_init(const char *hidname) +{ + FILE *f; + char line[100], name[100], *p, *n; + int no; + int lineno; + struct usage_page *curpage = NULL; + + if (hidname == NULL) + hidname = _PATH_HIDTABLE; + + f = fopen(hidname, "r"); + if (f == NULL) + err(1, "%s", hidname); + for (lineno = 1; ; lineno++) { + if (fgets(line, sizeof line, f) == NULL) + break; + if (line[0] == '#') + continue; + for (p = line; *p && isspace(*p); p++) + ; + if (!*p) + continue; + if (sscanf(line, " * %[^\n]", name) == 1) + no = -1; + else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 && + sscanf(line, " %d %[^\n]", &no, name) != 2) + errx(1, "file %s, line %d, syntax error", + hidname, lineno); + for (p = name; *p; p++) + if (isspace(*p) || *p == '.') + *p = '_'; + n = strdup(name); + if (!n) + err(1, "strdup"); + if (isspace(line[0])) { + if (!curpage) + errx(1, "file %s, line %d, syntax error", + hidname, lineno); + if (curpage->pagesize >= curpage->pagesizemax) { + curpage->pagesizemax += 10; + curpage->page_contents = + realloc(curpage->page_contents, + curpage->pagesizemax * + sizeof (struct usage_in_page)); + if (!curpage->page_contents) + err(1, "realloc"); + } + curpage->page_contents[curpage->pagesize].name = n; + curpage->page_contents[curpage->pagesize].usage = no; + curpage->pagesize++; + } else { + if (npages >= npagesmax) { + if (pages == NULL) { + npagesmax = 5; + pages = malloc(npagesmax * + sizeof (struct usage_page)); + } else { + npagesmax += 5; + pages = realloc(pages, + npagesmax * + sizeof (struct usage_page)); + } + if (!pages) + err(1, "alloc"); + } + curpage = &pages[npages++]; + curpage->name = n; + curpage->usage = no; + curpage->pagesize = 0; + curpage->pagesizemax = 10; + curpage->page_contents = + malloc(curpage->pagesizemax * + sizeof (struct usage_in_page)); + if (!curpage->page_contents) + err(1, "malloc"); + } + } + fclose(f); +#ifdef DEBUG + dump_hid_table(); +#endif +} + +const char * +hid_usage_page(int i) +{ + static char b[10]; + int k; + + if (!pages) + errx(1, "no hid table"); + + for (k = 0; k < npages; k++) + if (pages[k].usage == i) + return pages[k].name; + sprintf(b, "0x%04x", i); + return b; +} + +const char * +hid_usage_in_page(unsigned int u) +{ + int page = HID_PAGE(u); + int i = HID_USAGE(u); + static char b[100]; + int j, k, us; + + for (k = 0; k < npages; k++) + if (pages[k].usage == page) + break; + if (k >= npages) + goto bad; + for (j = 0; j < pages[k].pagesize; j++) { + us = pages[k].page_contents[j].usage; + if (us == -1) { + sprintf(b, + fmtcheck(pages[k].page_contents[j].name, "%d"), + i); + return b; + } + if (us == i) + return pages[k].page_contents[j].name; + } + bad: + sprintf(b, "0x%04x", i); + return b; +} + +int +hid_parse_usage_page(const char *name) +{ + int k; + + if (!pages) + errx(1, "no hid table"); + + for (k = 0; k < npages; k++) + if (strcmp(pages[k].name, name) == 0) + return pages[k].usage; + return -1; +} + +/* XXX handle hex */ +int +hid_parse_usage_in_page(const char *name) +{ + const char *sep; + int k, j; + unsigned int l; + + sep = strchr(name, ':'); + if (sep == NULL) + return -1; + l = sep - name; + for (k = 0; k < npages; k++) + if (strncmp(pages[k].name, name, l) == 0) + goto found; + return -1; + found: + sep++; + for (j = 0; j < pages[k].pagesize; j++) + if (strcmp(pages[k].page_contents[j].name, sep) == 0) + return (pages[k].usage << 16) | pages[k].page_contents[j].usage; + return (-1); +} diff --git a/lib/libusbhid/usbhid.3 b/lib/libusbhid/usbhid.3 new file mode 100644 index 000000000000..27a84402c279 --- /dev/null +++ b/lib/libusbhid/usbhid.3 @@ -0,0 +1,246 @@ +.\" $NetBSD: usb.3,v 1.13 2000/09/24 02:17:52 augustss Exp $ +.\" +.\" Copyright (c) 1999, 2001 Lennart Augustsson <augustss@NetBSD.org> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd January 27, 2009 +.Dt USBHID 3 +.Os +.Sh NAME +.Nm usbhid , +.Nm hid_get_report_desc , +.Nm hid_get_report_id , +.Nm hid_use_report_desc , +.Nm hid_dispose_report_desc , +.Nm hid_start_parse , +.Nm hid_end_parse , +.Nm hid_get_item , +.Nm hid_report_size , +.Nm hid_locate , +.Nm hid_usage_page , +.Nm hid_usage_in_page , +.Nm hid_init , +.Nm hid_get_data , +.Nm hid_set_data , +.Nm hid_get_report , +.Nm hid_set_report +.Nd USB HID access routines +.Sh LIBRARY +.Lb libusbhid +.Sh SYNOPSIS +.In usbhid.h +.Ft report_desc_t +.Fn hid_get_report_desc "int file" +.Ft int +.Fn hid_get_report_id "int file" +.Ft int +.Fn hid_set_immed "int fd" "int enable" +.Ft report_desc_t +.Fn hid_use_report_desc "unsigned char *data" "unsigned int size" +.Ft void +.Fn hid_dispose_report_desc "report_desc_t d" +.Ft hid_data_t +.Fn hid_start_parse "report_desc_t d" "int kindset" "int id" +.Ft void +.Fn hid_end_parse "hid_data_t s" +.Ft int +.Fn hid_get_item "hid_data_t s" "hid_item_t *h" +.Ft int +.Fn hid_report_size "report_desc_t d" "hid_kind_t k" "int id" +.Ft int +.Fn hid_locate "report_desc_t d" "u_int usage" "hid_kind_t k" "hid_item_t *h" "int id" +.Ft "const char *" +.Fn hid_usage_page "int i" +.Ft "const char *" +.Fn hid_usage_in_page "u_int u" +.Ft int +.Fn hid_parse_usage_page "const char *" +.Ft int +.Fn hid_parse_usage_in_page "const char *" +.Ft void +.Fn hid_init "const char *file" +.Ft int +.Fn hid_get_data "const void *data" "const hid_item_t *h" +.Ft void +.Fn hid_set_data "void *buf" "const hid_item_t *h" "int data" +.Ft int +.Fn hid_get_report "int fd" "enum hid_kind k" "unsigned char *data" "unsigned int size" +.Ft int +.Fn hid_set_report "int fd" "enum hid_kind k" "unsigned char *data" "unsigned int size" +.Sh DESCRIPTION +The +.Nm +library provides routines to extract data from USB Human Interface Devices. +.Ss Introduction +USB HID devices send and receive data laid out in a device dependent way. +The +.Nm +library contains routines to extract the +.Em "report descriptor" +which contains the data layout information and then use this information. +.Pp +The routines can be divided into four parts: extraction of the descriptor, +parsing of the descriptor, translating to/from symbolic names, and +data manipulation. +.Ss Synchronous HID operation +Synchronous HID operation can be enabled or disabled by a call to +.Fn hid_set_immed . +If the second argument is zero synchronous HID operation is disabled. +Else synchronous HID operation is enabled. +The function returns a negative value on failure. +.Pp +.Fn hid_get_report +and +.Fn hid_set_report +functions allow to synchronously get and set specific report if device +supports it. +For devices with multiple report IDs, wanted ID should be provided in the +first byte of the buffer for both get and set. +.Ss Descriptor Functions +The report descriptor ID can be obtained by calling +.Fn hid_get_report_id . +A report descriptor can be obtained by calling +.Fn hid_get_report_desc +with a file descriptor obtained by opening a +.Xr uhid 4 +device. +Alternatively a data buffer containing the report descriptor can be +passed into +.Fn hid_use_report_desc . +The data is copied into an internal structure. +When the report descriptor +is no longer needed it should be freed by calling +.Fn hid_dispose_report_desc . +The type +.Vt report_desc_t +is opaque and should be used when calling the parsing functions. +If +.Fn hid_dispose_report_desc +fails it will return +.Dv NULL . +.Ss Descriptor Parsing Functions +To parse the report descriptor the +.Fn hid_start_parse +function should be called with a report descriptor, a set that +describes which items that are interesting, and the desired report +ID (or -1 to obtain items of all report IDs). +The set is obtained by OR-ing together values +.Fa "(1 << k)" +where +.Fa k +is an item of type +.Vt hid_kind_t . +The function returns +.Dv NULL +if the initialization fails, otherwise an opaque value to be used +in subsequent calls. +After parsing the +.Fn hid_end_parse +function should be called to free internal data structures. +.Pp +To iterate through all the items in the report descriptor +.Fn hid_get_item +should be called while it returns a value greater than 0. +When the report descriptor ends it will returns 0; a syntax +error within the report descriptor will cause a return value less +than 0. +The struct pointed to by +.Fa h +will be filled with the relevant data for the item. +The definition of +.Vt hid_item_t +can be found in +.In usbhid.h +and the meaning of the components in the USB HID documentation. +.Pp +Data should be read/written to the device in the size of +the report. +The size of a report (of a certain kind) can be computed by the +.Fn hid_report_size +function. +If the report is prefixed by an ID byte it is given by +.Fa id . +.Pp +To locate a single item the +.Fn hid_locate +function can be used. +It should be given the usage code of +the item and its kind and it will fill the item and return +non-zero if the item was found. +.Ss Name Translation Functions +The function +.Fn hid_usage_page +will return the symbolic name of a usage page, and the function +.Fn hid_usage_in_page +will return the symbolic name of the usage within the page. +Both these functions may return a pointer to static data. +.Pp +The functions +.Fn hid_parse_usage_page +and +.Fn hid_parse_usage_in_page +are the inverses of +.Fn hid_usage_page +and +.Fn hid_usage_in_page . +They take a usage string and return the number of the usage, or \-1 +if it cannot be found. +.Pp +Before any of these functions can be called the usage table +must be parsed, this is done by calling +.Fn hid_init +with the name of the table. +Passing +.Dv NULL +to this function will cause it to use the default table. +.Ss Data Extraction Functions +Given the data obtained from a HID device and an item in the +report descriptor the +.Fn hid_get_data +function extracts the value of the item. +Conversely +.Fn hid_set_data +can be used to put data into a report (which must be zeroed first). +.Sh FILES +.Bl -tag -width ".Pa /usr/share/misc/usb_hid_usages" +.It Pa /usr/share/misc/usb_hid_usages +The default HID usage table. +.El +.Sh EXAMPLES +Not yet. +.Sh SEE ALSO +The +.Tn USB +specifications can be found at +.Pa http://www.usb.org/developers/docs/ . +.Pp +.Xr uhid 4 , +.Xr usb 4 +.Sh HISTORY +The +.Nm +library first appeared in +.Nx 1.5 . +.Sh BUGS +This man page is woefully incomplete. diff --git a/lib/libusbhid/usbhid.h b/lib/libusbhid/usbhid.h new file mode 100644 index 000000000000..637fb3d846f7 --- /dev/null +++ b/lib/libusbhid/usbhid.h @@ -0,0 +1,118 @@ +/* $NetBSD: usb.h,v 1.8 2000/08/13 22:22:02 augustss Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _USBHID_H_ +#define _USBHID_H_ + +#include <stdint.h> + +typedef struct report_desc *report_desc_t; + +typedef struct hid_data *hid_data_t; + +typedef enum hid_kind { + hid_input, hid_output, hid_feature, hid_collection, hid_endcollection +} hid_kind_t; + +typedef struct hid_item { + /* Global */ + uint32_t _usage_page; + int32_t logical_minimum; + int32_t logical_maximum; + int32_t physical_minimum; + int32_t physical_maximum; + int32_t unit_exponent; + int32_t unit; + int32_t report_size; + int32_t report_ID; +#define NO_REPORT_ID 0 + int32_t report_count; + /* Local */ + uint32_t usage; + int32_t usage_minimum; + int32_t usage_maximum; + int32_t designator_index; + int32_t designator_minimum; + int32_t designator_maximum; + int32_t string_index; + int32_t string_minimum; + int32_t string_maximum; + int32_t set_delimiter; + /* Misc */ + int32_t collection; + int collevel; + enum hid_kind kind; + uint32_t flags; + /* Location */ + uint32_t pos; + /* unused */ + struct hid_item *next; +} hid_item_t; + +#define HID_PAGE(u) (((u) >> 16) & 0xffff) +#define HID_USAGE(u) ((u) & 0xffff) +#define HID_HAS_GET_SET_REPORT 1 + +__BEGIN_DECLS + +/* Obtaining a report descriptor, descr.c: */ +report_desc_t hid_get_report_desc(int file); +report_desc_t hid_use_report_desc(unsigned char *data, unsigned int size); +void hid_dispose_report_desc(report_desc_t); +int hid_get_report_id(int file); +int hid_set_immed(int fd, int enable); + +/* Parsing of a HID report descriptor, parse.c: */ +hid_data_t hid_start_parse(report_desc_t d, int kindset, int id); +void hid_end_parse(hid_data_t s); +int hid_get_item(hid_data_t s, hid_item_t *h); +int hid_report_size(report_desc_t d, enum hid_kind k, int id); +int hid_locate(report_desc_t d, unsigned int usage, enum hid_kind k, + hid_item_t *h, int id); + +/* Conversion to/from usage names, usage.c: */ +const char *hid_usage_page(int i); +const char *hid_usage_in_page(unsigned int u); +void hid_init(const char *file); +int hid_parse_usage_in_page(const char *name); +int hid_parse_usage_page(const char *name); + +/* Extracting/insertion of data, data.c: */ +int32_t hid_get_data(const void *p, const hid_item_t *h); +void hid_set_data(void *p, const hid_item_t *h, int32_t data); +int hid_get_report(int fd, enum hid_kind k, + unsigned char *data, unsigned int size); +int hid_set_report(int fd, enum hid_kind k, + unsigned char *data, unsigned int size); + +__END_DECLS + +#endif /* !_USBHID_H_ */ diff --git a/lib/libusbhid/usbvar.h b/lib/libusbhid/usbvar.h new file mode 100644 index 000000000000..d23f580f1679 --- /dev/null +++ b/lib/libusbhid/usbvar.h @@ -0,0 +1,48 @@ +/* $NetBSD: usbvar.h,v 1.2 1999/05/11 21:15:46 augustss Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _USBVAR_H_ +#define _USBVAR_H_ + +struct report_desc { + uint32_t size; + uint8_t data[1]; +}; + +/* internal backwards compatibility functions */ + +#ifdef HID_COMPAT7 +int hid_set_immed_compat7(int fd, int enable); +int hid_get_report_id_compat7(int fd); +report_desc_t hid_get_report_desc_compat7(int fd); +#endif + +#endif /* _USBVAR_H_ */ |