1 /* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */ 2 3 4 #include <sys/cdefs.h> 5 __FBSDID("$FreeBSD$"); 6 /*- 7 * Copyright (c) 1998 The NetBSD Foundation, Inc. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Lennart Augustsson (lennart@augustsson.net) at 12 * Carlstedt Research & Technology. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 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 68 static void hid_clear_local(struct hid_item *); 69 static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize); 70 71 #define MAXUSAGE 64 72 #define MAXPUSH 4 73 #define MAXID 16 74 75 struct hid_pos_data { 76 int32_t rid; 77 uint32_t pos; 78 }; 79 80 struct hid_data { 81 const uint8_t *start; 82 const uint8_t *end; 83 const uint8_t *p; 84 struct hid_item cur[MAXPUSH]; 85 struct hid_pos_data last_pos[MAXID]; 86 int32_t usages_min[MAXUSAGE]; 87 int32_t usages_max[MAXUSAGE]; 88 int32_t usage_last; /* last seen usage */ 89 uint32_t loc_size; /* last seen size */ 90 uint32_t loc_count; /* last seen count */ 91 uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ 92 uint8_t pushlevel; /* current pushlevel */ 93 uint8_t ncount; /* end usage item count */ 94 uint8_t icount; /* current usage item count */ 95 uint8_t nusage; /* end "usages_min/max" index */ 96 uint8_t iusage; /* current "usages_min/max" index */ 97 uint8_t ousage; /* current "usages_min/max" offset */ 98 uint8_t susage; /* usage set flags */ 99 }; 100 101 /*------------------------------------------------------------------------* 102 * hid_clear_local 103 *------------------------------------------------------------------------*/ 104 static void 105 hid_clear_local(struct hid_item *c) 106 { 107 108 c->loc.count = 0; 109 c->loc.size = 0; 110 c->usage = 0; 111 c->usage_minimum = 0; 112 c->usage_maximum = 0; 113 c->designator_index = 0; 114 c->designator_minimum = 0; 115 c->designator_maximum = 0; 116 c->string_index = 0; 117 c->string_minimum = 0; 118 c->string_maximum = 0; 119 c->set_delimiter = 0; 120 } 121 122 static void 123 hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) 124 { 125 uint8_t i; 126 127 /* check for same report ID - optimise */ 128 129 if (c->report_ID == next_rID) 130 return; 131 132 /* save current position for current rID */ 133 134 if (c->report_ID == 0) { 135 i = 0; 136 } else { 137 for (i = 1; i != MAXID; i++) { 138 if (s->last_pos[i].rid == c->report_ID) 139 break; 140 if (s->last_pos[i].rid == 0) 141 break; 142 } 143 } 144 if (i != MAXID) { 145 s->last_pos[i].rid = c->report_ID; 146 s->last_pos[i].pos = c->loc.pos; 147 } 148 149 /* store next report ID */ 150 151 c->report_ID = next_rID; 152 153 /* lookup last position for next rID */ 154 155 if (next_rID == 0) { 156 i = 0; 157 } else { 158 for (i = 1; i != MAXID; i++) { 159 if (s->last_pos[i].rid == next_rID) 160 break; 161 if (s->last_pos[i].rid == 0) 162 break; 163 } 164 } 165 if (i != MAXID) { 166 s->last_pos[i].rid = next_rID; 167 c->loc.pos = s->last_pos[i].pos; 168 } else { 169 DPRINTF("Out of RID entries, position is set to zero!\n"); 170 c->loc.pos = 0; 171 } 172 } 173 174 /*------------------------------------------------------------------------* 175 * hid_start_parse 176 *------------------------------------------------------------------------*/ 177 struct hid_data * 178 hid_start_parse(const void *d, usb_size_t len, int kindset) 179 { 180 struct hid_data *s; 181 182 if ((kindset-1) & kindset) { 183 DPRINTFN(0, "Only one bit can be " 184 "set in the kindset\n"); 185 return (NULL); 186 } 187 188 s = malloc(sizeof *s, M_TEMP, M_WAITOK | M_ZERO); 189 s->start = s->p = d; 190 s->end = ((const uint8_t *)d) + len; 191 s->kindset = kindset; 192 return (s); 193 } 194 195 /*------------------------------------------------------------------------* 196 * hid_end_parse 197 *------------------------------------------------------------------------*/ 198 void 199 hid_end_parse(struct hid_data *s) 200 { 201 if (s == NULL) 202 return; 203 204 free(s, M_TEMP); 205 } 206 207 /*------------------------------------------------------------------------* 208 * get byte from HID descriptor 209 *------------------------------------------------------------------------*/ 210 static uint8_t 211 hid_get_byte(struct hid_data *s, const uint16_t wSize) 212 { 213 const uint8_t *ptr; 214 uint8_t retval; 215 216 ptr = s->p; 217 218 /* check if end is reached */ 219 if (ptr == s->end) 220 return (0); 221 222 /* read out a byte */ 223 retval = *ptr; 224 225 /* check if data pointer can be advanced by "wSize" bytes */ 226 if ((s->end - ptr) < wSize) 227 ptr = s->end; 228 else 229 ptr += wSize; 230 231 /* update pointer */ 232 s->p = ptr; 233 234 return (retval); 235 } 236 237 /*------------------------------------------------------------------------* 238 * hid_get_item 239 *------------------------------------------------------------------------*/ 240 int 241 hid_get_item(struct hid_data *s, struct hid_item *h) 242 { 243 struct hid_item *c; 244 unsigned int bTag, bType, bSize; 245 uint32_t oldpos; 246 int32_t mask; 247 int32_t dval; 248 249 if (s == NULL) 250 return (0); 251 252 c = &s->cur[s->pushlevel]; 253 254 top: 255 /* check if there is an array of items */ 256 if (s->icount < s->ncount) { 257 /* get current usage */ 258 if (s->iusage < s->nusage) { 259 dval = s->usages_min[s->iusage] + s->ousage; 260 c->usage = dval; 261 s->usage_last = dval; 262 if (dval == s->usages_max[s->iusage]) { 263 s->iusage ++; 264 s->ousage = 0; 265 } else { 266 s->ousage ++; 267 } 268 } else { 269 DPRINTFN(1, "Using last usage\n"); 270 dval = s->usage_last; 271 } 272 s->icount ++; 273 /* 274 * Only copy HID item, increment position and return 275 * if correct kindset! 276 */ 277 if (s->kindset & (1 << c->kind)) { 278 *h = *c; 279 DPRINTFN(1, "%u,%u,%u\n", h->loc.pos, 280 h->loc.size, h->loc.count); 281 c->loc.pos += c->loc.size * c->loc.count; 282 return (1); 283 } 284 } 285 286 /* reset state variables */ 287 s->icount = 0; 288 s->ncount = 0; 289 s->iusage = 0; 290 s->nusage = 0; 291 s->susage = 0; 292 s->ousage = 0; 293 hid_clear_local(c); 294 295 /* get next item */ 296 while (s->p != s->end) { 297 298 bSize = hid_get_byte(s, 1); 299 if (bSize == 0xfe) { 300 /* long item */ 301 bSize = hid_get_byte(s, 1); 302 bSize |= hid_get_byte(s, 1) << 8; 303 bTag = hid_get_byte(s, 1); 304 bType = 0xff; /* XXX what should it be */ 305 } else { 306 /* short item */ 307 bTag = bSize >> 4; 308 bType = (bSize >> 2) & 3; 309 bSize &= 3; 310 if (bSize == 3) 311 bSize = 4; 312 } 313 switch (bSize) { 314 case 0: 315 dval = 0; 316 mask = 0; 317 break; 318 case 1: 319 dval = (int8_t)hid_get_byte(s, 1); 320 mask = 0xFF; 321 break; 322 case 2: 323 dval = hid_get_byte(s, 1); 324 dval |= hid_get_byte(s, 1) << 8; 325 dval = (int16_t)dval; 326 mask = 0xFFFF; 327 break; 328 case 4: 329 dval = hid_get_byte(s, 1); 330 dval |= hid_get_byte(s, 1) << 8; 331 dval |= hid_get_byte(s, 1) << 16; 332 dval |= hid_get_byte(s, 1) << 24; 333 mask = 0xFFFFFFFF; 334 break; 335 default: 336 dval = hid_get_byte(s, bSize); 337 DPRINTFN(0, "bad length %u (data=0x%02x)\n", 338 bSize, dval); 339 continue; 340 } 341 342 switch (bType) { 343 case 0: /* Main */ 344 switch (bTag) { 345 case 8: /* Input */ 346 c->kind = hid_input; 347 c->flags = dval; 348 ret: 349 c->loc.count = s->loc_count; 350 c->loc.size = s->loc_size; 351 352 if (c->flags & HIO_VARIABLE) { 353 /* range check usage count */ 354 if (c->loc.count > 255) { 355 DPRINTFN(0, "Number of " 356 "items truncated to 255\n"); 357 s->ncount = 255; 358 } else 359 s->ncount = c->loc.count; 360 361 /* 362 * The "top" loop will return 363 * one and one item: 364 */ 365 c->loc.count = 1; 366 } else { 367 s->ncount = 1; 368 } 369 goto top; 370 371 case 9: /* Output */ 372 c->kind = hid_output; 373 c->flags = dval; 374 goto ret; 375 case 10: /* Collection */ 376 c->kind = hid_collection; 377 c->collection = dval; 378 c->collevel++; 379 c->usage = s->usage_last; 380 *h = *c; 381 return (1); 382 case 11: /* Feature */ 383 c->kind = hid_feature; 384 c->flags = dval; 385 goto ret; 386 case 12: /* End collection */ 387 c->kind = hid_endcollection; 388 if (c->collevel == 0) { 389 DPRINTFN(0, "invalid end collection\n"); 390 return (0); 391 } 392 c->collevel--; 393 *h = *c; 394 return (1); 395 default: 396 DPRINTFN(0, "Main bTag=%d\n", bTag); 397 break; 398 } 399 break; 400 case 1: /* Global */ 401 switch (bTag) { 402 case 0: 403 c->_usage_page = dval << 16; 404 break; 405 case 1: 406 c->logical_minimum = dval; 407 break; 408 case 2: 409 c->logical_maximum = dval; 410 break; 411 case 3: 412 c->physical_minimum = dval; 413 break; 414 case 4: 415 c->physical_maximum = dval; 416 break; 417 case 5: 418 c->unit_exponent = dval; 419 break; 420 case 6: 421 c->unit = dval; 422 break; 423 case 7: 424 /* mask because value is unsigned */ 425 s->loc_size = dval & mask; 426 break; 427 case 8: 428 hid_switch_rid(s, c, dval); 429 break; 430 case 9: 431 /* mask because value is unsigned */ 432 s->loc_count = dval & mask; 433 break; 434 case 10: /* Push */ 435 s->pushlevel ++; 436 if (s->pushlevel < MAXPUSH) { 437 s->cur[s->pushlevel] = *c; 438 /* store size and count */ 439 c->loc.size = s->loc_size; 440 c->loc.count = s->loc_count; 441 /* update current item pointer */ 442 c = &s->cur[s->pushlevel]; 443 } else { 444 DPRINTFN(0, "Cannot push " 445 "item @ %d\n", s->pushlevel); 446 } 447 break; 448 case 11: /* Pop */ 449 s->pushlevel --; 450 if (s->pushlevel < MAXPUSH) { 451 /* preserve position */ 452 oldpos = c->loc.pos; 453 c = &s->cur[s->pushlevel]; 454 /* restore size and count */ 455 s->loc_size = c->loc.size; 456 s->loc_count = c->loc.count; 457 /* set default item location */ 458 c->loc.pos = oldpos; 459 c->loc.size = 0; 460 c->loc.count = 0; 461 } else { 462 DPRINTFN(0, "Cannot pop " 463 "item @ %d\n", s->pushlevel); 464 } 465 break; 466 default: 467 DPRINTFN(0, "Global bTag=%d\n", bTag); 468 break; 469 } 470 break; 471 case 2: /* Local */ 472 switch (bTag) { 473 case 0: 474 if (bSize != 4) 475 dval = (dval & mask) | c->_usage_page; 476 477 /* set last usage, in case of a collection */ 478 s->usage_last = dval; 479 480 if (s->nusage < MAXUSAGE) { 481 s->usages_min[s->nusage] = dval; 482 s->usages_max[s->nusage] = dval; 483 s->nusage ++; 484 } else { 485 DPRINTFN(0, "max usage reached\n"); 486 } 487 488 /* clear any pending usage sets */ 489 s->susage = 0; 490 break; 491 case 1: 492 s->susage |= 1; 493 494 if (bSize != 4) 495 dval = (dval & mask) | c->_usage_page; 496 c->usage_minimum = dval; 497 498 goto check_set; 499 case 2: 500 s->susage |= 2; 501 502 if (bSize != 4) 503 dval = (dval & mask) | c->_usage_page; 504 c->usage_maximum = dval; 505 506 check_set: 507 if (s->susage != 3) 508 break; 509 510 /* sanity check */ 511 if ((s->nusage < MAXUSAGE) && 512 (c->usage_minimum <= c->usage_maximum)) { 513 /* add usage range */ 514 s->usages_min[s->nusage] = 515 c->usage_minimum; 516 s->usages_max[s->nusage] = 517 c->usage_maximum; 518 s->nusage ++; 519 } else { 520 DPRINTFN(0, "Usage set dropped\n"); 521 } 522 s->susage = 0; 523 break; 524 case 3: 525 c->designator_index = dval; 526 break; 527 case 4: 528 c->designator_minimum = dval; 529 break; 530 case 5: 531 c->designator_maximum = dval; 532 break; 533 case 7: 534 c->string_index = dval; 535 break; 536 case 8: 537 c->string_minimum = dval; 538 break; 539 case 9: 540 c->string_maximum = dval; 541 break; 542 case 10: 543 c->set_delimiter = dval; 544 break; 545 default: 546 DPRINTFN(0, "Local bTag=%d\n", bTag); 547 break; 548 } 549 break; 550 default: 551 DPRINTFN(0, "default bType=%d\n", bType); 552 break; 553 } 554 } 555 return (0); 556 } 557 558 /*------------------------------------------------------------------------* 559 * hid_report_size 560 *------------------------------------------------------------------------*/ 561 int 562 hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, uint8_t *id) 563 { 564 struct hid_data *d; 565 struct hid_item h; 566 uint32_t temp; 567 uint32_t hpos; 568 uint32_t lpos; 569 uint8_t any_id; 570 571 any_id = 0; 572 hpos = 0; 573 lpos = 0xFFFFFFFF; 574 575 for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { 576 if (h.kind == k) { 577 /* check for ID-byte presense */ 578 if ((h.report_ID != 0) && !any_id) { 579 if (id != NULL) 580 *id = h.report_ID; 581 any_id = 1; 582 } 583 /* compute minimum */ 584 if (lpos > h.loc.pos) 585 lpos = h.loc.pos; 586 /* compute end position */ 587 temp = h.loc.pos + (h.loc.size * h.loc.count); 588 /* compute maximum */ 589 if (hpos < temp) 590 hpos = temp; 591 } 592 } 593 hid_end_parse(d); 594 595 /* safety check - can happen in case of currupt descriptors */ 596 if (lpos > hpos) 597 temp = 0; 598 else 599 temp = hpos - lpos; 600 601 /* check for ID byte */ 602 if (any_id) 603 temp += 8; 604 else if (id != NULL) 605 *id = 0; 606 607 /* return length in bytes rounded up */ 608 return ((temp + 7) / 8); 609 } 610 611 /*------------------------------------------------------------------------* 612 * hid_locate 613 *------------------------------------------------------------------------*/ 614 int 615 hid_locate(const void *desc, usb_size_t size, uint32_t u, enum hid_kind k, 616 uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id) 617 { 618 struct hid_data *d; 619 struct hid_item h; 620 621 for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) { 622 if (h.kind == k && !(h.flags & HIO_CONST) && h.usage == u) { 623 if (index--) 624 continue; 625 if (loc != NULL) 626 *loc = h.loc; 627 if (flags != NULL) 628 *flags = h.flags; 629 if (id != NULL) 630 *id = h.report_ID; 631 hid_end_parse(d); 632 return (1); 633 } 634 } 635 if (loc != NULL) 636 loc->size = 0; 637 if (flags != NULL) 638 *flags = 0; 639 if (id != NULL) 640 *id = 0; 641 hid_end_parse(d); 642 return (0); 643 } 644 645 /*------------------------------------------------------------------------* 646 * hid_get_data 647 *------------------------------------------------------------------------*/ 648 static uint32_t 649 hid_get_data_sub(const uint8_t *buf, usb_size_t len, struct hid_location *loc, 650 int is_signed) 651 { 652 uint32_t hpos = loc->pos; 653 uint32_t hsize = loc->size; 654 uint32_t data; 655 uint32_t rpos; 656 uint8_t n; 657 658 DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize); 659 660 /* Range check and limit */ 661 if (hsize == 0) 662 return (0); 663 if (hsize > 32) 664 hsize = 32; 665 666 /* Get data in a safe way */ 667 data = 0; 668 rpos = (hpos / 8); 669 n = (hsize + 7) / 8; 670 rpos += n; 671 while (n--) { 672 rpos--; 673 if (rpos < len) 674 data |= buf[rpos] << (8 * n); 675 } 676 677 /* Correctly shift down data */ 678 data = (data >> (hpos % 8)); 679 n = 32 - hsize; 680 681 /* Mask and sign extend in one */ 682 if (is_signed != 0) 683 data = (int32_t)((int32_t)data << n) >> n; 684 else 685 data = (uint32_t)((uint32_t)data << n) >> n; 686 687 DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n", 688 loc->pos, loc->size, (long)data); 689 return (data); 690 } 691 692 int32_t 693 hid_get_data(const uint8_t *buf, usb_size_t len, struct hid_location *loc) 694 { 695 return (hid_get_data_sub(buf, len, loc, 1)); 696 } 697 698 uint32_t 699 hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, struct hid_location *loc) 700 { 701 return (hid_get_data_sub(buf, len, loc, 0)); 702 } 703 704 /*------------------------------------------------------------------------* 705 * hid_is_collection 706 *------------------------------------------------------------------------*/ 707 int 708 hid_is_collection(const void *desc, usb_size_t size, uint32_t usage) 709 { 710 struct hid_data *hd; 711 struct hid_item hi; 712 int err; 713 714 hd = hid_start_parse(desc, size, hid_input); 715 if (hd == NULL) 716 return (0); 717 718 while ((err = hid_get_item(hd, &hi))) { 719 if (hi.kind == hid_collection && 720 hi.usage == usage) 721 break; 722 } 723 hid_end_parse(hd); 724 return (err); 725 } 726 727 /*------------------------------------------------------------------------* 728 * hid_get_descriptor_from_usb 729 * 730 * This function will search for a HID descriptor between two USB 731 * interface descriptors. 732 * 733 * Return values: 734 * NULL: No more HID descriptors. 735 * Else: Pointer to HID descriptor. 736 *------------------------------------------------------------------------*/ 737 struct usb_hid_descriptor * 738 hid_get_descriptor_from_usb(struct usb_config_descriptor *cd, 739 struct usb_interface_descriptor *id) 740 { 741 struct usb_descriptor *desc = (void *)id; 742 743 if (desc == NULL) { 744 return (NULL); 745 } 746 while ((desc = usb_desc_foreach(cd, desc))) { 747 if ((desc->bDescriptorType == UDESC_HID) && 748 (desc->bLength >= USB_HID_DESCRIPTOR_SIZE(0))) { 749 return (void *)desc; 750 } 751 if (desc->bDescriptorType == UDESC_INTERFACE) { 752 break; 753 } 754 } 755 return (NULL); 756 } 757 758 /*------------------------------------------------------------------------* 759 * usbd_req_get_hid_desc 760 * 761 * This function will read out an USB report descriptor from the USB 762 * device. 763 * 764 * Return values: 765 * NULL: Failure. 766 * Else: Success. The pointer should eventually be passed to free(). 767 *------------------------------------------------------------------------*/ 768 usb_error_t 769 usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, 770 void **descp, uint16_t *sizep, 771 struct malloc_type *mem, uint8_t iface_index) 772 { 773 struct usb_interface *iface = usbd_get_iface(udev, iface_index); 774 struct usb_hid_descriptor *hid; 775 usb_error_t err; 776 777 if ((iface == NULL) || (iface->idesc == NULL)) { 778 return (USB_ERR_INVAL); 779 } 780 hid = hid_get_descriptor_from_usb 781 (usbd_get_config_descriptor(udev), iface->idesc); 782 783 if (hid == NULL) { 784 return (USB_ERR_IOERROR); 785 } 786 *sizep = UGETW(hid->descrs[0].wDescriptorLength); 787 if (*sizep == 0) { 788 return (USB_ERR_IOERROR); 789 } 790 if (mtx) 791 mtx_unlock(mtx); 792 793 *descp = malloc(*sizep, mem, M_ZERO | M_WAITOK); 794 795 if (mtx) 796 mtx_lock(mtx); 797 798 if (*descp == NULL) { 799 return (USB_ERR_NOMEM); 800 } 801 err = usbd_req_get_report_descriptor 802 (udev, mtx, *descp, *sizep, iface_index); 803 804 if (err) { 805 free(*descp, mem); 806 *descp = NULL; 807 return (err); 808 } 809 return (USB_ERR_NORMAL_COMPLETION); 810 } 811