11ffa5c63SVladimir Kondratyev /* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */ 21ffa5c63SVladimir Kondratyev /*- 3b61a5730SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 41ffa5c63SVladimir Kondratyev * 51ffa5c63SVladimir Kondratyev * Copyright (c) 1998 The NetBSD Foundation, Inc. 61ffa5c63SVladimir Kondratyev * All rights reserved. 71ffa5c63SVladimir Kondratyev * 81ffa5c63SVladimir Kondratyev * This code is derived from software contributed to The NetBSD Foundation 91ffa5c63SVladimir Kondratyev * by Lennart Augustsson (lennart@augustsson.net) at 101ffa5c63SVladimir Kondratyev * Carlstedt Research & Technology. 111ffa5c63SVladimir Kondratyev * 121ffa5c63SVladimir Kondratyev * Redistribution and use in source and binary forms, with or without 131ffa5c63SVladimir Kondratyev * modification, are permitted provided that the following conditions 141ffa5c63SVladimir Kondratyev * are met: 151ffa5c63SVladimir Kondratyev * 1. Redistributions of source code must retain the above copyright 161ffa5c63SVladimir Kondratyev * notice, this list of conditions and the following disclaimer. 171ffa5c63SVladimir Kondratyev * 2. Redistributions in binary form must reproduce the above copyright 181ffa5c63SVladimir Kondratyev * notice, this list of conditions and the following disclaimer in the 191ffa5c63SVladimir Kondratyev * documentation and/or other materials provided with the distribution. 201ffa5c63SVladimir Kondratyev * 211ffa5c63SVladimir Kondratyev * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 221ffa5c63SVladimir Kondratyev * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 231ffa5c63SVladimir Kondratyev * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 241ffa5c63SVladimir Kondratyev * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 251ffa5c63SVladimir Kondratyev * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 261ffa5c63SVladimir Kondratyev * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 271ffa5c63SVladimir Kondratyev * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 281ffa5c63SVladimir Kondratyev * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 291ffa5c63SVladimir Kondratyev * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 301ffa5c63SVladimir Kondratyev * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 311ffa5c63SVladimir Kondratyev * POSSIBILITY OF SUCH DAMAGE. 321ffa5c63SVladimir Kondratyev */ 331ffa5c63SVladimir Kondratyev 3419758786SVladimir Kondratyev #include "opt_hid.h" 3519758786SVladimir Kondratyev 361ffa5c63SVladimir Kondratyev #include <sys/param.h> 371ffa5c63SVladimir Kondratyev #include <sys/bus.h> 3819758786SVladimir Kondratyev #include <sys/kdb.h> 3919758786SVladimir Kondratyev #include <sys/kernel.h> 401ffa5c63SVladimir Kondratyev #include <sys/malloc.h> 4119758786SVladimir Kondratyev #include <sys/module.h> 4219758786SVladimir Kondratyev #include <sys/sysctl.h> 431ffa5c63SVladimir Kondratyev 4419758786SVladimir Kondratyev #define HID_DEBUG_VAR hid_debug 4519758786SVladimir Kondratyev #include <dev/hid/hid.h> 4619758786SVladimir Kondratyev #include <dev/hid/hidquirk.h> 471ffa5c63SVladimir Kondratyev 48961a3535SVladimir Kondratyev #include "hid_if.h" 49961a3535SVladimir Kondratyev 5019758786SVladimir Kondratyev /* 5119758786SVladimir Kondratyev * Define this unconditionally in case a kernel module is loaded that 5219758786SVladimir Kondratyev * has been compiled with debugging options. 5319758786SVladimir Kondratyev */ 5419758786SVladimir Kondratyev int hid_debug = 0; 551ffa5c63SVladimir Kondratyev 5619758786SVladimir Kondratyev SYSCTL_NODE(_hw, OID_AUTO, hid, CTLFLAG_RW, 0, "HID debugging"); 5719758786SVladimir Kondratyev SYSCTL_INT(_hw_hid, OID_AUTO, debug, CTLFLAG_RWTUN, 5819758786SVladimir Kondratyev &hid_debug, 0, "Debug level"); 591ffa5c63SVladimir Kondratyev 601ffa5c63SVladimir Kondratyev static void hid_clear_local(struct hid_item *); 611ffa5c63SVladimir Kondratyev static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize); 621ffa5c63SVladimir Kondratyev 6319758786SVladimir Kondratyev static hid_test_quirk_t hid_test_quirk_w; 6419758786SVladimir Kondratyev hid_test_quirk_t *hid_test_quirk_p = &hid_test_quirk_w; 6519758786SVladimir Kondratyev 661ffa5c63SVladimir Kondratyev #define MAXUSAGE 64 671ffa5c63SVladimir Kondratyev #define MAXPUSH 4 681ffa5c63SVladimir Kondratyev #define MAXID 16 691ffa5c63SVladimir Kondratyev #define MAXLOCCNT 2048 701ffa5c63SVladimir Kondratyev 711ffa5c63SVladimir Kondratyev struct hid_pos_data { 72*38b67578SVladimir Kondratyev uint32_t rid; 731ffa5c63SVladimir Kondratyev uint32_t pos; 741ffa5c63SVladimir Kondratyev }; 751ffa5c63SVladimir Kondratyev 761ffa5c63SVladimir Kondratyev struct hid_data { 771ffa5c63SVladimir Kondratyev const uint8_t *start; 781ffa5c63SVladimir Kondratyev const uint8_t *end; 791ffa5c63SVladimir Kondratyev const uint8_t *p; 801ffa5c63SVladimir Kondratyev struct hid_item cur[MAXPUSH]; 811ffa5c63SVladimir Kondratyev struct hid_pos_data last_pos[MAXID]; 82*38b67578SVladimir Kondratyev uint32_t usages_min[MAXUSAGE]; 83*38b67578SVladimir Kondratyev uint32_t usages_max[MAXUSAGE]; 84*38b67578SVladimir Kondratyev uint32_t usage_last; /* last seen usage */ 851ffa5c63SVladimir Kondratyev uint32_t loc_size; /* last seen size */ 861ffa5c63SVladimir Kondratyev uint32_t loc_count; /* last seen count */ 871ffa5c63SVladimir Kondratyev uint32_t ncount; /* end usage item count */ 881ffa5c63SVladimir Kondratyev uint32_t icount; /* current usage item count */ 891ffa5c63SVladimir Kondratyev uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ 901ffa5c63SVladimir Kondratyev uint8_t pushlevel; /* current pushlevel */ 911ffa5c63SVladimir Kondratyev uint8_t nusage; /* end "usages_min/max" index */ 921ffa5c63SVladimir Kondratyev uint8_t iusage; /* current "usages_min/max" index */ 931ffa5c63SVladimir Kondratyev uint8_t ousage; /* current "usages_min/max" offset */ 941ffa5c63SVladimir Kondratyev uint8_t susage; /* usage set flags */ 951ffa5c63SVladimir Kondratyev }; 961ffa5c63SVladimir Kondratyev 971ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 981ffa5c63SVladimir Kondratyev * hid_clear_local 991ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 1001ffa5c63SVladimir Kondratyev static void 1011ffa5c63SVladimir Kondratyev hid_clear_local(struct hid_item *c) 1021ffa5c63SVladimir Kondratyev { 1031ffa5c63SVladimir Kondratyev 1041ffa5c63SVladimir Kondratyev c->loc.count = 0; 1051ffa5c63SVladimir Kondratyev c->loc.size = 0; 1061ffa5c63SVladimir Kondratyev c->nusages = 0; 1071ffa5c63SVladimir Kondratyev memset(c->usages, 0, sizeof(c->usages)); 1081ffa5c63SVladimir Kondratyev c->usage_minimum = 0; 1091ffa5c63SVladimir Kondratyev c->usage_maximum = 0; 1101ffa5c63SVladimir Kondratyev c->designator_index = 0; 1111ffa5c63SVladimir Kondratyev c->designator_minimum = 0; 1121ffa5c63SVladimir Kondratyev c->designator_maximum = 0; 1131ffa5c63SVladimir Kondratyev c->string_index = 0; 1141ffa5c63SVladimir Kondratyev c->string_minimum = 0; 1151ffa5c63SVladimir Kondratyev c->string_maximum = 0; 1161ffa5c63SVladimir Kondratyev c->set_delimiter = 0; 1171ffa5c63SVladimir Kondratyev } 1181ffa5c63SVladimir Kondratyev 1191ffa5c63SVladimir Kondratyev static void 120*38b67578SVladimir Kondratyev hid_switch_rid(struct hid_data *s, struct hid_item *c, uint32_t next_rID) 1211ffa5c63SVladimir Kondratyev { 1221ffa5c63SVladimir Kondratyev uint8_t i; 1231ffa5c63SVladimir Kondratyev 1241ffa5c63SVladimir Kondratyev /* check for same report ID - optimise */ 1251ffa5c63SVladimir Kondratyev 1261ffa5c63SVladimir Kondratyev if (c->report_ID == next_rID) 1271ffa5c63SVladimir Kondratyev return; 1281ffa5c63SVladimir Kondratyev 1291ffa5c63SVladimir Kondratyev /* save current position for current rID */ 1301ffa5c63SVladimir Kondratyev 1311ffa5c63SVladimir Kondratyev if (c->report_ID == 0) { 1321ffa5c63SVladimir Kondratyev i = 0; 1331ffa5c63SVladimir Kondratyev } else { 1341ffa5c63SVladimir Kondratyev for (i = 1; i != MAXID; i++) { 1351ffa5c63SVladimir Kondratyev if (s->last_pos[i].rid == c->report_ID) 1361ffa5c63SVladimir Kondratyev break; 1371ffa5c63SVladimir Kondratyev if (s->last_pos[i].rid == 0) 1381ffa5c63SVladimir Kondratyev break; 1391ffa5c63SVladimir Kondratyev } 1401ffa5c63SVladimir Kondratyev } 1411ffa5c63SVladimir Kondratyev if (i != MAXID) { 1421ffa5c63SVladimir Kondratyev s->last_pos[i].rid = c->report_ID; 1431ffa5c63SVladimir Kondratyev s->last_pos[i].pos = c->loc.pos; 1441ffa5c63SVladimir Kondratyev } 1451ffa5c63SVladimir Kondratyev 1461ffa5c63SVladimir Kondratyev /* store next report ID */ 1471ffa5c63SVladimir Kondratyev 1481ffa5c63SVladimir Kondratyev c->report_ID = next_rID; 1491ffa5c63SVladimir Kondratyev 1501ffa5c63SVladimir Kondratyev /* lookup last position for next rID */ 1511ffa5c63SVladimir Kondratyev 1521ffa5c63SVladimir Kondratyev if (next_rID == 0) { 1531ffa5c63SVladimir Kondratyev i = 0; 1541ffa5c63SVladimir Kondratyev } else { 1551ffa5c63SVladimir Kondratyev for (i = 1; i != MAXID; i++) { 1561ffa5c63SVladimir Kondratyev if (s->last_pos[i].rid == next_rID) 1571ffa5c63SVladimir Kondratyev break; 1581ffa5c63SVladimir Kondratyev if (s->last_pos[i].rid == 0) 1591ffa5c63SVladimir Kondratyev break; 1601ffa5c63SVladimir Kondratyev } 1611ffa5c63SVladimir Kondratyev } 1621ffa5c63SVladimir Kondratyev if (i != MAXID) { 1631ffa5c63SVladimir Kondratyev s->last_pos[i].rid = next_rID; 1641ffa5c63SVladimir Kondratyev c->loc.pos = s->last_pos[i].pos; 1651ffa5c63SVladimir Kondratyev } else { 1661ffa5c63SVladimir Kondratyev DPRINTF("Out of RID entries, position is set to zero!\n"); 1671ffa5c63SVladimir Kondratyev c->loc.pos = 0; 1681ffa5c63SVladimir Kondratyev } 1691ffa5c63SVladimir Kondratyev } 1701ffa5c63SVladimir Kondratyev 1711ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 1721ffa5c63SVladimir Kondratyev * hid_start_parse 1731ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 1741ffa5c63SVladimir Kondratyev struct hid_data * 17519758786SVladimir Kondratyev hid_start_parse(const void *d, hid_size_t len, int kindset) 1761ffa5c63SVladimir Kondratyev { 1771ffa5c63SVladimir Kondratyev struct hid_data *s; 1781ffa5c63SVladimir Kondratyev 1791ffa5c63SVladimir Kondratyev if ((kindset-1) & kindset) { 1801ffa5c63SVladimir Kondratyev DPRINTFN(0, "Only one bit can be " 1811ffa5c63SVladimir Kondratyev "set in the kindset\n"); 1821ffa5c63SVladimir Kondratyev return (NULL); 1831ffa5c63SVladimir Kondratyev } 1841ffa5c63SVladimir Kondratyev 1851ffa5c63SVladimir Kondratyev s = malloc(sizeof *s, M_TEMP, M_WAITOK | M_ZERO); 1861ffa5c63SVladimir Kondratyev s->start = s->p = d; 1871ffa5c63SVladimir Kondratyev s->end = ((const uint8_t *)d) + len; 1881ffa5c63SVladimir Kondratyev s->kindset = kindset; 1891ffa5c63SVladimir Kondratyev return (s); 1901ffa5c63SVladimir Kondratyev } 1911ffa5c63SVladimir Kondratyev 1921ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 1931ffa5c63SVladimir Kondratyev * hid_end_parse 1941ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 1951ffa5c63SVladimir Kondratyev void 1961ffa5c63SVladimir Kondratyev hid_end_parse(struct hid_data *s) 1971ffa5c63SVladimir Kondratyev { 1981ffa5c63SVladimir Kondratyev if (s == NULL) 1991ffa5c63SVladimir Kondratyev return; 2001ffa5c63SVladimir Kondratyev 2011ffa5c63SVladimir Kondratyev free(s, M_TEMP); 2021ffa5c63SVladimir Kondratyev } 2031ffa5c63SVladimir Kondratyev 2041ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 2051ffa5c63SVladimir Kondratyev * get byte from HID descriptor 2061ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 2071ffa5c63SVladimir Kondratyev static uint8_t 2081ffa5c63SVladimir Kondratyev hid_get_byte(struct hid_data *s, const uint16_t wSize) 2091ffa5c63SVladimir Kondratyev { 2101ffa5c63SVladimir Kondratyev const uint8_t *ptr; 2111ffa5c63SVladimir Kondratyev uint8_t retval; 2121ffa5c63SVladimir Kondratyev 2131ffa5c63SVladimir Kondratyev ptr = s->p; 2141ffa5c63SVladimir Kondratyev 2151ffa5c63SVladimir Kondratyev /* check if end is reached */ 2161ffa5c63SVladimir Kondratyev if (ptr == s->end) 2171ffa5c63SVladimir Kondratyev return (0); 2181ffa5c63SVladimir Kondratyev 2191ffa5c63SVladimir Kondratyev /* read out a byte */ 2201ffa5c63SVladimir Kondratyev retval = *ptr; 2211ffa5c63SVladimir Kondratyev 2221ffa5c63SVladimir Kondratyev /* check if data pointer can be advanced by "wSize" bytes */ 2231ffa5c63SVladimir Kondratyev if ((s->end - ptr) < wSize) 2241ffa5c63SVladimir Kondratyev ptr = s->end; 2251ffa5c63SVladimir Kondratyev else 2261ffa5c63SVladimir Kondratyev ptr += wSize; 2271ffa5c63SVladimir Kondratyev 2281ffa5c63SVladimir Kondratyev /* update pointer */ 2291ffa5c63SVladimir Kondratyev s->p = ptr; 2301ffa5c63SVladimir Kondratyev 2311ffa5c63SVladimir Kondratyev return (retval); 2321ffa5c63SVladimir Kondratyev } 2331ffa5c63SVladimir Kondratyev 2341ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 2351ffa5c63SVladimir Kondratyev * hid_get_item 2361ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 2371ffa5c63SVladimir Kondratyev int 2381ffa5c63SVladimir Kondratyev hid_get_item(struct hid_data *s, struct hid_item *h) 2391ffa5c63SVladimir Kondratyev { 2401ffa5c63SVladimir Kondratyev struct hid_item *c; 2411ffa5c63SVladimir Kondratyev unsigned int bTag, bType, bSize; 2421ffa5c63SVladimir Kondratyev uint32_t oldpos; 2431ffa5c63SVladimir Kondratyev int32_t mask; 2441ffa5c63SVladimir Kondratyev int32_t dval; 245*38b67578SVladimir Kondratyev uint32_t uval; 2461ffa5c63SVladimir Kondratyev 2471ffa5c63SVladimir Kondratyev if (s == NULL) 2481ffa5c63SVladimir Kondratyev return (0); 2491ffa5c63SVladimir Kondratyev 2501ffa5c63SVladimir Kondratyev c = &s->cur[s->pushlevel]; 2511ffa5c63SVladimir Kondratyev 2521ffa5c63SVladimir Kondratyev top: 2531ffa5c63SVladimir Kondratyev /* check if there is an array of items */ 2541ffa5c63SVladimir Kondratyev if (s->icount < s->ncount) { 2551ffa5c63SVladimir Kondratyev /* get current usage */ 2561ffa5c63SVladimir Kondratyev if (s->iusage < s->nusage) { 257*38b67578SVladimir Kondratyev uval = s->usages_min[s->iusage] + s->ousage; 258*38b67578SVladimir Kondratyev c->usage = uval; 259*38b67578SVladimir Kondratyev s->usage_last = uval; 260*38b67578SVladimir Kondratyev if (uval == s->usages_max[s->iusage]) { 2611ffa5c63SVladimir Kondratyev s->iusage ++; 2621ffa5c63SVladimir Kondratyev s->ousage = 0; 2631ffa5c63SVladimir Kondratyev } else { 2641ffa5c63SVladimir Kondratyev s->ousage ++; 2651ffa5c63SVladimir Kondratyev } 2661ffa5c63SVladimir Kondratyev } else { 2671ffa5c63SVladimir Kondratyev DPRINTFN(1, "Using last usage\n"); 268*38b67578SVladimir Kondratyev uval = s->usage_last; 2691ffa5c63SVladimir Kondratyev } 2701ffa5c63SVladimir Kondratyev c->nusages = 1; 2711ffa5c63SVladimir Kondratyev /* array type HID item may have multiple usages */ 2721ffa5c63SVladimir Kondratyev while ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && 2731ffa5c63SVladimir Kondratyev s->iusage < s->nusage && c->nusages < HID_ITEM_MAXUSAGE) 2741ffa5c63SVladimir Kondratyev c->usages[c->nusages++] = s->usages_min[s->iusage++]; 2751ffa5c63SVladimir Kondratyev if ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && 2761ffa5c63SVladimir Kondratyev s->iusage < s->nusage) 2771ffa5c63SVladimir Kondratyev DPRINTFN(0, "HID_ITEM_MAXUSAGE should be increased " 2781ffa5c63SVladimir Kondratyev "up to %hhu to parse the HID report descriptor\n", 2791ffa5c63SVladimir Kondratyev s->nusage); 2801ffa5c63SVladimir Kondratyev s->icount ++; 2811ffa5c63SVladimir Kondratyev /* 2821ffa5c63SVladimir Kondratyev * Only copy HID item, increment position and return 2831ffa5c63SVladimir Kondratyev * if correct kindset! 2841ffa5c63SVladimir Kondratyev */ 2851ffa5c63SVladimir Kondratyev if (s->kindset & (1 << c->kind)) { 2861ffa5c63SVladimir Kondratyev *h = *c; 2871ffa5c63SVladimir Kondratyev DPRINTFN(1, "%u,%u,%u\n", h->loc.pos, 2881ffa5c63SVladimir Kondratyev h->loc.size, h->loc.count); 2891ffa5c63SVladimir Kondratyev c->loc.pos += c->loc.size * c->loc.count; 2901ffa5c63SVladimir Kondratyev return (1); 2911ffa5c63SVladimir Kondratyev } 2921ffa5c63SVladimir Kondratyev } 2931ffa5c63SVladimir Kondratyev 2941ffa5c63SVladimir Kondratyev /* reset state variables */ 2951ffa5c63SVladimir Kondratyev s->icount = 0; 2961ffa5c63SVladimir Kondratyev s->ncount = 0; 2971ffa5c63SVladimir Kondratyev s->iusage = 0; 2981ffa5c63SVladimir Kondratyev s->nusage = 0; 2991ffa5c63SVladimir Kondratyev s->susage = 0; 3001ffa5c63SVladimir Kondratyev s->ousage = 0; 3011ffa5c63SVladimir Kondratyev hid_clear_local(c); 3021ffa5c63SVladimir Kondratyev 3031ffa5c63SVladimir Kondratyev /* get next item */ 3041ffa5c63SVladimir Kondratyev while (s->p != s->end) { 3051ffa5c63SVladimir Kondratyev bSize = hid_get_byte(s, 1); 3061ffa5c63SVladimir Kondratyev if (bSize == 0xfe) { 3071ffa5c63SVladimir Kondratyev /* long item */ 3081ffa5c63SVladimir Kondratyev bSize = hid_get_byte(s, 1); 3091ffa5c63SVladimir Kondratyev bSize |= hid_get_byte(s, 1) << 8; 3101ffa5c63SVladimir Kondratyev bTag = hid_get_byte(s, 1); 3111ffa5c63SVladimir Kondratyev bType = 0xff; /* XXX what should it be */ 3121ffa5c63SVladimir Kondratyev } else { 3131ffa5c63SVladimir Kondratyev /* short item */ 3141ffa5c63SVladimir Kondratyev bTag = bSize >> 4; 3151ffa5c63SVladimir Kondratyev bType = (bSize >> 2) & 3; 3161ffa5c63SVladimir Kondratyev bSize &= 3; 3171ffa5c63SVladimir Kondratyev if (bSize == 3) 3181ffa5c63SVladimir Kondratyev bSize = 4; 3191ffa5c63SVladimir Kondratyev } 3201ffa5c63SVladimir Kondratyev switch (bSize) { 3211ffa5c63SVladimir Kondratyev case 0: 322*38b67578SVladimir Kondratyev uval = 0; 323*38b67578SVladimir Kondratyev dval = uval; 3241ffa5c63SVladimir Kondratyev mask = 0; 3251ffa5c63SVladimir Kondratyev break; 3261ffa5c63SVladimir Kondratyev case 1: 327*38b67578SVladimir Kondratyev uval = hid_get_byte(s, 1); 328*38b67578SVladimir Kondratyev dval = (int8_t)uval; 3291ffa5c63SVladimir Kondratyev mask = 0xFF; 3301ffa5c63SVladimir Kondratyev break; 3311ffa5c63SVladimir Kondratyev case 2: 332*38b67578SVladimir Kondratyev uval = hid_get_byte(s, 1); 333*38b67578SVladimir Kondratyev uval |= hid_get_byte(s, 1) << 8; 334*38b67578SVladimir Kondratyev dval = (int16_t)uval; 3351ffa5c63SVladimir Kondratyev mask = 0xFFFF; 3361ffa5c63SVladimir Kondratyev break; 3371ffa5c63SVladimir Kondratyev case 4: 338*38b67578SVladimir Kondratyev uval = hid_get_byte(s, 1); 339*38b67578SVladimir Kondratyev uval |= hid_get_byte(s, 1) << 8; 340*38b67578SVladimir Kondratyev uval |= hid_get_byte(s, 1) << 16; 341*38b67578SVladimir Kondratyev uval |= hid_get_byte(s, 1) << 24; 342*38b67578SVladimir Kondratyev dval = uval; 3431ffa5c63SVladimir Kondratyev mask = 0xFFFFFFFF; 3441ffa5c63SVladimir Kondratyev break; 3451ffa5c63SVladimir Kondratyev default: 346*38b67578SVladimir Kondratyev uval = hid_get_byte(s, bSize); 347*38b67578SVladimir Kondratyev dval = uval; 3481ffa5c63SVladimir Kondratyev DPRINTFN(0, "bad length %u (data=0x%02x)\n", 3491ffa5c63SVladimir Kondratyev bSize, dval); 3501ffa5c63SVladimir Kondratyev continue; 3511ffa5c63SVladimir Kondratyev } 3521ffa5c63SVladimir Kondratyev 3531ffa5c63SVladimir Kondratyev switch (bType) { 3541ffa5c63SVladimir Kondratyev case 0: /* Main */ 3551ffa5c63SVladimir Kondratyev switch (bTag) { 3561ffa5c63SVladimir Kondratyev case 8: /* Input */ 3571ffa5c63SVladimir Kondratyev c->kind = hid_input; 3581ffa5c63SVladimir Kondratyev ret: 359*38b67578SVladimir Kondratyev c->flags = uval; 3601ffa5c63SVladimir Kondratyev c->loc.count = s->loc_count; 3611ffa5c63SVladimir Kondratyev c->loc.size = s->loc_size; 3621ffa5c63SVladimir Kondratyev 3631ffa5c63SVladimir Kondratyev if (c->flags & HIO_VARIABLE) { 3641ffa5c63SVladimir Kondratyev /* range check usage count */ 3651ffa5c63SVladimir Kondratyev if (c->loc.count > MAXLOCCNT) { 3661ffa5c63SVladimir Kondratyev DPRINTFN(0, "Number of " 3671ffa5c63SVladimir Kondratyev "items(%u) truncated to %u\n", 3681ffa5c63SVladimir Kondratyev (unsigned)(c->loc.count), 3691ffa5c63SVladimir Kondratyev MAXLOCCNT); 3701ffa5c63SVladimir Kondratyev s->ncount = MAXLOCCNT; 3711ffa5c63SVladimir Kondratyev } else 3721ffa5c63SVladimir Kondratyev s->ncount = c->loc.count; 3731ffa5c63SVladimir Kondratyev 3741ffa5c63SVladimir Kondratyev /* 3751ffa5c63SVladimir Kondratyev * The "top" loop will return 3761ffa5c63SVladimir Kondratyev * one and one item: 3771ffa5c63SVladimir Kondratyev */ 3781ffa5c63SVladimir Kondratyev c->loc.count = 1; 3791ffa5c63SVladimir Kondratyev } else { 3801ffa5c63SVladimir Kondratyev s->ncount = 1; 3811ffa5c63SVladimir Kondratyev } 3821ffa5c63SVladimir Kondratyev goto top; 3831ffa5c63SVladimir Kondratyev 3841ffa5c63SVladimir Kondratyev case 9: /* Output */ 3851ffa5c63SVladimir Kondratyev c->kind = hid_output; 3861ffa5c63SVladimir Kondratyev goto ret; 3871ffa5c63SVladimir Kondratyev case 10: /* Collection */ 3881ffa5c63SVladimir Kondratyev c->kind = hid_collection; 389*38b67578SVladimir Kondratyev c->collection = uval; 3901ffa5c63SVladimir Kondratyev c->collevel++; 3911ffa5c63SVladimir Kondratyev c->usage = s->usage_last; 3921ffa5c63SVladimir Kondratyev c->nusages = 1; 3931ffa5c63SVladimir Kondratyev *h = *c; 3941ffa5c63SVladimir Kondratyev return (1); 3951ffa5c63SVladimir Kondratyev case 11: /* Feature */ 3961ffa5c63SVladimir Kondratyev c->kind = hid_feature; 3971ffa5c63SVladimir Kondratyev goto ret; 3981ffa5c63SVladimir Kondratyev case 12: /* End collection */ 3991ffa5c63SVladimir Kondratyev c->kind = hid_endcollection; 4001ffa5c63SVladimir Kondratyev if (c->collevel == 0) { 4011ffa5c63SVladimir Kondratyev DPRINTFN(0, "invalid end collection\n"); 4021ffa5c63SVladimir Kondratyev return (0); 4031ffa5c63SVladimir Kondratyev } 4041ffa5c63SVladimir Kondratyev c->collevel--; 4051ffa5c63SVladimir Kondratyev *h = *c; 4061ffa5c63SVladimir Kondratyev return (1); 4071ffa5c63SVladimir Kondratyev default: 4081ffa5c63SVladimir Kondratyev DPRINTFN(0, "Main bTag=%d\n", bTag); 4091ffa5c63SVladimir Kondratyev break; 4101ffa5c63SVladimir Kondratyev } 4111ffa5c63SVladimir Kondratyev break; 4121ffa5c63SVladimir Kondratyev case 1: /* Global */ 4131ffa5c63SVladimir Kondratyev switch (bTag) { 4141ffa5c63SVladimir Kondratyev case 0: 415*38b67578SVladimir Kondratyev c->_usage_page = uval << 16; 4161ffa5c63SVladimir Kondratyev break; 4171ffa5c63SVladimir Kondratyev case 1: 4181ffa5c63SVladimir Kondratyev c->logical_minimum = dval; 4191ffa5c63SVladimir Kondratyev break; 4201ffa5c63SVladimir Kondratyev case 2: 4211ffa5c63SVladimir Kondratyev c->logical_maximum = dval; 4221ffa5c63SVladimir Kondratyev break; 4231ffa5c63SVladimir Kondratyev case 3: 4241ffa5c63SVladimir Kondratyev c->physical_minimum = dval; 4251ffa5c63SVladimir Kondratyev break; 4261ffa5c63SVladimir Kondratyev case 4: 4271ffa5c63SVladimir Kondratyev c->physical_maximum = dval; 4281ffa5c63SVladimir Kondratyev break; 4291ffa5c63SVladimir Kondratyev case 5: 430*38b67578SVladimir Kondratyev c->unit_exponent = uval; 4311ffa5c63SVladimir Kondratyev break; 4321ffa5c63SVladimir Kondratyev case 6: 433*38b67578SVladimir Kondratyev c->unit = uval; 4341ffa5c63SVladimir Kondratyev break; 4351ffa5c63SVladimir Kondratyev case 7: 4361ffa5c63SVladimir Kondratyev /* mask because value is unsigned */ 437*38b67578SVladimir Kondratyev s->loc_size = uval & mask; 4381ffa5c63SVladimir Kondratyev break; 4391ffa5c63SVladimir Kondratyev case 8: 440*38b67578SVladimir Kondratyev hid_switch_rid(s, c, uval & mask); 4411ffa5c63SVladimir Kondratyev break; 4421ffa5c63SVladimir Kondratyev case 9: 4431ffa5c63SVladimir Kondratyev /* mask because value is unsigned */ 444*38b67578SVladimir Kondratyev s->loc_count = uval & mask; 4451ffa5c63SVladimir Kondratyev break; 4461ffa5c63SVladimir Kondratyev case 10: /* Push */ 4471ffa5c63SVladimir Kondratyev /* stop parsing, if invalid push level */ 4481ffa5c63SVladimir Kondratyev if ((s->pushlevel + 1) >= MAXPUSH) { 4491ffa5c63SVladimir Kondratyev DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel); 4501ffa5c63SVladimir Kondratyev return (0); 4511ffa5c63SVladimir Kondratyev } 4521ffa5c63SVladimir Kondratyev s->pushlevel ++; 4531ffa5c63SVladimir Kondratyev s->cur[s->pushlevel] = *c; 4541ffa5c63SVladimir Kondratyev /* store size and count */ 4551ffa5c63SVladimir Kondratyev c->loc.size = s->loc_size; 4561ffa5c63SVladimir Kondratyev c->loc.count = s->loc_count; 4571ffa5c63SVladimir Kondratyev /* update current item pointer */ 4581ffa5c63SVladimir Kondratyev c = &s->cur[s->pushlevel]; 4591ffa5c63SVladimir Kondratyev break; 4601ffa5c63SVladimir Kondratyev case 11: /* Pop */ 4611ffa5c63SVladimir Kondratyev /* stop parsing, if invalid push level */ 4621ffa5c63SVladimir Kondratyev if (s->pushlevel == 0) { 4631ffa5c63SVladimir Kondratyev DPRINTFN(0, "Cannot pop item @ 0\n"); 4641ffa5c63SVladimir Kondratyev return (0); 4651ffa5c63SVladimir Kondratyev } 4661ffa5c63SVladimir Kondratyev s->pushlevel --; 4671ffa5c63SVladimir Kondratyev /* preserve position */ 4681ffa5c63SVladimir Kondratyev oldpos = c->loc.pos; 4691ffa5c63SVladimir Kondratyev c = &s->cur[s->pushlevel]; 4701ffa5c63SVladimir Kondratyev /* restore size and count */ 4711ffa5c63SVladimir Kondratyev s->loc_size = c->loc.size; 4721ffa5c63SVladimir Kondratyev s->loc_count = c->loc.count; 4731ffa5c63SVladimir Kondratyev /* set default item location */ 4741ffa5c63SVladimir Kondratyev c->loc.pos = oldpos; 4751ffa5c63SVladimir Kondratyev c->loc.size = 0; 4761ffa5c63SVladimir Kondratyev c->loc.count = 0; 4771ffa5c63SVladimir Kondratyev break; 4781ffa5c63SVladimir Kondratyev default: 4791ffa5c63SVladimir Kondratyev DPRINTFN(0, "Global bTag=%d\n", bTag); 4801ffa5c63SVladimir Kondratyev break; 4811ffa5c63SVladimir Kondratyev } 4821ffa5c63SVladimir Kondratyev break; 4831ffa5c63SVladimir Kondratyev case 2: /* Local */ 4841ffa5c63SVladimir Kondratyev switch (bTag) { 4851ffa5c63SVladimir Kondratyev case 0: 4861ffa5c63SVladimir Kondratyev if (bSize != 4) 487*38b67578SVladimir Kondratyev uval = (uval & mask) | c->_usage_page; 4881ffa5c63SVladimir Kondratyev 4891ffa5c63SVladimir Kondratyev /* set last usage, in case of a collection */ 490*38b67578SVladimir Kondratyev s->usage_last = uval; 4911ffa5c63SVladimir Kondratyev 4921ffa5c63SVladimir Kondratyev if (s->nusage < MAXUSAGE) { 493*38b67578SVladimir Kondratyev s->usages_min[s->nusage] = uval; 494*38b67578SVladimir Kondratyev s->usages_max[s->nusage] = uval; 4951ffa5c63SVladimir Kondratyev s->nusage ++; 4961ffa5c63SVladimir Kondratyev } else { 4971ffa5c63SVladimir Kondratyev DPRINTFN(0, "max usage reached\n"); 4981ffa5c63SVladimir Kondratyev } 4991ffa5c63SVladimir Kondratyev 5001ffa5c63SVladimir Kondratyev /* clear any pending usage sets */ 5011ffa5c63SVladimir Kondratyev s->susage = 0; 5021ffa5c63SVladimir Kondratyev break; 5031ffa5c63SVladimir Kondratyev case 1: 5041ffa5c63SVladimir Kondratyev s->susage |= 1; 5051ffa5c63SVladimir Kondratyev 5061ffa5c63SVladimir Kondratyev if (bSize != 4) 507*38b67578SVladimir Kondratyev uval = (uval & mask) | c->_usage_page; 508*38b67578SVladimir Kondratyev c->usage_minimum = uval; 5091ffa5c63SVladimir Kondratyev 5101ffa5c63SVladimir Kondratyev goto check_set; 5111ffa5c63SVladimir Kondratyev case 2: 5121ffa5c63SVladimir Kondratyev s->susage |= 2; 5131ffa5c63SVladimir Kondratyev 5141ffa5c63SVladimir Kondratyev if (bSize != 4) 515*38b67578SVladimir Kondratyev uval = (uval & mask) | c->_usage_page; 516*38b67578SVladimir Kondratyev c->usage_maximum = uval; 5171ffa5c63SVladimir Kondratyev 5181ffa5c63SVladimir Kondratyev check_set: 5191ffa5c63SVladimir Kondratyev if (s->susage != 3) 5201ffa5c63SVladimir Kondratyev break; 5211ffa5c63SVladimir Kondratyev 5221ffa5c63SVladimir Kondratyev /* sanity check */ 5231ffa5c63SVladimir Kondratyev if ((s->nusage < MAXUSAGE) && 5241ffa5c63SVladimir Kondratyev (c->usage_minimum <= c->usage_maximum)) { 5251ffa5c63SVladimir Kondratyev /* add usage range */ 5261ffa5c63SVladimir Kondratyev s->usages_min[s->nusage] = 5271ffa5c63SVladimir Kondratyev c->usage_minimum; 5281ffa5c63SVladimir Kondratyev s->usages_max[s->nusage] = 5291ffa5c63SVladimir Kondratyev c->usage_maximum; 5301ffa5c63SVladimir Kondratyev s->nusage ++; 5311ffa5c63SVladimir Kondratyev } else { 5321ffa5c63SVladimir Kondratyev DPRINTFN(0, "Usage set dropped\n"); 5331ffa5c63SVladimir Kondratyev } 5341ffa5c63SVladimir Kondratyev s->susage = 0; 5351ffa5c63SVladimir Kondratyev break; 5361ffa5c63SVladimir Kondratyev case 3: 537*38b67578SVladimir Kondratyev c->designator_index = uval; 5381ffa5c63SVladimir Kondratyev break; 5391ffa5c63SVladimir Kondratyev case 4: 540*38b67578SVladimir Kondratyev c->designator_minimum = uval; 5411ffa5c63SVladimir Kondratyev break; 5421ffa5c63SVladimir Kondratyev case 5: 543*38b67578SVladimir Kondratyev c->designator_maximum = uval; 5441ffa5c63SVladimir Kondratyev break; 5451ffa5c63SVladimir Kondratyev case 7: 546*38b67578SVladimir Kondratyev c->string_index = uval; 5471ffa5c63SVladimir Kondratyev break; 5481ffa5c63SVladimir Kondratyev case 8: 549*38b67578SVladimir Kondratyev c->string_minimum = uval; 5501ffa5c63SVladimir Kondratyev break; 5511ffa5c63SVladimir Kondratyev case 9: 552*38b67578SVladimir Kondratyev c->string_maximum = uval; 5531ffa5c63SVladimir Kondratyev break; 5541ffa5c63SVladimir Kondratyev case 10: 555*38b67578SVladimir Kondratyev c->set_delimiter = uval; 5561ffa5c63SVladimir Kondratyev break; 5571ffa5c63SVladimir Kondratyev default: 5581ffa5c63SVladimir Kondratyev DPRINTFN(0, "Local bTag=%d\n", bTag); 5591ffa5c63SVladimir Kondratyev break; 5601ffa5c63SVladimir Kondratyev } 5611ffa5c63SVladimir Kondratyev break; 5621ffa5c63SVladimir Kondratyev default: 5631ffa5c63SVladimir Kondratyev DPRINTFN(0, "default bType=%d\n", bType); 5641ffa5c63SVladimir Kondratyev break; 5651ffa5c63SVladimir Kondratyev } 5661ffa5c63SVladimir Kondratyev } 5671ffa5c63SVladimir Kondratyev return (0); 5681ffa5c63SVladimir Kondratyev } 5691ffa5c63SVladimir Kondratyev 5701ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 5711ffa5c63SVladimir Kondratyev * hid_report_size 5721ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 5731ffa5c63SVladimir Kondratyev int 57419758786SVladimir Kondratyev hid_report_size(const void *buf, hid_size_t len, enum hid_kind k, uint8_t id) 57519758786SVladimir Kondratyev { 57619758786SVladimir Kondratyev struct hid_data *d; 57719758786SVladimir Kondratyev struct hid_item h; 57819758786SVladimir Kondratyev uint32_t temp; 57919758786SVladimir Kondratyev uint32_t hpos; 58019758786SVladimir Kondratyev uint32_t lpos; 58119758786SVladimir Kondratyev int report_id = 0; 58219758786SVladimir Kondratyev 58319758786SVladimir Kondratyev hpos = 0; 58419758786SVladimir Kondratyev lpos = 0xFFFFFFFF; 58519758786SVladimir Kondratyev 58619758786SVladimir Kondratyev for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { 58719758786SVladimir Kondratyev if (h.kind == k && h.report_ID == id) { 58819758786SVladimir Kondratyev /* compute minimum */ 58919758786SVladimir Kondratyev if (lpos > h.loc.pos) 59019758786SVladimir Kondratyev lpos = h.loc.pos; 59119758786SVladimir Kondratyev /* compute end position */ 59219758786SVladimir Kondratyev temp = h.loc.pos + (h.loc.size * h.loc.count); 59319758786SVladimir Kondratyev /* compute maximum */ 59419758786SVladimir Kondratyev if (hpos < temp) 59519758786SVladimir Kondratyev hpos = temp; 59619758786SVladimir Kondratyev if (h.report_ID != 0) 59719758786SVladimir Kondratyev report_id = 1; 59819758786SVladimir Kondratyev } 59919758786SVladimir Kondratyev } 60019758786SVladimir Kondratyev hid_end_parse(d); 60119758786SVladimir Kondratyev 60219758786SVladimir Kondratyev /* safety check - can happen in case of currupt descriptors */ 60319758786SVladimir Kondratyev if (lpos > hpos) 60419758786SVladimir Kondratyev temp = 0; 60519758786SVladimir Kondratyev else 60619758786SVladimir Kondratyev temp = hpos - lpos; 60719758786SVladimir Kondratyev 60819758786SVladimir Kondratyev /* return length in bytes rounded up */ 60919758786SVladimir Kondratyev return ((temp + 7) / 8 + report_id); 61019758786SVladimir Kondratyev } 61119758786SVladimir Kondratyev 61219758786SVladimir Kondratyev int 61319758786SVladimir Kondratyev hid_report_size_max(const void *buf, hid_size_t len, enum hid_kind k, 61419758786SVladimir Kondratyev uint8_t *id) 6151ffa5c63SVladimir Kondratyev { 6161ffa5c63SVladimir Kondratyev struct hid_data *d; 6171ffa5c63SVladimir Kondratyev struct hid_item h; 6181ffa5c63SVladimir Kondratyev uint32_t temp; 6191ffa5c63SVladimir Kondratyev uint32_t hpos; 6201ffa5c63SVladimir Kondratyev uint32_t lpos; 6211ffa5c63SVladimir Kondratyev uint8_t any_id; 6221ffa5c63SVladimir Kondratyev 6231ffa5c63SVladimir Kondratyev any_id = 0; 6241ffa5c63SVladimir Kondratyev hpos = 0; 6251ffa5c63SVladimir Kondratyev lpos = 0xFFFFFFFF; 6261ffa5c63SVladimir Kondratyev 6271ffa5c63SVladimir Kondratyev for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { 6281ffa5c63SVladimir Kondratyev if (h.kind == k) { 6291ffa5c63SVladimir Kondratyev /* check for ID-byte presence */ 6301ffa5c63SVladimir Kondratyev if ((h.report_ID != 0) && !any_id) { 6311ffa5c63SVladimir Kondratyev if (id != NULL) 6321ffa5c63SVladimir Kondratyev *id = h.report_ID; 6331ffa5c63SVladimir Kondratyev any_id = 1; 6341ffa5c63SVladimir Kondratyev } 6351ffa5c63SVladimir Kondratyev /* compute minimum */ 6361ffa5c63SVladimir Kondratyev if (lpos > h.loc.pos) 6371ffa5c63SVladimir Kondratyev lpos = h.loc.pos; 6381ffa5c63SVladimir Kondratyev /* compute end position */ 6391ffa5c63SVladimir Kondratyev temp = h.loc.pos + (h.loc.size * h.loc.count); 6401ffa5c63SVladimir Kondratyev /* compute maximum */ 6411ffa5c63SVladimir Kondratyev if (hpos < temp) 6421ffa5c63SVladimir Kondratyev hpos = temp; 6431ffa5c63SVladimir Kondratyev } 6441ffa5c63SVladimir Kondratyev } 6451ffa5c63SVladimir Kondratyev hid_end_parse(d); 6461ffa5c63SVladimir Kondratyev 6471ffa5c63SVladimir Kondratyev /* safety check - can happen in case of currupt descriptors */ 6481ffa5c63SVladimir Kondratyev if (lpos > hpos) 6491ffa5c63SVladimir Kondratyev temp = 0; 6501ffa5c63SVladimir Kondratyev else 6511ffa5c63SVladimir Kondratyev temp = hpos - lpos; 6521ffa5c63SVladimir Kondratyev 6531ffa5c63SVladimir Kondratyev /* check for ID byte */ 6541ffa5c63SVladimir Kondratyev if (any_id) 6551ffa5c63SVladimir Kondratyev temp += 8; 6561ffa5c63SVladimir Kondratyev else if (id != NULL) 6571ffa5c63SVladimir Kondratyev *id = 0; 6581ffa5c63SVladimir Kondratyev 6591ffa5c63SVladimir Kondratyev /* return length in bytes rounded up */ 6601ffa5c63SVladimir Kondratyev return ((temp + 7) / 8); 6611ffa5c63SVladimir Kondratyev } 6621ffa5c63SVladimir Kondratyev 6631ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 6641ffa5c63SVladimir Kondratyev * hid_locate 6651ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 6661ffa5c63SVladimir Kondratyev int 66719758786SVladimir Kondratyev hid_locate(const void *desc, hid_size_t size, int32_t u, enum hid_kind k, 6681ffa5c63SVladimir Kondratyev uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id) 6691ffa5c63SVladimir Kondratyev { 6701ffa5c63SVladimir Kondratyev struct hid_data *d; 6711ffa5c63SVladimir Kondratyev struct hid_item h; 6721ffa5c63SVladimir Kondratyev int i; 6731ffa5c63SVladimir Kondratyev 6741ffa5c63SVladimir Kondratyev for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) { 6751ffa5c63SVladimir Kondratyev for (i = 0; i < h.nusages; i++) { 6761ffa5c63SVladimir Kondratyev if (h.kind == k && h.usages[i] == u) { 6771ffa5c63SVladimir Kondratyev if (index--) 6781ffa5c63SVladimir Kondratyev break; 6791ffa5c63SVladimir Kondratyev if (loc != NULL) 6801ffa5c63SVladimir Kondratyev *loc = h.loc; 6811ffa5c63SVladimir Kondratyev if (flags != NULL) 6821ffa5c63SVladimir Kondratyev *flags = h.flags; 6831ffa5c63SVladimir Kondratyev if (id != NULL) 6841ffa5c63SVladimir Kondratyev *id = h.report_ID; 6851ffa5c63SVladimir Kondratyev hid_end_parse(d); 6861ffa5c63SVladimir Kondratyev return (1); 6871ffa5c63SVladimir Kondratyev } 6881ffa5c63SVladimir Kondratyev } 6891ffa5c63SVladimir Kondratyev } 6901ffa5c63SVladimir Kondratyev if (loc != NULL) 6911ffa5c63SVladimir Kondratyev loc->size = 0; 6921ffa5c63SVladimir Kondratyev if (flags != NULL) 6931ffa5c63SVladimir Kondratyev *flags = 0; 6941ffa5c63SVladimir Kondratyev if (id != NULL) 6951ffa5c63SVladimir Kondratyev *id = 0; 6961ffa5c63SVladimir Kondratyev hid_end_parse(d); 6971ffa5c63SVladimir Kondratyev return (0); 6981ffa5c63SVladimir Kondratyev } 6991ffa5c63SVladimir Kondratyev 7001ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 7011ffa5c63SVladimir Kondratyev * hid_get_data 7021ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 7031ffa5c63SVladimir Kondratyev static uint32_t 70419758786SVladimir Kondratyev hid_get_data_sub(const uint8_t *buf, hid_size_t len, struct hid_location *loc, 7051ffa5c63SVladimir Kondratyev int is_signed) 7061ffa5c63SVladimir Kondratyev { 7071ffa5c63SVladimir Kondratyev uint32_t hpos = loc->pos; 7081ffa5c63SVladimir Kondratyev uint32_t hsize = loc->size; 7091ffa5c63SVladimir Kondratyev uint32_t data; 7101ffa5c63SVladimir Kondratyev uint32_t rpos; 7111ffa5c63SVladimir Kondratyev uint8_t n; 7121ffa5c63SVladimir Kondratyev 7131ffa5c63SVladimir Kondratyev DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize); 7141ffa5c63SVladimir Kondratyev 7151ffa5c63SVladimir Kondratyev /* Range check and limit */ 7161ffa5c63SVladimir Kondratyev if (hsize == 0) 7171ffa5c63SVladimir Kondratyev return (0); 7181ffa5c63SVladimir Kondratyev if (hsize > 32) 7191ffa5c63SVladimir Kondratyev hsize = 32; 7201ffa5c63SVladimir Kondratyev 7211ffa5c63SVladimir Kondratyev /* Get data in a safe way */ 7221ffa5c63SVladimir Kondratyev data = 0; 7231ffa5c63SVladimir Kondratyev rpos = (hpos / 8); 7241ffa5c63SVladimir Kondratyev n = (hsize + 7) / 8; 7251ffa5c63SVladimir Kondratyev rpos += n; 7261ffa5c63SVladimir Kondratyev while (n--) { 7271ffa5c63SVladimir Kondratyev rpos--; 7281ffa5c63SVladimir Kondratyev if (rpos < len) 7291ffa5c63SVladimir Kondratyev data |= buf[rpos] << (8 * n); 7301ffa5c63SVladimir Kondratyev } 7311ffa5c63SVladimir Kondratyev 7321ffa5c63SVladimir Kondratyev /* Correctly shift down data */ 7331ffa5c63SVladimir Kondratyev data = (data >> (hpos % 8)); 7341ffa5c63SVladimir Kondratyev n = 32 - hsize; 7351ffa5c63SVladimir Kondratyev 7361ffa5c63SVladimir Kondratyev /* Mask and sign extend in one */ 7371ffa5c63SVladimir Kondratyev if (is_signed != 0) 7381ffa5c63SVladimir Kondratyev data = (int32_t)((int32_t)data << n) >> n; 7391ffa5c63SVladimir Kondratyev else 7401ffa5c63SVladimir Kondratyev data = (uint32_t)((uint32_t)data << n) >> n; 7411ffa5c63SVladimir Kondratyev 7421ffa5c63SVladimir Kondratyev DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n", 7431ffa5c63SVladimir Kondratyev loc->pos, loc->size, (long)data); 7441ffa5c63SVladimir Kondratyev return (data); 7451ffa5c63SVladimir Kondratyev } 7461ffa5c63SVladimir Kondratyev 7471ffa5c63SVladimir Kondratyev int32_t 74819758786SVladimir Kondratyev hid_get_data(const uint8_t *buf, hid_size_t len, struct hid_location *loc) 7491ffa5c63SVladimir Kondratyev { 7501ffa5c63SVladimir Kondratyev return (hid_get_data_sub(buf, len, loc, 1)); 7511ffa5c63SVladimir Kondratyev } 7521ffa5c63SVladimir Kondratyev 7531ffa5c63SVladimir Kondratyev uint32_t 75419758786SVladimir Kondratyev hid_get_udata(const uint8_t *buf, hid_size_t len, struct hid_location *loc) 7551ffa5c63SVladimir Kondratyev { 7561ffa5c63SVladimir Kondratyev return (hid_get_data_sub(buf, len, loc, 0)); 7571ffa5c63SVladimir Kondratyev } 7581ffa5c63SVladimir Kondratyev 7591ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 7601ffa5c63SVladimir Kondratyev * hid_put_data 7611ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 7621ffa5c63SVladimir Kondratyev void 76319758786SVladimir Kondratyev hid_put_udata(uint8_t *buf, hid_size_t len, 7641ffa5c63SVladimir Kondratyev struct hid_location *loc, unsigned int value) 7651ffa5c63SVladimir Kondratyev { 7661ffa5c63SVladimir Kondratyev uint32_t hpos = loc->pos; 7671ffa5c63SVladimir Kondratyev uint32_t hsize = loc->size; 7681ffa5c63SVladimir Kondratyev uint64_t data; 7691ffa5c63SVladimir Kondratyev uint64_t mask; 7701ffa5c63SVladimir Kondratyev uint32_t rpos; 7711ffa5c63SVladimir Kondratyev uint8_t n; 7721ffa5c63SVladimir Kondratyev 7731ffa5c63SVladimir Kondratyev DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value); 7741ffa5c63SVladimir Kondratyev 7751ffa5c63SVladimir Kondratyev /* Range check and limit */ 7761ffa5c63SVladimir Kondratyev if (hsize == 0) 7771ffa5c63SVladimir Kondratyev return; 7781ffa5c63SVladimir Kondratyev if (hsize > 32) 7791ffa5c63SVladimir Kondratyev hsize = 32; 7801ffa5c63SVladimir Kondratyev 7811ffa5c63SVladimir Kondratyev /* Put data in a safe way */ 7821ffa5c63SVladimir Kondratyev rpos = (hpos / 8); 7831ffa5c63SVladimir Kondratyev n = (hsize + 7) / 8; 7841ffa5c63SVladimir Kondratyev data = ((uint64_t)value) << (hpos % 8); 7851ffa5c63SVladimir Kondratyev mask = ((1ULL << hsize) - 1ULL) << (hpos % 8); 7861ffa5c63SVladimir Kondratyev rpos += n; 7871ffa5c63SVladimir Kondratyev while (n--) { 7881ffa5c63SVladimir Kondratyev rpos--; 7891ffa5c63SVladimir Kondratyev if (rpos < len) { 7901ffa5c63SVladimir Kondratyev buf[rpos] &= ~(mask >> (8 * n)); 7911ffa5c63SVladimir Kondratyev buf[rpos] |= (data >> (8 * n)); 7921ffa5c63SVladimir Kondratyev } 7931ffa5c63SVladimir Kondratyev } 7941ffa5c63SVladimir Kondratyev } 7951ffa5c63SVladimir Kondratyev 7961ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 7971ffa5c63SVladimir Kondratyev * hid_is_collection 7981ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 7991ffa5c63SVladimir Kondratyev int 80019758786SVladimir Kondratyev hid_is_collection(const void *desc, hid_size_t size, int32_t usage) 8011ffa5c63SVladimir Kondratyev { 8021ffa5c63SVladimir Kondratyev struct hid_data *hd; 8031ffa5c63SVladimir Kondratyev struct hid_item hi; 8041ffa5c63SVladimir Kondratyev int err; 8051ffa5c63SVladimir Kondratyev 8066ed3b9caSHu Shunchao hd = hid_start_parse(desc, size, 0); 8071ffa5c63SVladimir Kondratyev if (hd == NULL) 8081ffa5c63SVladimir Kondratyev return (0); 8091ffa5c63SVladimir Kondratyev 8101ffa5c63SVladimir Kondratyev while ((err = hid_get_item(hd, &hi))) { 8111ffa5c63SVladimir Kondratyev if (hi.kind == hid_collection && 8121ffa5c63SVladimir Kondratyev hi.usage == usage) 8131ffa5c63SVladimir Kondratyev break; 8141ffa5c63SVladimir Kondratyev } 8151ffa5c63SVladimir Kondratyev hid_end_parse(hd); 8161ffa5c63SVladimir Kondratyev return (err); 8171ffa5c63SVladimir Kondratyev } 8181ffa5c63SVladimir Kondratyev 8191ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 8201ffa5c63SVladimir Kondratyev * calculate HID item resolution. unit/mm for distances, unit/rad for angles 8211ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 8221ffa5c63SVladimir Kondratyev int32_t 8231ffa5c63SVladimir Kondratyev hid_item_resolution(struct hid_item *hi) 8241ffa5c63SVladimir Kondratyev { 8251ffa5c63SVladimir Kondratyev /* 8261ffa5c63SVladimir Kondratyev * hid unit scaling table according to HID Usage Table Review 8271ffa5c63SVladimir Kondratyev * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf 8281ffa5c63SVladimir Kondratyev */ 8291ffa5c63SVladimir Kondratyev static const int64_t scale[0x10][2] = { 8301ffa5c63SVladimir Kondratyev [0x00] = { 1, 1 }, 8311ffa5c63SVladimir Kondratyev [0x01] = { 1, 10 }, 8321ffa5c63SVladimir Kondratyev [0x02] = { 1, 100 }, 8331ffa5c63SVladimir Kondratyev [0x03] = { 1, 1000 }, 8341ffa5c63SVladimir Kondratyev [0x04] = { 1, 10000 }, 8351ffa5c63SVladimir Kondratyev [0x05] = { 1, 100000 }, 8361ffa5c63SVladimir Kondratyev [0x06] = { 1, 1000000 }, 8371ffa5c63SVladimir Kondratyev [0x07] = { 1, 10000000 }, 8381ffa5c63SVladimir Kondratyev [0x08] = { 100000000, 1 }, 8391ffa5c63SVladimir Kondratyev [0x09] = { 10000000, 1 }, 8401ffa5c63SVladimir Kondratyev [0x0A] = { 1000000, 1 }, 8411ffa5c63SVladimir Kondratyev [0x0B] = { 100000, 1 }, 8421ffa5c63SVladimir Kondratyev [0x0C] = { 10000, 1 }, 8431ffa5c63SVladimir Kondratyev [0x0D] = { 1000, 1 }, 8441ffa5c63SVladimir Kondratyev [0x0E] = { 100, 1 }, 8451ffa5c63SVladimir Kondratyev [0x0F] = { 10, 1 }, 8461ffa5c63SVladimir Kondratyev }; 8471ffa5c63SVladimir Kondratyev int64_t logical_size; 8481ffa5c63SVladimir Kondratyev int64_t physical_size; 8491ffa5c63SVladimir Kondratyev int64_t multiplier; 8501ffa5c63SVladimir Kondratyev int64_t divisor; 8511ffa5c63SVladimir Kondratyev int64_t resolution; 8521ffa5c63SVladimir Kondratyev 8531ffa5c63SVladimir Kondratyev switch (hi->unit) { 8541ffa5c63SVladimir Kondratyev case HUM_CENTIMETER: 8551ffa5c63SVladimir Kondratyev multiplier = 1; 8561ffa5c63SVladimir Kondratyev divisor = 10; 8571ffa5c63SVladimir Kondratyev break; 8581ffa5c63SVladimir Kondratyev case HUM_INCH: 859be75951aSVladimir Kondratyev case HUM_INCH_EGALAX: 8601ffa5c63SVladimir Kondratyev multiplier = 10; 8611ffa5c63SVladimir Kondratyev divisor = 254; 8621ffa5c63SVladimir Kondratyev break; 8631ffa5c63SVladimir Kondratyev case HUM_RADIAN: 8641ffa5c63SVladimir Kondratyev multiplier = 1; 8651ffa5c63SVladimir Kondratyev divisor = 1; 8661ffa5c63SVladimir Kondratyev break; 8671ffa5c63SVladimir Kondratyev case HUM_DEGREE: 8681ffa5c63SVladimir Kondratyev multiplier = 573; 8691ffa5c63SVladimir Kondratyev divisor = 10; 8701ffa5c63SVladimir Kondratyev break; 8711ffa5c63SVladimir Kondratyev default: 8721ffa5c63SVladimir Kondratyev return (0); 8731ffa5c63SVladimir Kondratyev } 8741ffa5c63SVladimir Kondratyev 8751ffa5c63SVladimir Kondratyev if ((hi->logical_maximum <= hi->logical_minimum) || 8761ffa5c63SVladimir Kondratyev (hi->physical_maximum <= hi->physical_minimum) || 8771ffa5c63SVladimir Kondratyev (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale))) 8781ffa5c63SVladimir Kondratyev return (0); 8791ffa5c63SVladimir Kondratyev 8801ffa5c63SVladimir Kondratyev logical_size = (int64_t)hi->logical_maximum - 8811ffa5c63SVladimir Kondratyev (int64_t)hi->logical_minimum; 8821ffa5c63SVladimir Kondratyev physical_size = (int64_t)hi->physical_maximum - 8831ffa5c63SVladimir Kondratyev (int64_t)hi->physical_minimum; 8841ffa5c63SVladimir Kondratyev /* Round to ceiling */ 8851ffa5c63SVladimir Kondratyev resolution = logical_size * multiplier * scale[hi->unit_exponent][0] / 8861ffa5c63SVladimir Kondratyev (physical_size * divisor * scale[hi->unit_exponent][1]); 8871ffa5c63SVladimir Kondratyev 8881ffa5c63SVladimir Kondratyev if (resolution > INT32_MAX) 8891ffa5c63SVladimir Kondratyev return (0); 8901ffa5c63SVladimir Kondratyev 8911ffa5c63SVladimir Kondratyev return (resolution); 8921ffa5c63SVladimir Kondratyev } 8931ffa5c63SVladimir Kondratyev 8941ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 8951ffa5c63SVladimir Kondratyev * hid_is_mouse 8961ffa5c63SVladimir Kondratyev * 8971ffa5c63SVladimir Kondratyev * This function will decide if a USB descriptor belongs to a USB mouse. 8981ffa5c63SVladimir Kondratyev * 8991ffa5c63SVladimir Kondratyev * Return values: 9001ffa5c63SVladimir Kondratyev * Zero: Not a USB mouse. 9011ffa5c63SVladimir Kondratyev * Else: Is a USB mouse. 9021ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 9031ffa5c63SVladimir Kondratyev int 9041ffa5c63SVladimir Kondratyev hid_is_mouse(const void *d_ptr, uint16_t d_len) 9051ffa5c63SVladimir Kondratyev { 9061ffa5c63SVladimir Kondratyev struct hid_data *hd; 9071ffa5c63SVladimir Kondratyev struct hid_item hi; 9081ffa5c63SVladimir Kondratyev int mdepth; 9091ffa5c63SVladimir Kondratyev int found; 9101ffa5c63SVladimir Kondratyev 9111ffa5c63SVladimir Kondratyev hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 9121ffa5c63SVladimir Kondratyev if (hd == NULL) 9131ffa5c63SVladimir Kondratyev return (0); 9141ffa5c63SVladimir Kondratyev 9151ffa5c63SVladimir Kondratyev mdepth = 0; 9161ffa5c63SVladimir Kondratyev found = 0; 9171ffa5c63SVladimir Kondratyev 9181ffa5c63SVladimir Kondratyev while (hid_get_item(hd, &hi)) { 9191ffa5c63SVladimir Kondratyev switch (hi.kind) { 9201ffa5c63SVladimir Kondratyev case hid_collection: 9211ffa5c63SVladimir Kondratyev if (mdepth != 0) 9221ffa5c63SVladimir Kondratyev mdepth++; 9231ffa5c63SVladimir Kondratyev else if (hi.collection == 1 && 9241ffa5c63SVladimir Kondratyev hi.usage == 9251ffa5c63SVladimir Kondratyev HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) 9261ffa5c63SVladimir Kondratyev mdepth++; 9271ffa5c63SVladimir Kondratyev break; 9281ffa5c63SVladimir Kondratyev case hid_endcollection: 9291ffa5c63SVladimir Kondratyev if (mdepth != 0) 9301ffa5c63SVladimir Kondratyev mdepth--; 9311ffa5c63SVladimir Kondratyev break; 9321ffa5c63SVladimir Kondratyev case hid_input: 9331ffa5c63SVladimir Kondratyev if (mdepth == 0) 9341ffa5c63SVladimir Kondratyev break; 9351ffa5c63SVladimir Kondratyev if (hi.usage == 9361ffa5c63SVladimir Kondratyev HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && 9371ffa5c63SVladimir Kondratyev (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) 9381ffa5c63SVladimir Kondratyev found++; 9391ffa5c63SVladimir Kondratyev if (hi.usage == 9401ffa5c63SVladimir Kondratyev HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && 9411ffa5c63SVladimir Kondratyev (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) 9421ffa5c63SVladimir Kondratyev found++; 9431ffa5c63SVladimir Kondratyev break; 9441ffa5c63SVladimir Kondratyev default: 9451ffa5c63SVladimir Kondratyev break; 9461ffa5c63SVladimir Kondratyev } 9471ffa5c63SVladimir Kondratyev } 9481ffa5c63SVladimir Kondratyev hid_end_parse(hd); 9491ffa5c63SVladimir Kondratyev return (found); 9501ffa5c63SVladimir Kondratyev } 9511ffa5c63SVladimir Kondratyev 9521ffa5c63SVladimir Kondratyev /*------------------------------------------------------------------------* 9531ffa5c63SVladimir Kondratyev * hid_is_keyboard 9541ffa5c63SVladimir Kondratyev * 9551ffa5c63SVladimir Kondratyev * This function will decide if a USB descriptor belongs to a USB keyboard. 9561ffa5c63SVladimir Kondratyev * 9571ffa5c63SVladimir Kondratyev * Return values: 9581ffa5c63SVladimir Kondratyev * Zero: Not a USB keyboard. 9591ffa5c63SVladimir Kondratyev * Else: Is a USB keyboard. 9601ffa5c63SVladimir Kondratyev *------------------------------------------------------------------------*/ 9611ffa5c63SVladimir Kondratyev int 9621ffa5c63SVladimir Kondratyev hid_is_keyboard(const void *d_ptr, uint16_t d_len) 9631ffa5c63SVladimir Kondratyev { 9641ffa5c63SVladimir Kondratyev if (hid_is_collection(d_ptr, d_len, 9651ffa5c63SVladimir Kondratyev HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) 9661ffa5c63SVladimir Kondratyev return (1); 9671ffa5c63SVladimir Kondratyev return (0); 9681ffa5c63SVladimir Kondratyev } 96967de2db2SVladimir Kondratyev 97019758786SVladimir Kondratyev /*------------------------------------------------------------------------* 97119758786SVladimir Kondratyev * hid_test_quirk - test a device for a given quirk 97219758786SVladimir Kondratyev * 97319758786SVladimir Kondratyev * Return values: 97419758786SVladimir Kondratyev * false: The HID device does not have the given quirk. 97519758786SVladimir Kondratyev * true: The HID device has the given quirk. 97619758786SVladimir Kondratyev *------------------------------------------------------------------------*/ 97719758786SVladimir Kondratyev bool 97819758786SVladimir Kondratyev hid_test_quirk(const struct hid_device_info *dev_info, uint16_t quirk) 97919758786SVladimir Kondratyev { 98019758786SVladimir Kondratyev bool found; 98119758786SVladimir Kondratyev uint8_t x; 98219758786SVladimir Kondratyev 98319758786SVladimir Kondratyev if (quirk == HQ_NONE) 98419758786SVladimir Kondratyev return (false); 98519758786SVladimir Kondratyev 98619758786SVladimir Kondratyev /* search the automatic per device quirks first */ 98719758786SVladimir Kondratyev for (x = 0; x != HID_MAX_AUTO_QUIRK; x++) { 98819758786SVladimir Kondratyev if (dev_info->autoQuirk[x] == quirk) 98919758786SVladimir Kondratyev return (true); 99019758786SVladimir Kondratyev } 99119758786SVladimir Kondratyev 99219758786SVladimir Kondratyev /* search global quirk table, if any */ 99319758786SVladimir Kondratyev found = (hid_test_quirk_p) (dev_info, quirk); 99419758786SVladimir Kondratyev 99519758786SVladimir Kondratyev return (found); 99619758786SVladimir Kondratyev } 99719758786SVladimir Kondratyev 99819758786SVladimir Kondratyev static bool 99919758786SVladimir Kondratyev hid_test_quirk_w(const struct hid_device_info *dev_info, uint16_t quirk) 100019758786SVladimir Kondratyev { 100119758786SVladimir Kondratyev return (false); /* no match */ 100219758786SVladimir Kondratyev } 100319758786SVladimir Kondratyev 100419758786SVladimir Kondratyev int 100519758786SVladimir Kondratyev hid_add_dynamic_quirk(struct hid_device_info *dev_info, uint16_t quirk) 100619758786SVladimir Kondratyev { 100719758786SVladimir Kondratyev uint8_t x; 100819758786SVladimir Kondratyev 100919758786SVladimir Kondratyev for (x = 0; x != HID_MAX_AUTO_QUIRK; x++) { 101019758786SVladimir Kondratyev if (dev_info->autoQuirk[x] == 0 || 101119758786SVladimir Kondratyev dev_info->autoQuirk[x] == quirk) { 101219758786SVladimir Kondratyev dev_info->autoQuirk[x] = quirk; 101319758786SVladimir Kondratyev return (0); /* success */ 101419758786SVladimir Kondratyev } 101519758786SVladimir Kondratyev } 101619758786SVladimir Kondratyev return (ENOSPC); 101719758786SVladimir Kondratyev } 101819758786SVladimir Kondratyev 101919758786SVladimir Kondratyev void 102019758786SVladimir Kondratyev hid_quirk_unload(void *arg) 102119758786SVladimir Kondratyev { 102219758786SVladimir Kondratyev /* reset function pointer */ 102319758786SVladimir Kondratyev hid_test_quirk_p = &hid_test_quirk_w; 102419758786SVladimir Kondratyev #ifdef NOT_YET 102519758786SVladimir Kondratyev hidquirk_ioctl_p = &hidquirk_ioctl_w; 102619758786SVladimir Kondratyev #endif 102719758786SVladimir Kondratyev 102819758786SVladimir Kondratyev /* wait for CPU to exit the loaded functions, if any */ 102919758786SVladimir Kondratyev 103019758786SVladimir Kondratyev /* XXX this is a tradeoff */ 103119758786SVladimir Kondratyev 103219758786SVladimir Kondratyev pause("WAIT", hz); 103319758786SVladimir Kondratyev } 103419758786SVladimir Kondratyev 1035961a3535SVladimir Kondratyev int 10364151ac9fSVladimir Kondratyev hid_intr_start(device_t dev) 10374151ac9fSVladimir Kondratyev { 10384151ac9fSVladimir Kondratyev return (HID_INTR_START(device_get_parent(dev), dev)); 10394151ac9fSVladimir Kondratyev } 10404151ac9fSVladimir Kondratyev 10414151ac9fSVladimir Kondratyev int 10424151ac9fSVladimir Kondratyev hid_intr_stop(device_t dev) 10434151ac9fSVladimir Kondratyev { 10444151ac9fSVladimir Kondratyev return (HID_INTR_STOP(device_get_parent(dev), dev)); 10454151ac9fSVladimir Kondratyev } 10464151ac9fSVladimir Kondratyev 10474151ac9fSVladimir Kondratyev void 10484151ac9fSVladimir Kondratyev hid_intr_poll(device_t dev) 10494151ac9fSVladimir Kondratyev { 10504151ac9fSVladimir Kondratyev HID_INTR_POLL(device_get_parent(dev), dev); 10514151ac9fSVladimir Kondratyev } 10524151ac9fSVladimir Kondratyev 10534151ac9fSVladimir Kondratyev int 1054961a3535SVladimir Kondratyev hid_get_rdesc(device_t dev, void *data, hid_size_t len) 1055961a3535SVladimir Kondratyev { 10564b171281SVladimir Kondratyev return (HID_GET_RDESC(device_get_parent(dev), dev, data, len)); 1057961a3535SVladimir Kondratyev } 1058961a3535SVladimir Kondratyev 1059961a3535SVladimir Kondratyev int 1060961a3535SVladimir Kondratyev hid_read(device_t dev, void *data, hid_size_t maxlen, hid_size_t *actlen) 1061961a3535SVladimir Kondratyev { 10624b171281SVladimir Kondratyev return (HID_READ(device_get_parent(dev), dev, data, maxlen, actlen)); 1063961a3535SVladimir Kondratyev } 1064961a3535SVladimir Kondratyev 1065961a3535SVladimir Kondratyev int 1066961a3535SVladimir Kondratyev hid_write(device_t dev, const void *data, hid_size_t len) 1067961a3535SVladimir Kondratyev { 10684b171281SVladimir Kondratyev return (HID_WRITE(device_get_parent(dev), dev, data, len)); 1069961a3535SVladimir Kondratyev } 1070961a3535SVladimir Kondratyev 1071961a3535SVladimir Kondratyev int 1072961a3535SVladimir Kondratyev hid_get_report(device_t dev, void *data, hid_size_t maxlen, hid_size_t *actlen, 1073961a3535SVladimir Kondratyev uint8_t type, uint8_t id) 1074961a3535SVladimir Kondratyev { 10754b171281SVladimir Kondratyev return (HID_GET_REPORT(device_get_parent(dev), dev, data, maxlen, 10764b171281SVladimir Kondratyev actlen, type, id)); 1077961a3535SVladimir Kondratyev } 1078961a3535SVladimir Kondratyev 1079961a3535SVladimir Kondratyev int 1080961a3535SVladimir Kondratyev hid_set_report(device_t dev, const void *data, hid_size_t len, uint8_t type, 1081961a3535SVladimir Kondratyev uint8_t id) 1082961a3535SVladimir Kondratyev { 10834b171281SVladimir Kondratyev return (HID_SET_REPORT(device_get_parent(dev), dev, data, len, type, 10844b171281SVladimir Kondratyev id)); 1085961a3535SVladimir Kondratyev } 1086961a3535SVladimir Kondratyev 1087961a3535SVladimir Kondratyev int 1088961a3535SVladimir Kondratyev hid_set_idle(device_t dev, uint16_t duration, uint8_t id) 1089961a3535SVladimir Kondratyev { 10904b171281SVladimir Kondratyev return (HID_SET_IDLE(device_get_parent(dev), dev, duration, id)); 1091961a3535SVladimir Kondratyev } 1092961a3535SVladimir Kondratyev 1093961a3535SVladimir Kondratyev int 1094961a3535SVladimir Kondratyev hid_set_protocol(device_t dev, uint16_t protocol) 1095961a3535SVladimir Kondratyev { 10964b171281SVladimir Kondratyev return (HID_SET_PROTOCOL(device_get_parent(dev), dev, protocol)); 1097961a3535SVladimir Kondratyev } 1098961a3535SVladimir Kondratyev 10995f47c5a3SVladimir Kondratyev int 11005f47c5a3SVladimir Kondratyev hid_ioctl(device_t dev, unsigned long cmd, uintptr_t data) 11015f47c5a3SVladimir Kondratyev { 11024b171281SVladimir Kondratyev return (HID_IOCTL(device_get_parent(dev), dev, cmd, data)); 11035f47c5a3SVladimir Kondratyev } 11045f47c5a3SVladimir Kondratyev 110567de2db2SVladimir Kondratyev MODULE_VERSION(hid, 1); 1106