usb_hid.c revision 361919
1/* $FreeBSD: stable/11/sys/dev/usb/usb_hid.c 361919 2020-06-08 09:33:37Z hselasky $ */ 2/* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */ 3/*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#ifdef USB_GLOBAL_INCLUDE_FILE 34#include USB_GLOBAL_INCLUDE_FILE 35#else 36#include <sys/stdint.h> 37#include <sys/stddef.h> 38#include <sys/param.h> 39#include <sys/queue.h> 40#include <sys/types.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43#include <sys/bus.h> 44#include <sys/module.h> 45#include <sys/lock.h> 46#include <sys/mutex.h> 47#include <sys/condvar.h> 48#include <sys/sysctl.h> 49#include <sys/sx.h> 50#include <sys/unistd.h> 51#include <sys/callout.h> 52#include <sys/malloc.h> 53#include <sys/priv.h> 54 55#include <dev/usb/usb.h> 56#include <dev/usb/usbdi.h> 57#include <dev/usb/usbdi_util.h> 58#include <dev/usb/usbhid.h> 59 60#define USB_DEBUG_VAR usb_debug 61 62#include <dev/usb/usb_core.h> 63#include <dev/usb/usb_debug.h> 64#include <dev/usb/usb_process.h> 65#include <dev/usb/usb_device.h> 66#include <dev/usb/usb_request.h> 67#endif /* USB_GLOBAL_INCLUDE_FILE */ 68 69static void hid_clear_local(struct hid_item *); 70static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize); 71 72#define MAXUSAGE 64 73#define MAXPUSH 4 74#define MAXID 16 75#define MAXLOCCNT 1024 76 77struct hid_pos_data { 78 int32_t rid; 79 uint32_t pos; 80}; 81 82struct hid_data { 83 const uint8_t *start; 84 const uint8_t *end; 85 const uint8_t *p; 86 struct hid_item cur[MAXPUSH]; 87 struct hid_pos_data last_pos[MAXID]; 88 int32_t usages_min[MAXUSAGE]; 89 int32_t usages_max[MAXUSAGE]; 90 int32_t usage_last; /* last seen usage */ 91 uint32_t loc_size; /* last seen size */ 92 uint32_t loc_count; /* last seen count */ 93 uint32_t ncount; /* end usage item count */ 94 uint32_t icount; /* current usage item count */ 95 uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ 96 uint8_t pushlevel; /* current pushlevel */ 97 uint8_t nusage; /* end "usages_min/max" index */ 98 uint8_t iusage; /* current "usages_min/max" index */ 99 uint8_t ousage; /* current "usages_min/max" offset */ 100 uint8_t susage; /* usage set flags */ 101}; 102 103/*------------------------------------------------------------------------* 104 * hid_clear_local 105 *------------------------------------------------------------------------*/ 106static void 107hid_clear_local(struct hid_item *c) 108{ 109 110 c->loc.count = 0; 111 c->loc.size = 0; 112 c->usage = 0; 113 c->usage_minimum = 0; 114 c->usage_maximum = 0; 115 c->designator_index = 0; 116 c->designator_minimum = 0; 117 c->designator_maximum = 0; 118 c->string_index = 0; 119 c->string_minimum = 0; 120 c->string_maximum = 0; 121 c->set_delimiter = 0; 122} 123 124static void 125hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) 126{ 127 uint8_t i; 128 129 /* check for same report ID - optimise */ 130 131 if (c->report_ID == next_rID) 132 return; 133 134 /* save current position for current rID */ 135 136 if (c->report_ID == 0) { 137 i = 0; 138 } else { 139 for (i = 1; i != MAXID; i++) { 140 if (s->last_pos[i].rid == c->report_ID) 141 break; 142 if (s->last_pos[i].rid == 0) 143 break; 144 } 145 } 146 if (i != MAXID) { 147 s->last_pos[i].rid = c->report_ID; 148 s->last_pos[i].pos = c->loc.pos; 149 } 150 151 /* store next report ID */ 152 153 c->report_ID = next_rID; 154 155 /* lookup last position for next rID */ 156 157 if (next_rID == 0) { 158 i = 0; 159 } else { 160 for (i = 1; i != MAXID; i++) { 161 if (s->last_pos[i].rid == next_rID) 162 break; 163 if (s->last_pos[i].rid == 0) 164 break; 165 } 166 } 167 if (i != MAXID) { 168 s->last_pos[i].rid = next_rID; 169 c->loc.pos = s->last_pos[i].pos; 170 } else { 171 DPRINTF("Out of RID entries, position is set to zero!\n"); 172 c->loc.pos = 0; 173 } 174} 175 176/*------------------------------------------------------------------------* 177 * hid_start_parse 178 *------------------------------------------------------------------------*/ 179struct hid_data * 180hid_start_parse(const void *d, usb_size_t len, int kindset) 181{ 182 struct hid_data *s; 183 184 if ((kindset-1) & kindset) { 185 DPRINTFN(0, "Only one bit can be " 186 "set in the kindset\n"); 187 return (NULL); 188 } 189 190 s = malloc(sizeof *s, M_TEMP, M_WAITOK | M_ZERO); 191 s->start = s->p = d; 192 s->end = ((const uint8_t *)d) + len; 193 s->kindset = kindset; 194 return (s); 195} 196 197/*------------------------------------------------------------------------* 198 * hid_end_parse 199 *------------------------------------------------------------------------*/ 200void 201hid_end_parse(struct hid_data *s) 202{ 203 if (s == NULL) 204 return; 205 206 free(s, M_TEMP); 207} 208 209/*------------------------------------------------------------------------* 210 * get byte from HID descriptor 211 *------------------------------------------------------------------------*/ 212static uint8_t 213hid_get_byte(struct hid_data *s, const uint16_t wSize) 214{ 215 const uint8_t *ptr; 216 uint8_t retval; 217 218 ptr = s->p; 219 220 /* check if end is reached */ 221 if (ptr == s->end) 222 return (0); 223 224 /* read out a byte */ 225 retval = *ptr; 226 227 /* check if data pointer can be advanced by "wSize" bytes */ 228 if ((s->end - ptr) < wSize) 229 ptr = s->end; 230 else 231 ptr += wSize; 232 233 /* update pointer */ 234 s->p = ptr; 235 236 return (retval); 237} 238 239/*------------------------------------------------------------------------* 240 * hid_get_item 241 *------------------------------------------------------------------------*/ 242int 243hid_get_item(struct hid_data *s, struct hid_item *h) 244{ 245 struct hid_item *c; 246 unsigned int bTag, bType, bSize; 247 uint32_t oldpos; 248 int32_t mask; 249 int32_t dval; 250 251 if (s == NULL) 252 return (0); 253 254 c = &s->cur[s->pushlevel]; 255 256 top: 257 /* check if there is an array of items */ 258 if (s->icount < s->ncount) { 259 /* get current usage */ 260 if (s->iusage < s->nusage) { 261 dval = s->usages_min[s->iusage] + s->ousage; 262 c->usage = dval; 263 s->usage_last = dval; 264 if (dval == s->usages_max[s->iusage]) { 265 s->iusage ++; 266 s->ousage = 0; 267 } else { 268 s->ousage ++; 269 } 270 } else { 271 DPRINTFN(1, "Using last usage\n"); 272 dval = s->usage_last; 273 } 274 s->icount ++; 275 /* 276 * Only copy HID item, increment position and return 277 * if correct kindset! 278 */ 279 if (s->kindset & (1 << c->kind)) { 280 *h = *c; 281 DPRINTFN(1, "%u,%u,%u\n", h->loc.pos, 282 h->loc.size, h->loc.count); 283 c->loc.pos += c->loc.size * c->loc.count; 284 return (1); 285 } 286 } 287 288 /* reset state variables */ 289 s->icount = 0; 290 s->ncount = 0; 291 s->iusage = 0; 292 s->nusage = 0; 293 s->susage = 0; 294 s->ousage = 0; 295 hid_clear_local(c); 296 297 /* get next item */ 298 while (s->p != s->end) { 299 300 bSize = hid_get_byte(s, 1); 301 if (bSize == 0xfe) { 302 /* long item */ 303 bSize = hid_get_byte(s, 1); 304 bSize |= hid_get_byte(s, 1) << 8; 305 bTag = hid_get_byte(s, 1); 306 bType = 0xff; /* XXX what should it be */ 307 } else { 308 /* short item */ 309 bTag = bSize >> 4; 310 bType = (bSize >> 2) & 3; 311 bSize &= 3; 312 if (bSize == 3) 313 bSize = 4; 314 } 315 switch (bSize) { 316 case 0: 317 dval = 0; 318 mask = 0; 319 break; 320 case 1: 321 dval = (int8_t)hid_get_byte(s, 1); 322 mask = 0xFF; 323 break; 324 case 2: 325 dval = hid_get_byte(s, 1); 326 dval |= hid_get_byte(s, 1) << 8; 327 dval = (int16_t)dval; 328 mask = 0xFFFF; 329 break; 330 case 4: 331 dval = hid_get_byte(s, 1); 332 dval |= hid_get_byte(s, 1) << 8; 333 dval |= hid_get_byte(s, 1) << 16; 334 dval |= hid_get_byte(s, 1) << 24; 335 mask = 0xFFFFFFFF; 336 break; 337 default: 338 dval = hid_get_byte(s, bSize); 339 DPRINTFN(0, "bad length %u (data=0x%02x)\n", 340 bSize, dval); 341 continue; 342 } 343 344 switch (bType) { 345 case 0: /* Main */ 346 switch (bTag) { 347 case 8: /* Input */ 348 c->kind = hid_input; 349 ret: 350 c->flags = dval; 351 c->loc.count = s->loc_count; 352 c->loc.size = s->loc_size; 353 354 if (c->flags & HIO_VARIABLE) { 355 /* range check usage count */ 356 if (c->loc.count > MAXLOCCNT) { 357 DPRINTFN(0, "Number of " 358 "items(%u) truncated to %u\n", 359 (unsigned)(c->loc.count), 360 MAXLOCCNT); 361 s->ncount = MAXLOCCNT; 362 } else 363 s->ncount = c->loc.count; 364 365 /* 366 * The "top" loop will return 367 * one and one item: 368 */ 369 c->loc.count = 1; 370 } else { 371 s->ncount = 1; 372 } 373 goto top; 374 375 case 9: /* Output */ 376 c->kind = hid_output; 377 goto ret; 378 case 10: /* Collection */ 379 c->kind = hid_collection; 380 c->collection = dval; 381 c->collevel++; 382 c->usage = s->usage_last; 383 *h = *c; 384 return (1); 385 case 11: /* Feature */ 386 c->kind = hid_feature; 387 goto ret; 388 case 12: /* End collection */ 389 c->kind = hid_endcollection; 390 if (c->collevel == 0) { 391 DPRINTFN(0, "invalid end collection\n"); 392 return (0); 393 } 394 c->collevel--; 395 *h = *c; 396 return (1); 397 default: 398 DPRINTFN(0, "Main bTag=%d\n", bTag); 399 break; 400 } 401 break; 402 case 1: /* Global */ 403 switch (bTag) { 404 case 0: 405 c->_usage_page = dval << 16; 406 break; 407 case 1: 408 c->logical_minimum = dval; 409 break; 410 case 2: 411 c->logical_maximum = dval; 412 break; 413 case 3: 414 c->physical_minimum = dval; 415 break; 416 case 4: 417 c->physical_maximum = dval; 418 break; 419 case 5: 420 c->unit_exponent = dval; 421 break; 422 case 6: 423 c->unit = dval; 424 break; 425 case 7: 426 /* mask because value is unsigned */ 427 s->loc_size = dval & mask; 428 break; 429 case 8: 430 hid_switch_rid(s, c, dval & mask); 431 break; 432 case 9: 433 /* mask because value is unsigned */ 434 s->loc_count = dval & mask; 435 break; 436 case 10: /* Push */ 437 /* stop parsing, if invalid push level */ 438 if ((s->pushlevel + 1) >= MAXPUSH) { 439 DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel); 440 return (0); 441 } 442 s->pushlevel ++; 443 s->cur[s->pushlevel] = *c; 444 /* store size and count */ 445 c->loc.size = s->loc_size; 446 c->loc.count = s->loc_count; 447 /* update current item pointer */ 448 c = &s->cur[s->pushlevel]; 449 break; 450 case 11: /* Pop */ 451 /* stop parsing, if invalid push level */ 452 if (s->pushlevel == 0) { 453 DPRINTFN(0, "Cannot pop item @ 0\n"); 454 return (0); 455 } 456 s->pushlevel --; 457 /* preserve position */ 458 oldpos = c->loc.pos; 459 c = &s->cur[s->pushlevel]; 460 /* restore size and count */ 461 s->loc_size = c->loc.size; 462 s->loc_count = c->loc.count; 463 /* set default item location */ 464 c->loc.pos = oldpos; 465 c->loc.size = 0; 466 c->loc.count = 0; 467 break; 468 default: 469 DPRINTFN(0, "Global bTag=%d\n", bTag); 470 break; 471 } 472 break; 473 case 2: /* Local */ 474 switch (bTag) { 475 case 0: 476 if (bSize != 4) 477 dval = (dval & mask) | c->_usage_page; 478 479 /* set last usage, in case of a collection */ 480 s->usage_last = dval; 481 482 if (s->nusage < MAXUSAGE) { 483 s->usages_min[s->nusage] = dval; 484 s->usages_max[s->nusage] = dval; 485 s->nusage ++; 486 } else { 487 DPRINTFN(0, "max usage reached\n"); 488 } 489 490 /* clear any pending usage sets */ 491 s->susage = 0; 492 break; 493 case 1: 494 s->susage |= 1; 495 496 if (bSize != 4) 497 dval = (dval & mask) | c->_usage_page; 498 c->usage_minimum = dval; 499 500 goto check_set; 501 case 2: 502 s->susage |= 2; 503 504 if (bSize != 4) 505 dval = (dval & mask) | c->_usage_page; 506 c->usage_maximum = dval; 507 508 check_set: 509 if (s->susage != 3) 510 break; 511 512 /* sanity check */ 513 if ((s->nusage < MAXUSAGE) && 514 (c->usage_minimum <= c->usage_maximum)) { 515 /* add usage range */ 516 s->usages_min[s->nusage] = 517 c->usage_minimum; 518 s->usages_max[s->nusage] = 519 c->usage_maximum; 520 s->nusage ++; 521 } else { 522 DPRINTFN(0, "Usage set dropped\n"); 523 } 524 s->susage = 0; 525 break; 526 case 3: 527 c->designator_index = dval; 528 break; 529 case 4: 530 c->designator_minimum = dval; 531 break; 532 case 5: 533 c->designator_maximum = dval; 534 break; 535 case 7: 536 c->string_index = dval; 537 break; 538 case 8: 539 c->string_minimum = dval; 540 break; 541 case 9: 542 c->string_maximum = dval; 543 break; 544 case 10: 545 c->set_delimiter = dval; 546 break; 547 default: 548 DPRINTFN(0, "Local bTag=%d\n", bTag); 549 break; 550 } 551 break; 552 default: 553 DPRINTFN(0, "default bType=%d\n", bType); 554 break; 555 } 556 } 557 return (0); 558} 559 560/*------------------------------------------------------------------------* 561 * hid_report_size 562 *------------------------------------------------------------------------*/ 563int 564hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, uint8_t *id) 565{ 566 struct hid_data *d; 567 struct hid_item h; 568 uint32_t temp; 569 uint32_t hpos; 570 uint32_t lpos; 571 uint8_t any_id; 572 573 any_id = 0; 574 hpos = 0; 575 lpos = 0xFFFFFFFF; 576 577 for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { 578 if (h.kind == k) { 579 /* check for ID-byte presence */ 580 if ((h.report_ID != 0) && !any_id) { 581 if (id != NULL) 582 *id = h.report_ID; 583 any_id = 1; 584 } 585 /* compute minimum */ 586 if (lpos > h.loc.pos) 587 lpos = h.loc.pos; 588 /* compute end position */ 589 temp = h.loc.pos + (h.loc.size * h.loc.count); 590 /* compute maximum */ 591 if (hpos < temp) 592 hpos = temp; 593 } 594 } 595 hid_end_parse(d); 596 597 /* safety check - can happen in case of currupt descriptors */ 598 if (lpos > hpos) 599 temp = 0; 600 else 601 temp = hpos - lpos; 602 603 /* check for ID byte */ 604 if (any_id) 605 temp += 8; 606 else if (id != NULL) 607 *id = 0; 608 609 /* return length in bytes rounded up */ 610 return ((temp + 7) / 8); 611} 612 613/*------------------------------------------------------------------------* 614 * hid_locate 615 *------------------------------------------------------------------------*/ 616int 617hid_locate(const void *desc, usb_size_t size, int32_t u, enum hid_kind k, 618 uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id) 619{ 620 struct hid_data *d; 621 struct hid_item h; 622 623 for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) { 624 if (h.kind == k && !(h.flags & HIO_CONST) && h.usage == u) { 625 if (index--) 626 continue; 627 if (loc != NULL) 628 *loc = h.loc; 629 if (flags != NULL) 630 *flags = h.flags; 631 if (id != NULL) 632 *id = h.report_ID; 633 hid_end_parse(d); 634 return (1); 635 } 636 } 637 if (loc != NULL) 638 loc->size = 0; 639 if (flags != NULL) 640 *flags = 0; 641 if (id != NULL) 642 *id = 0; 643 hid_end_parse(d); 644 return (0); 645} 646 647/*------------------------------------------------------------------------* 648 * hid_get_data 649 *------------------------------------------------------------------------*/ 650static uint32_t 651hid_get_data_sub(const uint8_t *buf, usb_size_t len, struct hid_location *loc, 652 int is_signed) 653{ 654 uint32_t hpos = loc->pos; 655 uint32_t hsize = loc->size; 656 uint32_t data; 657 uint32_t rpos; 658 uint8_t n; 659 660 DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize); 661 662 /* Range check and limit */ 663 if (hsize == 0) 664 return (0); 665 if (hsize > 32) 666 hsize = 32; 667 668 /* Get data in a safe way */ 669 data = 0; 670 rpos = (hpos / 8); 671 n = (hsize + 7) / 8; 672 rpos += n; 673 while (n--) { 674 rpos--; 675 if (rpos < len) 676 data |= buf[rpos] << (8 * n); 677 } 678 679 /* Correctly shift down data */ 680 data = (data >> (hpos % 8)); 681 n = 32 - hsize; 682 683 /* Mask and sign extend in one */ 684 if (is_signed != 0) 685 data = (int32_t)((int32_t)data << n) >> n; 686 else 687 data = (uint32_t)((uint32_t)data << n) >> n; 688 689 DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n", 690 loc->pos, loc->size, (long)data); 691 return (data); 692} 693 694int32_t 695hid_get_data(const uint8_t *buf, usb_size_t len, struct hid_location *loc) 696{ 697 return (hid_get_data_sub(buf, len, loc, 1)); 698} 699 700uint32_t 701hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, struct hid_location *loc) 702{ 703 return (hid_get_data_sub(buf, len, loc, 0)); 704} 705 706/*------------------------------------------------------------------------* 707 * hid_put_data 708 *------------------------------------------------------------------------*/ 709void 710hid_put_data_unsigned(uint8_t *buf, usb_size_t len, 711 struct hid_location *loc, unsigned int value) 712{ 713 uint32_t hpos = loc->pos; 714 uint32_t hsize = loc->size; 715 uint64_t data; 716 uint64_t mask; 717 uint32_t rpos; 718 uint8_t n; 719 720 DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value); 721 722 /* Range check and limit */ 723 if (hsize == 0) 724 return; 725 if (hsize > 32) 726 hsize = 32; 727 728 /* Put data in a safe way */ 729 rpos = (hpos / 8); 730 n = (hsize + 7) / 8; 731 data = ((uint64_t)value) << (hpos % 8); 732 mask = ((1ULL << hsize) - 1ULL) << (hpos % 8); 733 rpos += n; 734 while (n--) { 735 rpos--; 736 if (rpos < len) { 737 buf[rpos] &= ~(mask >> (8 * n)); 738 buf[rpos] |= (data >> (8 * n)); 739 } 740 } 741} 742 743/*------------------------------------------------------------------------* 744 * hid_is_collection 745 *------------------------------------------------------------------------*/ 746int 747hid_is_collection(const void *desc, usb_size_t size, int32_t usage) 748{ 749 struct hid_data *hd; 750 struct hid_item hi; 751 int err; 752 753 hd = hid_start_parse(desc, size, hid_input); 754 if (hd == NULL) 755 return (0); 756 757 while ((err = hid_get_item(hd, &hi))) { 758 if (hi.kind == hid_collection && 759 hi.usage == usage) 760 break; 761 } 762 hid_end_parse(hd); 763 return (err); 764} 765 766/*------------------------------------------------------------------------* 767 * hid_get_descriptor_from_usb 768 * 769 * This function will search for a HID descriptor between two USB 770 * interface descriptors. 771 * 772 * Return values: 773 * NULL: No more HID descriptors. 774 * Else: Pointer to HID descriptor. 775 *------------------------------------------------------------------------*/ 776struct usb_hid_descriptor * 777hid_get_descriptor_from_usb(struct usb_config_descriptor *cd, 778 struct usb_interface_descriptor *id) 779{ 780 struct usb_descriptor *desc = (void *)id; 781 782 if (desc == NULL) { 783 return (NULL); 784 } 785 while ((desc = usb_desc_foreach(cd, desc))) { 786 if ((desc->bDescriptorType == UDESC_HID) && 787 (desc->bLength >= USB_HID_DESCRIPTOR_SIZE(0))) { 788 return (void *)desc; 789 } 790 if (desc->bDescriptorType == UDESC_INTERFACE) { 791 break; 792 } 793 } 794 return (NULL); 795} 796 797/*------------------------------------------------------------------------* 798 * usbd_req_get_hid_desc 799 * 800 * This function will read out an USB report descriptor from the USB 801 * device. 802 * 803 * Return values: 804 * NULL: Failure. 805 * Else: Success. The pointer should eventually be passed to free(). 806 *------------------------------------------------------------------------*/ 807usb_error_t 808usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, 809 void **descp, uint16_t *sizep, 810 struct malloc_type *mem, uint8_t iface_index) 811{ 812 struct usb_interface *iface = usbd_get_iface(udev, iface_index); 813 struct usb_hid_descriptor *hid; 814 usb_error_t err; 815 816 if ((iface == NULL) || (iface->idesc == NULL)) { 817 return (USB_ERR_INVAL); 818 } 819 hid = hid_get_descriptor_from_usb 820 (usbd_get_config_descriptor(udev), iface->idesc); 821 822 if (hid == NULL) { 823 return (USB_ERR_IOERROR); 824 } 825 *sizep = UGETW(hid->descrs[0].wDescriptorLength); 826 if (*sizep == 0) { 827 return (USB_ERR_IOERROR); 828 } 829 if (mtx) 830 mtx_unlock(mtx); 831 832 *descp = malloc(*sizep, mem, M_ZERO | M_WAITOK); 833 834 if (mtx) 835 mtx_lock(mtx); 836 837 if (*descp == NULL) { 838 return (USB_ERR_NOMEM); 839 } 840 err = usbd_req_get_report_descriptor 841 (udev, mtx, *descp, *sizep, iface_index); 842 843 if (err) { 844 free(*descp, mem); 845 *descp = NULL; 846 return (err); 847 } 848 return (USB_ERR_NORMAL_COMPLETION); 849} 850 851/*------------------------------------------------------------------------* 852 * calculate HID item resolution. unit/mm for distances, unit/rad for angles 853 *------------------------------------------------------------------------*/ 854int32_t 855hid_item_resolution(struct hid_item *hi) 856{ 857 /* 858 * hid unit scaling table according to HID Usage Table Review 859 * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf 860 */ 861 static const int64_t scale[0x10][2] = { 862 [0x00] = { 1, 1 }, 863 [0x01] = { 1, 10 }, 864 [0x02] = { 1, 100 }, 865 [0x03] = { 1, 1000 }, 866 [0x04] = { 1, 10000 }, 867 [0x05] = { 1, 100000 }, 868 [0x06] = { 1, 1000000 }, 869 [0x07] = { 1, 10000000 }, 870 [0x08] = { 100000000, 1 }, 871 [0x09] = { 10000000, 1 }, 872 [0x0A] = { 1000000, 1 }, 873 [0x0B] = { 100000, 1 }, 874 [0x0C] = { 10000, 1 }, 875 [0x0D] = { 1000, 1 }, 876 [0x0E] = { 100, 1 }, 877 [0x0F] = { 10, 1 }, 878 }; 879 int64_t logical_size; 880 int64_t physical_size; 881 int64_t multiplier; 882 int64_t divisor; 883 int64_t resolution; 884 885 switch (hi->unit) { 886 case HUM_CENTIMETER: 887 multiplier = 1; 888 divisor = 10; 889 break; 890 case HUM_INCH: 891 multiplier = 10; 892 divisor = 254; 893 break; 894 case HUM_RADIAN: 895 multiplier = 1; 896 divisor = 1; 897 break; 898 case HUM_DEGREE: 899 multiplier = 573; 900 divisor = 10; 901 break; 902 default: 903 return (0); 904 } 905 906 if ((hi->logical_maximum <= hi->logical_minimum) || 907 (hi->physical_maximum <= hi->physical_minimum) || 908 (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale))) 909 return (0); 910 911 logical_size = (int64_t)hi->logical_maximum - 912 (int64_t)hi->logical_minimum; 913 physical_size = (int64_t)hi->physical_maximum - 914 (int64_t)hi->physical_minimum; 915 /* Round to ceiling */ 916 resolution = logical_size * multiplier * scale[hi->unit_exponent][0] / 917 (physical_size * divisor * scale[hi->unit_exponent][1]); 918 919 if (resolution > INT32_MAX) 920 return (0); 921 922 return (resolution); 923} 924 925/*------------------------------------------------------------------------* 926 * hid_is_mouse 927 * 928 * This function will decide if a USB descriptor belongs to a USB mouse. 929 * 930 * Return values: 931 * Zero: Not a USB mouse. 932 * Else: Is a USB mouse. 933 *------------------------------------------------------------------------*/ 934int 935hid_is_mouse(const void *d_ptr, uint16_t d_len) 936{ 937 struct hid_data *hd; 938 struct hid_item hi; 939 int mdepth; 940 int found; 941 942 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 943 if (hd == NULL) 944 return (0); 945 946 mdepth = 0; 947 found = 0; 948 949 while (hid_get_item(hd, &hi)) { 950 switch (hi.kind) { 951 case hid_collection: 952 if (mdepth != 0) 953 mdepth++; 954 else if (hi.collection == 1 && 955 hi.usage == 956 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) 957 mdepth++; 958 break; 959 case hid_endcollection: 960 if (mdepth != 0) 961 mdepth--; 962 break; 963 case hid_input: 964 if (mdepth == 0) 965 break; 966 if (hi.usage == 967 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && 968 (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) 969 found++; 970 if (hi.usage == 971 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && 972 (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) 973 found++; 974 break; 975 default: 976 break; 977 } 978 } 979 hid_end_parse(hd); 980 return (found); 981} 982 983/*------------------------------------------------------------------------* 984 * hid_is_keyboard 985 * 986 * This function will decide if a USB descriptor belongs to a USB keyboard. 987 * 988 * Return values: 989 * Zero: Not a USB keyboard. 990 * Else: Is a USB keyboard. 991 *------------------------------------------------------------------------*/ 992int 993hid_is_keyboard(const void *d_ptr, uint16_t d_len) 994{ 995 if (hid_is_collection(d_ptr, d_len, 996 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) 997 return (1); 998 return (0); 999} 1000