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