xref: /freebsd/sys/dev/hid/hidmap.c (revision 6be3386466ab79a84b48429ae66244f21526d3df)
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);
833