xref: /freebsd/sys/dev/hid/hidmap.c (revision 4d846d26)
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 __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,
455 		    M_WAITOK | M_ZERO);
456 		do_free = true;
457 	} else
458 		bzero (caps, HIDMAP_CAPS_SZ(nitems_map));
459 
460 	/* Parse inputs */
461 	hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
462 	HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) {
463 		if (hi.kind != hid_input)
464 			continue;
465 		if (hi.flags & HIO_CONST)
466 			continue;
467 		for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size)
468 			if (hidmap_probe_hid_item(&hi, map, nitems_map, caps))
469 				items++;
470 	}
471 	hid_end_parse(hd);
472 
473 	/* Take finalizing callbacks in to account */
474 	for (i = 0; i < nitems_map; i++) {
475 		if (map[i].has_cb && map[i].final_cb &&
476 		    map[i].cb(NULL, NULL, (union hidmap_cb_ctx){}) == 0) {
477 			setbit(caps, i);
478 			items++;
479 		}
480 	}
481 
482 	/* Check that all mandatory usages are present in report descriptor */
483 	if (items != 0) {
484 		for (i = 0; i < nitems_map; i++) {
485 			KASSERT(!(map[i].required && map[i].forbidden),
486 			    ("both required & forbidden item flags are set"));
487 			if ((map[i].required && isclr(caps, i)) ||
488 			    (map[i].forbidden && isset(caps, i))) {
489 				items = 0;
490 				break;
491 			}
492 		}
493 	}
494 
495 	if (do_free)
496 		free(caps, M_DEVBUF);
497 
498 	return (items);
499 }
500 
501 uint32_t
502 hidmap_add_map(struct hidmap *hm, const struct hidmap_item *map,
503     int nitems_map, hidmap_caps_t caps)
504 {
505 	void *d_ptr;
506 	uint32_t items;
507 	int i, error;
508 	hid_size_t d_len;
509 	uint8_t tlc_index = hidbus_get_index(hm->dev);
510 
511 	/* Avoid double-adding of map in probe() handler */
512 	for (i = 0; i < hm->nmaps; i++)
513 		if (hm->map[i] == map)
514 			return (0);
515 
516 	error = hid_get_report_descr(hm->dev, &d_ptr, &d_len);
517 	if (error != 0) {
518 		device_printf(hm->dev, "could not retrieve report descriptor "
519 		     "from device: %d\n", error);
520 		return (error);
521 	}
522 
523 	hm->cb_state = HIDMAP_CB_IS_PROBING;
524 	items = hidmap_probe_hid_descr(d_ptr, d_len, tlc_index, map,
525 	    nitems_map, caps);
526 	if (items == 0)
527 		return (ENXIO);
528 
529 	KASSERT(hm->nmaps < HIDMAP_MAX_MAPS,
530 	    ("Not more than %d maps is supported", HIDMAP_MAX_MAPS));
531 	hm->nhid_items += items;
532 	hm->map[hm->nmaps] = map;
533 	hm->nmap_items[hm->nmaps] = nitems_map;
534 	hm->nmaps++;
535 
536 	return (0);
537 }
538 
539 static bool
540 hidmap_parse_hid_item(struct hidmap *hm, struct hid_item *hi,
541     struct hidmap_hid_item *item)
542 {
543 	const struct hidmap_item *mi;
544 	struct hidmap_hid_item hi_temp;
545 	uint32_t i;
546 	uint16_t uoff;
547 	bool found = false;
548 
549 	HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
550 		if (can_map_callback(hi, mi, uoff)) {
551 			bzero(&hi_temp, sizeof(hi_temp));
552 			hi_temp.cb = mi->cb;
553 			hi_temp.type = HIDMAP_TYPE_CALLBACK;
554 			/*
555 			 * Values returned by probe- and attach-stage
556 			 * callbacks MUST be identical.
557 			 */
558 			if (mi->cb(hm, &hi_temp,
559 			    (union hidmap_cb_ctx){.hi = hi}) != 0)
560 				break;
561 			bcopy(&hi_temp, item, sizeof(hi_temp));
562 			goto mapped;
563 		}
564 	}
565 
566 	if (hi->flags & HIO_VARIABLE) {
567 		HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
568 			if (can_map_variable(hi, mi, uoff)) {
569 				item->evtype = mi->type;
570 				item->code = mi->code + uoff;
571 				item->type = hi->flags & HIO_NULLSTATE
572 				    ? HIDMAP_TYPE_VAR_NULLST
573 				    : HIDMAP_TYPE_VARIABLE;
574 				item->last_val = 0;
575 				item->invert_value = mi->invert_value;
576 				switch (mi->type) {
577 				case EV_KEY:
578 					hidmap_support_key(hm, item->code);
579 					break;
580 				case EV_REL:
581 					evdev_support_event(hm->evdev, EV_REL);
582 					evdev_support_rel(hm->evdev,
583 					    item->code);
584 					break;
585 				case EV_ABS:
586 					evdev_support_event(hm->evdev, EV_ABS);
587 					evdev_support_abs(hm->evdev,
588 					    item->code,
589 					    hi->logical_minimum,
590 					    hi->logical_maximum,
591 					    mi->fuzz,
592 					    mi->flat,
593 					    hid_item_resolution(hi));
594 					break;
595 				case EV_SW:
596 					evdev_support_event(hm->evdev, EV_SW);
597 					evdev_support_sw(hm->evdev,
598 					    item->code);
599 					break;
600 				default:
601 					KASSERT(0, ("Unsupported event type"));
602 				}
603 				goto mapped;
604 			}
605 		}
606 		return (false);
607 	}
608 
609 	if (hi->usage_minimum != 0 || hi->usage_maximum != 0) {
610 		HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
611 			if (can_map_arr_range(hi, mi, uoff)) {
612 				hidmap_support_key(hm, mi->code + uoff);
613 				found = true;
614 			}
615 		}
616 		if (!found)
617 			return (false);
618 		item->umin = hi->usage_minimum;
619 		item->type = HIDMAP_TYPE_ARR_RANGE;
620 		item->last_key = KEY_RESERVED;
621 		goto mapped;
622 	}
623 
624 	for (i = 0; i < hi->nusages; i++) {
625 		HIDMAP_FOREACH_ITEM(hm, mi, uoff) {
626 			if (can_map_arr_list(hi, mi, hi->usages[i], uoff)) {
627 				hidmap_support_key(hm, mi->code + uoff);
628 				if (item->codes == NULL)
629 					item->codes = malloc(
630 					    hi->nusages * sizeof(uint16_t),
631 					    M_DEVBUF, M_WAITOK | M_ZERO);
632 				item->codes[i] = mi->code + uoff;
633 				found = true;
634 				break;
635 			}
636 		}
637 	}
638 	if (!found)
639 		return (false);
640 	item->type = HIDMAP_TYPE_ARR_LIST;
641 	item->last_key = KEY_RESERVED;
642 
643 mapped:
644 	item->id = hi->report_ID;
645 	item->loc = hi->loc;
646 	item->loc.count = 1;
647 	item->lmin = hi->logical_minimum;
648 	item->lmax = hi->logical_maximum;
649 
650 	DPRINTFN(hm, 6, "usage=%04x id=%d loc=%u/%u type=%d item=%*D\n",
651 	    hi->usage, hi->report_ID, hi->loc.pos, hi->loc.size, item->type,
652 	    (int)sizeof(item->cb), &item->cb, " ");
653 
654 	return (true);
655 }
656 
657 static int
658 hidmap_parse_hid_descr(struct hidmap *hm, uint8_t tlc_index)
659 {
660 	const struct hidmap_item *map;
661 	struct hidmap_hid_item *item = hm->hid_items;
662 	void *d_ptr;
663 	struct hid_data *hd;
664 	struct hid_item hi;
665 	int i, error;
666 	hid_size_t d_len;
667 
668 	error = hid_get_report_descr(hm->dev, &d_ptr, &d_len);
669 	if (error != 0) {
670 		DPRINTF(hm, "could not retrieve report descriptor from "
671 		     "device: %d\n", error);
672 		return (error);
673 	}
674 
675 	/* Parse inputs */
676 	hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
677 	HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) {
678 		if (hi.kind != hid_input)
679 			continue;
680 		if (hi.flags & HIO_CONST)
681 			continue;
682 		for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size)
683 			if (hidmap_parse_hid_item(hm, &hi, item))
684 				item++;
685 		KASSERT(item <= hm->hid_items + hm->nhid_items,
686 		    ("Parsed HID item array overflow"));
687 	}
688 	hid_end_parse(hd);
689 
690 	/* Add finalizing callbacks to the end of list */
691 	for (i = 0; i < hm->nmaps; i++) {
692 		for (map = hm->map[i];
693 		     map < hm->map[i] + hm->nmap_items[i];
694 		     map++) {
695 			if (map->has_cb && map->final_cb &&
696 			    map->cb(hm, item, (union hidmap_cb_ctx){}) == 0) {
697 				item->cb = map->cb;
698 				item->type = HIDMAP_TYPE_FINALCB;
699 				item++;
700 			}
701 		}
702 	}
703 
704 	/*
705 	 * Resulting number of parsed HID items can be less than expected as
706 	 * map items might be duplicated in different maps. Save real number.
707 	 */
708 	if (hm->nhid_items != item - hm->hid_items)
709 		DPRINTF(hm, "Parsed HID item number mismatch: expected=%u "
710 		    "result=%td\n", hm->nhid_items, item - hm->hid_items);
711 	hm->nhid_items = item - hm->hid_items;
712 
713 	if (HIDMAP_WANT_MERGE_KEYS(hm))
714 		bzero(hm->key_press, howmany(KEY_CNT, 8));
715 
716 	return (0);
717 }
718 
719 int
720 hidmap_probe(struct hidmap* hm, device_t dev,
721     const struct hid_device_id *id, int nitems_id,
722     const struct hidmap_item *map, int nitems_map,
723     const char *suffix, hidmap_caps_t caps)
724 {
725 	int error;
726 
727 	error = hidbus_lookup_driver_info(dev, id, nitems_id);
728 	if (error != 0)
729 		return (error);
730 
731 	hidmap_set_dev(hm, dev);
732 
733 	error = hidmap_add_map(hm, map, nitems_map, caps);
734 	if (error != 0)
735 		return (error);
736 
737 	hidbus_set_desc(dev, suffix);
738 
739 	return (BUS_PROBE_DEFAULT);
740 }
741 
742 int
743 hidmap_attach(struct hidmap* hm)
744 {
745 	const struct hid_device_info *hw = hid_get_device_info(hm->dev);
746 #ifdef HID_DEBUG
747 	char tunable[40];
748 #endif
749 	int error;
750 
751 #ifdef HID_DEBUG
752 	if (hm->debug_var == NULL) {
753 		hm->debug_var = &hm->debug_level;
754 		snprintf(tunable, sizeof(tunable), "hw.hid.%s.debug",
755 		    device_get_name(hm->dev));
756 		TUNABLE_INT_FETCH(tunable, &hm->debug_level);
757 		SYSCTL_ADD_INT(device_get_sysctl_ctx(hm->dev),
758 			SYSCTL_CHILDREN(device_get_sysctl_tree(hm->dev)),
759 			OID_AUTO, "debug", CTLFLAG_RWTUN,
760 			&hm->debug_level, 0, "Verbosity level");
761 	}
762 #endif
763 
764 	DPRINTFN(hm, 11, "hm=%p\n", hm);
765 
766 	hm->cb_state = HIDMAP_CB_IS_ATTACHING;
767 
768 	hm->hid_items = malloc(hm->nhid_items * sizeof(struct hid_item),
769 	    M_DEVBUF, M_WAITOK | M_ZERO);
770 
771 	hidbus_set_intr(hm->dev, hidmap_intr, hm);
772 	hm->evdev_methods = (struct evdev_methods) {
773 		.ev_open = &hidmap_ev_open,
774 		.ev_close = &hidmap_ev_close,
775 	};
776 
777 	hm->evdev = evdev_alloc();
778 	evdev_set_name(hm->evdev, device_get_desc(hm->dev));
779 	evdev_set_phys(hm->evdev, device_get_nameunit(hm->dev));
780 	evdev_set_id(hm->evdev, hw->idBus, hw->idVendor, hw->idProduct,
781 	    hw->idVersion);
782 	evdev_set_serial(hm->evdev, hw->serial);
783 	evdev_set_flag(hm->evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
784 	evdev_support_event(hm->evdev, EV_SYN);
785 	error = hidmap_parse_hid_descr(hm, hidbus_get_index(hm->dev));
786 	if (error) {
787 		DPRINTF(hm, "error=%d\n", error);
788 		hidmap_detach(hm);
789 		return (ENXIO);
790 	}
791 
792 	evdev_set_methods(hm->evdev, hm->dev, &hm->evdev_methods);
793 	hm->cb_state = HIDMAP_CB_IS_RUNNING;
794 
795 	error = evdev_register(hm->evdev);
796 	if (error) {
797 		DPRINTF(hm, "error=%d\n", error);
798 		hidmap_detach(hm);
799 		return (ENXIO);
800 	}
801 
802 	return (0);
803 }
804 
805 int
806 hidmap_detach(struct hidmap* hm)
807 {
808 	struct hidmap_hid_item *hi;
809 
810 	DPRINTFN(hm, 11, "\n");
811 
812 	hm->cb_state = HIDMAP_CB_IS_DETACHING;
813 
814 	evdev_free(hm->evdev);
815 	if (hm->hid_items != NULL) {
816 		for (hi = hm->hid_items;
817 		     hi < hm->hid_items + hm->nhid_items;
818 		     hi++)
819 			if (hi->type == HIDMAP_TYPE_FINALCB ||
820 			    hi->type == HIDMAP_TYPE_CALLBACK)
821 				hi->cb(hm, hi, (union hidmap_cb_ctx){});
822 			else if (hi->type == HIDMAP_TYPE_ARR_LIST)
823 				free(hi->codes, M_DEVBUF);
824 		free(hm->hid_items, M_DEVBUF);
825 	}
826 
827 	free(hm->key_press, M_DEVBUF);
828 	free(hm->key_rel, M_DEVBUF);
829 
830 	return (0);
831 }
832 
833 MODULE_DEPEND(hidmap, hid, 1, 1, 1);
834 MODULE_DEPEND(hidmap, hidbus, 1, 1, 1);
835 MODULE_DEPEND(hidmap, evdev, 1, 1, 1);
836 MODULE_VERSION(hidmap, 1);
837