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