]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hid/hidmap.c
Merge bmake-20210206
[FreeBSD/FreeBSD.git] / sys / dev / hid / hidmap.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32  * Abstract 1 to 1 HID input usage to evdev event mapper driver.
33  */
34
35 #include "opt_hid.h"
36
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/kernel.h>
40 #include <sys/lock.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
43 #include <sys/sysctl.h>
44 #include <sys/systm.h>
45
46 #include <dev/evdev/input.h>
47 #include <dev/evdev/evdev.h>
48
49 #include <dev/hid/hid.h>
50 #include <dev/hid/hidbus.h>
51 #include <dev/hid/hidmap.h>
52
53 #ifdef HID_DEBUG
54 #define DPRINTFN(hm, n, fmt, ...) do {                                  \
55         if ((hm)->debug_var != NULL && *(hm)->debug_var >= (n)) {       \
56                 device_printf((hm)->dev, "%s: " fmt,                    \
57                     __FUNCTION__ ,##__VA_ARGS__);                       \
58         }                                                               \
59 } while (0)
60 #define DPRINTF(hm, ...)        DPRINTFN(hm, 1, __VA_ARGS__)
61 #else
62 #define DPRINTF(...) do { } while (0)
63 #define DPRINTFN(...) do { } while (0)
64 #endif
65
66 static evdev_open_t hidmap_ev_open;
67 static evdev_close_t hidmap_ev_close;
68
69 #define HIDMAP_WANT_MERGE_KEYS(hm)      ((hm)->key_rel != NULL)
70
71 #define HIDMAP_FOREACH_ITEM(hm, mi, uoff)                               \
72         for (u_int _map = 0, _item = 0, _uoff_priv = -1;                \
73             ((mi) = hidmap_get_next_map_item(                           \
74                 (hm), &_map, &_item, &_uoff_priv, &(uoff))) != NULL;)
75
76 static inline bool
77 hidmap_get_next_map_index(const struct hidmap_item *map, int nmap_items,
78     uint32_t *index, uint16_t *usage_offset)
79 {
80
81         ++*usage_offset;
82         if ((*index != 0 || *usage_offset != 0) &&
83             *usage_offset >= map[*index].nusages) {
84                 ++*index;
85                 *usage_offset = 0;
86         }
87
88         return (*index < nmap_items);
89 }
90
91 static inline const struct hidmap_item *
92 hidmap_get_next_map_item(struct hidmap *hm, u_int *map, u_int *item,
93     u_int *uoff_priv, uint16_t *uoff)
94 {
95
96         *uoff = *uoff_priv;
97         while (!hidmap_get_next_map_index(
98            hm->map[*map], hm->nmap_items[*map], item, uoff)) {
99                 ++*map;
100                 *item = 0;
101                 *uoff = -1;
102                 if (*map >= hm->nmaps)
103                         return (NULL);
104         }
105         *uoff_priv = *uoff;
106
107         return (hm->map[*map] + *item);
108 }
109
110 void
111 _hidmap_set_debug_var(struct hidmap *hm, int *debug_var)
112 {
113 #ifdef HID_DEBUG
114         hm->debug_var = debug_var;
115 #endif
116 }
117
118 static int
119 hidmap_ev_close(struct evdev_dev *evdev)
120 {
121         return (hidbus_intr_stop(evdev_get_softc(evdev)));
122 }
123
124 static int
125 hidmap_ev_open(struct evdev_dev *evdev)
126 {
127         return (hidbus_intr_start(evdev_get_softc(evdev)));
128 }
129
130 void
131 hidmap_support_key(struct hidmap *hm, uint16_t key)
132 {
133         if (hm->key_press == NULL) {
134                 hm->key_press = malloc(howmany(KEY_CNT, 8), M_DEVBUF,
135                     M_ZERO | M_WAITOK);
136                 evdev_support_event(hm->evdev, EV_KEY);
137                 hm->key_min = key;
138                 hm->key_max = key;
139         }
140         hm->key_min = MIN(hm->key_min, key);
141         hm->key_max = MAX(hm->key_max, key);
142         if (isset(hm->key_press, key)) {
143                 if (hm->key_rel == NULL)
144                         hm->key_rel = malloc(howmany(KEY_CNT, 8), M_DEVBUF,
145                             M_ZERO | M_WAITOK);
146         } else {
147                 setbit(hm->key_press, key);
148                 evdev_support_key(hm->evdev, key);
149         }
150 }
151
152 void
153 hidmap_push_key(struct hidmap *hm, uint16_t key, int32_t value)
154 {
155         if (HIDMAP_WANT_MERGE_KEYS(hm))
156                 setbit(value != 0 ? hm->key_press : hm->key_rel, key);
157         else
158                 evdev_push_key(hm->evdev, key, value);
159 }
160
161 static void
162 hidmap_sync_keys(struct hidmap *hm)
163 {
164         int i, j;
165         bool press, rel;
166
167         for (j = hm->key_min / 8; j <= hm->key_max / 8; j++) {
168                 if (hm->key_press[j] != hm->key_rel[j]) {
169                         for (i = j * 8; i < j * 8 + 8; i++) {
170                                 press = isset(hm->key_press, i);
171                                 rel = isset(hm->key_rel, i);
172                                 if (press != rel)
173                                         evdev_push_key(hm->evdev, i, press);
174                         }
175                 }
176         }
177         bzero(hm->key_press, howmany(KEY_CNT, 8));
178         bzero(hm->key_rel, howmany(KEY_CNT, 8));
179 }
180
181 void
182 hidmap_intr(void *context, void *buf, hid_size_t len)
183 {
184         struct hidmap *hm = context;
185         struct hidmap_hid_item *hi;
186         const struct hidmap_item *mi;
187         int32_t usage;
188         int32_t data;
189         uint16_t key, uoff;
190         uint8_t id = 0;
191         bool found, do_sync = false;
192
193         DPRINTFN(hm, 6, "hm=%p len=%d\n", hm, len);
194         DPRINTFN(hm, 6, "data = %*D\n", len, buf, " ");
195
196         /* Strip leading "report ID" byte */
197         if (hm->hid_items[0].id) {
198                 id = *(uint8_t *)buf;
199                 len--;
200                 buf = (uint8_t *)buf + 1;
201         }
202
203         hm->intr_buf = buf;
204         hm->intr_len = len;
205
206         for (hi = hm->hid_items; hi < hm->hid_items + hm->nhid_items; hi++) {
207                 /* At first run callbacks that not tied to HID items */
208                 if (hi->type == HIDMAP_TYPE_FINALCB) {
209                         DPRINTFN(hm, 6, "type=%d item=%*D\n", hi->type,
210                             (int)sizeof(hi->cb), &hi->cb, " ");
211                         if (hi->cb(hm, hi, (union hidmap_cb_ctx){.rid = id})
212                             == 0)
213                                 do_sync = true;
214                         continue;
215                 }
216
217                 /* Ignore irrelevant reports */
218                 if (id != hi->id)
219                         continue;
220
221                 /*
222                  * 5.8. If Logical Minimum and Logical Maximum are both
223                  * positive values then the contents of a field can be assumed
224                  * to be an unsigned value. Otherwise, all integer values are
225                  * signed values represented in 2’s complement format.
226                  */
227                 data = hi->lmin < 0 || hi->lmax < 0
228                     ? hid_get_data(buf, len, &hi->loc)
229                     : hid_get_udata(buf, len, &hi->loc);
230
231                 DPRINTFN(hm, 6, "type=%d data=%d item=%*D\n", hi->type, data,
232                     (int)sizeof(hi->cb), &hi->cb, " ");
233
234                 if (hi->invert_value && hi->type < HIDMAP_TYPE_ARR_LIST)
235                         data = hi->evtype == EV_REL
236                             ? -data
237                             : hi->lmin + hi->lmax - data;
238
239                 switch (hi->type) {
240                 case HIDMAP_TYPE_CALLBACK:
241                         if (hi->cb(hm, hi, (union hidmap_cb_ctx){.data = data})
242                             != 0)
243                                 continue;
244                         break;
245
246                 case HIDMAP_TYPE_VAR_NULLST:
247                         /*
248                          * 5.10. If the host or the device receives an
249                          * out-of-range value then the current value for the
250                          * respective control will not be modified.
251                          */
252                         if (data < hi->lmin || data > hi->lmax)
253                                 continue;
254                         /* FALLTHROUGH */
255                 case HIDMAP_TYPE_VARIABLE:
256                         /*
257                          * Ignore reports for absolute data if the data did not
258                          * change and for relative data if data is 0.
259                          * Evdev layer filters out them anyway.
260                          */
261                         if (data == (hi->evtype == EV_REL ? 0 : hi->last_val))
262                                 continue;
263                         if (hi->evtype == EV_KEY)
264                                 hidmap_push_key(hm, hi->code, data);
265                         else
266                                 evdev_push_event(hm->evdev, hi->evtype,
267                                     hi->code, data);
268                         hi->last_val = data;
269                         break;
270
271                 case HIDMAP_TYPE_ARR_LIST:
272                         key = KEY_RESERVED;
273                         /*
274                          * 6.2.2.5. An out-of range value in an array field
275                          * is considered no controls asserted.
276                          */
277                         if (data < hi->lmin || data > hi->lmax)
278                                 goto report_key;
279                         /*
280                          * 6.2.2.5. Rather than returning a single bit for each
281                          * button in the group, an array returns an index in
282                          * each field that corresponds to the pressed button.
283                          */
284                         key = hi->codes[data - hi->lmin];
285                         if (key == KEY_RESERVED)
286                                 DPRINTF(hm, "Can not map unknown HID "
287                                     "array index: %08x\n", data);
288                         goto report_key;
289
290                 case HIDMAP_TYPE_ARR_RANGE:
291                         key = KEY_RESERVED;
292                         /*
293                          * 6.2.2.5. An out-of range value in an array field
294                          * is considered no controls asserted.
295                          */
296                         if (data < hi->lmin || data > hi->lmax)
297                                 goto report_key;
298                         /*
299                          * When the input field is an array and the usage is
300                          * specified with a range instead of an ID, we have to
301                          * derive the actual usage by using the item value as
302                          * an index in the usage range list.
303                          */
304                         usage = data - hi->lmin + hi->umin;
305                         found = false;
306                         HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
307                                 if (usage == mi->usage + uoff &&
308                                     mi->type == EV_KEY && !mi->has_cb) {
309                                         key = mi->code;
310                                         found = true;
311                                         break;
312                                 }
313                         }
314                         if (!found)
315                                 DPRINTF(hm, "Can not map unknown HID "
316                                     "usage: %08x\n", usage);
317 report_key:
318                         if (key == HIDMAP_KEY_NULL || key == hi->last_key)
319                                 continue;
320                         if (hi->last_key != KEY_RESERVED)
321                                 hidmap_push_key(hm, hi->last_key, 0);
322                         if (key != KEY_RESERVED)
323                                 hidmap_push_key(hm, key, 1);
324                         hi->last_key = key;
325                         break;
326
327                 default:
328                         KASSERT(0, ("Unknown map type (%d)", hi->type));
329                 }
330                 do_sync = true;
331         }
332
333         if (do_sync) {
334                 if (HIDMAP_WANT_MERGE_KEYS(hm))
335                         hidmap_sync_keys(hm);
336                 evdev_sync(hm->evdev);
337         }
338 }
339
340 static inline bool
341 can_map_callback(struct hid_item *hi, const struct hidmap_item *mi,
342     uint16_t usage_offset)
343 {
344
345         return (mi->has_cb && !mi->final_cb &&
346             hi->usage == mi->usage + usage_offset &&
347             (mi->relabs == HIDMAP_RELABS_ANY ||
348             !(hi->flags & HIO_RELATIVE) == !(mi->relabs == HIDMAP_RELATIVE)));
349 }
350
351 static inline bool
352 can_map_variable(struct hid_item *hi, const struct hidmap_item *mi,
353     uint16_t usage_offset)
354 {
355
356         return ((hi->flags & HIO_VARIABLE) != 0 && !mi->has_cb &&
357             hi->usage == mi->usage + usage_offset &&
358             (mi->relabs == HIDMAP_RELABS_ANY ||
359             !(hi->flags & HIO_RELATIVE) == !(mi->relabs == HIDMAP_RELATIVE)));
360 }
361
362 static inline bool
363 can_map_arr_range(struct hid_item *hi, const struct hidmap_item *mi,
364     uint16_t usage_offset)
365 {
366
367         return ((hi->flags & HIO_VARIABLE) == 0 && !mi->has_cb &&
368             hi->usage_minimum <= mi->usage + usage_offset &&
369             hi->usage_maximum >= mi->usage + usage_offset &&
370             mi->type == EV_KEY &&
371             (mi->code != KEY_RESERVED && mi->code != HIDMAP_KEY_NULL));
372 }
373
374 static inline bool
375 can_map_arr_list(struct hid_item *hi, const struct hidmap_item *mi,
376     uint32_t usage, uint16_t usage_offset)
377 {
378
379         return ((hi->flags & HIO_VARIABLE) == 0 && !mi->has_cb &&
380             usage == mi->usage + usage_offset &&
381             mi->type == EV_KEY &&
382             (mi->code != KEY_RESERVED && mi->code != HIDMAP_KEY_NULL));
383 }
384
385 static bool
386 hidmap_probe_hid_item(struct hid_item *hi, const struct hidmap_item *map,
387     int nitems_map, hidmap_caps_t caps)
388 {
389         u_int i, j;
390         uint16_t uoff;
391         bool found = false;
392
393 #define HIDMAP_FOREACH_INDEX(map, nitems, idx, uoff)    \
394         for ((idx) = 0, (uoff) = -1;                    \
395              hidmap_get_next_map_index((map), (nitems), &(idx), &(uoff));)
396
397         HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) {
398                 if (can_map_callback(hi, map + i, uoff)) {
399                         if (map[i].cb(NULL, NULL,
400                             (union hidmap_cb_ctx){.hi = hi}) != 0)
401                                 break;
402                         setbit(caps, i);
403                         return (true);
404                 }
405         }
406
407         if (hi->flags & HIO_VARIABLE) {
408                 HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) {
409                         if (can_map_variable(hi, map + i, uoff)) {
410                                 KASSERT(map[i].type == EV_KEY ||
411                                         map[i].type == EV_REL ||
412                                         map[i].type == EV_ABS ||
413                                         map[i].type == EV_SW,
414                                     ("Unsupported event type"));
415                                 setbit(caps, i);
416                                 return (true);
417                         }
418                 }
419                 return (false);
420         }
421
422         if (hi->usage_minimum != 0 || hi->usage_maximum != 0) {
423                 HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) {
424                         if (can_map_arr_range(hi, map + i, uoff)) {
425                                 setbit(caps, i);
426                                 found = true;
427                         }
428                 }
429                 return (found);
430         }
431
432         for (j = 0; j < hi->nusages; j++) {
433                 HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) {
434                         if (can_map_arr_list(hi, map+i, hi->usages[j], uoff)) {
435                                 setbit(caps, i);
436                                 found = true;
437                         }
438                 }
439         }
440
441         return (found);
442 }
443
444 static uint32_t
445 hidmap_probe_hid_descr(void *d_ptr, hid_size_t d_len, uint8_t tlc_index,
446     const struct hidmap_item *map, int nitems_map, hidmap_caps_t caps)
447 {
448         struct hid_data *hd;
449         struct hid_item hi;
450         uint32_t i, items = 0;
451         bool do_free = false;
452
453         if (caps == NULL) {
454                 caps = malloc(HIDMAP_CAPS_SZ(nitems_map), M_DEVBUF, M_WAITOK);
455                 do_free = true;
456         } else
457                 bzero (caps, HIDMAP_CAPS_SZ(nitems_map));
458
459         /* Parse inputs */
460         hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
461         HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) {
462                 if (hi.kind != hid_input)
463                         continue;
464                 if (hi.flags & HIO_CONST)
465                         continue;
466                 for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size)
467                         if (hidmap_probe_hid_item(&hi, map, nitems_map, caps))
468                                 items++;
469         }
470         hid_end_parse(hd);
471
472         /* Take finalizing callbacks in to account */
473         for (i = 0; i < nitems_map; i++) {
474                 if (map[i].has_cb && map[i].final_cb &&
475                     map[i].cb(NULL, NULL, (union hidmap_cb_ctx){}) == 0) {
476                         setbit(caps, i);
477                         items++;
478                 }
479         }
480
481         /* Check that all mandatory usages are present in report descriptor */
482         if (items != 0) {
483                 for (i = 0; i < nitems_map; i++) {
484                         if (map[i].required && isclr(caps, i)) {
485                                 items = 0;
486                                 break;
487                         }
488                 }
489         }
490
491         if (do_free)
492                 free(caps, M_DEVBUF);
493
494         return (items);
495 }
496
497 uint32_t
498 hidmap_add_map(struct hidmap *hm, const struct hidmap_item *map,
499     int nitems_map, hidmap_caps_t caps)
500 {
501         void *d_ptr;
502         uint32_t items;
503         int i, error;
504         hid_size_t d_len;
505         uint8_t tlc_index = hidbus_get_index(hm->dev);
506
507         /* Avoid double-adding of map in probe() handler */
508         for (i = 0; i < hm->nmaps; i++)
509                 if (hm->map[i] == map)
510                         return (0);
511
512         error = hid_get_report_descr(hm->dev, &d_ptr, &d_len);
513         if (error != 0) {
514                 device_printf(hm->dev, "could not retrieve report descriptor "
515                      "from device: %d\n", error);
516                 return (error);
517         }
518
519         hm->cb_state = HIDMAP_CB_IS_PROBING;
520         items = hidmap_probe_hid_descr(d_ptr, d_len, tlc_index, map,
521             nitems_map, caps);
522         if (items == 0)
523                 return (ENXIO);
524
525         KASSERT(hm->nmaps < HIDMAP_MAX_MAPS,
526             ("Not more than %d maps is supported", HIDMAP_MAX_MAPS));
527         hm->nhid_items += items;
528         hm->map[hm->nmaps] = map;
529         hm->nmap_items[hm->nmaps] = nitems_map;
530         hm->nmaps++;
531
532         return (0);
533 }
534
535 static bool
536 hidmap_parse_hid_item(struct hidmap *hm, struct hid_item *hi,
537     struct hidmap_hid_item *item)
538 {
539         const struct hidmap_item *mi;
540         struct hidmap_hid_item hi_temp;
541         uint32_t i;
542         uint16_t uoff;
543         bool found = false;
544
545         HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
546                 if (can_map_callback(hi, mi, uoff)) {
547                         bzero(&hi_temp, sizeof(hi_temp));
548                         hi_temp.cb = mi->cb;
549                         hi_temp.type = HIDMAP_TYPE_CALLBACK;
550                         /*
551                          * Values returned by probe- and attach-stage
552                          * callbacks MUST be identical.
553                          */
554                         if (mi->cb(hm, &hi_temp,
555                             (union hidmap_cb_ctx){.hi = hi}) != 0)
556                                 break;
557                         bcopy(&hi_temp, item, sizeof(hi_temp));
558                         goto mapped;
559                 }
560         }
561
562         if (hi->flags & HIO_VARIABLE) {
563                 HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
564                         if (can_map_variable(hi, mi, uoff)) {
565                                 item->evtype = mi->type;
566                                 item->code = mi->code + uoff;
567                                 item->type = hi->flags & HIO_NULLSTATE
568                                     ? HIDMAP_TYPE_VAR_NULLST
569                                     : HIDMAP_TYPE_VARIABLE;
570                                 item->last_val = 0;
571                                 item->invert_value = mi->invert_value;
572                                 switch (mi->type) {
573                                 case EV_KEY:
574                                         hidmap_support_key(hm, item->code);
575                                         break;
576                                 case EV_REL:
577                                         evdev_support_event(hm->evdev, EV_REL);
578                                         evdev_support_rel(hm->evdev,
579                                             item->code);
580                                         break;
581                                 case EV_ABS:
582                                         evdev_support_event(hm->evdev, EV_ABS);
583                                         evdev_support_abs(hm->evdev,
584                                             item->code,
585                                             hi->logical_minimum,
586                                             hi->logical_maximum,
587                                             mi->fuzz,
588                                             mi->flat,
589                                             hid_item_resolution(hi));
590                                         break;
591                                 case EV_SW:
592                                         evdev_support_event(hm->evdev, EV_SW);
593                                         evdev_support_sw(hm->evdev,
594                                             item->code);
595                                         break;
596                                 default:
597                                         KASSERT(0, ("Unsupported event type"));
598                                 }
599                                 goto mapped;
600                         }
601                 }
602                 return (false);
603         }
604
605         if (hi->usage_minimum != 0 || hi->usage_maximum != 0) {
606                 HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
607                         if (can_map_arr_range(hi, mi, uoff)) {
608                                 hidmap_support_key(hm, mi->code + uoff);
609                                 found = true;
610                         }
611                 }
612                 if (!found)
613                         return (false);
614                 item->umin = hi->usage_minimum;
615                 item->type = HIDMAP_TYPE_ARR_RANGE;
616                 item->last_key = KEY_RESERVED;
617                 goto mapped;
618         }
619
620         for (i = 0; i < hi->nusages; i++) {
621                 HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
622                         if (can_map_arr_list(hi, mi, hi->usages[i], uoff)) {
623                                 hidmap_support_key(hm, mi->code + uoff);
624                                 if (item->codes == NULL)
625                                         item->codes = malloc(
626                                             hi->nusages * sizeof(uint16_t),
627                                             M_DEVBUF, M_WAITOK | M_ZERO);
628                                 item->codes[i] = mi->code + uoff;
629                                 found = true;
630                                 break;
631                         }
632                 }
633         }
634         if (!found)
635                 return (false);
636         item->type = HIDMAP_TYPE_ARR_LIST;
637         item->last_key = KEY_RESERVED;
638
639 mapped:
640         item->id = hi->report_ID;
641         item->loc = hi->loc;
642         item->loc.count = 1;
643         item->lmin = hi->logical_minimum;
644         item->lmax = hi->logical_maximum;
645
646         DPRINTFN(hm, 6, "usage=%04x id=%d loc=%u/%u type=%d item=%*D\n",
647             hi->usage, hi->report_ID, hi->loc.pos, hi->loc.size, item->type,
648             (int)sizeof(item->cb), &item->cb, " ");
649
650         return (true);
651 }
652
653 static int
654 hidmap_parse_hid_descr(struct hidmap *hm, uint8_t tlc_index)
655 {
656         const struct hidmap_item *map;
657         struct hidmap_hid_item *item = hm->hid_items;
658         void *d_ptr;
659         struct hid_data *hd;
660         struct hid_item hi;
661         int i, error;
662         hid_size_t d_len;
663
664         error = hid_get_report_descr(hm->dev, &d_ptr, &d_len);
665         if (error != 0) {
666                 DPRINTF(hm, "could not retrieve report descriptor from "
667                      "device: %d\n", error);
668                 return (error);
669         }
670
671         /* Parse inputs */
672         hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
673         HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) {
674                 if (hi.kind != hid_input)
675                         continue;
676                 if (hi.flags & HIO_CONST)
677                         continue;
678                 for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size)
679                         if (hidmap_parse_hid_item(hm, &hi, item))
680                                 item++;
681                 KASSERT(item <= hm->hid_items + hm->nhid_items,
682                     ("Parsed HID item array overflow"));
683         }
684         hid_end_parse(hd);
685
686         /* Add finalizing callbacks to the end of list */
687         for (i = 0; i < hm->nmaps; i++) {
688                 for (map = hm->map[i];
689                      map < hm->map[i] + hm->nmap_items[i];
690                      map++) {
691                         if (map->has_cb && map->final_cb &&
692                             map->cb(hm, item, (union hidmap_cb_ctx){}) == 0) {
693                                 item->cb = map->cb;
694                                 item->type = HIDMAP_TYPE_FINALCB;
695                                 item++;
696                         }
697                 }
698         }
699
700         /*
701          * Resulting number of parsed HID items can be less than expected as
702          * map items might be duplicated in different maps. Save real number.
703          */
704         if (hm->nhid_items != item - hm->hid_items)
705                 DPRINTF(hm, "Parsed HID item number mismatch: expected=%u "
706                     "result=%td\n", hm->nhid_items, item - hm->hid_items);
707         hm->nhid_items = item - hm->hid_items;
708
709         if (HIDMAP_WANT_MERGE_KEYS(hm))
710                 bzero(hm->key_press, howmany(KEY_CNT, 8));
711
712         return (0);
713 }
714
715 int
716 hidmap_probe(struct hidmap* hm, device_t dev,
717     const struct hid_device_id *id, int nitems_id,
718     const struct hidmap_item *map, int nitems_map,
719     const char *suffix, hidmap_caps_t caps)
720 {
721         int error;
722
723         error = hidbus_lookup_driver_info(dev, id, nitems_id);
724         if (error != 0)
725                 return (error);
726
727         hidmap_set_dev(hm, dev);
728
729         error = hidmap_add_map(hm, map, nitems_map, caps);
730         if (error != 0)
731                 return (error);
732
733         hidbus_set_desc(dev, suffix);
734
735         return (BUS_PROBE_DEFAULT);
736 }
737
738 int
739 hidmap_attach(struct hidmap* hm)
740 {
741         const struct hid_device_info *hw = hid_get_device_info(hm->dev);
742 #ifdef HID_DEBUG
743         char tunable[40];
744 #endif
745         int error;
746
747 #ifdef HID_DEBUG
748         if (hm->debug_var == NULL) {
749                 hm->debug_var = &hm->debug_level;
750                 snprintf(tunable, sizeof(tunable), "hw.hid.%s.debug",
751                     device_get_name(hm->dev));
752                 TUNABLE_INT_FETCH(tunable, &hm->debug_level);
753                 SYSCTL_ADD_INT(device_get_sysctl_ctx(hm->dev),
754                         SYSCTL_CHILDREN(device_get_sysctl_tree(hm->dev)),
755                         OID_AUTO, "debug", CTLFLAG_RWTUN,
756                         &hm->debug_level, 0, "Verbosity level");
757         }
758 #endif
759
760         DPRINTFN(hm, 11, "hm=%p\n", hm);
761
762         hm->cb_state = HIDMAP_CB_IS_ATTACHING;
763
764         hm->hid_items = malloc(hm->nhid_items * sizeof(struct hid_item),
765             M_DEVBUF, M_WAITOK | M_ZERO);
766
767         hidbus_set_intr(hm->dev, hidmap_intr, hm);
768         hm->evdev_methods = (struct evdev_methods) {
769                 .ev_open = &hidmap_ev_open,
770                 .ev_close = &hidmap_ev_close,
771         };
772
773         hm->evdev = evdev_alloc();
774         evdev_set_name(hm->evdev, device_get_desc(hm->dev));
775         evdev_set_phys(hm->evdev, device_get_nameunit(hm->dev));
776         evdev_set_id(hm->evdev, hw->idBus, hw->idVendor, hw->idProduct,
777             hw->idVersion);
778         evdev_set_serial(hm->evdev, hw->serial);
779         evdev_set_flag(hm->evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
780         evdev_support_event(hm->evdev, EV_SYN);
781         error = hidmap_parse_hid_descr(hm, hidbus_get_index(hm->dev));
782         if (error) {
783                 DPRINTF(hm, "error=%d\n", error);
784                 hidmap_detach(hm);
785                 return (ENXIO);
786         }
787
788         evdev_set_methods(hm->evdev, hm->dev, &hm->evdev_methods);
789         hm->cb_state = HIDMAP_CB_IS_RUNNING;
790
791         error = evdev_register(hm->evdev);
792         if (error) {
793                 DPRINTF(hm, "error=%d\n", error);
794                 hidmap_detach(hm);
795                 return (ENXIO);
796         }
797
798         return (0);
799 }
800
801 int
802 hidmap_detach(struct hidmap* hm)
803 {
804         struct hidmap_hid_item *hi;
805
806         DPRINTFN(hm, 11, "\n");
807
808         hm->cb_state = HIDMAP_CB_IS_DETACHING;
809
810         evdev_free(hm->evdev);
811         if (hm->hid_items != NULL) {
812                 for (hi = hm->hid_items;
813                      hi < hm->hid_items + hm->nhid_items;
814                      hi++)
815                         if (hi->type == HIDMAP_TYPE_FINALCB ||
816                             hi->type == HIDMAP_TYPE_CALLBACK)
817                                 hi->cb(hm, hi, (union hidmap_cb_ctx){});
818                         else if (hi->type == HIDMAP_TYPE_ARR_LIST)
819                                 free(hi->codes, M_DEVBUF);
820                 free(hm->hid_items, M_DEVBUF);
821         }
822
823         free(hm->key_press, M_DEVBUF);
824         free(hm->key_rel, M_DEVBUF);
825
826         return (0);
827 }
828
829 MODULE_DEPEND(hidmap, hid, 1, 1, 1);
830 MODULE_DEPEND(hidmap, hidbus, 1, 1, 1);
831 MODULE_DEPEND(hidmap, evdev, 1, 1, 1);
832 MODULE_VERSION(hidmap, 1);