1b425e319SNick Hibma /* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ 29e2046dfSNick Hibma 39e2046dfSNick Hibma /* 4cf0e07e5SMatthew N. Dodd * Copyright (c) 1999, 2001 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 29209040d8SMatthew Dillon #include <sys/cdefs.h> 30209040d8SMatthew Dillon __FBSDID("$FreeBSD$"); 31209040d8SMatthew Dillon 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 40cf0e07e5SMatthew N. Dodd #include "usbhid.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; 52cf0e07e5SMatthew N. Dodd int logminsize; 539e2046dfSNick Hibma int multi; 549e2046dfSNick Hibma int multimax; 559e2046dfSNick Hibma int kindset; 56cf0e07e5SMatthew N. Dodd int reportid; 57b425e319SNick Hibma 58cf0e07e5SMatthew N. Dodd /* 59cf0e07e5SMatthew N. Dodd * The start of collection item has no report ID set, so save 60cf0e07e5SMatthew N. Dodd * it until we know the ID. 61cf0e07e5SMatthew N. Dodd */ 62cf0e07e5SMatthew N. Dodd hid_item_t savedcoll; 63cf0e07e5SMatthew N. Dodd u_char hassavedcoll; 64cf0e07e5SMatthew N. Dodd /* 65cf0e07e5SMatthew N. Dodd * Absolute data position (bits) for input/output/feature. 66cf0e07e5SMatthew N. Dodd * Assumes that hid_input, hid_output and hid_feature have 67cf0e07e5SMatthew N. Dodd * values 0, 1 and 2. 68cf0e07e5SMatthew N. Dodd */ 69b425e319SNick Hibma unsigned int kindpos[3]; 709e2046dfSNick Hibma }; 719e2046dfSNick Hibma 729e2046dfSNick Hibma static int min(int x, int y) { return x < y ? x : y; } 739e2046dfSNick Hibma 74cf0e07e5SMatthew N. Dodd static int hid_get_item_raw(hid_data_t s, hid_item_t *h); 75cf0e07e5SMatthew N. Dodd 769e2046dfSNick Hibma static void 779e2046dfSNick Hibma hid_clear_local(hid_item_t *c) 789e2046dfSNick Hibma { 799e2046dfSNick Hibma c->usage = 0; 809e2046dfSNick Hibma c->usage_minimum = 0; 819e2046dfSNick Hibma c->usage_maximum = 0; 829e2046dfSNick Hibma c->designator_index = 0; 839e2046dfSNick Hibma c->designator_minimum = 0; 849e2046dfSNick Hibma c->designator_maximum = 0; 859e2046dfSNick Hibma c->string_index = 0; 869e2046dfSNick Hibma c->string_minimum = 0; 879e2046dfSNick Hibma c->string_maximum = 0; 889e2046dfSNick Hibma c->set_delimiter = 0; 89234e6b87SMatthew N. Dodd c->report_size = 0; 909e2046dfSNick Hibma } 919e2046dfSNick Hibma 929e2046dfSNick Hibma hid_data_t 93cf0e07e5SMatthew N. Dodd hid_start_parse(report_desc_t d, int kindset, int id) 949e2046dfSNick Hibma { 959e2046dfSNick Hibma struct hid_data *s; 969e2046dfSNick Hibma 979e2046dfSNick Hibma s = malloc(sizeof *s); 989e2046dfSNick Hibma memset(s, 0, sizeof *s); 999e2046dfSNick Hibma s->start = s->p = d->data; 1009e2046dfSNick Hibma s->end = d->data + d->size; 1019e2046dfSNick Hibma s->kindset = kindset; 102cf0e07e5SMatthew N. Dodd s->reportid = id; 103cf0e07e5SMatthew N. Dodd s->hassavedcoll = 0; 1049e2046dfSNick Hibma return (s); 1059e2046dfSNick Hibma } 1069e2046dfSNick Hibma 1079e2046dfSNick Hibma void 1089e2046dfSNick Hibma hid_end_parse(hid_data_t s) 1099e2046dfSNick Hibma { 1109e2046dfSNick Hibma while (s->cur.next) { 1119e2046dfSNick Hibma hid_item_t *hi = s->cur.next->next; 1129e2046dfSNick Hibma free(s->cur.next); 1139e2046dfSNick Hibma s->cur.next = hi; 1149e2046dfSNick Hibma } 1159e2046dfSNick Hibma free(s); 1169e2046dfSNick Hibma } 1179e2046dfSNick Hibma 1189e2046dfSNick Hibma int 1199e2046dfSNick Hibma hid_get_item(hid_data_t s, hid_item_t *h) 1209e2046dfSNick Hibma { 121cf0e07e5SMatthew N. Dodd int r; 122cf0e07e5SMatthew N. Dodd 123cf0e07e5SMatthew N. Dodd for (;;) { 124cf0e07e5SMatthew N. Dodd r = hid_get_item_raw(s, h); 125cf0e07e5SMatthew N. Dodd if (r <= 0) 126cf0e07e5SMatthew N. Dodd break; 127cf0e07e5SMatthew N. Dodd if (h->report_ID == s->reportid || s->reportid == -1) 128cf0e07e5SMatthew N. Dodd break; 129cf0e07e5SMatthew N. Dodd } 130cf0e07e5SMatthew N. Dodd return (r); 131cf0e07e5SMatthew N. Dodd } 132cf0e07e5SMatthew N. Dodd 133cf0e07e5SMatthew N. Dodd #define REPORT_SAVED_COLL \ 134cf0e07e5SMatthew N. Dodd do { \ 135cf0e07e5SMatthew N. Dodd if (s->hassavedcoll) { \ 136cf0e07e5SMatthew N. Dodd *h = s->savedcoll; \ 137cf0e07e5SMatthew N. Dodd h->report_ID = c->report_ID; \ 138cf0e07e5SMatthew N. Dodd s->hassavedcoll = 0; \ 139cf0e07e5SMatthew N. Dodd return (1); \ 140cf0e07e5SMatthew N. Dodd } \ 141cf0e07e5SMatthew N. Dodd } while(/*LINTED*/ 0) 142cf0e07e5SMatthew N. Dodd 143cf0e07e5SMatthew N. Dodd static int 144cf0e07e5SMatthew N. Dodd hid_get_item_raw(hid_data_t s, hid_item_t *h) 145cf0e07e5SMatthew N. Dodd { 1469e2046dfSNick Hibma hid_item_t *c; 147b425e319SNick Hibma unsigned int bTag = 0, bType = 0, bSize; 1489e2046dfSNick Hibma unsigned char *data; 1499e2046dfSNick Hibma int dval; 1509e2046dfSNick Hibma unsigned char *p; 1519e2046dfSNick Hibma hid_item_t *hi; 152cf0e07e5SMatthew N. Dodd hid_item_t nc; 1539e2046dfSNick Hibma int i; 154b425e319SNick Hibma hid_kind_t retkind; 1559e2046dfSNick Hibma 1569e2046dfSNick Hibma c = &s->cur; 1579e2046dfSNick Hibma 1589e2046dfSNick Hibma top: 1599e2046dfSNick Hibma if (s->multimax) { 160cf0e07e5SMatthew N. Dodd REPORT_SAVED_COLL; 161cf0e07e5SMatthew N. Dodd if (c->logical_minimum >= c->logical_maximum) { 162cf0e07e5SMatthew N. Dodd if (s->logminsize == 1) 163cf0e07e5SMatthew N. Dodd c->logical_minimum =(int8_t)c->logical_minimum; 164cf0e07e5SMatthew N. Dodd else if (s->logminsize == 2) 165cf0e07e5SMatthew N. Dodd c->logical_minimum =(int16_t)c->logical_minimum; 166cf0e07e5SMatthew N. Dodd } 1679e2046dfSNick Hibma if (s->multi < s->multimax) { 1689e2046dfSNick Hibma c->usage = s->usages[min(s->multi, s->nusage-1)]; 1699e2046dfSNick Hibma s->multi++; 1709e2046dfSNick Hibma *h = *c; 171cf0e07e5SMatthew N. Dodd /* 172cf0e07e5SMatthew N. Dodd * 'multimax' is only non-zero if the current 173cf0e07e5SMatthew N. Dodd * item kind is input/output/feature 174cf0e07e5SMatthew N. Dodd */ 175b425e319SNick Hibma h->pos = s->kindpos[c->kind]; 176b425e319SNick Hibma s->kindpos[c->kind] += c->report_size; 1779e2046dfSNick Hibma h->next = 0; 1789e2046dfSNick Hibma return (1); 1799e2046dfSNick Hibma } else { 1809e2046dfSNick Hibma c->report_count = s->multimax; 1819e2046dfSNick Hibma s->multimax = 0; 1829e2046dfSNick Hibma s->nusage = 0; 1839e2046dfSNick Hibma hid_clear_local(c); 1849e2046dfSNick Hibma } 1859e2046dfSNick Hibma } 1869e2046dfSNick Hibma for (;;) { 1879e2046dfSNick Hibma p = s->p; 1889e2046dfSNick Hibma if (p >= s->end) 1899e2046dfSNick Hibma return (0); 1909e2046dfSNick Hibma 1919e2046dfSNick Hibma bSize = *p++; 1929e2046dfSNick Hibma if (bSize == 0xfe) { 1939e2046dfSNick Hibma /* long item */ 1949e2046dfSNick Hibma bSize = *p++; 1959e2046dfSNick Hibma bSize |= *p++ << 8; 1969e2046dfSNick Hibma bTag = *p++; 1979e2046dfSNick Hibma data = p; 1989e2046dfSNick Hibma p += bSize; 1999e2046dfSNick Hibma } else { 2009e2046dfSNick Hibma /* short item */ 2019e2046dfSNick Hibma bTag = bSize >> 4; 2029e2046dfSNick Hibma bType = (bSize >> 2) & 3; 2039e2046dfSNick Hibma bSize &= 3; 2049e2046dfSNick Hibma if (bSize == 3) bSize = 4; 2059e2046dfSNick Hibma data = p; 2069e2046dfSNick Hibma p += bSize; 2079e2046dfSNick Hibma } 2089e2046dfSNick Hibma s->p = p; 2099e2046dfSNick Hibma /* 2109e2046dfSNick Hibma * The spec is unclear if the data is signed or unsigned. 2119e2046dfSNick Hibma */ 2129e2046dfSNick Hibma switch(bSize) { 2139e2046dfSNick Hibma case 0: 2149e2046dfSNick Hibma dval = 0; 2159e2046dfSNick Hibma break; 2169e2046dfSNick Hibma case 1: 2179e2046dfSNick Hibma dval = (int8_t)*data++; 2189e2046dfSNick Hibma break; 2199e2046dfSNick Hibma case 2: 2209e2046dfSNick Hibma dval = *data++; 2219e2046dfSNick Hibma dval |= *data++ << 8; 2229e2046dfSNick Hibma dval = (int16_t)dval; 2239e2046dfSNick Hibma break; 2249e2046dfSNick Hibma case 4: 2259e2046dfSNick Hibma dval = *data++; 2269e2046dfSNick Hibma dval |= *data++ << 8; 2279e2046dfSNick Hibma dval |= *data++ << 16; 2289e2046dfSNick Hibma dval |= *data++ << 24; 2299e2046dfSNick Hibma break; 2309e2046dfSNick Hibma default: 2319e2046dfSNick Hibma return (-1); 2329e2046dfSNick Hibma } 2339e2046dfSNick Hibma 2349e2046dfSNick Hibma switch (bType) { 2359e2046dfSNick Hibma case 0: /* Main */ 2369e2046dfSNick Hibma switch (bTag) { 2379e2046dfSNick Hibma case 8: /* Input */ 238b425e319SNick Hibma retkind = hid_input; 2399e2046dfSNick Hibma ret: 240b425e319SNick Hibma if (!(s->kindset & (1 << retkind))) { 241b425e319SNick Hibma /* Drop the items of this kind */ 242b425e319SNick Hibma s->nusage = 0; 243b425e319SNick Hibma continue; 244b425e319SNick Hibma } 245b425e319SNick Hibma c->kind = retkind; 246b425e319SNick Hibma c->flags = dval; 2479e2046dfSNick Hibma if (c->flags & HIO_VARIABLE) { 2489e2046dfSNick Hibma s->multimax = c->report_count; 2499e2046dfSNick Hibma s->multi = 0; 2509e2046dfSNick Hibma c->report_count = 1; 2519e2046dfSNick Hibma if (s->minset) { 2529e2046dfSNick Hibma for (i = c->usage_minimum; 2539e2046dfSNick Hibma i <= c->usage_maximum; 2549e2046dfSNick Hibma i++) { 2559e2046dfSNick Hibma s->usages[s->nusage] = i; 2569e2046dfSNick Hibma if (s->nusage < MAXUSAGE-1) 2579e2046dfSNick Hibma s->nusage++; 2589e2046dfSNick Hibma } 259cf0e07e5SMatthew N. Dodd c->usage_minimum = 0; 260cf0e07e5SMatthew N. Dodd c->usage_maximum = 0; 2619e2046dfSNick Hibma s->minset = 0; 2629e2046dfSNick Hibma } 2639e2046dfSNick Hibma goto top; 2649e2046dfSNick Hibma } else { 2659e2046dfSNick Hibma if (s->minset) 2669e2046dfSNick Hibma c->usage = c->usage_minimum; 2679e2046dfSNick Hibma *h = *c; 2689e2046dfSNick Hibma h->next = 0; 269b425e319SNick Hibma h->pos = s->kindpos[c->kind]; 270cf0e07e5SMatthew N. Dodd s->kindpos[c->kind] += 271cf0e07e5SMatthew N. Dodd c->report_size * c->report_count; 2729e2046dfSNick Hibma hid_clear_local(c); 2739e2046dfSNick Hibma s->minset = 0; 2749e2046dfSNick Hibma return (1); 2759e2046dfSNick Hibma } 2769e2046dfSNick Hibma case 9: /* Output */ 277b425e319SNick Hibma retkind = hid_output; 2789e2046dfSNick Hibma goto ret; 2799e2046dfSNick Hibma case 10: /* Collection */ 2809e2046dfSNick Hibma c->kind = hid_collection; 2819e2046dfSNick Hibma c->collection = dval; 2829e2046dfSNick Hibma c->collevel++; 283cf0e07e5SMatthew N. Dodd nc = *c; 2849e2046dfSNick Hibma hid_clear_local(c); 285cf0e07e5SMatthew N. Dodd /*c->report_ID = NO_REPORT_ID;*/ 2869e2046dfSNick Hibma s->nusage = 0; 287cf0e07e5SMatthew N. Dodd if (s->hassavedcoll) { 288cf0e07e5SMatthew N. Dodd *h = s->savedcoll; 289cf0e07e5SMatthew N. Dodd h->report_ID = nc.report_ID; 290cf0e07e5SMatthew N. Dodd s->savedcoll = nc; 2919e2046dfSNick Hibma return (1); 292cf0e07e5SMatthew N. Dodd } else { 293cf0e07e5SMatthew N. Dodd s->hassavedcoll = 1; 294cf0e07e5SMatthew N. Dodd s->savedcoll = nc; 295cf0e07e5SMatthew N. Dodd } 296cf0e07e5SMatthew N. Dodd break; 2979e2046dfSNick Hibma case 11: /* Feature */ 298b425e319SNick Hibma retkind = hid_feature; 2999e2046dfSNick Hibma goto ret; 3009e2046dfSNick Hibma case 12: /* End collection */ 301cf0e07e5SMatthew N. Dodd REPORT_SAVED_COLL; 3029e2046dfSNick Hibma c->kind = hid_endcollection; 3039e2046dfSNick Hibma c->collevel--; 3049e2046dfSNick Hibma *h = *c; 3059e2046dfSNick Hibma /*hid_clear_local(c);*/ 3069e2046dfSNick Hibma s->nusage = 0; 3079e2046dfSNick Hibma return (1); 3089e2046dfSNick Hibma default: 3099e2046dfSNick Hibma return (-2); 3109e2046dfSNick Hibma } 311cf0e07e5SMatthew N. Dodd break; 3129e2046dfSNick Hibma 3139e2046dfSNick Hibma case 1: /* Global */ 3149e2046dfSNick Hibma switch (bTag) { 3159e2046dfSNick Hibma case 0: 3169e2046dfSNick Hibma c->_usage_page = dval << 16; 3179e2046dfSNick Hibma break; 3189e2046dfSNick Hibma case 1: 3199e2046dfSNick Hibma c->logical_minimum = dval; 320cf0e07e5SMatthew N. Dodd s->logminsize = bSize; 3219e2046dfSNick Hibma break; 3229e2046dfSNick Hibma case 2: 3239e2046dfSNick Hibma c->logical_maximum = dval; 3249e2046dfSNick Hibma break; 3259e2046dfSNick Hibma case 3: 3269e2046dfSNick Hibma c->physical_maximum = dval; 3279e2046dfSNick Hibma break; 3289e2046dfSNick Hibma case 4: 3299e2046dfSNick Hibma c->physical_maximum = dval; 3309e2046dfSNick Hibma break; 3319e2046dfSNick Hibma case 5: 3329e2046dfSNick Hibma c->unit_exponent = dval; 3339e2046dfSNick Hibma break; 3349e2046dfSNick Hibma case 6: 3359e2046dfSNick Hibma c->unit = dval; 3369e2046dfSNick Hibma break; 3379e2046dfSNick Hibma case 7: 3389e2046dfSNick Hibma c->report_size = dval; 3399e2046dfSNick Hibma break; 3409e2046dfSNick Hibma case 8: 3419e2046dfSNick Hibma c->report_ID = dval; 342cf0e07e5SMatthew N. Dodd s->kindpos[hid_input] = 343cf0e07e5SMatthew N. Dodd s->kindpos[hid_output] = 344cf0e07e5SMatthew N. Dodd s->kindpos[hid_feature] = 0; 3459e2046dfSNick Hibma break; 3469e2046dfSNick Hibma case 9: 3479e2046dfSNick Hibma c->report_count = dval; 3489e2046dfSNick Hibma break; 3499e2046dfSNick Hibma case 10: /* Push */ 3509e2046dfSNick Hibma hi = malloc(sizeof *hi); 3519e2046dfSNick Hibma *hi = s->cur; 3529e2046dfSNick Hibma c->next = hi; 3539e2046dfSNick Hibma break; 3549e2046dfSNick Hibma case 11: /* Pop */ 3559e2046dfSNick Hibma hi = c->next; 3569e2046dfSNick Hibma s->cur = *hi; 3579e2046dfSNick Hibma free(hi); 3589e2046dfSNick Hibma break; 3599e2046dfSNick Hibma default: 3609e2046dfSNick Hibma return (-3); 3619e2046dfSNick Hibma } 3629e2046dfSNick Hibma break; 3639e2046dfSNick Hibma case 2: /* Local */ 3649e2046dfSNick Hibma switch (bTag) { 3659e2046dfSNick Hibma case 0: 366cf0e07e5SMatthew N. Dodd c->usage = c->_usage_page | dval; 3679e2046dfSNick Hibma if (s->nusage < MAXUSAGE) 368cf0e07e5SMatthew N. Dodd s->usages[s->nusage++] = c->usage; 3699e2046dfSNick Hibma /* else XXX */ 3709e2046dfSNick Hibma break; 3719e2046dfSNick Hibma case 1: 3729e2046dfSNick Hibma s->minset = 1; 373cf0e07e5SMatthew N. Dodd c->usage_minimum = c->_usage_page | dval; 3749e2046dfSNick Hibma break; 3759e2046dfSNick Hibma case 2: 376cf0e07e5SMatthew N. Dodd c->usage_maximum = c->_usage_page | dval; 3779e2046dfSNick Hibma break; 3789e2046dfSNick Hibma case 3: 3799e2046dfSNick Hibma c->designator_index = dval; 3809e2046dfSNick Hibma break; 3819e2046dfSNick Hibma case 4: 3829e2046dfSNick Hibma c->designator_minimum = dval; 3839e2046dfSNick Hibma break; 3849e2046dfSNick Hibma case 5: 3859e2046dfSNick Hibma c->designator_maximum = dval; 3869e2046dfSNick Hibma break; 3879e2046dfSNick Hibma case 7: 3889e2046dfSNick Hibma c->string_index = dval; 3899e2046dfSNick Hibma break; 3909e2046dfSNick Hibma case 8: 3919e2046dfSNick Hibma c->string_minimum = dval; 3929e2046dfSNick Hibma break; 3939e2046dfSNick Hibma case 9: 3949e2046dfSNick Hibma c->string_maximum = dval; 3959e2046dfSNick Hibma break; 3969e2046dfSNick Hibma case 10: 3979e2046dfSNick Hibma c->set_delimiter = dval; 3989e2046dfSNick Hibma break; 3999e2046dfSNick Hibma default: 4009e2046dfSNick Hibma return (-4); 4019e2046dfSNick Hibma } 4029e2046dfSNick Hibma break; 4039e2046dfSNick Hibma default: 4049e2046dfSNick Hibma return (-5); 4059e2046dfSNick Hibma } 4069e2046dfSNick Hibma } 4079e2046dfSNick Hibma } 4089e2046dfSNick Hibma 4099e2046dfSNick Hibma int 410cf0e07e5SMatthew N. Dodd hid_report_size(report_desc_t r, enum hid_kind k, int id) 4119e2046dfSNick Hibma { 4129e2046dfSNick Hibma struct hid_data *d; 4139e2046dfSNick Hibma hid_item_t h; 414cf0e07e5SMatthew N. Dodd int size; 4159e2046dfSNick Hibma 4169e2046dfSNick Hibma memset(&h, 0, sizeof h); 417cf0e07e5SMatthew N. Dodd size = 0; 418cf0e07e5SMatthew N. Dodd for (d = hid_start_parse(r, 1<<k, id); hid_get_item(d, &h); ) { 419b425e319SNick Hibma if (h.report_ID == id && h.kind == k) { 420cf0e07e5SMatthew N. Dodd size = d->kindpos[k]; 4219e2046dfSNick Hibma } 4229e2046dfSNick Hibma } 4239e2046dfSNick Hibma hid_end_parse(d); 424cf0e07e5SMatthew N. Dodd return ((size + 7) / 8); 4259e2046dfSNick Hibma } 4269e2046dfSNick Hibma 4279e2046dfSNick Hibma int 428cf0e07e5SMatthew N. Dodd hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, 429cf0e07e5SMatthew N. Dodd hid_item_t *h, int id) 4309e2046dfSNick Hibma { 4319e2046dfSNick Hibma hid_data_t d; 4329e2046dfSNick Hibma 433cf0e07e5SMatthew N. Dodd for (d = hid_start_parse(desc, 1<<k, id); hid_get_item(d, h); ) { 4349e2046dfSNick Hibma if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) { 4359e2046dfSNick Hibma hid_end_parse(d); 4369e2046dfSNick Hibma return (1); 4379e2046dfSNick Hibma } 4389e2046dfSNick Hibma } 4399e2046dfSNick Hibma hid_end_parse(d); 4409e2046dfSNick Hibma h->report_size = 0; 4419e2046dfSNick Hibma return (0); 4429e2046dfSNick Hibma } 443