1 /* $FreeBSD$ */ 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 69 static void hid_clear_local(struct hid_item *); 70 static 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 76 struct hid_pos_data { 77 int32_t rid; 78 uint32_t pos; 79 }; 80 81 struct hid_data { 82 const uint8_t *start; 83 const uint8_t *end; 84 const uint8_t *p; 85 struct hid_item cur[MAXPUSH]; 86 struct hid_pos_data last_pos[MAXID]; 87 int32_t usages_min[MAXUSAGE]; 88 int32_t usages_max[MAXUSAGE]; 89 int32_t usage_last; /* last seen usage */ 90 uint32_t loc_size; /* last seen size */ 91 uint32_t loc_count; /* last seen count */ 92 uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ 93 uint8_t pushlevel; /* current pushlevel */ 94 uint8_t ncount; /* end usage item count */ 95 uint8_t icount; /* current usage item count */ 96 uint8_t nusage; /* end "usages_min/max" index */ 97 uint8_t iusage; /* current "usages_min/max" index */ 98 uint8_t ousage; /* current "usages_min/max" offset */ 99 uint8_t susage; /* usage set flags */ 100 }; 101 102 /*------------------------------------------------------------------------* 103 * hid_clear_local 104 *------------------------------------------------------------------------*/ 105 static void 106 hid_clear_local(struct hid_item *c) 107 { 108 109 c->loc.count = 0; 110 c->loc.size = 0; 111 c->usage = 0; 112 c->usage_minimum = 0; 113 c->usage_maximum = 0; 114 c->designator_index = 0; 115 c->designator_minimum = 0; 116 c->designator_maximum = 0; 117 c->string_index = 0; 118 c->string_minimum = 0; 119 c->string_maximum = 0; 120 c->set_delimiter = 0; 121 } 122 123 static void 124 hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) 125 { 126 uint8_t i; 127 128 /* check for same report ID - optimise */ 129 130 if (c->report_ID == next_rID) 131 return; 132 133 /* save current position for current rID */ 134 135 if (c->report_ID == 0) { 136 i = 0; 137 } else { 138 for (i = 1; i != MAXID; i++) { 139 if (s->last_pos[i].rid == c->report_ID) 140 break; 141 if (s->last_pos[i].rid == 0) 142 break; 143 } 144 } 145 if (i != MAXID) { 146 s->last_pos[i].rid = c->report_ID; 147 s->last_pos[i].pos = c->loc.pos; 148 } 149 150 /* store next report ID */ 151 152 c->report_ID = next_rID; 153 154 /* lookup last position for next rID */ 155 156 if (next_rID == 0) { 157 i = 0; 158 } else { 159 for (i = 1; i != MAXID; i++) { 160 if (s->last_pos[i].rid == next_rID) 161 break; 162 if (s->last_pos[i].rid == 0) 163 break; 164 } 165 } 166 if (i != MAXID) { 167 s->last_pos[i].rid = next_rID; 168 c->loc.pos = s->last_pos[i].pos; 169 } else { 170 DPRINTF("Out of RID entries, position is set to zero!\n"); 171 c->loc.pos = 0; 172 } 173 } 174 175 /*------------------------------------------------------------------------* 176 * hid_start_parse 177 *------------------------------------------------------------------------*/ 178 struct hid_data * 179 hid_start_parse(const void *d, usb_size_t len, int kindset) 180 { 181 struct hid_data *s; 182 183 if ((kindset-1) & kindset) { 184 DPRINTFN(0, "Only one bit can be " 185 "set in the kindset\n"); 186 return (NULL); 187 } 188 189 s = malloc(sizeof *s, M_TEMP, M_WAITOK | M_ZERO); 190 s->start = s->p = d; 191 s->end = ((const uint8_t *)d) + len; 192 s->kindset = kindset; 193 return (s); 194 } 195 196 /*------------------------------------------------------------------------* 197 * hid_end_parse 198 *------------------------------------------------------------------------*/ 199 void 200 hid_end_parse(struct hid_data *s) 201 { 202 if (s == NULL) 203 return; 204 205 free(s, M_TEMP); 206 } 207 208 /*------------------------------------------------------------------------* 209 * get byte from HID descriptor 210 *------------------------------------------------------------------------*/ 211 static uint8_t 212 hid_get_byte(struct hid_data *s, const uint16_t wSize) 213 { 214 const uint8_t *ptr; 215 uint8_t retval; 216 217 ptr = s->p; 218 219 /* check if end is reached */ 220 if (ptr == s->end) 221 return (0); 222 223 /* read out a byte */ 224 retval = *ptr; 225 226 /* check if data pointer can be advanced by "wSize" bytes */ 227 if ((s->end - ptr) < wSize) 228 ptr = s->end; 229 else 230 ptr += wSize; 231 232 /* update pointer */ 233 s->p = ptr; 234 235 return (retval); 236 } 237 238 /*------------------------------------------------------------------------* 239 * hid_get_item 240 *------------------------------------------------------------------------*/ 241 int 242 hid_get_item(struct hid_data *s, struct hid_item *h) 243 { 244 struct hid_item *c; 245 unsigned int bTag, bType, bSize; 246 uint32_t oldpos; 247 int32_t mask; 248 int32_t dval; 249 250 if (s == NULL) 251 return (0); 252 253 c = &s->cur[s->pushlevel]; 254 255 top: 256 /* check if there is an array of items */ 257 if (s->icount < s->ncount) { 258 /* get current usage */ 259 if (s->iusage < s->nusage) { 260 dval = s->usages_min[s->iusage] + s->ousage; 261 c->usage = dval; 262 s->usage_last = dval; 263 if (dval == s->usages_max[s->iusage]) { 264 s->iusage ++; 265 s->ousage = 0; 266 } else { 267 s->ousage ++; 268 } 269 } else { 270 DPRINTFN(1, "Using last usage\n"); 271 dval = s->usage_last; 272 } 273 s->icount ++; 274 /* 275 * Only copy HID item, increment position and return 276 * if correct kindset! 277 */ 278 if (s->kindset & (1 << c->kind)) { 279 *h = *c; 280 DPRINTFN(1, "%u,%u,%u\n", h->loc.pos, 281 h->loc.size, h->loc.count); 282 c->loc.pos += c->loc.size * c->loc.count; 283 return (1); 284 } 285 } 286 287 /* reset state variables */ 288 s->icount = 0; 289 s->ncount = 0; 290 s->iusage = 0; 291 s->nusage = 0; 292 s->susage = 0; 293 s->ousage = 0; 294 hid_clear_local(c); 295 296 /* get next item */ 297 while (s->p != s->end) { 298 299 bSize = hid_get_byte(s, 1); 300 if (bSize == 0xfe) { 301 /* long item */ 302 bSize = hid_get_byte(s, 1); 303 bSize |= hid_get_byte(s, 1) << 8; 304 bTag = hid_get_byte(s, 1); 305 bType = 0xff; /* XXX what should it be */ 306 } else { 307 /* short item */ 308 bTag = bSize >> 4; 309 bType = (bSize >> 2) & 3; 310 bSize &= 3; 311 if (bSize == 3) 312 bSize = 4; 313 } 314 switch (bSize) { 315 case 0: 316 dval = 0; 317 mask = 0; 318 break; 319 case 1: 320 dval = (int8_t)hid_get_byte(s, 1); 321 mask = 0xFF; 322 break; 323 case 2: 324 dval = hid_get_byte(s, 1); 325 dval |= hid_get_byte(s, 1) << 8; 326 dval = (int16_t)dval; 327 mask = 0xFFFF; 328 break; 329 case 4: 330 dval = hid_get_byte(s, 1); 331 dval |= hid_get_byte(s, 1) << 8; 332 dval |= hid_get_byte(s, 1) << 16; 333 dval |= hid_get_byte(s, 1) << 24; 334 mask = 0xFFFFFFFF; 335 break; 336 default: 337 dval = hid_get_byte(s, bSize); 338 DPRINTFN(0, "bad length %u (data=0x%02x)\n", 339 bSize, dval); 340 continue; 341 } 342 343 switch (bType) { 344 case 0: /* Main */ 345 switch (bTag) { 346 case 8: /* Input */ 347 c->kind = hid_input; 348 c->flags = dval; 349 ret: 350 c->loc.count = s->loc_count; 351 c->loc.size = s->loc_size; 352 353 if (c->flags & HIO_VARIABLE) { 354 /* range check usage count */ 355 if (c->loc.count > 255) { 356 DPRINTFN(0, "Number of " 357 "items truncated to 255\n"); 358 s->ncount = 255; 359 } else 360 s->ncount = c->loc.count; 361 362 /* 363 * The "top" loop will return 364 * one and one item: 365 */ 366 c->loc.count = 1; 367 } else { 368 s->ncount = 1; 369 } 370 goto top; 371 372 case 9: /* Output */ 373 c->kind = hid_output; 374 c->flags = dval; 375 goto ret; 376 case 10: /* Collection */ 377 c->kind = hid_collection; 378 c->collection = dval; 379 c->collevel++; 380 c->usage = s->usage_last; 381 *h = *c; 382 return (1); 383 case 11: /* Feature */ 384 c->kind = hid_feature; 385 c->flags = dval; 386 goto ret; 387 case 12: /* End collection */ 388 c->kind = hid_endcollection; 389 if (c->collevel == 0) { 390 DPRINTFN(0, "invalid end collection\n"); 391 return (0); 392 } 393 c->collevel--; 394 *h = *c; 395 return (1); 396 default: 397 DPRINTFN(0, "Main bTag=%d\n", bTag); 398 break; 399 } 400 break; 401 case 1: /* Global */ 402 switch (bTag) { 403 case 0: 404 c->_usage_page = dval << 16; 405 break; 406 case 1: 407 c->logical_minimum = dval; 408 break; 409 case 2: 410 c->logical_maximum = dval; 411 break; 412 case 3: 413 c->physical_minimum = dval; 414 break; 415 case 4: 416 c->physical_maximum = dval; 417 break; 418 case 5: 419 c->unit_exponent = dval; 420 break; 421 case 6: 422 c->unit = dval; 423 break; 424 case 7: 425 /* mask because value is unsigned */ 426 s->loc_size = dval & mask; 427 break; 428 case 8: 429 hid_switch_rid(s, c, dval & mask); 430 break; 431 case 9: 432 /* mask because value is unsigned */ 433 s->loc_count = dval & mask; 434 break; 435 case 10: /* Push */ 436 s->pushlevel ++; 437 if (s->pushlevel < MAXPUSH) { 438 s->cur[s->pushlevel] = *c; 439 /* store size and count */ 440 c->loc.size = s->loc_size; 441 c->loc.count = s->loc_count; 442 /* update current item pointer */ 443 c = &s->cur[s->pushlevel]; 444 } else { 445 DPRINTFN(0, "Cannot push " 446 "item @ %d\n", s->pushlevel); 447 } 448 break; 449 case 11: /* Pop */ 450 s->pushlevel --; 451 if (s->pushlevel < MAXPUSH) { 452 /* preserve position */ 453 oldpos = c->loc.pos; 454 c = &s->cur[s->pushlevel]; 455 /* restore size and count */ 456 s->loc_size = c->loc.size; 457 s->loc_count = c->loc.count; 458 /* set default item location */ 459 c->loc.pos = oldpos; 460 c->loc.size = 0; 461 c->loc.count = 0; 462 } else { 463 DPRINTFN(0, "Cannot pop " 464 "item @ %d\n", s->pushlevel); 465 } 466 break; 467 default: 468 DPRINTFN(0, "Global bTag=%d\n", bTag); 469 break; 470 } 471 break; 472 case 2: /* Local */ 473 switch (bTag) { 474 case 0: 475 if (bSize != 4) 476 dval = (dval & mask) | c->_usage_page; 477 478 /* set last usage, in case of a collection */ 479 s->usage_last = dval; 480 481 if (s->nusage < MAXUSAGE) { 482 s->usages_min[s->nusage] = dval; 483 s->usages_max[s->nusage] = dval; 484 s->nusage ++; 485 } else { 486 DPRINTFN(0, "max usage reached\n"); 487 } 488 489 /* clear any pending usage sets */ 490 s->susage = 0; 491 break; 492 case 1: 493 s->susage |= 1; 494 495 if (bSize != 4) 496 dval = (dval & mask) | c->_usage_page; 497 c->usage_minimum = dval; 498 499 goto check_set; 500 case 2: 501 s->susage |= 2; 502 503 if (bSize != 4) 504 dval = (dval & mask) | c->_usage_page; 505 c->usage_maximum = dval; 506 507 check_set: 508 if (s->susage != 3) 509 break; 510 511 /* sanity check */ 512 if ((s->nusage < MAXUSAGE) && 513 (c->usage_minimum <= c->usage_maximum)) { 514 /* add usage range */ 515 s->usages_min[s->nusage] = 516 c->usage_minimum; 517 s->usages_max[s->nusage] = 518 c->usage_maximum; 519 s->nusage ++; 520 } else { 521 DPRINTFN(0, "Usage set dropped\n"); 522 } 523 s->susage = 0; 524 break; 525 case 3: 526 c->designator_index = dval; 527 break; 528 case 4: 529 c->designator_minimum = dval; 530 break; 531 case 5: 532 c->designator_maximum = dval; 533 break; 534 case 7: 535 c->string_index = dval; 536 break; 537 case 8: 538 c->string_minimum = dval; 539 break; 540 case 9: 541 c->string_maximum = dval; 542 break; 543 case 10: 544 c->set_delimiter = dval; 545 break; 546 default: 547 DPRINTFN(0, "Local bTag=%d\n", bTag); 548 break; 549 } 550 break; 551 default: 552 DPRINTFN(0, "default bType=%d\n", bType); 553 break; 554 } 555 } 556 return (0); 557 } 558 559 /*------------------------------------------------------------------------* 560 * hid_report_size 561 *------------------------------------------------------------------------*/ 562 int 563 hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, uint8_t *id) 564 { 565 struct hid_data *d; 566 struct hid_item h; 567 uint32_t temp; 568 uint32_t hpos; 569 uint32_t lpos; 570 uint8_t any_id; 571 572 any_id = 0; 573 hpos = 0; 574 lpos = 0xFFFFFFFF; 575 576 for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { 577 if (h.kind == k) { 578 /* check for ID-byte presense */ 579 if ((h.report_ID != 0) && !any_id) { 580 if (id != NULL) 581 *id = h.report_ID; 582 any_id = 1; 583 } 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 } 593 } 594 hid_end_parse(d); 595 596 /* safety check - can happen in case of currupt descriptors */ 597 if (lpos > hpos) 598 temp = 0; 599 else 600 temp = hpos - lpos; 601 602 /* check for ID byte */ 603 if (any_id) 604 temp += 8; 605 else if (id != NULL) 606 *id = 0; 607 608 /* return length in bytes rounded up */ 609 return ((temp + 7) / 8); 610 } 611 612 /*------------------------------------------------------------------------* 613 * hid_locate 614 *------------------------------------------------------------------------*/ 615 int 616 hid_locate(const void *desc, usb_size_t size, int32_t u, enum hid_kind k, 617 uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id) 618 { 619 struct hid_data *d; 620 struct hid_item h; 621 622 for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) { 623 if (h.kind == k && !(h.flags & HIO_CONST) && h.usage == u) { 624 if (index--) 625 continue; 626 if (loc != NULL) 627 *loc = h.loc; 628 if (flags != NULL) 629 *flags = h.flags; 630 if (id != NULL) 631 *id = h.report_ID; 632 hid_end_parse(d); 633 return (1); 634 } 635 } 636 if (loc != NULL) 637 loc->size = 0; 638 if (flags != NULL) 639 *flags = 0; 640 if (id != NULL) 641 *id = 0; 642 hid_end_parse(d); 643 return (0); 644 } 645 646 /*------------------------------------------------------------------------* 647 * hid_get_data 648 *------------------------------------------------------------------------*/ 649 static uint32_t 650 hid_get_data_sub(const uint8_t *buf, usb_size_t len, struct hid_location *loc, 651 int is_signed) 652 { 653 uint32_t hpos = loc->pos; 654 uint32_t hsize = loc->size; 655 uint32_t data; 656 uint32_t rpos; 657 uint8_t n; 658 659 DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize); 660 661 /* Range check and limit */ 662 if (hsize == 0) 663 return (0); 664 if (hsize > 32) 665 hsize = 32; 666 667 /* Get data in a safe way */ 668 data = 0; 669 rpos = (hpos / 8); 670 n = (hsize + 7) / 8; 671 rpos += n; 672 while (n--) { 673 rpos--; 674 if (rpos < len) 675 data |= buf[rpos] << (8 * n); 676 } 677 678 /* Correctly shift down data */ 679 data = (data >> (hpos % 8)); 680 n = 32 - hsize; 681 682 /* Mask and sign extend in one */ 683 if (is_signed != 0) 684 data = (int32_t)((int32_t)data << n) >> n; 685 else 686 data = (uint32_t)((uint32_t)data << n) >> n; 687 688 DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n", 689 loc->pos, loc->size, (long)data); 690 return (data); 691 } 692 693 int32_t 694 hid_get_data(const uint8_t *buf, usb_size_t len, struct hid_location *loc) 695 { 696 return (hid_get_data_sub(buf, len, loc, 1)); 697 } 698 699 uint32_t 700 hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, struct hid_location *loc) 701 { 702 return (hid_get_data_sub(buf, len, loc, 0)); 703 } 704 705 /*------------------------------------------------------------------------* 706 * hid_put_data 707 *------------------------------------------------------------------------*/ 708 void 709 hid_put_data_unsigned(uint8_t *buf, usb_size_t len, 710 struct hid_location *loc, unsigned int value) 711 { 712 uint32_t hpos = loc->pos; 713 uint32_t hsize = loc->size; 714 uint64_t data; 715 uint64_t mask; 716 uint32_t rpos; 717 uint8_t n; 718 719 DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value); 720 721 /* Range check and limit */ 722 if (hsize == 0) 723 return; 724 if (hsize > 32) 725 hsize = 32; 726 727 /* Put data in a safe way */ 728 rpos = (hpos / 8); 729 n = (hsize + 7) / 8; 730 data = ((uint64_t)value) << (hpos % 8); 731 mask = ((1ULL << hsize) - 1ULL) << (hpos % 8); 732 rpos += n; 733 while (n--) { 734 rpos--; 735 if (rpos < len) { 736 buf[rpos] &= ~(mask >> (8 * n)); 737 buf[rpos] |= (data >> (8 * n)); 738 } 739 } 740 } 741 742 /*------------------------------------------------------------------------* 743 * hid_is_collection 744 *------------------------------------------------------------------------*/ 745 int 746 hid_is_collection(const void *desc, usb_size_t size, int32_t usage) 747 { 748 struct hid_data *hd; 749 struct hid_item hi; 750 int err; 751 752 hd = hid_start_parse(desc, size, hid_input); 753 if (hd == NULL) 754 return (0); 755 756 while ((err = hid_get_item(hd, &hi))) { 757 if (hi.kind == hid_collection && 758 hi.usage == usage) 759 break; 760 } 761 hid_end_parse(hd); 762 return (err); 763 } 764 765 /*------------------------------------------------------------------------* 766 * hid_get_descriptor_from_usb 767 * 768 * This function will search for a HID descriptor between two USB 769 * interface descriptors. 770 * 771 * Return values: 772 * NULL: No more HID descriptors. 773 * Else: Pointer to HID descriptor. 774 *------------------------------------------------------------------------*/ 775 struct usb_hid_descriptor * 776 hid_get_descriptor_from_usb(struct usb_config_descriptor *cd, 777 struct usb_interface_descriptor *id) 778 { 779 struct usb_descriptor *desc = (void *)id; 780 781 if (desc == NULL) { 782 return (NULL); 783 } 784 while ((desc = usb_desc_foreach(cd, desc))) { 785 if ((desc->bDescriptorType == UDESC_HID) && 786 (desc->bLength >= USB_HID_DESCRIPTOR_SIZE(0))) { 787 return (void *)desc; 788 } 789 if (desc->bDescriptorType == UDESC_INTERFACE) { 790 break; 791 } 792 } 793 return (NULL); 794 } 795 796 /*------------------------------------------------------------------------* 797 * usbd_req_get_hid_desc 798 * 799 * This function will read out an USB report descriptor from the USB 800 * device. 801 * 802 * Return values: 803 * NULL: Failure. 804 * Else: Success. The pointer should eventually be passed to free(). 805 *------------------------------------------------------------------------*/ 806 usb_error_t 807 usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, 808 void **descp, uint16_t *sizep, 809 struct malloc_type *mem, uint8_t iface_index) 810 { 811 struct usb_interface *iface = usbd_get_iface(udev, iface_index); 812 struct usb_hid_descriptor *hid; 813 usb_error_t err; 814 815 if ((iface == NULL) || (iface->idesc == NULL)) { 816 return (USB_ERR_INVAL); 817 } 818 hid = hid_get_descriptor_from_usb 819 (usbd_get_config_descriptor(udev), iface->idesc); 820 821 if (hid == NULL) { 822 return (USB_ERR_IOERROR); 823 } 824 *sizep = UGETW(hid->descrs[0].wDescriptorLength); 825 if (*sizep == 0) { 826 return (USB_ERR_IOERROR); 827 } 828 if (mtx) 829 mtx_unlock(mtx); 830 831 *descp = malloc(*sizep, mem, M_ZERO | M_WAITOK); 832 833 if (mtx) 834 mtx_lock(mtx); 835 836 if (*descp == NULL) { 837 return (USB_ERR_NOMEM); 838 } 839 err = usbd_req_get_report_descriptor 840 (udev, mtx, *descp, *sizep, iface_index); 841 842 if (err) { 843 free(*descp, mem); 844 *descp = NULL; 845 return (err); 846 } 847 return (USB_ERR_NORMAL_COMPLETION); 848 } 849 850 /*------------------------------------------------------------------------* 851 * hid_is_mouse 852 * 853 * This function will decide if a USB descriptor belongs to a USB mouse. 854 * 855 * Return values: 856 * Zero: Not a USB mouse. 857 * Else: Is a USB mouse. 858 *------------------------------------------------------------------------*/ 859 int 860 hid_is_mouse(const void *d_ptr, uint16_t d_len) 861 { 862 struct hid_data *hd; 863 struct hid_item hi; 864 int mdepth; 865 int found; 866 867 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 868 if (hd == NULL) 869 return (0); 870 871 mdepth = 0; 872 found = 0; 873 874 while (hid_get_item(hd, &hi)) { 875 switch (hi.kind) { 876 case hid_collection: 877 if (mdepth != 0) 878 mdepth++; 879 else if (hi.collection == 1 && 880 hi.usage == 881 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) 882 mdepth++; 883 break; 884 case hid_endcollection: 885 if (mdepth != 0) 886 mdepth--; 887 break; 888 case hid_input: 889 if (mdepth == 0) 890 break; 891 if (hi.usage == 892 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && 893 (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) 894 found++; 895 if (hi.usage == 896 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && 897 (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) 898 found++; 899 break; 900 default: 901 break; 902 } 903 } 904 hid_end_parse(hd); 905 return (found); 906 } 907 908 /*------------------------------------------------------------------------* 909 * hid_is_keyboard 910 * 911 * This function will decide if a USB descriptor belongs to a USB keyboard. 912 * 913 * Return values: 914 * Zero: Not a USB keyboard. 915 * Else: Is a USB keyboard. 916 *------------------------------------------------------------------------*/ 917 int 918 hid_is_keyboard(const void *d_ptr, uint16_t d_len) 919 { 920 if (hid_is_collection(d_ptr, d_len, 921 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) 922 return (1); 923 return (0); 924 } 925