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