xref: /freebsd-13-stable/sys/dev/hid/hid.c (revision ecf605de97b702ef09c64ee51c5a70f427ae0bfa)
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