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