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