parse.c revision 235510
167217Sn_hibma/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ 261560Sn_hibma 361560Sn_hibma/* 4113273Smdodd * Copyright (c) 1999, 2001 Lennart Augustsson <augustss@netbsd.org> 561560Sn_hibma * All rights reserved. 661560Sn_hibma * 761560Sn_hibma * Redistribution and use in source and binary forms, with or without 861560Sn_hibma * modification, are permitted provided that the following conditions 961560Sn_hibma * are met: 1061560Sn_hibma * 1. Redistributions of source code must retain the above copyright 1161560Sn_hibma * notice, this list of conditions and the following disclaimer. 1261560Sn_hibma * 2. Redistributions in binary form must reproduce the above copyright 1361560Sn_hibma * notice, this list of conditions and the following disclaimer in the 1461560Sn_hibma * documentation and/or other materials provided with the distribution. 1561560Sn_hibma * 1661560Sn_hibma * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1761560Sn_hibma * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1861560Sn_hibma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1961560Sn_hibma * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2061560Sn_hibma * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2161560Sn_hibma * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2261560Sn_hibma * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2361560Sn_hibma * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2461560Sn_hibma * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2561560Sn_hibma * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2661560Sn_hibma * SUCH DAMAGE. 2761560Sn_hibma */ 2861560Sn_hibma 2984224Sdillon#include <sys/cdefs.h> 3084224Sdillon__FBSDID("$FreeBSD: head/lib/libusbhid/parse.c 235510 2012-05-16 17:51:56Z mav $"); 3184224Sdillon 3261560Sn_hibma#include <assert.h> 3361560Sn_hibma#include <stdlib.h> 3461560Sn_hibma#include <string.h> 3561560Sn_hibma#include <sys/time.h> 3661560Sn_hibma 3761560Sn_hibma#include <dev/usb/usb.h> 3861560Sn_hibma#include <dev/usb/usbhid.h> 3961560Sn_hibma 40113273Smdodd#include "usbhid.h" 4161560Sn_hibma#include "usbvar.h" 4261560Sn_hibma 43205728Skaiw#define MAXUSAGE 100 44205728Skaiw#define MAXPUSH 4 45205728Skaiw#define MAXID 64 46225839Smav#define ITEMTYPES 3 4767217Sn_hibma 48205728Skaiwstruct hid_pos_data { 49205728Skaiw int32_t rid; 50225839Smav uint32_t pos[ITEMTYPES]; 5161560Sn_hibma}; 5261560Sn_hibma 53205728Skaiwstruct hid_data { 54205728Skaiw const uint8_t *start; 55205728Skaiw const uint8_t *end; 56205728Skaiw const uint8_t *p; 57205728Skaiw struct hid_item cur[MAXPUSH]; 58205728Skaiw struct hid_pos_data last_pos[MAXID]; 59225839Smav uint32_t pos[ITEMTYPES]; 60205728Skaiw int32_t usages_min[MAXUSAGE]; 61205728Skaiw int32_t usages_max[MAXUSAGE]; 62205728Skaiw int32_t usage_last; /* last seen usage */ 63205728Skaiw uint32_t loc_size; /* last seen size */ 64205728Skaiw uint32_t loc_count; /* last seen count */ 65205728Skaiw uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ 66205728Skaiw uint8_t pushlevel; /* current pushlevel */ 67205728Skaiw uint8_t ncount; /* end usage item count */ 68205728Skaiw uint8_t icount; /* current usage item count */ 69205728Skaiw uint8_t nusage; /* end "usages_min/max" index */ 70205728Skaiw uint8_t iusage; /* current "usages_min/max" index */ 71205728Skaiw uint8_t ousage; /* current "usages_min/max" offset */ 72205728Skaiw uint8_t susage; /* usage set flags */ 73205728Skaiw}; 7461560Sn_hibma 75205728Skaiw/*------------------------------------------------------------------------* 76205728Skaiw * hid_clear_local 77205728Skaiw *------------------------------------------------------------------------*/ 7861560Sn_hibmastatic void 7961560Sn_hibmahid_clear_local(hid_item_t *c) 8061560Sn_hibma{ 81205728Skaiw 8261560Sn_hibma c->usage = 0; 8361560Sn_hibma c->usage_minimum = 0; 8461560Sn_hibma c->usage_maximum = 0; 8561560Sn_hibma c->designator_index = 0; 8661560Sn_hibma c->designator_minimum = 0; 8761560Sn_hibma c->designator_maximum = 0; 8861560Sn_hibma c->string_index = 0; 8961560Sn_hibma c->string_minimum = 0; 9061560Sn_hibma c->string_maximum = 0; 9161560Sn_hibma c->set_delimiter = 0; 9261560Sn_hibma} 9361560Sn_hibma 94205728Skaiwstatic void 95205728Skaiwhid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) 96205728Skaiw{ 97225839Smav uint8_t i, j; 98205728Skaiw 99205728Skaiw /* check for same report ID - optimise */ 100205728Skaiw 101205728Skaiw if (c->report_ID == next_rID) 102205728Skaiw return; 103205728Skaiw 104205728Skaiw /* save current position for current rID */ 105205728Skaiw 106205728Skaiw if (c->report_ID == 0) { 107205728Skaiw i = 0; 108205728Skaiw } else { 109205728Skaiw for (i = 1; i != MAXID; i++) { 110205728Skaiw if (s->last_pos[i].rid == c->report_ID) 111205728Skaiw break; 112205728Skaiw if (s->last_pos[i].rid == 0) 113205728Skaiw break; 114205728Skaiw } 115205728Skaiw } 116205728Skaiw if (i != MAXID) { 117205728Skaiw s->last_pos[i].rid = c->report_ID; 118225839Smav for (j = 0; j < ITEMTYPES; j++) 119225839Smav s->last_pos[i].pos[j] = s->pos[j]; 120205728Skaiw } 121205728Skaiw 122205728Skaiw /* store next report ID */ 123205728Skaiw 124205728Skaiw c->report_ID = next_rID; 125205728Skaiw 126205728Skaiw /* lookup last position for next rID */ 127205728Skaiw 128205728Skaiw if (next_rID == 0) { 129205728Skaiw i = 0; 130205728Skaiw } else { 131205728Skaiw for (i = 1; i != MAXID; i++) { 132205728Skaiw if (s->last_pos[i].rid == next_rID) 133205728Skaiw break; 134205728Skaiw if (s->last_pos[i].rid == 0) 135205728Skaiw break; 136205728Skaiw } 137205728Skaiw } 138205728Skaiw if (i != MAXID) { 139205728Skaiw s->last_pos[i].rid = next_rID; 140225839Smav for (j = 0; j < ITEMTYPES; j++) 141225839Smav s->pos[j] = s->last_pos[i].pos[j]; 142225839Smav } else { 143225839Smav for (j = 0; j < ITEMTYPES; j++) 144225839Smav s->pos[j] = 0; /* Out of RID entries. */ 145225839Smav } 146205728Skaiw} 147205728Skaiw 148205728Skaiw/*------------------------------------------------------------------------* 149205728Skaiw * hid_start_parse 150205728Skaiw *------------------------------------------------------------------------*/ 15161560Sn_hibmahid_data_t 152205728Skaiwhid_start_parse(report_desc_t d, int kindset, int id __unused) 15361560Sn_hibma{ 15461560Sn_hibma struct hid_data *s; 15561560Sn_hibma 15661560Sn_hibma s = malloc(sizeof *s); 15761560Sn_hibma memset(s, 0, sizeof *s); 15861560Sn_hibma s->start = s->p = d->data; 15961560Sn_hibma s->end = d->data + d->size; 16061560Sn_hibma s->kindset = kindset; 16161560Sn_hibma return (s); 16261560Sn_hibma} 16361560Sn_hibma 164205728Skaiw/*------------------------------------------------------------------------* 165205728Skaiw * hid_end_parse 166205728Skaiw *------------------------------------------------------------------------*/ 16761560Sn_hibmavoid 16861560Sn_hibmahid_end_parse(hid_data_t s) 16961560Sn_hibma{ 170205728Skaiw 171205728Skaiw if (s == NULL) 172205728Skaiw return; 173205728Skaiw 17461560Sn_hibma free(s); 17561560Sn_hibma} 17661560Sn_hibma 177205728Skaiw/*------------------------------------------------------------------------* 178205728Skaiw * get byte from HID descriptor 179205728Skaiw *------------------------------------------------------------------------*/ 180205728Skaiwstatic uint8_t 181205728Skaiwhid_get_byte(struct hid_data *s, const uint16_t wSize) 18261560Sn_hibma{ 183205728Skaiw const uint8_t *ptr; 184205728Skaiw uint8_t retval; 185113273Smdodd 186205728Skaiw ptr = s->p; 187205728Skaiw 188205728Skaiw /* check if end is reached */ 189205728Skaiw if (ptr == s->end) 190205728Skaiw return (0); 191205728Skaiw 192205728Skaiw /* read out a byte */ 193205728Skaiw retval = *ptr; 194205728Skaiw 195205728Skaiw /* check if data pointer can be advanced by "wSize" bytes */ 196205728Skaiw if ((s->end - ptr) < wSize) 197205728Skaiw ptr = s->end; 198205728Skaiw else 199205728Skaiw ptr += wSize; 200205728Skaiw 201205728Skaiw /* update pointer */ 202205728Skaiw s->p = ptr; 203205728Skaiw 204205728Skaiw return (retval); 205113273Smdodd} 206113273Smdodd 207205728Skaiw/*------------------------------------------------------------------------* 208205728Skaiw * hid_get_item 209205728Skaiw *------------------------------------------------------------------------*/ 210205728Skaiwint 211205728Skaiwhid_get_item(hid_data_t s, hid_item_t *h) 212113273Smdodd{ 21361560Sn_hibma hid_item_t *c; 214205728Skaiw unsigned int bTag, bType, bSize; 215205728Skaiw int32_t mask; 216205728Skaiw int32_t dval; 21761560Sn_hibma 218205728Skaiw if (s == NULL) 219205728Skaiw return (0); 22061560Sn_hibma 221205728Skaiw c = &s->cur[s->pushlevel]; 222205728Skaiw 22361560Sn_hibma top: 224205728Skaiw /* check if there is an array of items */ 225205728Skaiw if (s->icount < s->ncount) { 226205728Skaiw /* get current usage */ 227205728Skaiw if (s->iusage < s->nusage) { 228205728Skaiw dval = s->usages_min[s->iusage] + s->ousage; 229205728Skaiw c->usage = dval; 230205728Skaiw s->usage_last = dval; 231205728Skaiw if (dval == s->usages_max[s->iusage]) { 232205728Skaiw s->iusage ++; 233205728Skaiw s->ousage = 0; 234205728Skaiw } else { 235205728Skaiw s->ousage ++; 236205728Skaiw } 237205728Skaiw } else { 238205728Skaiw /* Using last usage */ 239205728Skaiw dval = s->usage_last; 240113273Smdodd } 241205728Skaiw s->icount ++; 242205728Skaiw /* 243205728Skaiw * Only copy HID item, increment position and return 244205728Skaiw * if correct kindset! 245205728Skaiw */ 246205728Skaiw if (s->kindset & (1 << c->kind)) { 24761560Sn_hibma *h = *c; 248225839Smav h->pos = s->pos[c->kind]; 249225839Smav s->pos[c->kind] += c->report_size * c->report_count; 25061560Sn_hibma return (1); 25161560Sn_hibma } 25261560Sn_hibma } 25361560Sn_hibma 254205728Skaiw /* reset state variables */ 255205728Skaiw s->icount = 0; 256205728Skaiw s->ncount = 0; 257205728Skaiw s->iusage = 0; 258205728Skaiw s->nusage = 0; 259205728Skaiw s->susage = 0; 260205728Skaiw s->ousage = 0; 261205728Skaiw hid_clear_local(c); 262205728Skaiw 263205728Skaiw /* get next item */ 264205728Skaiw while (s->p != s->end) { 265205728Skaiw 266205728Skaiw bSize = hid_get_byte(s, 1); 26761560Sn_hibma if (bSize == 0xfe) { 26861560Sn_hibma /* long item */ 269205728Skaiw bSize = hid_get_byte(s, 1); 270205728Skaiw bSize |= hid_get_byte(s, 1) << 8; 271205728Skaiw bTag = hid_get_byte(s, 1); 272205728Skaiw bType = 0xff; /* XXX what should it be */ 27361560Sn_hibma } else { 27461560Sn_hibma /* short item */ 27561560Sn_hibma bTag = bSize >> 4; 27661560Sn_hibma bType = (bSize >> 2) & 3; 27761560Sn_hibma bSize &= 3; 278205728Skaiw if (bSize == 3) 279205728Skaiw bSize = 4; 28061560Sn_hibma } 281205728Skaiw 28261560Sn_hibma switch(bSize) { 28361560Sn_hibma case 0: 28461560Sn_hibma dval = 0; 285205728Skaiw mask = 0; 28661560Sn_hibma break; 28761560Sn_hibma case 1: 288205728Skaiw dval = (int8_t)hid_get_byte(s, 1); 289205728Skaiw mask = 0xFF; 29061560Sn_hibma break; 29161560Sn_hibma case 2: 292205728Skaiw dval = hid_get_byte(s, 1); 293205728Skaiw dval |= hid_get_byte(s, 1) << 8; 294205728Skaiw dval = (int16_t)dval; 295205728Skaiw mask = 0xFFFF; 29661560Sn_hibma break; 29761560Sn_hibma case 4: 298205728Skaiw dval = hid_get_byte(s, 1); 299205728Skaiw dval |= hid_get_byte(s, 1) << 8; 300205728Skaiw dval |= hid_get_byte(s, 1) << 16; 301205728Skaiw dval |= hid_get_byte(s, 1) << 24; 302205728Skaiw mask = 0xFFFFFFFF; 30361560Sn_hibma break; 30461560Sn_hibma default: 305205728Skaiw dval = hid_get_byte(s, bSize); 306205728Skaiw continue; 30761560Sn_hibma } 30861560Sn_hibma 30961560Sn_hibma switch (bType) { 310205728Skaiw case 0: /* Main */ 31161560Sn_hibma switch (bTag) { 312205728Skaiw case 8: /* Input */ 313205728Skaiw c->kind = hid_input; 31461560Sn_hibma c->flags = dval; 315205728Skaiw ret: 316205728Skaiw c->report_count = s->loc_count; 317205728Skaiw c->report_size = s->loc_size; 318205728Skaiw 31961560Sn_hibma if (c->flags & HIO_VARIABLE) { 320205728Skaiw /* range check usage count */ 321205728Skaiw if (c->report_count > 255) { 322205728Skaiw s->ncount = 255; 323205728Skaiw } else 324205728Skaiw s->ncount = c->report_count; 325205728Skaiw 326205728Skaiw /* 327205728Skaiw * The "top" loop will return 328205728Skaiw * one and one item: 329205728Skaiw */ 33061560Sn_hibma c->report_count = 1; 331224511Smav c->usage_minimum = 0; 332224511Smav c->usage_maximum = 0; 33361560Sn_hibma } else { 334205728Skaiw s->ncount = 1; 33561560Sn_hibma } 336205728Skaiw goto top; 337205728Skaiw 338205728Skaiw case 9: /* Output */ 339205728Skaiw c->kind = hid_output; 340205728Skaiw c->flags = dval; 34161560Sn_hibma goto ret; 34261560Sn_hibma case 10: /* Collection */ 34361560Sn_hibma c->kind = hid_collection; 34461560Sn_hibma c->collection = dval; 34561560Sn_hibma c->collevel++; 346205728Skaiw c->usage = s->usage_last; 347205728Skaiw *h = *c; 348205728Skaiw return (1); 34961560Sn_hibma case 11: /* Feature */ 350205728Skaiw c->kind = hid_feature; 351205728Skaiw c->flags = dval; 35261560Sn_hibma goto ret; 35361560Sn_hibma case 12: /* End collection */ 35461560Sn_hibma c->kind = hid_endcollection; 355205728Skaiw if (c->collevel == 0) { 356205728Skaiw /* Invalid end collection. */ 357205728Skaiw return (0); 358205728Skaiw } 35961560Sn_hibma c->collevel--; 36061560Sn_hibma *h = *c; 36161560Sn_hibma return (1); 36261560Sn_hibma default: 363205728Skaiw break; 36461560Sn_hibma } 365113273Smdodd break; 36661560Sn_hibma 36761560Sn_hibma case 1: /* Global */ 36861560Sn_hibma switch (bTag) { 36961560Sn_hibma case 0: 37061560Sn_hibma c->_usage_page = dval << 16; 37161560Sn_hibma break; 37261560Sn_hibma case 1: 37361560Sn_hibma c->logical_minimum = dval; 37461560Sn_hibma break; 37561560Sn_hibma case 2: 37661560Sn_hibma c->logical_maximum = dval; 37761560Sn_hibma break; 37861560Sn_hibma case 3: 379205728Skaiw c->physical_minimum = dval; 38061560Sn_hibma break; 38161560Sn_hibma case 4: 38261560Sn_hibma c->physical_maximum = dval; 38361560Sn_hibma break; 38461560Sn_hibma case 5: 38561560Sn_hibma c->unit_exponent = dval; 38661560Sn_hibma break; 38761560Sn_hibma case 6: 38861560Sn_hibma c->unit = dval; 38961560Sn_hibma break; 39061560Sn_hibma case 7: 391205728Skaiw /* mask because value is unsigned */ 392205728Skaiw s->loc_size = dval & mask; 39361560Sn_hibma break; 39461560Sn_hibma case 8: 395235510Smav hid_switch_rid(s, c, dval & mask); 39661560Sn_hibma break; 39761560Sn_hibma case 9: 398205728Skaiw /* mask because value is unsigned */ 399205728Skaiw s->loc_count = dval & mask; 40061560Sn_hibma break; 401205728Skaiw case 10: /* Push */ 402205728Skaiw s->pushlevel ++; 403205728Skaiw if (s->pushlevel < MAXPUSH) { 404205728Skaiw s->cur[s->pushlevel] = *c; 405205728Skaiw /* store size and count */ 406205728Skaiw c->report_size = s->loc_size; 407205728Skaiw c->report_count = s->loc_count; 408205728Skaiw /* update current item pointer */ 409205728Skaiw c = &s->cur[s->pushlevel]; 410205728Skaiw } 41161560Sn_hibma break; 412205728Skaiw case 11: /* Pop */ 413205728Skaiw s->pushlevel --; 414205728Skaiw if (s->pushlevel < MAXPUSH) { 415205728Skaiw c = &s->cur[s->pushlevel]; 416205728Skaiw /* restore size and count */ 417205728Skaiw s->loc_size = c->report_size; 418205728Skaiw s->loc_count = c->report_count; 419205728Skaiw c->report_size = 0; 420205728Skaiw c->report_count = 0; 421205728Skaiw } 42261560Sn_hibma break; 42361560Sn_hibma default: 424205728Skaiw break; 42561560Sn_hibma } 42661560Sn_hibma break; 42761560Sn_hibma case 2: /* Local */ 42861560Sn_hibma switch (bTag) { 42961560Sn_hibma case 0: 430205728Skaiw if (bSize != 4) 431205728Skaiw dval = (dval & mask) | c->_usage_page; 432205728Skaiw 433205728Skaiw /* set last usage, in case of a collection */ 434205728Skaiw s->usage_last = dval; 435205728Skaiw 436205728Skaiw if (s->nusage < MAXUSAGE) { 437205728Skaiw s->usages_min[s->nusage] = dval; 438205728Skaiw s->usages_max[s->nusage] = dval; 439205728Skaiw s->nusage ++; 440205728Skaiw } 44161560Sn_hibma /* else XXX */ 442205728Skaiw 443205728Skaiw /* clear any pending usage sets */ 444205728Skaiw s->susage = 0; 44561560Sn_hibma break; 44661560Sn_hibma case 1: 447205728Skaiw s->susage |= 1; 448205728Skaiw 449205728Skaiw if (bSize != 4) 450205728Skaiw dval = (dval & mask) | c->_usage_page; 451205728Skaiw c->usage_minimum = dval; 452205728Skaiw 453205728Skaiw goto check_set; 45461560Sn_hibma case 2: 455205728Skaiw s->susage |= 2; 456205728Skaiw 457205728Skaiw if (bSize != 4) 458205728Skaiw dval = (dval & mask) | c->_usage_page; 459205728Skaiw c->usage_maximum = dval; 460205728Skaiw 461205728Skaiw check_set: 462205728Skaiw if (s->susage != 3) 463205728Skaiw break; 464205728Skaiw 465205728Skaiw /* sanity check */ 466205728Skaiw if ((s->nusage < MAXUSAGE) && 467205728Skaiw (c->usage_minimum <= c->usage_maximum)) { 468205728Skaiw /* add usage range */ 469205728Skaiw s->usages_min[s->nusage] = 470205728Skaiw c->usage_minimum; 471205728Skaiw s->usages_max[s->nusage] = 472205728Skaiw c->usage_maximum; 473205728Skaiw s->nusage ++; 474205728Skaiw } 475205728Skaiw /* else XXX */ 476205728Skaiw 477205728Skaiw s->susage = 0; 47861560Sn_hibma break; 47961560Sn_hibma case 3: 48061560Sn_hibma c->designator_index = dval; 48161560Sn_hibma break; 48261560Sn_hibma case 4: 48361560Sn_hibma c->designator_minimum = dval; 48461560Sn_hibma break; 48561560Sn_hibma case 5: 48661560Sn_hibma c->designator_maximum = dval; 48761560Sn_hibma break; 48861560Sn_hibma case 7: 48961560Sn_hibma c->string_index = dval; 49061560Sn_hibma break; 49161560Sn_hibma case 8: 49261560Sn_hibma c->string_minimum = dval; 49361560Sn_hibma break; 49461560Sn_hibma case 9: 49561560Sn_hibma c->string_maximum = dval; 49661560Sn_hibma break; 49761560Sn_hibma case 10: 49861560Sn_hibma c->set_delimiter = dval; 49961560Sn_hibma break; 50061560Sn_hibma default: 501205728Skaiw break; 50261560Sn_hibma } 50361560Sn_hibma break; 50461560Sn_hibma default: 505205728Skaiw break; 50661560Sn_hibma } 50761560Sn_hibma } 508205728Skaiw return (0); 50961560Sn_hibma} 51061560Sn_hibma 51161560Sn_hibmaint 512113273Smdoddhid_report_size(report_desc_t r, enum hid_kind k, int id) 51361560Sn_hibma{ 51461560Sn_hibma struct hid_data *d; 515205728Skaiw struct hid_item h; 516205728Skaiw uint32_t temp; 517205728Skaiw uint32_t hpos; 518205728Skaiw uint32_t lpos; 519224511Smav int report_id = 0; 52061560Sn_hibma 521205728Skaiw hpos = 0; 522205728Skaiw lpos = 0xFFFFFFFF; 523205728Skaiw 52461560Sn_hibma memset(&h, 0, sizeof h); 525205728Skaiw for (d = hid_start_parse(r, 1 << k, id); hid_get_item(d, &h); ) { 526224511Smav if ((h.report_ID == id || id < 0) && h.kind == k) { 527205728Skaiw /* compute minimum */ 528205728Skaiw if (lpos > h.pos) 529205728Skaiw lpos = h.pos; 530205728Skaiw /* compute end position */ 531205728Skaiw temp = h.pos + (h.report_size * h.report_count); 532205728Skaiw /* compute maximum */ 533205728Skaiw if (hpos < temp) 534205728Skaiw hpos = temp; 535224511Smav if (h.report_ID != 0) 536224511Smav report_id = 1; 53761560Sn_hibma } 53861560Sn_hibma } 53961560Sn_hibma hid_end_parse(d); 540205728Skaiw 541205728Skaiw /* safety check - can happen in case of currupt descriptors */ 542205728Skaiw if (lpos > hpos) 543205728Skaiw temp = 0; 544205728Skaiw else 545205728Skaiw temp = hpos - lpos; 546205728Skaiw 547205728Skaiw /* return length in bytes rounded up */ 548224511Smav return ((temp + 7) / 8 + report_id); 54961560Sn_hibma} 55061560Sn_hibma 55161560Sn_hibmaint 552113273Smdoddhid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, 553113273Smdodd hid_item_t *h, int id) 55461560Sn_hibma{ 555205728Skaiw struct hid_data *d; 55661560Sn_hibma 557205728Skaiw for (d = hid_start_parse(desc, 1 << k, id); hid_get_item(d, h); ) { 55861560Sn_hibma if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) { 55961560Sn_hibma hid_end_parse(d); 56061560Sn_hibma return (1); 56161560Sn_hibma } 56261560Sn_hibma } 56361560Sn_hibma hid_end_parse(d); 56461560Sn_hibma h->report_size = 0; 56561560Sn_hibma return (0); 56661560Sn_hibma} 567