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