]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hid/hid.c
zfs: merge openzfs/zfs@75b4cbf62 (master) into main
[FreeBSD/FreeBSD.git] / sys / dev / hid / hid.c
1 /* $FreeBSD$ */
2 /*      $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $   */
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
5  *
6  * Copyright (c) 1998 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Lennart Augustsson (lennart@augustsson.net) at
11  * Carlstedt Research & Technology.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "opt_hid.h"
36
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/kdb.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
43 #include <sys/sysctl.h>
44
45 #define HID_DEBUG_VAR   hid_debug
46 #include <dev/hid/hid.h>
47 #include <dev/hid/hidquirk.h>
48
49 #include "hid_if.h"
50
51 /*
52  * Define this unconditionally in case a kernel module is loaded that
53  * has been compiled with debugging options.
54  */
55 int     hid_debug = 0;
56
57 SYSCTL_NODE(_hw, OID_AUTO, hid, CTLFLAG_RW, 0, "HID debugging");
58 SYSCTL_INT(_hw_hid, OID_AUTO, debug, CTLFLAG_RWTUN,
59     &hid_debug, 0, "Debug level");
60
61 #ifdef HIDRAW_MAKE_UHID_ALIAS
62 devclass_t hidraw_devclass;
63 #endif
64
65 static void hid_clear_local(struct hid_item *);
66 static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize);
67
68 static hid_test_quirk_t hid_test_quirk_w;
69 hid_test_quirk_t *hid_test_quirk_p = &hid_test_quirk_w;
70
71 #define MAXUSAGE 64
72 #define MAXPUSH 4
73 #define MAXID 16
74 #define MAXLOCCNT 2048
75
76 struct hid_pos_data {
77         int32_t rid;
78         uint32_t pos;
79 };
80
81 struct hid_data {
82         const uint8_t *start;
83         const uint8_t *end;
84         const uint8_t *p;
85         struct hid_item cur[MAXPUSH];
86         struct hid_pos_data last_pos[MAXID];
87         int32_t usages_min[MAXUSAGE];
88         int32_t usages_max[MAXUSAGE];
89         int32_t usage_last;     /* last seen usage */
90         uint32_t loc_size;      /* last seen size */
91         uint32_t loc_count;     /* last seen count */
92         uint32_t ncount;        /* end usage item count */
93         uint32_t icount;        /* current usage item count */
94         uint8_t kindset;        /* we have 5 kinds so 8 bits are enough */
95         uint8_t pushlevel;      /* current pushlevel */
96         uint8_t nusage;         /* end "usages_min/max" index */
97         uint8_t iusage;         /* current "usages_min/max" index */
98         uint8_t ousage;         /* current "usages_min/max" offset */
99         uint8_t susage;         /* usage set flags */
100 };
101
102 /*------------------------------------------------------------------------*
103  *      hid_clear_local
104  *------------------------------------------------------------------------*/
105 static void
106 hid_clear_local(struct hid_item *c)
107 {
108
109         c->loc.count = 0;
110         c->loc.size = 0;
111         c->nusages = 0;
112         memset(c->usages, 0, sizeof(c->usages));
113         c->usage_minimum = 0;
114         c->usage_maximum = 0;
115         c->designator_index = 0;
116         c->designator_minimum = 0;
117         c->designator_maximum = 0;
118         c->string_index = 0;
119         c->string_minimum = 0;
120         c->string_maximum = 0;
121         c->set_delimiter = 0;
122 }
123
124 static void
125 hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID)
126 {
127         uint8_t i;
128
129         /* check for same report ID - optimise */
130
131         if (c->report_ID == next_rID)
132                 return;
133
134         /* save current position for current rID */
135
136         if (c->report_ID == 0) {
137                 i = 0;
138         } else {
139                 for (i = 1; i != MAXID; i++) {
140                         if (s->last_pos[i].rid == c->report_ID)
141                                 break;
142                         if (s->last_pos[i].rid == 0)
143                                 break;
144                 }
145         }
146         if (i != MAXID) {
147                 s->last_pos[i].rid = c->report_ID;
148                 s->last_pos[i].pos = c->loc.pos;
149         }
150
151         /* store next report ID */
152
153         c->report_ID = next_rID;
154
155         /* lookup last position for next rID */
156
157         if (next_rID == 0) {
158                 i = 0;
159         } else {
160                 for (i = 1; i != MAXID; i++) {
161                         if (s->last_pos[i].rid == next_rID)
162                                 break;
163                         if (s->last_pos[i].rid == 0)
164                                 break;
165                 }
166         }
167         if (i != MAXID) {
168                 s->last_pos[i].rid = next_rID;
169                 c->loc.pos = s->last_pos[i].pos;
170         } else {
171                 DPRINTF("Out of RID entries, position is set to zero!\n");
172                 c->loc.pos = 0;
173         }
174 }
175
176 /*------------------------------------------------------------------------*
177  *      hid_start_parse
178  *------------------------------------------------------------------------*/
179 struct hid_data *
180 hid_start_parse(const void *d, hid_size_t len, int kindset)
181 {
182         struct hid_data *s;
183
184         if ((kindset-1) & kindset) {
185                 DPRINTFN(0, "Only one bit can be "
186                     "set in the kindset\n");
187                 return (NULL);
188         }
189
190         s = malloc(sizeof *s, M_TEMP, M_WAITOK | M_ZERO);
191         s->start = s->p = d;
192         s->end = ((const uint8_t *)d) + len;
193         s->kindset = kindset;
194         return (s);
195 }
196
197 /*------------------------------------------------------------------------*
198  *      hid_end_parse
199  *------------------------------------------------------------------------*/
200 void
201 hid_end_parse(struct hid_data *s)
202 {
203         if (s == NULL)
204                 return;
205
206         free(s, M_TEMP);
207 }
208
209 /*------------------------------------------------------------------------*
210  *      get byte from HID descriptor
211  *------------------------------------------------------------------------*/
212 static uint8_t
213 hid_get_byte(struct hid_data *s, const uint16_t wSize)
214 {
215         const uint8_t *ptr;
216         uint8_t retval;
217
218         ptr = s->p;
219
220         /* check if end is reached */
221         if (ptr == s->end)
222                 return (0);
223
224         /* read out a byte */
225         retval = *ptr;
226
227         /* check if data pointer can be advanced by "wSize" bytes */
228         if ((s->end - ptr) < wSize)
229                 ptr = s->end;
230         else
231                 ptr += wSize;
232
233         /* update pointer */
234         s->p = ptr;
235
236         return (retval);
237 }
238
239 /*------------------------------------------------------------------------*
240  *      hid_get_item
241  *------------------------------------------------------------------------*/
242 int
243 hid_get_item(struct hid_data *s, struct hid_item *h)
244 {
245         struct hid_item *c;
246         unsigned int bTag, bType, bSize;
247         uint32_t oldpos;
248         int32_t mask;
249         int32_t dval;
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                         dval = s->usages_min[s->iusage] + s->ousage;
262                         c->usage = dval;
263                         s->usage_last = dval;
264                         if (dval == 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                         dval = 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                         dval = 0;
327                         mask = 0;
328                         break;
329                 case 1:
330                         dval = (int8_t)hid_get_byte(s, 1);
331                         mask = 0xFF;
332                         break;
333                 case 2:
334                         dval = hid_get_byte(s, 1);
335                         dval |= hid_get_byte(s, 1) << 8;
336                         dval = (int16_t)dval;
337                         mask = 0xFFFF;
338                         break;
339                 case 4:
340                         dval = hid_get_byte(s, 1);
341                         dval |= hid_get_byte(s, 1) << 8;
342                         dval |= hid_get_byte(s, 1) << 16;
343                         dval |= hid_get_byte(s, 1) << 24;
344                         mask = 0xFFFFFFFF;
345                         break;
346                 default:
347                         dval = hid_get_byte(s, bSize);
348                         DPRINTFN(0, "bad length %u (data=0x%02x)\n",
349                             bSize, dval);
350                         continue;
351                 }
352
353                 switch (bType) {
354                 case 0:         /* Main */
355                         switch (bTag) {
356                         case 8: /* Input */
357                                 c->kind = hid_input;
358                 ret:
359                                 c->flags = dval;
360                                 c->loc.count = s->loc_count;
361                                 c->loc.size = s->loc_size;
362
363                                 if (c->flags & HIO_VARIABLE) {
364                                         /* range check usage count */
365                                         if (c->loc.count > MAXLOCCNT) {
366                                                 DPRINTFN(0, "Number of "
367                                                     "items(%u) truncated to %u\n",
368                                                     (unsigned)(c->loc.count),
369                                                     MAXLOCCNT);
370                                                 s->ncount = MAXLOCCNT;
371                                         } else
372                                                 s->ncount = c->loc.count;
373
374                                         /* 
375                                          * The "top" loop will return
376                                          * one and one item:
377                                          */
378                                         c->loc.count = 1;
379                                 } else {
380                                         s->ncount = 1;
381                                 }
382                                 goto top;
383
384                         case 9: /* Output */
385                                 c->kind = hid_output;
386                                 goto ret;
387                         case 10:        /* Collection */
388                                 c->kind = hid_collection;
389                                 c->collection = dval;
390                                 c->collevel++;
391                                 c->usage = s->usage_last;
392                                 c->nusages = 1;
393                                 *h = *c;
394                                 return (1);
395                         case 11:        /* Feature */
396                                 c->kind = hid_feature;
397                                 goto ret;
398                         case 12:        /* End collection */
399                                 c->kind = hid_endcollection;
400                                 if (c->collevel == 0) {
401                                         DPRINTFN(0, "invalid end collection\n");
402                                         return (0);
403                                 }
404                                 c->collevel--;
405                                 *h = *c;
406                                 return (1);
407                         default:
408                                 DPRINTFN(0, "Main bTag=%d\n", bTag);
409                                 break;
410                         }
411                         break;
412                 case 1:         /* Global */
413                         switch (bTag) {
414                         case 0:
415                                 c->_usage_page = dval << 16;
416                                 break;
417                         case 1:
418                                 c->logical_minimum = dval;
419                                 break;
420                         case 2:
421                                 c->logical_maximum = dval;
422                                 break;
423                         case 3:
424                                 c->physical_minimum = dval;
425                                 break;
426                         case 4:
427                                 c->physical_maximum = dval;
428                                 break;
429                         case 5:
430                                 c->unit_exponent = dval;
431                                 break;
432                         case 6:
433                                 c->unit = dval;
434                                 break;
435                         case 7:
436                                 /* mask because value is unsigned */
437                                 s->loc_size = dval & mask;
438                                 break;
439                         case 8:
440                                 hid_switch_rid(s, c, dval & mask);
441                                 break;
442                         case 9:
443                                 /* mask because value is unsigned */
444                                 s->loc_count = dval & mask;
445                                 break;
446                         case 10:        /* Push */
447                                 /* stop parsing, if invalid push level */
448                                 if ((s->pushlevel + 1) >= MAXPUSH) {
449                                         DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel);
450                                         return (0);
451                                 }
452                                 s->pushlevel ++;
453                                 s->cur[s->pushlevel] = *c;
454                                 /* store size and count */
455                                 c->loc.size = s->loc_size;
456                                 c->loc.count = s->loc_count;
457                                 /* update current item pointer */
458                                 c = &s->cur[s->pushlevel];
459                                 break;
460                         case 11:        /* Pop */
461                                 /* stop parsing, if invalid push level */
462                                 if (s->pushlevel == 0) {
463                                         DPRINTFN(0, "Cannot pop item @ 0\n");
464                                         return (0);
465                                 }
466                                 s->pushlevel --;
467                                 /* preserve position */
468                                 oldpos = c->loc.pos;
469                                 c = &s->cur[s->pushlevel];
470                                 /* restore size and count */
471                                 s->loc_size = c->loc.size;
472                                 s->loc_count = c->loc.count;
473                                 /* set default item location */
474                                 c->loc.pos = oldpos;
475                                 c->loc.size = 0;
476                                 c->loc.count = 0;
477                                 break;
478                         default:
479                                 DPRINTFN(0, "Global bTag=%d\n", bTag);
480                                 break;
481                         }
482                         break;
483                 case 2:         /* Local */
484                         switch (bTag) {
485                         case 0:
486                                 if (bSize != 4)
487                                         dval = (dval & mask) | c->_usage_page;
488
489                                 /* set last usage, in case of a collection */
490                                 s->usage_last = dval;
491
492                                 if (s->nusage < MAXUSAGE) {
493                                         s->usages_min[s->nusage] = dval;
494                                         s->usages_max[s->nusage] = dval;
495                                         s->nusage ++;
496                                 } else {
497                                         DPRINTFN(0, "max usage reached\n");
498                                 }
499
500                                 /* clear any pending usage sets */
501                                 s->susage = 0;
502                                 break;
503                         case 1:
504                                 s->susage |= 1;
505
506                                 if (bSize != 4)
507                                         dval = (dval & mask) | c->_usage_page;
508                                 c->usage_minimum = dval;
509
510                                 goto check_set;
511                         case 2:
512                                 s->susage |= 2;
513
514                                 if (bSize != 4)
515                                         dval = (dval & mask) | c->_usage_page;
516                                 c->usage_maximum = dval;
517
518                         check_set:
519                                 if (s->susage != 3)
520                                         break;
521
522                                 /* sanity check */
523                                 if ((s->nusage < MAXUSAGE) &&
524                                     (c->usage_minimum <= c->usage_maximum)) {
525                                         /* add usage range */
526                                         s->usages_min[s->nusage] = 
527                                             c->usage_minimum;
528                                         s->usages_max[s->nusage] = 
529                                             c->usage_maximum;
530                                         s->nusage ++;
531                                 } else {
532                                         DPRINTFN(0, "Usage set dropped\n");
533                                 }
534                                 s->susage = 0;
535                                 break;
536                         case 3:
537                                 c->designator_index = dval;
538                                 break;
539                         case 4:
540                                 c->designator_minimum = dval;
541                                 break;
542                         case 5:
543                                 c->designator_maximum = dval;
544                                 break;
545                         case 7:
546                                 c->string_index = dval;
547                                 break;
548                         case 8:
549                                 c->string_minimum = dval;
550                                 break;
551                         case 9:
552                                 c->string_maximum = dval;
553                                 break;
554                         case 10:
555                                 c->set_delimiter = dval;
556                                 break;
557                         default:
558                                 DPRINTFN(0, "Local bTag=%d\n", bTag);
559                                 break;
560                         }
561                         break;
562                 default:
563                         DPRINTFN(0, "default bType=%d\n", bType);
564                         break;
565                 }
566         }
567         return (0);
568 }
569
570 /*------------------------------------------------------------------------*
571  *      hid_report_size
572  *------------------------------------------------------------------------*/
573 int
574 hid_report_size(const void *buf, hid_size_t len, enum hid_kind k, uint8_t id)
575 {
576         struct hid_data *d;
577         struct hid_item h;
578         uint32_t temp;
579         uint32_t hpos;
580         uint32_t lpos;
581         int report_id = 0;
582
583         hpos = 0;
584         lpos = 0xFFFFFFFF;
585
586         for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) {
587                 if (h.kind == k && h.report_ID == id) {
588                         /* compute minimum */
589                         if (lpos > h.loc.pos)
590                                 lpos = h.loc.pos;
591                         /* compute end position */
592                         temp = h.loc.pos + (h.loc.size * h.loc.count);
593                         /* compute maximum */
594                         if (hpos < temp)
595                                 hpos = temp;
596                         if (h.report_ID != 0)
597                                 report_id = 1;
598                 }
599         }
600         hid_end_parse(d);
601
602         /* safety check - can happen in case of currupt descriptors */
603         if (lpos > hpos)
604                 temp = 0;
605         else
606                 temp = hpos - lpos;
607
608         /* return length in bytes rounded up */
609         return ((temp + 7) / 8 + report_id);
610 }
611
612 int
613 hid_report_size_max(const void *buf, hid_size_t len, enum hid_kind k,
614     uint8_t *id)
615 {
616         struct hid_data *d;
617         struct hid_item h;
618         uint32_t temp;
619         uint32_t hpos;
620         uint32_t lpos;
621         uint8_t any_id;
622
623         any_id = 0;
624         hpos = 0;
625         lpos = 0xFFFFFFFF;
626
627         for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) {
628                 if (h.kind == k) {
629                         /* check for ID-byte presence */
630                         if ((h.report_ID != 0) && !any_id) {
631                                 if (id != NULL)
632                                         *id = h.report_ID;
633                                 any_id = 1;
634                         }
635                         /* compute minimum */
636                         if (lpos > h.loc.pos)
637                                 lpos = h.loc.pos;
638                         /* compute end position */
639                         temp = h.loc.pos + (h.loc.size * h.loc.count);
640                         /* compute maximum */
641                         if (hpos < temp)
642                                 hpos = temp;
643                 }
644         }
645         hid_end_parse(d);
646
647         /* safety check - can happen in case of currupt descriptors */
648         if (lpos > hpos)
649                 temp = 0;
650         else
651                 temp = hpos - lpos;
652
653         /* check for ID byte */
654         if (any_id)
655                 temp += 8;
656         else if (id != NULL)
657                 *id = 0;
658
659         /* return length in bytes rounded up */
660         return ((temp + 7) / 8);
661 }
662
663 /*------------------------------------------------------------------------*
664  *      hid_locate
665  *------------------------------------------------------------------------*/
666 int
667 hid_locate(const void *desc, hid_size_t size, int32_t u, enum hid_kind k,
668     uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id)
669 {
670         struct hid_data *d;
671         struct hid_item h;
672         int i;
673
674         for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) {
675                 for (i = 0; i < h.nusages; i++) {
676                         if (h.kind == k && h.usages[i] == u) {
677                                 if (index--)
678                                         break;
679                                 if (loc != NULL)
680                                         *loc = h.loc;
681                                 if (flags != NULL)
682                                         *flags = h.flags;
683                                 if (id != NULL)
684                                         *id = h.report_ID;
685                                 hid_end_parse(d);
686                                 return (1);
687                         }
688                 }
689         }
690         if (loc != NULL)
691                 loc->size = 0;
692         if (flags != NULL)
693                 *flags = 0;
694         if (id != NULL)
695                 *id = 0;
696         hid_end_parse(d);
697         return (0);
698 }
699
700 /*------------------------------------------------------------------------*
701  *      hid_get_data
702  *------------------------------------------------------------------------*/
703 static uint32_t
704 hid_get_data_sub(const uint8_t *buf, hid_size_t len, struct hid_location *loc,
705     int is_signed)
706 {
707         uint32_t hpos = loc->pos;
708         uint32_t hsize = loc->size;
709         uint32_t data;
710         uint32_t rpos;
711         uint8_t n;
712
713         DPRINTFN(11, "hid_get_data: loc %d/%d\n", hpos, hsize);
714
715         /* Range check and limit */
716         if (hsize == 0)
717                 return (0);
718         if (hsize > 32)
719                 hsize = 32;
720
721         /* Get data in a safe way */    
722         data = 0;
723         rpos = (hpos / 8);
724         n = (hsize + 7) / 8;
725         rpos += n;
726         while (n--) {
727                 rpos--;
728                 if (rpos < len)
729                         data |= buf[rpos] << (8 * n);
730         }
731
732         /* Correctly shift down data */
733         data = (data >> (hpos % 8));
734         n = 32 - hsize;
735
736         /* Mask and sign extend in one */
737         if (is_signed != 0)
738                 data = (int32_t)((int32_t)data << n) >> n;
739         else
740                 data = (uint32_t)((uint32_t)data << n) >> n;
741
742         DPRINTFN(11, "hid_get_data: loc %d/%d = %lu\n",
743             loc->pos, loc->size, (long)data);
744         return (data);
745 }
746
747 int32_t
748 hid_get_data(const uint8_t *buf, hid_size_t len, struct hid_location *loc)
749 {
750         return (hid_get_data_sub(buf, len, loc, 1));
751 }
752
753 uint32_t
754 hid_get_udata(const uint8_t *buf, hid_size_t len, struct hid_location *loc)
755 {
756         return (hid_get_data_sub(buf, len, loc, 0));
757 }
758
759 /*------------------------------------------------------------------------*
760  *      hid_put_data
761  *------------------------------------------------------------------------*/
762 void
763 hid_put_udata(uint8_t *buf, hid_size_t len,
764     struct hid_location *loc, unsigned int value)
765 {
766         uint32_t hpos = loc->pos;
767         uint32_t hsize = loc->size;
768         uint64_t data;
769         uint64_t mask;
770         uint32_t rpos;
771         uint8_t n;
772
773         DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value);
774
775         /* Range check and limit */
776         if (hsize == 0)
777                 return;
778         if (hsize > 32)
779                 hsize = 32;
780
781         /* Put data in a safe way */    
782         rpos = (hpos / 8);
783         n = (hsize + 7) / 8;
784         data = ((uint64_t)value) << (hpos % 8);
785         mask = ((1ULL << hsize) - 1ULL) << (hpos % 8);
786         rpos += n;
787         while (n--) {
788                 rpos--;
789                 if (rpos < len) {
790                         buf[rpos] &= ~(mask >> (8 * n));
791                         buf[rpos] |= (data >> (8 * n));
792                 }
793         }
794 }
795
796 /*------------------------------------------------------------------------*
797  *      hid_is_collection
798  *------------------------------------------------------------------------*/
799 int
800 hid_is_collection(const void *desc, hid_size_t size, int32_t usage)
801 {
802         struct hid_data *hd;
803         struct hid_item hi;
804         int err;
805
806         hd = hid_start_parse(desc, size, hid_input);
807         if (hd == NULL)
808                 return (0);
809
810         while ((err = hid_get_item(hd, &hi))) {
811                  if (hi.kind == hid_collection &&
812                      hi.usage == usage)
813                         break;
814         }
815         hid_end_parse(hd);
816         return (err);
817 }
818
819 /*------------------------------------------------------------------------*
820  * calculate HID item resolution. unit/mm for distances, unit/rad for angles
821  *------------------------------------------------------------------------*/
822 int32_t
823 hid_item_resolution(struct hid_item *hi)
824 {
825         /*
826          * hid unit scaling table according to HID Usage Table Review
827          * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf
828          */
829         static const int64_t scale[0x10][2] = {
830             [0x00] = { 1, 1 },
831             [0x01] = { 1, 10 },
832             [0x02] = { 1, 100 },
833             [0x03] = { 1, 1000 },
834             [0x04] = { 1, 10000 },
835             [0x05] = { 1, 100000 },
836             [0x06] = { 1, 1000000 },
837             [0x07] = { 1, 10000000 },
838             [0x08] = { 100000000, 1 },
839             [0x09] = { 10000000, 1 },
840             [0x0A] = { 1000000, 1 },
841             [0x0B] = { 100000, 1 },
842             [0x0C] = { 10000, 1 },
843             [0x0D] = { 1000, 1 },
844             [0x0E] = { 100, 1 },
845             [0x0F] = { 10, 1 },
846         };
847         int64_t logical_size;
848         int64_t physical_size;
849         int64_t multiplier;
850         int64_t divisor;
851         int64_t resolution;
852
853         switch (hi->unit) {
854         case HUM_CENTIMETER:
855                 multiplier = 1;
856                 divisor = 10;
857                 break;
858         case HUM_INCH:
859                 multiplier = 10;
860                 divisor = 254;
861                 break;
862         case HUM_RADIAN:
863                 multiplier = 1;
864                 divisor = 1;
865                 break;
866         case HUM_DEGREE:
867                 multiplier = 573;
868                 divisor = 10;
869                 break;
870         default:
871                 return (0);
872         }
873
874         if ((hi->logical_maximum <= hi->logical_minimum) ||
875             (hi->physical_maximum <= hi->physical_minimum) ||
876             (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale)))
877                 return (0);
878
879         logical_size = (int64_t)hi->logical_maximum -
880             (int64_t)hi->logical_minimum;
881         physical_size = (int64_t)hi->physical_maximum -
882             (int64_t)hi->physical_minimum;
883         /* Round to ceiling */
884         resolution = logical_size * multiplier * scale[hi->unit_exponent][0] /
885             (physical_size * divisor * scale[hi->unit_exponent][1]);
886
887         if (resolution > INT32_MAX)
888                 return (0);
889
890         return (resolution);
891 }
892
893 /*------------------------------------------------------------------------*
894  *      hid_is_mouse
895  *
896  * This function will decide if a USB descriptor belongs to a USB mouse.
897  *
898  * Return values:
899  * Zero: Not a USB mouse.
900  * Else: Is a USB mouse.
901  *------------------------------------------------------------------------*/
902 int
903 hid_is_mouse(const void *d_ptr, uint16_t d_len)
904 {
905         struct hid_data *hd;
906         struct hid_item hi;
907         int mdepth;
908         int found;
909
910         hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
911         if (hd == NULL)
912                 return (0);
913
914         mdepth = 0;
915         found = 0;
916
917         while (hid_get_item(hd, &hi)) {
918                 switch (hi.kind) {
919                 case hid_collection:
920                         if (mdepth != 0)
921                                 mdepth++;
922                         else if (hi.collection == 1 &&
923                              hi.usage ==
924                               HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
925                                 mdepth++;
926                         break;
927                 case hid_endcollection:
928                         if (mdepth != 0)
929                                 mdepth--;
930                         break;
931                 case hid_input:
932                         if (mdepth == 0)
933                                 break;
934                         if (hi.usage ==
935                              HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
936                             (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
937                                 found++;
938                         if (hi.usage ==
939                              HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
940                             (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
941                                 found++;
942                         break;
943                 default:
944                         break;
945                 }
946         }
947         hid_end_parse(hd);
948         return (found);
949 }
950
951 /*------------------------------------------------------------------------*
952  *      hid_is_keyboard
953  *
954  * This function will decide if a USB descriptor belongs to a USB keyboard.
955  *
956  * Return values:
957  * Zero: Not a USB keyboard.
958  * Else: Is a USB keyboard.
959  *------------------------------------------------------------------------*/
960 int
961 hid_is_keyboard(const void *d_ptr, uint16_t d_len)
962 {
963         if (hid_is_collection(d_ptr, d_len,
964             HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
965                 return (1);
966         return (0);
967 }
968
969 /*------------------------------------------------------------------------*
970  *      hid_test_quirk - test a device for a given quirk
971  *
972  * Return values:
973  * false: The HID device does not have the given quirk.
974  * true: The HID device has the given quirk.
975  *------------------------------------------------------------------------*/
976 bool
977 hid_test_quirk(const struct hid_device_info *dev_info, uint16_t quirk)
978 {
979         bool found;
980         uint8_t x;
981
982         if (quirk == HQ_NONE)
983                 return (false);
984
985         /* search the automatic per device quirks first */
986         for (x = 0; x != HID_MAX_AUTO_QUIRK; x++) {
987                 if (dev_info->autoQuirk[x] == quirk)
988                         return (true);
989         }
990
991         /* search global quirk table, if any */
992         found = (hid_test_quirk_p) (dev_info, quirk);
993
994         return (found);
995 }
996
997 static bool
998 hid_test_quirk_w(const struct hid_device_info *dev_info, uint16_t quirk)
999 {
1000         return (false);                 /* no match */
1001 }
1002
1003 int
1004 hid_add_dynamic_quirk(struct hid_device_info *dev_info, uint16_t quirk)
1005 {
1006         uint8_t x;
1007
1008         for (x = 0; x != HID_MAX_AUTO_QUIRK; x++) {
1009                 if (dev_info->autoQuirk[x] == 0 ||
1010                     dev_info->autoQuirk[x] == quirk) {
1011                         dev_info->autoQuirk[x] = quirk;
1012                         return (0);     /* success */
1013                 }
1014         }
1015         return (ENOSPC);
1016 }
1017
1018 void
1019 hid_quirk_unload(void *arg)
1020 {
1021         /* reset function pointer */
1022         hid_test_quirk_p = &hid_test_quirk_w;
1023 #ifdef NOT_YET
1024         hidquirk_ioctl_p = &hidquirk_ioctl_w;
1025 #endif
1026
1027         /* wait for CPU to exit the loaded functions, if any */
1028
1029         /* XXX this is a tradeoff */
1030
1031         pause("WAIT", hz);
1032 }
1033
1034 int
1035 hid_get_rdesc(device_t dev, void *data, hid_size_t len)
1036 {
1037         return (HID_GET_RDESC(device_get_parent(dev), data, len));
1038 }
1039
1040 int
1041 hid_read(device_t dev, void *data, hid_size_t maxlen, hid_size_t *actlen)
1042 {
1043         return (HID_READ(device_get_parent(dev), data, maxlen, actlen));
1044 }
1045
1046 int
1047 hid_write(device_t dev, const void *data, hid_size_t len)
1048 {
1049         return (HID_WRITE(device_get_parent(dev), data, len));
1050 }
1051
1052 int
1053 hid_get_report(device_t dev, void *data, hid_size_t maxlen, hid_size_t *actlen,
1054     uint8_t type, uint8_t id)
1055 {
1056         return (HID_GET_REPORT(device_get_parent(dev), data, maxlen, actlen,
1057             type, id));
1058 }
1059
1060 int
1061 hid_set_report(device_t dev, const void *data, hid_size_t len, uint8_t type,
1062     uint8_t id)
1063 {
1064         return (HID_SET_REPORT(device_get_parent(dev), data, len, type, id));
1065 }
1066
1067 int
1068 hid_set_idle(device_t dev, uint16_t duration, uint8_t id)
1069 {
1070         return (HID_SET_IDLE(device_get_parent(dev), duration, id));
1071 }
1072
1073 int
1074 hid_set_protocol(device_t dev, uint16_t protocol)
1075 {
1076         return (HID_SET_PROTOCOL(device_get_parent(dev), protocol));
1077 }
1078
1079 MODULE_VERSION(hid, 1);