1 /* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */
2 /*-
3 * SPDX-License-Identifier: BSD-2-Clause
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 "opt_hid.h"
35
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/kdb.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/sysctl.h>
43
44 #define HID_DEBUG_VAR hid_debug
45 #include <dev/hid/hid.h>
46 #include <dev/hid/hidquirk.h>
47
48 #include "hid_if.h"
49
50 /*
51 * Define this unconditionally in case a kernel module is loaded that
52 * has been compiled with debugging options.
53 */
54 int hid_debug = 0;
55
56 SYSCTL_NODE(_hw, OID_AUTO, hid, CTLFLAG_RW, 0, "HID debugging");
57 SYSCTL_INT(_hw_hid, OID_AUTO, debug, CTLFLAG_RWTUN,
58 &hid_debug, 0, "Debug level");
59
60 static void hid_clear_local(struct hid_item *);
61 static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize);
62
63 static hid_test_quirk_t hid_test_quirk_w;
64 hid_test_quirk_t *hid_test_quirk_p = &hid_test_quirk_w;
65
66 #define MAXUSAGE 64
67 #define MAXPUSH 4
68 #define MAXID 16
69 #define MAXLOCCNT 2048
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 uint32_t ncount; /* end usage item count */
88 uint32_t icount; /* current usage item count */
89 uint8_t kindset; /* we have 5 kinds so 8 bits are enough */
90 uint8_t pushlevel; /* current pushlevel */
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
hid_clear_local(struct hid_item * c)101 hid_clear_local(struct hid_item *c)
102 {
103
104 c->loc.count = 0;
105 c->loc.size = 0;
106 c->nusages = 0;
107 memset(c->usages, 0, sizeof(c->usages));
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
hid_switch_rid(struct hid_data * s,struct hid_item * c,int32_t next_rID)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 *
hid_start_parse(const void * d,hid_size_t len,int kindset)175 hid_start_parse(const void *d, hid_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 = malloc(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
hid_end_parse(struct hid_data * s)196 hid_end_parse(struct hid_data *s)
197 {
198 if (s == NULL)
199 return;
200
201 free(s, M_TEMP);
202 }
203
204 /*------------------------------------------------------------------------*
205 * get byte from HID descriptor
206 *------------------------------------------------------------------------*/
207 static uint8_t
hid_get_byte(struct hid_data * s,const uint16_t wSize)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
hid_get_item(struct hid_data * s,struct hid_item * h)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 c->nusages = 1;
270 /* array type HID item may have multiple usages */
271 while ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 &&
272 s->iusage < s->nusage && c->nusages < HID_ITEM_MAXUSAGE)
273 c->usages[c->nusages++] = s->usages_min[s->iusage++];
274 if ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 &&
275 s->iusage < s->nusage)
276 DPRINTFN(0, "HID_ITEM_MAXUSAGE should be increased "
277 "up to %hhu to parse the HID report descriptor\n",
278 s->nusage);
279 s->icount ++;
280 /*
281 * Only copy HID item, increment position and return
282 * if correct kindset!
283 */
284 if (s->kindset & (1 << c->kind)) {
285 *h = *c;
286 DPRINTFN(1, "%u,%u,%u\n", h->loc.pos,
287 h->loc.size, h->loc.count);
288 c->loc.pos += c->loc.size * c->loc.count;
289 return (1);
290 }
291 }
292
293 /* reset state variables */
294 s->icount = 0;
295 s->ncount = 0;
296 s->iusage = 0;
297 s->nusage = 0;
298 s->susage = 0;
299 s->ousage = 0;
300 hid_clear_local(c);
301
302 /* get next item */
303 while (s->p != s->end) {
304 bSize = hid_get_byte(s, 1);
305 if (bSize == 0xfe) {
306 /* long item */
307 bSize = hid_get_byte(s, 1);
308 bSize |= hid_get_byte(s, 1) << 8;
309 bTag = hid_get_byte(s, 1);
310 bType = 0xff; /* XXX what should it be */
311 } else {
312 /* short item */
313 bTag = bSize >> 4;
314 bType = (bSize >> 2) & 3;
315 bSize &= 3;
316 if (bSize == 3)
317 bSize = 4;
318 }
319 switch (bSize) {
320 case 0:
321 dval = 0;
322 mask = 0;
323 break;
324 case 1:
325 dval = (int8_t)hid_get_byte(s, 1);
326 mask = 0xFF;
327 break;
328 case 2:
329 dval = hid_get_byte(s, 1);
330 dval |= hid_get_byte(s, 1) << 8;
331 dval = (int16_t)dval;
332 mask = 0xFFFF;
333 break;
334 case 4:
335 dval = hid_get_byte(s, 1);
336 dval |= hid_get_byte(s, 1) << 8;
337 dval |= hid_get_byte(s, 1) << 16;
338 dval |= hid_get_byte(s, 1) << 24;
339 mask = 0xFFFFFFFF;
340 break;
341 default:
342 dval = hid_get_byte(s, bSize);
343 DPRINTFN(0, "bad length %u (data=0x%02x)\n",
344 bSize, dval);
345 continue;
346 }
347
348 switch (bType) {
349 case 0: /* Main */
350 switch (bTag) {
351 case 8: /* Input */
352 c->kind = hid_input;
353 ret:
354 c->flags = dval;
355 c->loc.count = s->loc_count;
356 c->loc.size = s->loc_size;
357
358 if (c->flags & HIO_VARIABLE) {
359 /* range check usage count */
360 if (c->loc.count > MAXLOCCNT) {
361 DPRINTFN(0, "Number of "
362 "items(%u) truncated to %u\n",
363 (unsigned)(c->loc.count),
364 MAXLOCCNT);
365 s->ncount = MAXLOCCNT;
366 } else
367 s->ncount = c->loc.count;
368
369 /*
370 * The "top" loop will return
371 * one and one item:
372 */
373 c->loc.count = 1;
374 } else {
375 s->ncount = 1;
376 }
377 goto top;
378
379 case 9: /* Output */
380 c->kind = hid_output;
381 goto ret;
382 case 10: /* Collection */
383 c->kind = hid_collection;
384 c->collection = dval;
385 c->collevel++;
386 c->usage = s->usage_last;
387 c->nusages = 1;
388 *h = *c;
389 return (1);
390 case 11: /* Feature */
391 c->kind = hid_feature;
392 goto ret;
393 case 12: /* End collection */
394 c->kind = hid_endcollection;
395 if (c->collevel == 0) {
396 DPRINTFN(0, "invalid end collection\n");
397 return (0);
398 }
399 c->collevel--;
400 *h = *c;
401 return (1);
402 default:
403 DPRINTFN(0, "Main bTag=%d\n", bTag);
404 break;
405 }
406 break;
407 case 1: /* Global */
408 switch (bTag) {
409 case 0:
410 c->_usage_page = dval << 16;
411 break;
412 case 1:
413 c->logical_minimum = dval;
414 break;
415 case 2:
416 c->logical_maximum = dval;
417 break;
418 case 3:
419 c->physical_minimum = dval;
420 break;
421 case 4:
422 c->physical_maximum = dval;
423 break;
424 case 5:
425 c->unit_exponent = dval;
426 break;
427 case 6:
428 c->unit = dval;
429 break;
430 case 7:
431 /* mask because value is unsigned */
432 s->loc_size = dval & mask;
433 break;
434 case 8:
435 hid_switch_rid(s, c, dval & mask);
436 break;
437 case 9:
438 /* mask because value is unsigned */
439 s->loc_count = dval & mask;
440 break;
441 case 10: /* Push */
442 /* stop parsing, if invalid push level */
443 if ((s->pushlevel + 1) >= MAXPUSH) {
444 DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel);
445 return (0);
446 }
447 s->pushlevel ++;
448 s->cur[s->pushlevel] = *c;
449 /* store size and count */
450 c->loc.size = s->loc_size;
451 c->loc.count = s->loc_count;
452 /* update current item pointer */
453 c = &s->cur[s->pushlevel];
454 break;
455 case 11: /* Pop */
456 /* stop parsing, if invalid push level */
457 if (s->pushlevel == 0) {
458 DPRINTFN(0, "Cannot pop item @ 0\n");
459 return (0);
460 }
461 s->pushlevel --;
462 /* preserve position */
463 oldpos = c->loc.pos;
464 c = &s->cur[s->pushlevel];
465 /* restore size and count */
466 s->loc_size = c->loc.size;
467 s->loc_count = c->loc.count;
468 /* set default item location */
469 c->loc.pos = oldpos;
470 c->loc.size = 0;
471 c->loc.count = 0;
472 break;
473 default:
474 DPRINTFN(0, "Global bTag=%d\n", bTag);
475 break;
476 }
477 break;
478 case 2: /* Local */
479 switch (bTag) {
480 case 0:
481 if (bSize != 4)
482 dval = (dval & mask) | c->_usage_page;
483
484 /* set last usage, in case of a collection */
485 s->usage_last = dval;
486
487 if (s->nusage < MAXUSAGE) {
488 s->usages_min[s->nusage] = dval;
489 s->usages_max[s->nusage] = dval;
490 s->nusage ++;
491 } else {
492 DPRINTFN(0, "max usage reached\n");
493 }
494
495 /* clear any pending usage sets */
496 s->susage = 0;
497 break;
498 case 1:
499 s->susage |= 1;
500
501 if (bSize != 4)
502 dval = (dval & mask) | c->_usage_page;
503 c->usage_minimum = dval;
504
505 goto check_set;
506 case 2:
507 s->susage |= 2;
508
509 if (bSize != 4)
510 dval = (dval & mask) | c->_usage_page;
511 c->usage_maximum = dval;
512
513 check_set:
514 if (s->susage != 3)
515 break;
516
517 /* sanity check */
518 if ((s->nusage < MAXUSAGE) &&
519 (c->usage_minimum <= c->usage_maximum)) {
520 /* add usage range */
521 s->usages_min[s->nusage] =
522 c->usage_minimum;
523 s->usages_max[s->nusage] =
524 c->usage_maximum;
525 s->nusage ++;
526 } else {
527 DPRINTFN(0, "Usage set dropped\n");
528 }
529 s->susage = 0;
530 break;
531 case 3:
532 c->designator_index = dval;
533 break;
534 case 4:
535 c->designator_minimum = dval;
536 break;
537 case 5:
538 c->designator_maximum = dval;
539 break;
540 case 7:
541 c->string_index = dval;
542 break;
543 case 8:
544 c->string_minimum = dval;
545 break;
546 case 9:
547 c->string_maximum = dval;
548 break;
549 case 10:
550 c->set_delimiter = dval;
551 break;
552 default:
553 DPRINTFN(0, "Local bTag=%d\n", bTag);
554 break;
555 }
556 break;
557 default:
558 DPRINTFN(0, "default bType=%d\n", bType);
559 break;
560 }
561 }
562 return (0);
563 }
564
565 /*------------------------------------------------------------------------*
566 * hid_report_size
567 *------------------------------------------------------------------------*/
568 int
hid_report_size(const void * buf,hid_size_t len,enum hid_kind k,uint8_t id)569 hid_report_size(const void *buf, hid_size_t len, enum hid_kind k, uint8_t id)
570 {
571 struct hid_data *d;
572 struct hid_item h;
573 uint32_t temp;
574 uint32_t hpos;
575 uint32_t lpos;
576 int report_id = 0;
577
578 hpos = 0;
579 lpos = 0xFFFFFFFF;
580
581 for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) {
582 if (h.kind == k && h.report_ID == id) {
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 if (h.report_ID != 0)
592 report_id = 1;
593 }
594 }
595 hid_end_parse(d);
596
597 /* safety check - can happen in case of currupt descriptors */
598 if (lpos > hpos)
599 temp = 0;
600 else
601 temp = hpos - lpos;
602
603 /* return length in bytes rounded up */
604 return ((temp + 7) / 8 + report_id);
605 }
606
607 int
hid_report_size_max(const void * buf,hid_size_t len,enum hid_kind k,uint8_t * id)608 hid_report_size_max(const void *buf, hid_size_t len, enum hid_kind k,
609 uint8_t *id)
610 {
611 struct hid_data *d;
612 struct hid_item h;
613 uint32_t temp;
614 uint32_t hpos;
615 uint32_t lpos;
616 uint8_t any_id;
617
618 any_id = 0;
619 hpos = 0;
620 lpos = 0xFFFFFFFF;
621
622 for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) {
623 if (h.kind == k) {
624 /* check for ID-byte presence */
625 if ((h.report_ID != 0) && !any_id) {
626 if (id != NULL)
627 *id = h.report_ID;
628 any_id = 1;
629 }
630 /* compute minimum */
631 if (lpos > h.loc.pos)
632 lpos = h.loc.pos;
633 /* compute end position */
634 temp = h.loc.pos + (h.loc.size * h.loc.count);
635 /* compute maximum */
636 if (hpos < temp)
637 hpos = temp;
638 }
639 }
640 hid_end_parse(d);
641
642 /* safety check - can happen in case of currupt descriptors */
643 if (lpos > hpos)
644 temp = 0;
645 else
646 temp = hpos - lpos;
647
648 /* check for ID byte */
649 if (any_id)
650 temp += 8;
651 else if (id != NULL)
652 *id = 0;
653
654 /* return length in bytes rounded up */
655 return ((temp + 7) / 8);
656 }
657
658 /*------------------------------------------------------------------------*
659 * hid_locate
660 *------------------------------------------------------------------------*/
661 int
hid_locate(const void * desc,hid_size_t size,int32_t u,enum hid_kind k,uint8_t index,struct hid_location * loc,uint32_t * flags,uint8_t * id)662 hid_locate(const void *desc, hid_size_t size, int32_t u, enum hid_kind k,
663 uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id)
664 {
665 struct hid_data *d;
666 struct hid_item h;
667 int i;
668
669 for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) {
670 for (i = 0; i < h.nusages; i++) {
671 if (h.kind == k && h.usages[i] == u) {
672 if (index--)
673 break;
674 if (loc != NULL)
675 *loc = h.loc;
676 if (flags != NULL)
677 *flags = h.flags;
678 if (id != NULL)
679 *id = h.report_ID;
680 hid_end_parse(d);
681 return (1);
682 }
683 }
684 }
685 if (loc != NULL)
686 loc->size = 0;
687 if (flags != NULL)
688 *flags = 0;
689 if (id != NULL)
690 *id = 0;
691 hid_end_parse(d);
692 return (0);
693 }
694
695 /*------------------------------------------------------------------------*
696 * hid_get_data
697 *------------------------------------------------------------------------*/
698 static uint32_t
hid_get_data_sub(const uint8_t * buf,hid_size_t len,struct hid_location * loc,int is_signed)699 hid_get_data_sub(const uint8_t *buf, hid_size_t len, struct hid_location *loc,
700 int is_signed)
701 {
702 uint32_t hpos = loc->pos;
703 uint32_t hsize = loc->size;
704 uint32_t data;
705 uint32_t rpos;
706 uint8_t n;
707
708 DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize);
709
710 /* Range check and limit */
711 if (hsize == 0)
712 return (0);
713 if (hsize > 32)
714 hsize = 32;
715
716 /* Get data in a safe way */
717 data = 0;
718 rpos = (hpos / 8);
719 n = (hsize + 7) / 8;
720 rpos += n;
721 while (n--) {
722 rpos--;
723 if (rpos < len)
724 data |= buf[rpos] << (8 * n);
725 }
726
727 /* Correctly shift down data */
728 data = (data >> (hpos % 8));
729 n = 32 - hsize;
730
731 /* Mask and sign extend in one */
732 if (is_signed != 0)
733 data = (int32_t)((int32_t)data << n) >> n;
734 else
735 data = (uint32_t)((uint32_t)data << n) >> n;
736
737 DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n",
738 loc->pos, loc->size, (long)data);
739 return (data);
740 }
741
742 int32_t
hid_get_data(const uint8_t * buf,hid_size_t len,struct hid_location * loc)743 hid_get_data(const uint8_t *buf, hid_size_t len, struct hid_location *loc)
744 {
745 return (hid_get_data_sub(buf, len, loc, 1));
746 }
747
748 uint32_t
hid_get_udata(const uint8_t * buf,hid_size_t len,struct hid_location * loc)749 hid_get_udata(const uint8_t *buf, hid_size_t len, struct hid_location *loc)
750 {
751 return (hid_get_data_sub(buf, len, loc, 0));
752 }
753
754 /*------------------------------------------------------------------------*
755 * hid_put_data
756 *------------------------------------------------------------------------*/
757 void
hid_put_udata(uint8_t * buf,hid_size_t len,struct hid_location * loc,unsigned int value)758 hid_put_udata(uint8_t *buf, hid_size_t len,
759 struct hid_location *loc, unsigned int value)
760 {
761 uint32_t hpos = loc->pos;
762 uint32_t hsize = loc->size;
763 uint64_t data;
764 uint64_t mask;
765 uint32_t rpos;
766 uint8_t n;
767
768 DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value);
769
770 /* Range check and limit */
771 if (hsize == 0)
772 return;
773 if (hsize > 32)
774 hsize = 32;
775
776 /* Put data in a safe way */
777 rpos = (hpos / 8);
778 n = (hsize + 7) / 8;
779 data = ((uint64_t)value) << (hpos % 8);
780 mask = ((1ULL << hsize) - 1ULL) << (hpos % 8);
781 rpos += n;
782 while (n--) {
783 rpos--;
784 if (rpos < len) {
785 buf[rpos] &= ~(mask >> (8 * n));
786 buf[rpos] |= (data >> (8 * n));
787 }
788 }
789 }
790
791 /*------------------------------------------------------------------------*
792 * hid_is_collection
793 *------------------------------------------------------------------------*/
794 int
hid_is_collection(const void * desc,hid_size_t size,int32_t usage)795 hid_is_collection(const void *desc, hid_size_t size, int32_t usage)
796 {
797 struct hid_data *hd;
798 struct hid_item hi;
799 int err;
800
801 hd = hid_start_parse(desc, size, 0);
802 if (hd == NULL)
803 return (0);
804
805 while ((err = hid_get_item(hd, &hi))) {
806 if (hi.kind == hid_collection &&
807 hi.usage == usage)
808 break;
809 }
810 hid_end_parse(hd);
811 return (err);
812 }
813
814 /*------------------------------------------------------------------------*
815 * calculate HID item resolution. unit/mm for distances, unit/rad for angles
816 *------------------------------------------------------------------------*/
817 int32_t
hid_item_resolution(struct hid_item * hi)818 hid_item_resolution(struct hid_item *hi)
819 {
820 /*
821 * hid unit scaling table according to HID Usage Table Review
822 * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf
823 */
824 static const int64_t scale[0x10][2] = {
825 [0x00] = { 1, 1 },
826 [0x01] = { 1, 10 },
827 [0x02] = { 1, 100 },
828 [0x03] = { 1, 1000 },
829 [0x04] = { 1, 10000 },
830 [0x05] = { 1, 100000 },
831 [0x06] = { 1, 1000000 },
832 [0x07] = { 1, 10000000 },
833 [0x08] = { 100000000, 1 },
834 [0x09] = { 10000000, 1 },
835 [0x0A] = { 1000000, 1 },
836 [0x0B] = { 100000, 1 },
837 [0x0C] = { 10000, 1 },
838 [0x0D] = { 1000, 1 },
839 [0x0E] = { 100, 1 },
840 [0x0F] = { 10, 1 },
841 };
842 int64_t logical_size;
843 int64_t physical_size;
844 int64_t multiplier;
845 int64_t divisor;
846 int64_t resolution;
847
848 switch (hi->unit) {
849 case HUM_CENTIMETER:
850 multiplier = 1;
851 divisor = 10;
852 break;
853 case HUM_INCH:
854 case HUM_INCH_EGALAX:
855 multiplier = 10;
856 divisor = 254;
857 break;
858 case HUM_RADIAN:
859 multiplier = 1;
860 divisor = 1;
861 break;
862 case HUM_DEGREE:
863 multiplier = 573;
864 divisor = 10;
865 break;
866 default:
867 return (0);
868 }
869
870 if ((hi->logical_maximum <= hi->logical_minimum) ||
871 (hi->physical_maximum <= hi->physical_minimum) ||
872 (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale)))
873 return (0);
874
875 logical_size = (int64_t)hi->logical_maximum -
876 (int64_t)hi->logical_minimum;
877 physical_size = (int64_t)hi->physical_maximum -
878 (int64_t)hi->physical_minimum;
879 /* Round to ceiling */
880 resolution = logical_size * multiplier * scale[hi->unit_exponent][0] /
881 (physical_size * divisor * scale[hi->unit_exponent][1]);
882
883 if (resolution > INT32_MAX)
884 return (0);
885
886 return (resolution);
887 }
888
889 /*------------------------------------------------------------------------*
890 * hid_is_mouse
891 *
892 * This function will decide if a USB descriptor belongs to a USB mouse.
893 *
894 * Return values:
895 * Zero: Not a USB mouse.
896 * Else: Is a USB mouse.
897 *------------------------------------------------------------------------*/
898 int
hid_is_mouse(const void * d_ptr,uint16_t d_len)899 hid_is_mouse(const void *d_ptr, uint16_t d_len)
900 {
901 struct hid_data *hd;
902 struct hid_item hi;
903 int mdepth;
904 int found;
905
906 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
907 if (hd == NULL)
908 return (0);
909
910 mdepth = 0;
911 found = 0;
912
913 while (hid_get_item(hd, &hi)) {
914 switch (hi.kind) {
915 case hid_collection:
916 if (mdepth != 0)
917 mdepth++;
918 else if (hi.collection == 1 &&
919 hi.usage ==
920 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
921 mdepth++;
922 break;
923 case hid_endcollection:
924 if (mdepth != 0)
925 mdepth--;
926 break;
927 case hid_input:
928 if (mdepth == 0)
929 break;
930 if (hi.usage ==
931 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
932 (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
933 found++;
934 if (hi.usage ==
935 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
936 (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
937 found++;
938 break;
939 default:
940 break;
941 }
942 }
943 hid_end_parse(hd);
944 return (found);
945 }
946
947 /*------------------------------------------------------------------------*
948 * hid_is_keyboard
949 *
950 * This function will decide if a USB descriptor belongs to a USB keyboard.
951 *
952 * Return values:
953 * Zero: Not a USB keyboard.
954 * Else: Is a USB keyboard.
955 *------------------------------------------------------------------------*/
956 int
hid_is_keyboard(const void * d_ptr,uint16_t d_len)957 hid_is_keyboard(const void *d_ptr, uint16_t d_len)
958 {
959 if (hid_is_collection(d_ptr, d_len,
960 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
961 return (1);
962 return (0);
963 }
964
965 /*------------------------------------------------------------------------*
966 * hid_test_quirk - test a device for a given quirk
967 *
968 * Return values:
969 * false: The HID device does not have the given quirk.
970 * true: The HID device has the given quirk.
971 *------------------------------------------------------------------------*/
972 bool
hid_test_quirk(const struct hid_device_info * dev_info,uint16_t quirk)973 hid_test_quirk(const struct hid_device_info *dev_info, uint16_t quirk)
974 {
975 bool found;
976 uint8_t x;
977
978 if (quirk == HQ_NONE)
979 return (false);
980
981 /* search the automatic per device quirks first */
982 for (x = 0; x != HID_MAX_AUTO_QUIRK; x++) {
983 if (dev_info->autoQuirk[x] == quirk)
984 return (true);
985 }
986
987 /* search global quirk table, if any */
988 found = (hid_test_quirk_p) (dev_info, quirk);
989
990 return (found);
991 }
992
993 static bool
hid_test_quirk_w(const struct hid_device_info * dev_info,uint16_t quirk)994 hid_test_quirk_w(const struct hid_device_info *dev_info, uint16_t quirk)
995 {
996 return (false); /* no match */
997 }
998
999 int
hid_add_dynamic_quirk(struct hid_device_info * dev_info,uint16_t quirk)1000 hid_add_dynamic_quirk(struct hid_device_info *dev_info, uint16_t quirk)
1001 {
1002 uint8_t x;
1003
1004 for (x = 0; x != HID_MAX_AUTO_QUIRK; x++) {
1005 if (dev_info->autoQuirk[x] == 0 ||
1006 dev_info->autoQuirk[x] == quirk) {
1007 dev_info->autoQuirk[x] = quirk;
1008 return (0); /* success */
1009 }
1010 }
1011 return (ENOSPC);
1012 }
1013
1014 void
hid_quirk_unload(void * arg)1015 hid_quirk_unload(void *arg)
1016 {
1017 /* reset function pointer */
1018 hid_test_quirk_p = &hid_test_quirk_w;
1019 #ifdef NOT_YET
1020 hidquirk_ioctl_p = &hidquirk_ioctl_w;
1021 #endif
1022
1023 /* wait for CPU to exit the loaded functions, if any */
1024
1025 /* XXX this is a tradeoff */
1026
1027 pause("WAIT", hz);
1028 }
1029
1030 int
hid_intr_start(device_t dev)1031 hid_intr_start(device_t dev)
1032 {
1033 return (HID_INTR_START(device_get_parent(dev), dev));
1034 }
1035
1036 int
hid_intr_stop(device_t dev)1037 hid_intr_stop(device_t dev)
1038 {
1039 return (HID_INTR_STOP(device_get_parent(dev), dev));
1040 }
1041
1042 void
hid_intr_poll(device_t dev)1043 hid_intr_poll(device_t dev)
1044 {
1045 HID_INTR_POLL(device_get_parent(dev), dev);
1046 }
1047
1048 int
hid_get_rdesc(device_t dev,void * data,hid_size_t len)1049 hid_get_rdesc(device_t dev, void *data, hid_size_t len)
1050 {
1051 return (HID_GET_RDESC(device_get_parent(dev), dev, data, len));
1052 }
1053
1054 int
hid_read(device_t dev,void * data,hid_size_t maxlen,hid_size_t * actlen)1055 hid_read(device_t dev, void *data, hid_size_t maxlen, hid_size_t *actlen)
1056 {
1057 return (HID_READ(device_get_parent(dev), dev, data, maxlen, actlen));
1058 }
1059
1060 int
hid_write(device_t dev,const void * data,hid_size_t len)1061 hid_write(device_t dev, const void *data, hid_size_t len)
1062 {
1063 return (HID_WRITE(device_get_parent(dev), dev, data, len));
1064 }
1065
1066 int
hid_get_report(device_t dev,void * data,hid_size_t maxlen,hid_size_t * actlen,uint8_t type,uint8_t id)1067 hid_get_report(device_t dev, void *data, hid_size_t maxlen, hid_size_t *actlen,
1068 uint8_t type, uint8_t id)
1069 {
1070 return (HID_GET_REPORT(device_get_parent(dev), dev, data, maxlen,
1071 actlen, type, id));
1072 }
1073
1074 int
hid_set_report(device_t dev,const void * data,hid_size_t len,uint8_t type,uint8_t id)1075 hid_set_report(device_t dev, const void *data, hid_size_t len, uint8_t type,
1076 uint8_t id)
1077 {
1078 return (HID_SET_REPORT(device_get_parent(dev), dev, data, len, type,
1079 id));
1080 }
1081
1082 int
hid_set_idle(device_t dev,uint16_t duration,uint8_t id)1083 hid_set_idle(device_t dev, uint16_t duration, uint8_t id)
1084 {
1085 return (HID_SET_IDLE(device_get_parent(dev), dev, duration, id));
1086 }
1087
1088 int
hid_set_protocol(device_t dev,uint16_t protocol)1089 hid_set_protocol(device_t dev, uint16_t protocol)
1090 {
1091 return (HID_SET_PROTOCOL(device_get_parent(dev), dev, protocol));
1092 }
1093
1094 int
hid_ioctl(device_t dev,unsigned long cmd,uintptr_t data)1095 hid_ioctl(device_t dev, unsigned long cmd, uintptr_t data)
1096 {
1097 return (HID_IOCTL(device_get_parent(dev), dev, cmd, data));
1098 }
1099
1100 MODULE_VERSION(hid, 1);
1101