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