1/* 2 * \brief This file contains class specific functions for human interface 3 * devices such as keyboard and mouse 4 * 5 * USB Device Class 0x03 6 * =========================================================================== 7 */ 8 9/* 10 * Copyright (c) 2007-2013 ETH Zurich. 11 * All rights reserved. 12 * 13 * This file is distributed under the terms in the attached LICENSE file. 14 * If you do not find this file, copies can be found by writing to: 15 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 16 */ 17 18#include <stdlib.h> 19#include <stdio.h> 20#include <string.h> 21#include <barrelfish/barrelfish.h> 22 23#include <usb/usb.h> 24#include <usb/usb_request.h> 25#include <usb/usb_device.h> 26#include <usb/usb_parse.h> 27#include <usb/class/usb_hid.h> 28 29/** 30 * \brief clears out the local data of a HID item descriptor 31 */ 32static void usb_hid_item_clear_local(struct usb_hid_item *c) 33{ 34 c->loc.count = 0; 35 c->loc.size = 0; 36 c->usage = 0; 37 c->usage_minimum = 0; 38 c->usage_maximum = 0; 39 c->designator_index = 0; 40 c->designator_minimum = 0; 41 c->designator_maximum = 0; 42 c->string_index = 0; 43 c->string_minimum = 0; 44 c->string_maximum = 0; 45 c->set_delimiter = 0; 46} 47 48/** 49 * \brief this function switches the report ID of an hid item with the 50 * new value 51 * 52 * \param s the current HID data 53 * \param c the current HID item 54 * \param next_rID the report id to set 55 */ 56static void usb_hid_switch_reportid(struct usb_hid_data *s, 57 struct usb_hid_item *c, int32_t next_rID) 58{ 59 uint8_t i; 60 61 /* check for same report ID - optimize */ 62 63 if (c->report_ID == next_rID) 64 return; 65 66 /* save current position for current rID */ 67 68 if (c->report_ID == 0) { 69 i = 0; 70 } else { 71 for (i = 1; i != USB_HID_MAXID; i++) { 72 if (s->last_pos[i].rid == c->report_ID) 73 break; 74 if (s->last_pos[i].rid == 0) 75 break; 76 } 77 } 78 if (i != USB_HID_MAXID) { 79 s->last_pos[i].rid = c->report_ID; 80 s->last_pos[i].position = c->loc.position; 81 } 82 83 /* store next report ID */ 84 85 c->report_ID = next_rID; 86 87 /* lookup last position for next rID */ 88 89 if (next_rID == 0) { 90 i = 0; 91 } else { 92 for (i = 1; i != USB_HID_MAXID; i++) { 93 if (s->last_pos[i].rid == next_rID) 94 break; 95 if (s->last_pos[i].rid == 0) 96 break; 97 } 98 } 99 if (i != USB_HID_MAXID) { 100 s->last_pos[i].rid = next_rID; 101 c->loc.position = s->last_pos[i].position; 102 } else { 103 debug_printf("Out of RID entries, position is set to zero!\n"); 104 c->loc.position = 0; 105 } 106} 107 108/** 109 * \brief allocates a new usb_hid_data structure for parsing the USB HID 110 * reports 111 * 112 * \param d initial data pointer 113 * \param len length of the data 114 * \param kindset the kindset 115 * 116 * \return pointer to the usb_hid_data structure on sucess 117 * NULL on failure 118 */ 119struct usb_hid_data *usb_hid_start_parse(const void *d, uint32_t len, 120 int32_t kindset) 121{ 122 struct usb_hid_data *s; 123 124 if ((kindset - 1) & kindset) { 125 debug_printf("WARNING: Only one bit can be set in the kindset\n"); 126 return (NULL); 127 } 128 129 s = malloc(sizeof(*s)); 130 memset(s, 0, sizeof(*s)); 131 s->start = s->p = d; 132 s->end = ((const uint8_t *) d) + len; 133 s->kindset = kindset; 134 return (s); 135} 136 137/** 138 * \brief frees up the usb_hid_data structure from parsiDPRINTFNng the report 139 * descriptor 140 * 141 * \param s the usb_hid_data structure to be freed 142 */ 143void usb_hid_end_parse(struct usb_hid_data *s) 144{ 145 if (s == NULL) 146 return; 147 148 free(s); 149} 150 151/** 152 * \brief gets the next byte when parsing the USB HID report descriptor 153 * 154 * \param s pointer to the parsing state 155 * \param wSize bytes to advance the data pointer 156 * 157 * \return the next byte on success 158 * 0 on failure 159 */ 160static uint8_t usb_hid_get_byte(struct usb_hid_data *s, const uint16_t wSize) 161{ 162 const uint8_t *ptr; 163 uint8_t retval; 164 165 ptr = s->p; 166 167 /* check if end is reached */ 168 if (ptr == s->end) 169 return (0); 170 171 /* read out a byte */ 172 retval = *ptr; 173 174 /* check if data pointer can be advanced by "wSize" bytes */ 175 if ((s->end - ptr) < wSize) 176 ptr = s->end; 177 else 178 ptr += wSize; 179 180 /* update pointer */ 181 s->p = ptr; 182 183 return (retval); 184} 185 186/** 187 * \brief this function gets the the next usb_hid_item from the report 188 * descriptor according to the current parsing state 189 * 190 * \param s the current parsing state 191 * \param h pointer where to store the returned data 192 * 193 * \return 0: on failure 194 * 1: on success 195 */ 196int32_t usb_hid_get_item(struct usb_hid_data *s, struct usb_hid_item *h) 197{ 198 struct usb_hid_item *c; 199 uint32_t bTag, bType, bSize; 200 uint32_t oldpos; 201 int32_t mask; 202 int32_t dval; 203 204 if (s == NULL) 205 return (0); 206 207 c = &s->cur[s->pushlevel]; 208 209 top: 210 /* check if there is an array of items */ 211 if (s->icount < s->ncount) { 212 /* get current usage */ 213 if (s->iusage < s->nusage) { 214 dval = s->usages_min[s->iusage] + s->ousage; 215 c->usage = dval; 216 s->usage_last = dval; 217 if (dval == s->usages_max[s->iusage]) { 218 s->iusage++; 219 s->ousage = 0; 220 } else { 221 s->ousage++; 222 } 223 } else { 224 dval = s->usage_last; 225 } 226 s->icount++; 227 /* 228 * Only copy HID item, increment position and return 229 * if correct kindset! 230 */ 231 if (s->kindset & (1 << c->kind)) { 232 *h = *c; 233 c->loc.position += c->loc.size * c->loc.count; 234 return (1); 235 } 236 } 237 238 /* reset state variables */ 239 s->icount = 0; 240 s->ncount = 0; 241 s->iusage = 0; 242 s->nusage = 0; 243 s->susage = 0; 244 s->ousage = 0; 245 usb_hid_item_clear_local(c); 246 247 /* get next item */ 248 while (s->p != s->end) { 249 250 bSize = usb_hid_get_byte(s, 1); 251 if (bSize == 0xfe) { 252 /* long item */ 253 bSize = usb_hid_get_byte(s, 1); 254 bSize |= usb_hid_get_byte(s, 1) << 8; 255 bTag = usb_hid_get_byte(s, 1); 256 bType = 0xff; /* XXX what should it be */ 257 } else { 258 /* short item */ 259 bTag = bSize >> 4; 260 bType = (bSize >> 2) & 3; 261 bSize &= 3; 262 if (bSize == 3) 263 bSize = 4; 264 } 265 switch (bSize) { 266 case 0: 267 dval = 0; 268 mask = 0; 269 break; 270 case 1: 271 dval = (int8_t) usb_hid_get_byte(s, 1); 272 mask = 0xFF; 273 break; 274 case 2: 275 dval = usb_hid_get_byte(s, 1); 276 dval |= usb_hid_get_byte(s, 1) << 8; 277 dval = (int16_t) dval; 278 mask = 0xFFFF; 279 break; 280 case 4: 281 dval = usb_hid_get_byte(s, 1); 282 dval |= usb_hid_get_byte(s, 1) << 8; 283 dval |= usb_hid_get_byte(s, 1) << 16; 284 dval |= usb_hid_get_byte(s, 1) << 24; 285 mask = 0xFFFFFFFF; 286 break; 287 default: 288 dval = usb_hid_get_byte(s, bSize); 289 USB_DEBUG("bad length %"PRIu32" (data=0x%02"PRId32")\n", bSize, dval); 290 continue; 291 } 292 293 switch (bType) { 294 case 0: /* Main */ 295 switch (bTag) { 296 case 8: /* Input */ 297 c->kind = USB_HID_KIND_INPUT; 298 c->flags = dval; 299 ret: c->loc.count = s->loc_count; 300 c->loc.size = s->loc_size; 301 302 if (c->flags & USB_HID_IO_VARIABLE) { 303 /* range check usage count */ 304 if (c->loc.count > 255) { 305 USB_DEBUG("Number of " 306 "items truncated to 255\n"); 307 s->ncount = 255; 308 } else 309 s->ncount = c->loc.count; 310 311 /* 312 * The "top" loop will return 313 * one and one item: 314 */ 315 c->loc.count = 1; 316 } else { 317 s->ncount = 1; 318 } 319 goto top; 320 321 case 9: /* Output */ 322 c->kind = USB_HID_KIND_OUTPUT; 323 c->flags = dval; 324 goto ret; 325 case 10: /* Collection */ 326 c->kind = USB_HID_KIND_COLLECTION; 327 c->collection = dval; 328 c->collevel++; 329 c->usage = s->usage_last; 330 *h = *c; 331 return (1); 332 case 11: /* Feature */ 333 c->kind = USB_HID_KIND_FEATURE; 334 c->flags = dval; 335 goto ret; 336 case 12: /* End collection */ 337 c->kind = USB_HID_KIND_ENDCOLLECTION; 338 if (c->collevel == 0) { 339 USB_DEBUG("invalid end collection\n"); 340 return (0); 341 } 342 c->collevel--; 343 *h = *c; 344 return (1); 345 default: 346 /* noop */ 347 break; 348 } 349 break; 350 case 1: /* Global */ 351 switch (bTag) { 352 case 0: 353 c->_usage_page = dval << 16; 354 break; 355 case 1: 356 c->logical_minimum = dval; 357 break; 358 case 2: 359 c->logical_maximum = dval; 360 break; 361 case 3: 362 c->physical_minimum = dval; 363 break; 364 case 4: 365 c->physical_maximum = dval; 366 break; 367 case 5: 368 c->unit_exponent = dval; 369 break; 370 case 6: 371 c->unit = dval; 372 break; 373 case 7: 374 /* mask because value is unsigned */ 375 s->loc_size = dval & mask; 376 break; 377 case 8: 378 usb_hid_switch_reportid(s, c, dval); 379 break; 380 case 9: 381 /* mask because value is unsigned */ 382 s->loc_count = dval & mask; 383 break; 384 case 10: /* Push */ 385 s->pushlevel++; 386 if (s->pushlevel < USB_HID_MAXPUSH) { 387 s->cur[s->pushlevel] = *c; 388 /* store size and count */ 389 c->loc.size = s->loc_size; 390 c->loc.count = s->loc_count; 391 /* update current item pointer */ 392 c = &s->cur[s->pushlevel]; 393 } else { 394 USB_DEBUG("Cannot push " 395 "item @ %d\n", s->pushlevel); 396 } 397 break; 398 case 11: /* Pop */ 399 s->pushlevel--; 400 if (s->pushlevel < USB_HID_MAXPUSH) { 401 /* preserve position */ 402 oldpos = c->loc.position; 403 c = &s->cur[s->pushlevel]; 404 /* restore size and count */ 405 s->loc_size = c->loc.size; 406 s->loc_count = c->loc.count; 407 /* set default item location */ 408 c->loc.position = oldpos; 409 c->loc.size = 0; 410 c->loc.count = 0; 411 } else { 412 USB_DEBUG("Cannot pop " 413 "item @ %d\n", s->pushlevel); 414 } 415 break; 416 default: 417 /* noop */ 418 break; 419 } 420 break; 421 case 2: /* Local */ 422 switch (bTag) { 423 case 0: 424 if (bSize != 4) 425 dval = (dval & mask) | c->_usage_page; 426 427 /* set last usage, in case of a collection */ 428 s->usage_last = dval; 429 430 if (s->nusage < USB_HID_MAXUSAGE) { 431 s->usages_min[s->nusage] = dval; 432 s->usages_max[s->nusage] = dval; 433 s->nusage++; 434 } else { 435 USB_DEBUG("max usage reached\n"); 436 } 437 438 /* clear any pending usage sets */ 439 s->susage = 0; 440 break; 441 case 1: 442 s->susage |= 1; 443 444 if (bSize != 4) 445 dval = (dval & mask) | c->_usage_page; 446 c->usage_minimum = dval; 447 448 goto check_set; 449 case 2: 450 s->susage |= 2; 451 452 if (bSize != 4) 453 dval = (dval & mask) | c->_usage_page; 454 c->usage_maximum = dval; 455 456 check_set: if (s->susage != 3) 457 break; 458 459 /* sanity check */ 460 if ((s->nusage < USB_HID_MAXUSAGE) 461 && (c->usage_minimum <= c->usage_maximum)) { 462 /* add usage range */ 463 s->usages_min[s->nusage] = c->usage_minimum; 464 s->usages_max[s->nusage] = c->usage_maximum; 465 s->nusage++; 466 } else { 467 USB_DEBUG("Usage set dropped\n"); 468 } 469 s->susage = 0; 470 break; 471 case 3: 472 c->designator_index = dval; 473 break; 474 case 4: 475 c->designator_minimum = dval; 476 break; 477 case 5: 478 c->designator_maximum = dval; 479 break; 480 case 7: 481 c->string_index = dval; 482 break; 483 case 8: 484 c->string_minimum = dval; 485 break; 486 case 9: 487 c->string_maximum = dval; 488 break; 489 case 10: 490 c->set_delimiter = dval; 491 break; 492 default: 493 /* noop */ 494 break; 495 } 496 break; 497 default: 498 /* noop */ 499 break; 500 } 501 } 502 return (0); 503} 504 505/** 506 * \brief calculates the size of the USB HID report descriptor 507 * 508 * \param buf pointer to the buffer containing the data to parse 509 * \param len the length of the data in the buffer 510 * \param k the kind of the report descriptor we want to get the size of 511 * \param id the id of the descriptor we want to get 512 * 513 * \return the length of the report in bytes 514 */ 515int32_t usb_hid_report_size(const void *buf, uint32_t len, enum usb_hid_kind k, 516 uint8_t *id) 517{ 518 struct usb_hid_data *d; 519 struct usb_hid_item h; 520 uint32_t temp; 521 uint32_t hpos; 522 uint32_t lpos; 523 uint8_t any_id; 524 525 any_id = 0; 526 hpos = 0; 527 lpos = 0xFFFFFFFF; 528 529 for (d = usb_hid_start_parse(buf, len, 1 << k); usb_hid_get_item(d, &h);) { 530 if (h.kind == k) { 531 /* check for ID-byte presence */ 532 if ((h.report_ID != 0) && !any_id) { 533 if (id != NULL) 534 *id = h.report_ID; 535 any_id = 1; 536 } 537 /* compute minimum */ 538 if (lpos > h.loc.position) 539 lpos = h.loc.position; 540 /* compute end position */ 541 temp = h.loc.position + (h.loc.size * h.loc.count); 542 /* compute maximum */ 543 if (hpos < temp) 544 hpos = temp; 545 } 546 } 547 usb_hid_end_parse(d); 548 549 /* safety check - can happen in case of currupt descriptors */ 550 if (lpos > hpos) 551 temp = 0; 552 else 553 temp = hpos - lpos; 554 555 /* check for ID byte */ 556 if (any_id) 557 temp += 8; 558 else if (id != NULL) 559 *id = 0; 560 561 /* return length in bytes rounded up */ 562 return ((temp + 7) / 8); 563} 564 565/** 566 * \brief 567 * 568 * \param desc the pointer to the report descriptor descriptor 569 * \param size the size of the descriptor 570 * \param u the usage 571 * \param k the kind of the report item we want to locate 572 * \param index the index of the report with kind k we want to locate 573 * \param loc the returned location 574 * \param flags the returned flags 575 * \param id the returned id 576 * 577 * \return 0: there is no matching element 578 * Else: there is a matching element found at location loc 579 */ 580int32_t usb_hid_locate(const void *desc, uint32_t size, uint32_t usage, 581 enum usb_hid_kind k, uint8_t repindex, struct usb_hid_location *loc, 582 uint32_t *flags, uint8_t *id) 583{ 584 struct usb_hid_data *d; 585 struct usb_hid_item h; 586 587 d = usb_hid_start_parse(desc, size, 1 << k); 588 589 while (usb_hid_get_item(d, &h)) { 590 if (h.kind == k && !(h.flags & USB_HID_IO_CONST) && h.usage == usage) { 591 if (repindex--) 592 continue; 593 if (loc != NULL) 594 *loc = h.loc; 595 if (flags != NULL) 596 *flags = h.flags; 597 if (id != NULL) 598 *id = h.report_ID; 599 usb_hid_end_parse(d); 600 return (1); 601 } 602 } 603 if (loc != NULL) 604 loc->size = 0; 605 if (flags != NULL) 606 *flags = 0; 607 if (id != NULL) 608 *id = 0; 609 usb_hid_end_parse(d); 610 return (0); 611} 612 613/** 614 * \brief generic function that gets data out of some 615 * 616 * \param buf buffer containing the data 617 * \param len the length of the data in the buffer 618 * \param loc the location we want to extract 619 * \param is_signed the returned data is signed or not 620 * 621 * \return 0: on failure 622 * data: on success 623 */ 624static uint32_t usb_hid_get_data_generic(const uint8_t *buf, uint32_t len, 625 struct usb_hid_location *loc, int32_t is_signed) 626{ 627 uint32_t hpos = loc->position; 628 uint32_t hsize = loc->size; 629 uint32_t data; 630 uint32_t rpos; 631 uint8_t n; 632 633 /* Range check and limit */ 634 if (hsize == 0) 635 return (0); 636 if (hsize > 32) 637 hsize = 32; 638 639 /* Get data in a safe way */ 640 data = 0; 641 rpos = (hpos / 8); 642 n = (hsize + 7) / 8; 643 rpos += n; 644 645 while (n--) { 646 rpos--; 647 if (rpos < len) { 648 data |= buf[rpos] << (8 * n); 649 } 650 } 651 652 /* Correctly shift down data */ 653 data = (data >> (hpos % 8)); 654 n = 32 - hsize; 655 656 /* Mask and sign extend in one */ 657 if (is_signed != 0) { 658 data = (int32_t) ((int32_t) data << n) >> n; 659 } else { 660 data = (uint32_t) ((uint32_t) data << n) >> n; 661 } 662 663 USB_DEBUG_HID("Get data generic: pos=%u, size=%u, data=%x\n", hpos, hsize, data); 664 665 return (data); 666} 667 668/** 669 * \brief wrapper function for getting the data ouf of a report 670 * the data returned is signed 671 * 672 * \param buf buffer containing the data 673 * \param len the length of the data in the buffer 674 * \param loc the location we want to extract 675 * 676 * \return 0: on failure 677 * data: on sucess 678 */ 679int32_t usb_hid_get_data(const uint8_t *buf, uint32_t len, 680 struct usb_hid_location *loc) 681{ 682 return (usb_hid_get_data_generic(buf, len, loc, 1)); 683} 684 685/** 686 * \brief wrapper function for getting the data ouf of a report 687 * the data returned is unsigned 688 * 689 * \param buf buffer containing the data 690 * \param len the length of the data in the buffer 691 * \param loc the location we want to extract 692 * 693 * \return 0: on failure 694 * data: on sucess 695 */uint32_t usb_hid_get_data_unsigned(const uint8_t *buf, uint32_t len, 696 struct usb_hid_location *loc) 697{ 698 return (usb_hid_get_data_generic(buf, len, loc, 0)); 699} 700 701/* 702 * \brief inserts a data value into the report descriptor 703 * 704 * \param buf buffer containing the report descriptor 705 * \param len the length of the data in the buffer 706 * \param loc the location to put in the value 707 * \param value the value to put into the report 708 */ 709void usb_hid_put_data_unsigned(uint8_t *buf, uint32_t len, 710 struct usb_hid_location *loc, uint32_t value) 711{ 712 uint32_t hpos = loc->position; 713 uint32_t hsize = loc->size; 714 uint64_t data; 715 uint64_t mask; 716 uint32_t rpos; 717 uint8_t n; 718 719 /* Range check and limit */ 720 if (hsize == 0) 721 return; 722 if (hsize > 32) 723 hsize = 32; 724 725 /* Put data in a safe way */ 726 rpos = (hpos / 8); 727 n = (hsize + 7) / 8; 728 data = ((uint64_t) value) << (hpos % 8); 729 mask = ((1ULL << hsize) - 1ULL) << (hpos % 8); 730 rpos += n; 731 while (n--) { 732 rpos--; 733 if (rpos < len) { 734 buf[rpos] &= ~(mask >> (8 * n)); 735 buf[rpos] |= (data >> (8 * n)); 736 } 737 } 738} 739 740/* 741 * \brief checks if the HID device is a collection or a single function device 742 * 743 * \param desc the descriptor to analyize 744 * \param size the size of the descriptor to analize 745 * \param usage the usage of the device 746 * 747 * \return 1: the device is a collection 748 * 0: the device is not a collection 749 */ 750int32_t usb_hid_is_collection(const void *desc, uint32_t size, uint32_t usage) 751{ 752 struct usb_hid_data *hd; 753 struct usb_hid_item hi; 754 int32_t err; 755 756 hd = usb_hid_start_parse(desc, size, USB_HID_KIND_INPUT); 757 if (hd == NULL) 758 return (0); 759 760 while ((err = usb_hid_get_item(hd, &hi))) { 761 if (hi.kind == USB_HID_KIND_COLLECTION && hi.usage == usage) 762 break; 763 } 764 usb_hid_end_parse(hd); 765 return (err); 766} 767 768/** 769 * \brief search for a hid descriptor in a config descriptor between two 770 * interface descriptors 771 * 772 * 773 * \param cd the config descriptor to search 774 * \param id the interface descriptor to start searching 775 * 776 * \return usb_hid_descriptor on success 777 * NULL if there are moer HID descriptors 778 */ 779struct usb_hid_descriptor *usb_hid_get_descriptor_from_usb( 780 struct usb_config_descriptor *cd, struct usb_interface_descriptor *id) 781{ 782 struct usb_descriptor *desc = (void *) id; 783 784 if (desc == NULL) { 785 return (NULL); 786 } 787 788 while ((desc = usb_parse_next_descriptor(cd, desc))) { 789 if ((desc->bDescriptorType == USB_DESCRIPTOR_TYPE_HID) 790 && (desc->bLength >= USB_HID_DESCRIPTOR_SIZE(0))) { 791 return ((void *) desc); 792 } 793 if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE) { 794 break; 795 } 796 } 797 return (NULL); 798} 799 800/* 801 * \brief get the HID descriptor from the usb device using a USB request 802 * 803 * \param ret_desc the returned descriptor 804 * \param ret_size the returned size of the descriptor 805 * \param iface the interface number to get the idescriptor of 806 */ 807usb_error_t usb_hid_get_hid_descriptor(struct usb_hid_descriptor **ret_desc, 808 uint16_t *ret_size, uint8_t iface) 809{ 810 struct usb_hid_descriptor *hid; 811 812 struct usb_config_descriptor *cfg_desc = usb_device_get_cfg_desc(); 813 814 hid = usb_hid_get_descriptor_from_usb(cfg_desc, 815 (struct usb_interface_descriptor *) (cfg_desc + 1)); 816 817 if (hid == NULL) { 818 return (USB_ERR_IOERROR); 819 } 820 821 *ret_size = USB_HID_DTYPE_GET_LEN(hid->descriptors); 822 823 if (*ret_size == 0) { 824 return (USB_ERR_IOERROR); 825 } 826 827 if (*ret_desc == NULL) { 828 return (USB_ERR_NOMEM); 829 } 830 831 usb_error_t err = usb_hid_get_report_descriptor(ret_desc, *ret_size, iface); 832 833 if (err) { 834 *ret_desc = NULL; 835 return (err); 836 } 837 838 return (USB_ERR_OK); 839} 840 841/** 842 * \brief gets the report descriptor from the HID device 843 * 844 * \param d pointer to the report descriptror 845 * \param size the expected size of the report descriptor 846 * \param iface the interface we want to get the report of 847 */ 848usb_error_t usb_hid_get_report_descriptor(struct usb_hid_descriptor **d, 849 uint16_t size, uint8_t iface) 850{ 851 if (d == NULL) { 852 return (USB_ERR_INVAL); 853 } 854 struct usb_device_request req; 855 req.bType.direction = USB_REQUEST_READ; 856 req.bType.recipient = USB_REQUEST_RECIPIENT_INTERFACE; 857 req.bType.type = USB_REQUEST_TYPE_STANDARD; 858 req.bRequest = USB_HID_REQUEST_GET_DESCRIPTOR; 859 req.wValue = USB_DESCRIPTOR_TYPE_REPORT << 8; 860 req.wIndex = iface; 861 req.wLength = size; 862 863 uint16_t ret_data_length; 864 865 usb_error_t err = usb_do_request_read(&req, &ret_data_length, (void **) d); 866 867 if (err != USB_ERR_OK) { 868 *d = NULL; 869 } 870 871 if (ret_data_length != size) { 872 USB_DEBUG("WARNING: got wrong data size. \n"); 873 free(*d); 874 *d = NULL; 875 err = USB_ERR_IOERROR; 876 } 877 878 return (err); 879 880} 881 882/** 883 * \brief this function sets the idlerate of the HID device 884 * 885 * \param iface the interface to set the idle rate for 886 * \param duration the interval in 2 ms setps 887 * \param id the id of the report 888 */ 889usb_error_t usb_hid_set_idle(uint8_t iface, uint8_t duration, uint8_t id) 890{ 891 struct usb_device_request req; 892 893 req.bRequest = USB_HID_REQUEST_SET_IDLE; 894 req.bType.direction = USB_REQUEST_WRITE; 895 req.bType.recipient = USB_REQUEST_RECIPIENT_INTERFACE; 896 req.bType.type = USB_REQUEST_TYPE_CLASS; 897 898 req.wValue = (duration << 8) | id; 899 req.wIndex = iface; 900 req.wLength = 0; 901 902 return (usb_do_request(&req)); 903} 904