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