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$"); 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 */ 73240762Smav int32_t reportid; /* requested report ID */ 74205728Skaiw}; 7561560Sn_hibma 76205728Skaiw/*------------------------------------------------------------------------* 77205728Skaiw * hid_clear_local 78205728Skaiw *------------------------------------------------------------------------*/ 7961560Sn_hibmastatic void 8061560Sn_hibmahid_clear_local(hid_item_t *c) 8161560Sn_hibma{ 82205728Skaiw 8361560Sn_hibma c->usage = 0; 8461560Sn_hibma c->usage_minimum = 0; 8561560Sn_hibma c->usage_maximum = 0; 8661560Sn_hibma c->designator_index = 0; 8761560Sn_hibma c->designator_minimum = 0; 8861560Sn_hibma c->designator_maximum = 0; 8961560Sn_hibma c->string_index = 0; 9061560Sn_hibma c->string_minimum = 0; 9161560Sn_hibma c->string_maximum = 0; 9261560Sn_hibma c->set_delimiter = 0; 9361560Sn_hibma} 9461560Sn_hibma 95205728Skaiwstatic void 96205728Skaiwhid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) 97205728Skaiw{ 98225839Smav uint8_t i, j; 99205728Skaiw 100205728Skaiw /* check for same report ID - optimise */ 101205728Skaiw 102205728Skaiw if (c->report_ID == next_rID) 103205728Skaiw return; 104205728Skaiw 105205728Skaiw /* save current position for current rID */ 106205728Skaiw 107205728Skaiw if (c->report_ID == 0) { 108205728Skaiw i = 0; 109205728Skaiw } else { 110205728Skaiw for (i = 1; i != MAXID; i++) { 111205728Skaiw if (s->last_pos[i].rid == c->report_ID) 112205728Skaiw break; 113205728Skaiw if (s->last_pos[i].rid == 0) 114205728Skaiw break; 115205728Skaiw } 116205728Skaiw } 117205728Skaiw if (i != MAXID) { 118205728Skaiw s->last_pos[i].rid = c->report_ID; 119225839Smav for (j = 0; j < ITEMTYPES; j++) 120225839Smav s->last_pos[i].pos[j] = s->pos[j]; 121205728Skaiw } 122205728Skaiw 123205728Skaiw /* store next report ID */ 124205728Skaiw 125205728Skaiw c->report_ID = next_rID; 126205728Skaiw 127205728Skaiw /* lookup last position for next rID */ 128205728Skaiw 129205728Skaiw if (next_rID == 0) { 130205728Skaiw i = 0; 131205728Skaiw } else { 132205728Skaiw for (i = 1; i != MAXID; i++) { 133205728Skaiw if (s->last_pos[i].rid == next_rID) 134205728Skaiw break; 135205728Skaiw if (s->last_pos[i].rid == 0) 136205728Skaiw break; 137205728Skaiw } 138205728Skaiw } 139205728Skaiw if (i != MAXID) { 140205728Skaiw s->last_pos[i].rid = next_rID; 141225839Smav for (j = 0; j < ITEMTYPES; j++) 142225839Smav s->pos[j] = s->last_pos[i].pos[j]; 143225839Smav } else { 144225839Smav for (j = 0; j < ITEMTYPES; j++) 145225839Smav s->pos[j] = 0; /* Out of RID entries. */ 146225839Smav } 147205728Skaiw} 148205728Skaiw 149205728Skaiw/*------------------------------------------------------------------------* 150205728Skaiw * hid_start_parse 151205728Skaiw *------------------------------------------------------------------------*/ 15261560Sn_hibmahid_data_t 153240762Smavhid_start_parse(report_desc_t d, int kindset, int id) 15461560Sn_hibma{ 15561560Sn_hibma struct hid_data *s; 15661560Sn_hibma 15761560Sn_hibma s = malloc(sizeof *s); 15861560Sn_hibma memset(s, 0, sizeof *s); 15961560Sn_hibma s->start = s->p = d->data; 16061560Sn_hibma s->end = d->data + d->size; 16161560Sn_hibma s->kindset = kindset; 162240762Smav s->reportid = id; 16361560Sn_hibma return (s); 16461560Sn_hibma} 16561560Sn_hibma 166205728Skaiw/*------------------------------------------------------------------------* 167205728Skaiw * hid_end_parse 168205728Skaiw *------------------------------------------------------------------------*/ 16961560Sn_hibmavoid 17061560Sn_hibmahid_end_parse(hid_data_t s) 17161560Sn_hibma{ 172205728Skaiw 173205728Skaiw if (s == NULL) 174205728Skaiw return; 175205728Skaiw 17661560Sn_hibma free(s); 17761560Sn_hibma} 17861560Sn_hibma 179205728Skaiw/*------------------------------------------------------------------------* 180205728Skaiw * get byte from HID descriptor 181205728Skaiw *------------------------------------------------------------------------*/ 182205728Skaiwstatic uint8_t 183205728Skaiwhid_get_byte(struct hid_data *s, const uint16_t wSize) 18461560Sn_hibma{ 185205728Skaiw const uint8_t *ptr; 186205728Skaiw uint8_t retval; 187113273Smdodd 188205728Skaiw ptr = s->p; 189205728Skaiw 190205728Skaiw /* check if end is reached */ 191205728Skaiw if (ptr == s->end) 192205728Skaiw return (0); 193205728Skaiw 194205728Skaiw /* read out a byte */ 195205728Skaiw retval = *ptr; 196205728Skaiw 197205728Skaiw /* check if data pointer can be advanced by "wSize" bytes */ 198205728Skaiw if ((s->end - ptr) < wSize) 199205728Skaiw ptr = s->end; 200205728Skaiw else 201205728Skaiw ptr += wSize; 202205728Skaiw 203205728Skaiw /* update pointer */ 204205728Skaiw s->p = ptr; 205205728Skaiw 206205728Skaiw return (retval); 207113273Smdodd} 208113273Smdodd 209205728Skaiw/*------------------------------------------------------------------------* 210205728Skaiw * hid_get_item 211205728Skaiw *------------------------------------------------------------------------*/ 212240762Smavstatic int 213240762Smavhid_get_item_raw(hid_data_t s, hid_item_t *h) 214113273Smdodd{ 21561560Sn_hibma hid_item_t *c; 216205728Skaiw unsigned int bTag, bType, bSize; 217205728Skaiw int32_t mask; 218205728Skaiw int32_t dval; 21961560Sn_hibma 220205728Skaiw if (s == NULL) 221205728Skaiw return (0); 22261560Sn_hibma 223205728Skaiw c = &s->cur[s->pushlevel]; 224205728Skaiw 22561560Sn_hibma top: 226205728Skaiw /* check if there is an array of items */ 227205728Skaiw if (s->icount < s->ncount) { 228205728Skaiw /* get current usage */ 229205728Skaiw if (s->iusage < s->nusage) { 230205728Skaiw dval = s->usages_min[s->iusage] + s->ousage; 231205728Skaiw c->usage = dval; 232205728Skaiw s->usage_last = dval; 233205728Skaiw if (dval == s->usages_max[s->iusage]) { 234205728Skaiw s->iusage ++; 235205728Skaiw s->ousage = 0; 236205728Skaiw } else { 237205728Skaiw s->ousage ++; 238205728Skaiw } 239205728Skaiw } else { 240205728Skaiw /* Using last usage */ 241205728Skaiw dval = s->usage_last; 242113273Smdodd } 243205728Skaiw s->icount ++; 244205728Skaiw /* 245205728Skaiw * Only copy HID item, increment position and return 246205728Skaiw * if correct kindset! 247205728Skaiw */ 248205728Skaiw if (s->kindset & (1 << c->kind)) { 24961560Sn_hibma *h = *c; 250225839Smav h->pos = s->pos[c->kind]; 251225839Smav s->pos[c->kind] += c->report_size * c->report_count; 25261560Sn_hibma return (1); 25361560Sn_hibma } 25461560Sn_hibma } 25561560Sn_hibma 256205728Skaiw /* reset state variables */ 257205728Skaiw s->icount = 0; 258205728Skaiw s->ncount = 0; 259205728Skaiw s->iusage = 0; 260205728Skaiw s->nusage = 0; 261205728Skaiw s->susage = 0; 262205728Skaiw s->ousage = 0; 263205728Skaiw hid_clear_local(c); 264205728Skaiw 265205728Skaiw /* get next item */ 266205728Skaiw while (s->p != s->end) { 267205728Skaiw 268205728Skaiw bSize = hid_get_byte(s, 1); 26961560Sn_hibma if (bSize == 0xfe) { 27061560Sn_hibma /* long item */ 271205728Skaiw bSize = hid_get_byte(s, 1); 272205728Skaiw bSize |= hid_get_byte(s, 1) << 8; 273205728Skaiw bTag = hid_get_byte(s, 1); 274205728Skaiw bType = 0xff; /* XXX what should it be */ 27561560Sn_hibma } else { 27661560Sn_hibma /* short item */ 27761560Sn_hibma bTag = bSize >> 4; 27861560Sn_hibma bType = (bSize >> 2) & 3; 27961560Sn_hibma bSize &= 3; 280205728Skaiw if (bSize == 3) 281205728Skaiw bSize = 4; 28261560Sn_hibma } 283205728Skaiw 28461560Sn_hibma switch(bSize) { 28561560Sn_hibma case 0: 28661560Sn_hibma dval = 0; 287205728Skaiw mask = 0; 28861560Sn_hibma break; 28961560Sn_hibma case 1: 290205728Skaiw dval = (int8_t)hid_get_byte(s, 1); 291205728Skaiw mask = 0xFF; 29261560Sn_hibma break; 29361560Sn_hibma case 2: 294205728Skaiw dval = hid_get_byte(s, 1); 295205728Skaiw dval |= hid_get_byte(s, 1) << 8; 296205728Skaiw dval = (int16_t)dval; 297205728Skaiw mask = 0xFFFF; 29861560Sn_hibma break; 29961560Sn_hibma case 4: 300205728Skaiw dval = hid_get_byte(s, 1); 301205728Skaiw dval |= hid_get_byte(s, 1) << 8; 302205728Skaiw dval |= hid_get_byte(s, 1) << 16; 303205728Skaiw dval |= hid_get_byte(s, 1) << 24; 304205728Skaiw mask = 0xFFFFFFFF; 30561560Sn_hibma break; 30661560Sn_hibma default: 307205728Skaiw dval = hid_get_byte(s, bSize); 308205728Skaiw continue; 30961560Sn_hibma } 31061560Sn_hibma 31161560Sn_hibma switch (bType) { 312205728Skaiw case 0: /* Main */ 31361560Sn_hibma switch (bTag) { 314205728Skaiw case 8: /* Input */ 315205728Skaiw c->kind = hid_input; 31661560Sn_hibma c->flags = dval; 317205728Skaiw ret: 318205728Skaiw c->report_count = s->loc_count; 319205728Skaiw c->report_size = s->loc_size; 320205728Skaiw 32161560Sn_hibma if (c->flags & HIO_VARIABLE) { 322205728Skaiw /* range check usage count */ 323205728Skaiw if (c->report_count > 255) { 324205728Skaiw s->ncount = 255; 325205728Skaiw } else 326205728Skaiw s->ncount = c->report_count; 327205728Skaiw 328205728Skaiw /* 329205728Skaiw * The "top" loop will return 330205728Skaiw * one and one item: 331205728Skaiw */ 33261560Sn_hibma c->report_count = 1; 333224511Smav c->usage_minimum = 0; 334224511Smav c->usage_maximum = 0; 33561560Sn_hibma } else { 336205728Skaiw s->ncount = 1; 33761560Sn_hibma } 338205728Skaiw goto top; 339205728Skaiw 340205728Skaiw case 9: /* Output */ 341205728Skaiw c->kind = hid_output; 342205728Skaiw c->flags = dval; 34361560Sn_hibma goto ret; 34461560Sn_hibma case 10: /* Collection */ 34561560Sn_hibma c->kind = hid_collection; 34661560Sn_hibma c->collection = dval; 34761560Sn_hibma c->collevel++; 348205728Skaiw c->usage = s->usage_last; 349205728Skaiw *h = *c; 350205728Skaiw return (1); 35161560Sn_hibma case 11: /* Feature */ 352205728Skaiw c->kind = hid_feature; 353205728Skaiw c->flags = dval; 35461560Sn_hibma goto ret; 35561560Sn_hibma case 12: /* End collection */ 35661560Sn_hibma c->kind = hid_endcollection; 357205728Skaiw if (c->collevel == 0) { 358205728Skaiw /* Invalid end collection. */ 359205728Skaiw return (0); 360205728Skaiw } 36161560Sn_hibma c->collevel--; 36261560Sn_hibma *h = *c; 36361560Sn_hibma return (1); 36461560Sn_hibma default: 365205728Skaiw break; 36661560Sn_hibma } 367113273Smdodd break; 36861560Sn_hibma 36961560Sn_hibma case 1: /* Global */ 37061560Sn_hibma switch (bTag) { 37161560Sn_hibma case 0: 37261560Sn_hibma c->_usage_page = dval << 16; 37361560Sn_hibma break; 37461560Sn_hibma case 1: 37561560Sn_hibma c->logical_minimum = dval; 37661560Sn_hibma break; 37761560Sn_hibma case 2: 37861560Sn_hibma c->logical_maximum = dval; 37961560Sn_hibma break; 38061560Sn_hibma case 3: 381205728Skaiw c->physical_minimum = dval; 38261560Sn_hibma break; 38361560Sn_hibma case 4: 38461560Sn_hibma c->physical_maximum = dval; 38561560Sn_hibma break; 38661560Sn_hibma case 5: 38761560Sn_hibma c->unit_exponent = dval; 38861560Sn_hibma break; 38961560Sn_hibma case 6: 39061560Sn_hibma c->unit = dval; 39161560Sn_hibma break; 39261560Sn_hibma case 7: 393205728Skaiw /* mask because value is unsigned */ 394205728Skaiw s->loc_size = dval & mask; 39561560Sn_hibma break; 39661560Sn_hibma case 8: 397235510Smav hid_switch_rid(s, c, dval & mask); 39861560Sn_hibma break; 39961560Sn_hibma case 9: 400205728Skaiw /* mask because value is unsigned */ 401205728Skaiw s->loc_count = dval & mask; 40261560Sn_hibma break; 403205728Skaiw case 10: /* Push */ 404205728Skaiw s->pushlevel ++; 405205728Skaiw if (s->pushlevel < MAXPUSH) { 406205728Skaiw s->cur[s->pushlevel] = *c; 407205728Skaiw /* store size and count */ 408205728Skaiw c->report_size = s->loc_size; 409205728Skaiw c->report_count = s->loc_count; 410205728Skaiw /* update current item pointer */ 411205728Skaiw c = &s->cur[s->pushlevel]; 412205728Skaiw } 41361560Sn_hibma break; 414205728Skaiw case 11: /* Pop */ 415205728Skaiw s->pushlevel --; 416205728Skaiw if (s->pushlevel < MAXPUSH) { 417205728Skaiw c = &s->cur[s->pushlevel]; 418205728Skaiw /* restore size and count */ 419205728Skaiw s->loc_size = c->report_size; 420205728Skaiw s->loc_count = c->report_count; 421205728Skaiw c->report_size = 0; 422205728Skaiw c->report_count = 0; 423205728Skaiw } 42461560Sn_hibma break; 42561560Sn_hibma default: 426205728Skaiw break; 42761560Sn_hibma } 42861560Sn_hibma break; 42961560Sn_hibma case 2: /* Local */ 43061560Sn_hibma switch (bTag) { 43161560Sn_hibma case 0: 432205728Skaiw if (bSize != 4) 433205728Skaiw dval = (dval & mask) | c->_usage_page; 434205728Skaiw 435205728Skaiw /* set last usage, in case of a collection */ 436205728Skaiw s->usage_last = dval; 437205728Skaiw 438205728Skaiw if (s->nusage < MAXUSAGE) { 439205728Skaiw s->usages_min[s->nusage] = dval; 440205728Skaiw s->usages_max[s->nusage] = dval; 441205728Skaiw s->nusage ++; 442205728Skaiw } 44361560Sn_hibma /* else XXX */ 444205728Skaiw 445205728Skaiw /* clear any pending usage sets */ 446205728Skaiw s->susage = 0; 44761560Sn_hibma break; 44861560Sn_hibma case 1: 449205728Skaiw s->susage |= 1; 450205728Skaiw 451205728Skaiw if (bSize != 4) 452205728Skaiw dval = (dval & mask) | c->_usage_page; 453205728Skaiw c->usage_minimum = dval; 454205728Skaiw 455205728Skaiw goto check_set; 45661560Sn_hibma case 2: 457205728Skaiw s->susage |= 2; 458205728Skaiw 459205728Skaiw if (bSize != 4) 460205728Skaiw dval = (dval & mask) | c->_usage_page; 461205728Skaiw c->usage_maximum = dval; 462205728Skaiw 463205728Skaiw check_set: 464205728Skaiw if (s->susage != 3) 465205728Skaiw break; 466205728Skaiw 467205728Skaiw /* sanity check */ 468205728Skaiw if ((s->nusage < MAXUSAGE) && 469205728Skaiw (c->usage_minimum <= c->usage_maximum)) { 470205728Skaiw /* add usage range */ 471205728Skaiw s->usages_min[s->nusage] = 472205728Skaiw c->usage_minimum; 473205728Skaiw s->usages_max[s->nusage] = 474205728Skaiw c->usage_maximum; 475205728Skaiw s->nusage ++; 476205728Skaiw } 477205728Skaiw /* else XXX */ 478205728Skaiw 479205728Skaiw s->susage = 0; 48061560Sn_hibma break; 48161560Sn_hibma case 3: 48261560Sn_hibma c->designator_index = dval; 48361560Sn_hibma break; 48461560Sn_hibma case 4: 48561560Sn_hibma c->designator_minimum = dval; 48661560Sn_hibma break; 48761560Sn_hibma case 5: 48861560Sn_hibma c->designator_maximum = dval; 48961560Sn_hibma break; 49061560Sn_hibma case 7: 49161560Sn_hibma c->string_index = dval; 49261560Sn_hibma break; 49361560Sn_hibma case 8: 49461560Sn_hibma c->string_minimum = dval; 49561560Sn_hibma break; 49661560Sn_hibma case 9: 49761560Sn_hibma c->string_maximum = dval; 49861560Sn_hibma break; 49961560Sn_hibma case 10: 50061560Sn_hibma c->set_delimiter = dval; 50161560Sn_hibma break; 50261560Sn_hibma default: 503205728Skaiw break; 50461560Sn_hibma } 50561560Sn_hibma break; 50661560Sn_hibma default: 507205728Skaiw break; 50861560Sn_hibma } 50961560Sn_hibma } 510205728Skaiw return (0); 51161560Sn_hibma} 51261560Sn_hibma 51361560Sn_hibmaint 514240762Smavhid_get_item(hid_data_t s, hid_item_t *h) 515240762Smav{ 516240762Smav int r; 517240762Smav 518240762Smav for (;;) { 519240762Smav r = hid_get_item_raw(s, h); 520240762Smav if (r <= 0 || s->reportid == -1 || h->report_ID == s->reportid) 521240762Smav break; 522240762Smav } 523240762Smav return (r); 524240762Smav} 525240762Smav 526240762Smavint 527113273Smdoddhid_report_size(report_desc_t r, enum hid_kind k, int id) 52861560Sn_hibma{ 52961560Sn_hibma struct hid_data *d; 530205728Skaiw struct hid_item h; 531205728Skaiw uint32_t temp; 532205728Skaiw uint32_t hpos; 533205728Skaiw uint32_t lpos; 534224511Smav int report_id = 0; 53561560Sn_hibma 536205728Skaiw hpos = 0; 537205728Skaiw lpos = 0xFFFFFFFF; 538205728Skaiw 53961560Sn_hibma memset(&h, 0, sizeof h); 540205728Skaiw for (d = hid_start_parse(r, 1 << k, id); hid_get_item(d, &h); ) { 541240762Smav if (h.kind == k) { 542205728Skaiw /* compute minimum */ 543205728Skaiw if (lpos > h.pos) 544205728Skaiw lpos = h.pos; 545205728Skaiw /* compute end position */ 546205728Skaiw temp = h.pos + (h.report_size * h.report_count); 547205728Skaiw /* compute maximum */ 548205728Skaiw if (hpos < temp) 549205728Skaiw hpos = temp; 550224511Smav if (h.report_ID != 0) 551224511Smav report_id = 1; 55261560Sn_hibma } 55361560Sn_hibma } 55461560Sn_hibma hid_end_parse(d); 555205728Skaiw 556205728Skaiw /* safety check - can happen in case of currupt descriptors */ 557205728Skaiw if (lpos > hpos) 558205728Skaiw temp = 0; 559205728Skaiw else 560205728Skaiw temp = hpos - lpos; 561205728Skaiw 562205728Skaiw /* return length in bytes rounded up */ 563224511Smav return ((temp + 7) / 8 + report_id); 56461560Sn_hibma} 56561560Sn_hibma 56661560Sn_hibmaint 567113273Smdoddhid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, 568113273Smdodd hid_item_t *h, int id) 56961560Sn_hibma{ 570205728Skaiw struct hid_data *d; 57161560Sn_hibma 572205728Skaiw for (d = hid_start_parse(desc, 1 << k, id); hid_get_item(d, h); ) { 57361560Sn_hibma if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) { 57461560Sn_hibma hid_end_parse(d); 57561560Sn_hibma return (1); 57661560Sn_hibma } 57761560Sn_hibma } 57861560Sn_hibma hid_end_parse(d); 57961560Sn_hibma h->report_size = 0; 58061560Sn_hibma return (0); 58161560Sn_hibma} 582