diff options
author | mdodd <mdodd@FreeBSD.org> | 2003-04-09 01:52:49 +0000 |
---|---|---|
committer | mdodd <mdodd@FreeBSD.org> | 2003-04-09 01:52:49 +0000 |
commit | 339cdd9fae72c60095061f96c9d8ad19e8267275 (patch) | |
tree | 4973be599e3f1175e30998a134f2b847577c193f /lib/libusbhid/parse.c | |
parent | 641a7abeaeff651137abc582c6199146cfbd0aa9 (diff) | |
download | FreeBSD-src-339cdd9fae72c60095061f96c9d8ad19e8267275.zip FreeBSD-src-339cdd9fae72c60095061f96c9d8ad19e8267275.tar.gz |
Sync with NetBSD.
- Bump shared library version on libusbhid.
- Retire libusbhid.h; it is called usbhid.h now.
- hid_start_parse() takes a third argument.
- hid_locate() takes a fifth argument.
- hid_report_size() order of arguments changes.
- Other changes, including formatting and whitespace.
Bump __FreeBSD_version.
This change will break all third party applications that rely on previous
FreeBSD specific behavior.
Diffstat (limited to 'lib/libusbhid/parse.c')
-rw-r--r-- | lib/libusbhid/parse.c | 137 |
1 files changed, 93 insertions, 44 deletions
diff --git a/lib/libusbhid/parse.c b/lib/libusbhid/parse.c index d8c6462..6680d84 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); |