diff options
-rw-r--r-- | lib/libusbhid/Makefile | 5 | ||||
-rw-r--r-- | lib/libusbhid/data.c | 2 | ||||
-rw-r--r-- | lib/libusbhid/descr.c | 4 | ||||
-rw-r--r-- | lib/libusbhid/libusbhid.h | 105 | ||||
-rw-r--r-- | lib/libusbhid/parse.c | 137 | ||||
-rw-r--r-- | lib/libusbhid/usage.c | 3 | ||||
-rw-r--r-- | lib/libusbhid/usbhid.3 | 54 | ||||
-rw-r--r-- | lib/libusbhid/usbhid.h | 6 | ||||
-rw-r--r-- | sys/sys/param.h | 2 | ||||
-rw-r--r-- | usr.bin/usbhidctl/usbhid.c | 7 |
10 files changed, 135 insertions, 190 deletions
diff --git a/lib/libusbhid/Makefile b/lib/libusbhid/Makefile index 79cc2f6e6671..9594649b88d2 100644 --- a/lib/libusbhid/Makefile +++ b/lib/libusbhid/Makefile @@ -6,7 +6,7 @@ MAINTAINER= n_hibma@FreeBSD.ORG LIB= usbhid MAN= usbhid.3 -SHLIB_MAJOR= 0 +SHLIB_MAJOR= 1 MLINKS= usbhid.3 libusbhid.3 usbhid.3 hid_get_report_desc.3 \ usbhid.3 hid_dispose_report_desc.3 \ @@ -19,7 +19,6 @@ MLINKS= usbhid.3 libusbhid.3 usbhid.3 hid_get_report_desc.3 \ SRCS= descr.c parse.c usage.c data.c -INCS= libusbhid.h +INCS= usbhid.h .include <bsd.lib.mk> - diff --git a/lib/libusbhid/data.c b/lib/libusbhid/data.c index 9e7dc932b4eb..d278ddb8d875 100644 --- a/lib/libusbhid/data.c +++ b/lib/libusbhid/data.c @@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$"); #include <assert.h> #include <stdlib.h> -#include "libusbhid.h" +#include "usbhid.h" int hid_get_data(const void *p, const hid_item_t *h) diff --git a/lib/libusbhid/descr.c b/lib/libusbhid/descr.c index 5f87c3484b0c..4afdb61ce19b 100644 --- a/lib/libusbhid/descr.c +++ b/lib/libusbhid/descr.c @@ -37,13 +37,11 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> #include <sys/time.h> -#if defined(__FreeBSD__) #include <sys/ioctl.h> -#endif #include <dev/usb/usb.h> -#include "libusbhid.h" +#include "usbhid.h" #include "usbvar.h" report_desc_t diff --git a/lib/libusbhid/libusbhid.h b/lib/libusbhid/libusbhid.h deleted file mode 100644 index dd9c650cedb8..000000000000 --- a/lib/libusbhid/libusbhid.h +++ /dev/null @@ -1,105 +0,0 @@ -/* $NetBSD: usb.h,v 1.8 2000/08/13 22:22:02 augustss Exp $ */ - -/* - * 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. - * - * $FreeBSD$ - * - */ - -#include <sys/cdefs.h> - -typedef struct report_desc *report_desc_t; - -typedef struct hid_data *hid_data_t; - -typedef enum hid_kind { - hid_input = 0, - hid_output = 1, - hid_feature = 2, - hid_collection, - hid_endcollection -} hid_kind_t; - -typedef struct hid_item { - /* Global */ - int _usage_page; - int logical_minimum; - int logical_maximum; - int physical_minimum; - int physical_maximum; - int unit_exponent; - int unit; - int report_size; - int report_ID; -#define NO_REPORT_ID 0 - int report_count; - /* Local */ - unsigned int usage; - int usage_minimum; - int usage_maximum; - int designator_index; - int designator_minimum; - int designator_maximum; - int string_index; - int string_minimum; - int string_maximum; - int set_delimiter; - /* Misc */ - int collection; - int collevel; - enum hid_kind kind; - unsigned int flags; - /* Absolute data position (bits) */ - unsigned int pos; - /* */ - struct hid_item *next; -} hid_item_t; - -#define HID_PAGE(u) (((u) >> 16) & 0xffff) -#define HID_USAGE(u) ((u) & 0xffff) - -/* 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); - -/* Parsing of a HID report descriptor, parse.c: */ -hid_data_t hid_start_parse(report_desc_t d, int kindset); -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, unsigned int id, enum hid_kind k); -int hid_locate(report_desc_t d, unsigned int usage, enum hid_kind k, hid_item_t *h); - -/* 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: */ -int hid_get_data(const void *p, const hid_item_t *h); -void hid_set_data(void *p, const hid_item_t *h, int data); diff --git a/lib/libusbhid/parse.c b/lib/libusbhid/parse.c index d8c64625bfee..6680d84b9ed4 100644 --- a/lib/libusbhid/parse.c +++ b/lib/libusbhid/parse.c @@ -1,7 +1,7 @@ /* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ /* - * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> + * Copyright (c) 1999, 2001 Lennart Augustsson <augustss@netbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/usb.h> #include <dev/usb/usbhid.h> -#include "libusbhid.h" +#include "usbhid.h" #include "usbvar.h" #define MAXUSAGE 100 @@ -49,18 +49,30 @@ struct hid_data { unsigned int usages[MAXUSAGE]; int nusage; int minset; + int logminsize; int multi; int multimax; int kindset; + int reportid; - /* Absolute data position (bits) for input/output/feature. - Assumes that hid_input, hid_output and hid_feature have - values 0, 1 and 2. */ - unsigned int kindpos[3]; + /* + * The start of collection item has no report ID set, so save + * it until we know the ID. + */ + hid_item_t savedcoll; + u_char hassavedcoll; + /* + * Absolute data position (bits) for input/output/feature. + * Assumes that hid_input, hid_output and hid_feature have + * values 0, 1 and 2. + */ + unsigned int kindpos[3]; }; static int min(int x, int y) { return x < y ? x : y; } +static int hid_get_item_raw(hid_data_t s, hid_item_t *h); + static void hid_clear_local(hid_item_t *c) { @@ -78,7 +90,7 @@ hid_clear_local(hid_item_t *c) } hid_data_t -hid_start_parse(report_desc_t d, int kindset) +hid_start_parse(report_desc_t d, int kindset, int id) { struct hid_data *s; @@ -87,6 +99,8 @@ hid_start_parse(report_desc_t d, int kindset) s->start = s->p = d->data; s->end = d->data + d->size; s->kindset = kindset; + s->reportid = id; + s->hassavedcoll = 0; return (s); } @@ -104,12 +118,38 @@ hid_end_parse(hid_data_t s) 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) + break; + if (h->report_ID == s->reportid || s->reportid == -1) + break; + } + return (r); +} + +#define REPORT_SAVED_COLL \ + do { \ + if (s->hassavedcoll) { \ + *h = s->savedcoll; \ + h->report_ID = c->report_ID; \ + s->hassavedcoll = 0; \ + return (1); \ + } \ + } while(/*LINTED*/ 0) + +static int +hid_get_item_raw(hid_data_t s, hid_item_t *h) +{ hid_item_t *c; unsigned int bTag = 0, bType = 0, bSize; unsigned char *data; int dval; unsigned char *p; hid_item_t *hi; + hid_item_t nc; int i; hid_kind_t retkind; @@ -117,13 +157,21 @@ hid_get_item(hid_data_t s, hid_item_t *h) top: if (s->multimax) { + REPORT_SAVED_COLL; + if (c->logical_minimum >= c->logical_maximum) { + if (s->logminsize == 1) + c->logical_minimum =(int8_t)c->logical_minimum; + else if (s->logminsize == 2) + c->logical_minimum =(int16_t)c->logical_minimum; + } if (s->multi < s->multimax) { c->usage = s->usages[min(s->multi, s->nusage-1)]; s->multi++; *h = *c; - - /* 'multimax' is only non-zero if the current - item kind is input/output/feature */ + /* + * 'multimax' is only non-zero if the current + * item kind is input/output/feature + */ h->pos = s->kindpos[c->kind]; s->kindpos[c->kind] += c->report_size; h->next = 0; @@ -208,6 +256,8 @@ hid_get_item(hid_data_t s, hid_item_t *h) if (s->nusage < MAXUSAGE-1) s->nusage++; } + c->usage_minimum = 0; + c->usage_maximum = 0; s->minset = 0; } goto top; @@ -217,7 +267,8 @@ hid_get_item(hid_data_t s, hid_item_t *h) *h = *c; h->next = 0; h->pos = s->kindpos[c->kind]; - s->kindpos[c->kind] += c->report_size * c->report_count; + s->kindpos[c->kind] += + c->report_size * c->report_count; hid_clear_local(c); s->minset = 0; return (1); @@ -229,15 +280,25 @@ hid_get_item(hid_data_t s, hid_item_t *h) c->kind = hid_collection; c->collection = dval; c->collevel++; - *h = *c; + nc = *c; hid_clear_local(c); - c->report_ID = NO_REPORT_ID; + /*c->report_ID = NO_REPORT_ID;*/ s->nusage = 0; - return (1); + if (s->hassavedcoll) { + *h = s->savedcoll; + h->report_ID = nc.report_ID; + s->savedcoll = nc; + return (1); + } else { + s->hassavedcoll = 1; + s->savedcoll = nc; + } + break; case 11: /* Feature */ retkind = hid_feature; goto ret; case 12: /* End collection */ + REPORT_SAVED_COLL; c->kind = hid_endcollection; c->collevel--; *h = *c; @@ -247,6 +308,7 @@ hid_get_item(hid_data_t s, hid_item_t *h) default: return (-2); } + break; case 1: /* Global */ switch (bTag) { @@ -255,6 +317,7 @@ hid_get_item(hid_data_t s, hid_item_t *h) break; case 1: c->logical_minimum = dval; + s->logminsize = bSize; break; case 2: c->logical_maximum = dval; @@ -276,6 +339,9 @@ hid_get_item(hid_data_t s, hid_item_t *h) break; case 8: c->report_ID = dval; + s->kindpos[hid_input] = + s->kindpos[hid_output] = + s->kindpos[hid_feature] = 0; break; case 9: c->report_count = dval; @@ -297,29 +363,17 @@ hid_get_item(hid_data_t s, hid_item_t *h) case 2: /* Local */ switch (bTag) { case 0: - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage = dval; + c->usage = c->_usage_page | dval; if (s->nusage < MAXUSAGE) - s->usages[s->nusage++] = dval; + s->usages[s->nusage++] = c->usage; /* else XXX */ break; case 1: s->minset = 1; - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage_minimum = dval; + c->usage_minimum = c->_usage_page | dval; break; case 2: - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage_maximum = dval; + c->usage_maximum = c->_usage_page | dval; break; case 3: c->designator_index = dval; @@ -353,35 +407,30 @@ hid_get_item(hid_data_t s, hid_item_t *h) } int -hid_report_size(report_desc_t r, unsigned int id, enum hid_kind k) +hid_report_size(report_desc_t r, enum hid_kind k, int id) { struct hid_data *d; hid_item_t h; - unsigned int size = 0; + int size; memset(&h, 0, sizeof h); - d = hid_start_parse(r, 1<<k); - while (hid_get_item(d, &h)) { + size = 0; + for (d = hid_start_parse(r, 1<<k, id); hid_get_item(d, &h); ) { if (h.report_ID == id && h.kind == k) { - unsigned int newsize = h.pos + h.report_size; - if (newsize > size) - size = newsize; + size = d->kindpos[k]; } } hid_end_parse(d); - - if (id != NO_REPORT_ID) - size += 8; /* add 8 bits for the report ID */ - - return ((size + 7) / 8); /* return size in bytes */ + return ((size + 7) / 8); } int -hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, hid_item_t *h) +hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, + hid_item_t *h, int id) { hid_data_t d; - for (d = hid_start_parse(desc, 1<<k); hid_get_item(d, h); ) { + 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); diff --git a/lib/libusbhid/usage.c b/lib/libusbhid/usage.c index 8e6bfcaa10de..280ef69aae8c 100644 --- a/lib/libusbhid/usage.c +++ b/lib/libusbhid/usage.c @@ -29,13 +29,14 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <assert.h> #include <ctype.h> #include <err.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "libusbhid.h" +#include "usbhid.h" #define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages" diff --git a/lib/libusbhid/usbhid.3 b/lib/libusbhid/usbhid.3 index c0beea7f4314..6db749551b22 100644 --- a/lib/libusbhid/usbhid.3 +++ b/lib/libusbhid/usbhid.3 @@ -1,6 +1,6 @@ .\" $NetBSD: usb.3,v 1.13 2000/09/24 02:17:52 augustss Exp $ .\" -.\" Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> +.\" Copyright (c) 1999, 2001 Lennart Augustsson <augustss@NetBSD.org> .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 11, 1999 +.Dd December 29, 2001 .Dt USBHID 3 .Os .Sh NAME @@ -48,7 +48,7 @@ .Sh LIBRARY .Lb libusbhid .Sh SYNOPSIS -.In libusbhid.h +.In usbhid.h .Ft report_desc_t .Fn hid_get_report_desc "int file" .Ft report_desc_t @@ -56,34 +56,34 @@ .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" +.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" "unsigned int id" "hid_kind_t k" +.Fn hid_report_size "report_desc_t d" "hid_kind_t k" "int id" .Ft int -.Fn hid_locate "report_desc_t d" "unsigned int usage" "hid_kind_t k" "hid_item_t *h" -.Ft "const char *" +.Fn hid_locate "report_desc_t d" "u_int usage" "hid_kind_t k" "hid_item_t *h" "int id" +.Ft char * .Fn hid_usage_page "int i" -.Ft "const char *" -.Fn hid_usage_in_page "unsigned int u" +.Ft char * +.Fn hid_usage_in_page "u_int u" .Ft int -.Fn hid_parse_usage_page "const char *name" -.Ft int -.Fn hid_parse_usage_in_page "const char *name" +.Fn hid_parse_usage_page "const char *" +.Ft char * +.Fn hid_parse_usage_in_page "const char *" .Ft void -.Fn hid_init "const char *file" +.Fn hid_init "char *file" .Ft int -.Fn hid_get_data "const void *data" "const hid_item_t *h" +.Fn hid_get_data "void *data" "hid_item_t *h" .Ft void -.Fn hid_set_data "void *p" "const hid_item_t *h" "int data" +.Fn hid_set_data "void *data" "hid_item_t *h" "u_int data" .Sh DESCRIPTION The .Nm library provides routines to extract data from USB Human Interface Devices. -.Ss Introduction +.Ss INTRODUCTION USB HID devices send and receive data layed out in a device dependent way. The .Nm @@ -94,7 +94,7 @@ which contains the data layout information and then use this information. 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 Descriptor Functions +.Ss DESCRIPTOR FUNCTIONS A report descriptor can be obtained by calling .Fn hid_get_report_desc with a file descriptor obtained by opening a @@ -114,18 +114,19 @@ If .Fn hid_dispose_report_desc fails it will return .Dv NULL . -.Ss Descriptor Parsing Functions +.Ss DESCRIPTOR PARSING FUNCTIONS To parse the report descriptor the .Fn hid_start_parse function should be called with a report descriptor and a set that describes which items that are interesting. -The set is obtained -by OR-ing together values +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 report id (if present) is given by +.Fa id . The function returns .Dv NULL if the initialization fails, otherwise an opaque value to be used @@ -146,15 +147,16 @@ will be filled with the relevant data for the item. The definition of .Vt hid_item_t can be found in -.Aq Pa libusbhid.h +.Aq Pa 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 +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 @@ -162,7 +164,7 @@ 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 +.Ss Name TRANSLATION FUNCTIONS The function .Fn hid_usage_page will return the symbolic name of a usage page, and the function @@ -188,7 +190,7 @@ with the name of the table. Passing .Dv NULL to this function will cause it to use the default table. -.Ss Data Extraction Functions +.Ss Data EXTRACTION FUNCTIONS Given the data obtained from a HID device and an item in the report descriptor the .Fn hid_get_data @@ -209,7 +211,7 @@ This man page is woefully incomplete. The .Tn USB specifications can be found at -.Pa http://www.usb.org/developers/docs.htm . +.Pa http://www.usb.org/developers/docs.html . .Pp .Xr uhid 4 , .Xr usb 4 diff --git a/lib/libusbhid/usbhid.h b/lib/libusbhid/usbhid.h index dd9c650cedb8..536bf749ffbd 100644 --- a/lib/libusbhid/usbhid.h +++ b/lib/libusbhid/usbhid.h @@ -87,11 +87,11 @@ report_desc_t hid_use_report_desc(unsigned char *data, unsigned int size); void hid_dispose_report_desc(report_desc_t); /* Parsing of a HID report descriptor, parse.c: */ -hid_data_t hid_start_parse(report_desc_t d, int kindset); +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, unsigned int id, enum hid_kind k); -int hid_locate(report_desc_t d, unsigned int usage, enum hid_kind k, 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); diff --git a/sys/sys/param.h b/sys/sys/param.h index 3e2cbfb82ccc..e00246749b11 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -55,7 +55,7 @@ * doc/en_US.ISO8859-1/books/porters-handbook/book.sgml */ #undef __FreeBSD_version -#define __FreeBSD_version 500110 /* Master, propagated to newvers */ +#define __FreeBSD_version 500111 /* Master, propagated to newvers */ #ifndef NULL #define NULL 0 diff --git a/usr.bin/usbhidctl/usbhid.c b/usr.bin/usbhidctl/usbhid.c index 14855864f4b4..1e56a1ba3ded 100644 --- a/usr.bin/usbhidctl/usbhid.c +++ b/usr.bin/usbhidctl/usbhid.c @@ -47,13 +47,14 @@ #include <err.h> #include <ctype.h> #include <errno.h> -#include <libusbhid.h> +#include <usbhid.h> #include <dev/usb/usb.h> #include <dev/usb/usbhid.h> int verbose = 0; int all = 0; int noname = 0; +static int reportid; char **names; int nnames; @@ -125,7 +126,7 @@ dumpitems(report_desc_t r) struct hid_item h; int size; - for (d = hid_start_parse(r, ~0); hid_get_item(d, &h); ) { + for (d = hid_start_parse(r, ~0, reportid); hid_get_item(d, &h); ) { switch (h.kind) { case hid_collection: printf("Collection page=%s usage=%s\n", @@ -204,7 +205,7 @@ dumpdata(int f, report_desc_t rd, int loop) char namebuf[10000], *namep; hids = 0; - for (d = hid_start_parse(rd, 1<<hid_input); + for (d = hid_start_parse(rd, 1<<hid_input, reportid); hid_get_item(d, &h); ) { if (h.kind == hid_collection) colls[++sp] = h.usage; |