diff options
author | 2002-05-10 00:09:17 +0000 | |
---|---|---|
committer | 2002-05-10 00:09:17 +0000 | |
commit | 7517eab27d5826c1a463a3cd45d021e17e9bb423 (patch) | |
tree | c8ffa8a4d8a2766dab08a2b30c66addee732307f /lib/libusbhid/parse.c | |
parent | prototype open_socket() (diff) | |
download | wireguard-openbsd-7517eab27d5826c1a463a3cd45d021e17e9bb423.tar.xz wireguard-openbsd-7517eab27d5826c1a463a3cd45d021e17e9bb423.zip |
Update usb userland stuff to reflect hid changes in the kernel.
This adds the new program usbhidaction which can be used to assign actions
to events that occur on a uhid device. For example, you can now make the
volume buttons on some newer keyboards actually do something.
Diffstat (limited to 'lib/libusbhid/parse.c')
-rw-r--r-- | lib/libusbhid/parse.c | 147 |
1 files changed, 99 insertions, 48 deletions
diff --git a/lib/libusbhid/parse.c b/lib/libusbhid/parse.c index 737812254b1..4bc72344a5a 100644 --- a/lib/libusbhid/parse.c +++ b/lib/libusbhid/parse.c @@ -1,8 +1,8 @@ -/* $OpenBSD: parse.c,v 1.1 2001/12/30 07:04:38 pvalchev Exp $ */ -/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ +/* $OpenBSD: parse.c,v 1.2 2002/05/10 00:09:17 nate Exp $ */ +/* $NetBSD: parse.c,v 1.2 2001/12/29 20:44:22 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 @@ -46,18 +46,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) { @@ -72,17 +84,21 @@ hid_clear_local(hid_item_t *c) c->string_minimum = 0; c->string_maximum = 0; c->set_delimiter = 0; + c->report_size = 0; } 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 = malloc(sizeof *s); + 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; + s->hassavedcoll = 0; return (s); } @@ -101,12 +117,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; @@ -114,13 +156,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; @@ -163,12 +213,12 @@ hid_get_item(hid_data_t s, hid_item_t *h) dval = 0; break; case 1: - dval = (int8_t)*data++; + dval = /*(int8_t)*/*data++; break; case 2: dval = *data++; dval |= *data++ << 8; - dval = (int16_t)dval; + dval = /*(int16_t)*/dval; break; case 4: dval = *data++; @@ -205,6 +255,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; @@ -214,7 +266,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); @@ -226,15 +279,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; @@ -244,6 +307,7 @@ hid_get_item(hid_data_t s, hid_item_t *h) default: return (-2); } + break; case 1: /* Global */ switch (bTag) { @@ -252,6 +316,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; @@ -273,6 +338,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; @@ -294,29 +362,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; @@ -350,35 +406,30 @@ hid_get_item(hid_data_t s, hid_item_t *h) } int -hid_report_size(report_desc_t r, enum hid_kind k, int *idp) +hid_report_size(report_desc_t r, enum hid_kind k, int id) { struct hid_data *d; hid_item_t h; - int size, id; + int size; - id = 0; - if (idp) - *idp = 0; memset(&h, 0, sizeof h); - for (d = hid_start_parse(r, 1<<k); hid_get_item(d, &h); ) { - if (h.report_ID != NO_REPORT_ID) { - if (idp) - *idp = h.report_ID; - id = 8; + size = 0; + for (d = hid_start_parse(r, 1<<k, id); hid_get_item(d, &h); ) { + if (h.report_ID == id && h.kind == k) { + size = d->kindpos[k]; } } - - size = d->kindpos[k] + id; hid_end_parse(d); 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); |