2 * Copyright (c) 2016 Vladimir Kondratyev <wulf@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include "opt_evdev.h"
30 #include <sys/param.h>
32 #include <sys/malloc.h>
33 #include <sys/mutex.h>
34 #include <sys/systm.h>
36 #include <dev/misc/evdev/evdev.h>
37 #include <dev/misc/evdev/evdev_private.h>
38 #include <dev/misc/evdev/input.h>
41 #define debugf(fmt, args...) kprintf("evdev: " fmt "\n", ##args)
43 #define debugf(fmt, args...)
46 static uint16_t evdev_fngmap[] = {
54 static uint16_t evdev_mtstmap[][2] = {
55 { ABS_MT_POSITION_X, ABS_X },
56 { ABS_MT_POSITION_Y, ABS_Y },
57 { ABS_MT_PRESSURE, ABS_PRESSURE },
58 { ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH },
61 struct evdev_mt_slot {
63 int32_t ev_mt_states[MT_CNT];
67 int32_t ev_mt_last_reported_slot;
68 struct evdev_mt_slot ev_mt_slots[];
72 evdev_mt_init(struct evdev_dev *evdev)
76 slots = MAXIMAL_MT_SLOT(evdev) + 1;
78 evdev->ev_mt = kmalloc(offsetof(struct evdev_mt, ev_mt_slots) +
79 sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
81 /* Initialize multitouch protocol type B states */
82 for (slot = 0; slot < slots; slot++) {
84 * .ev_report should not be initialized to initial value of
85 * report counter (0) as it brokes free slot detection in
86 * evdev_get_mt_slot_by_tracking_id. So initialize it to -1
88 evdev->ev_mt->ev_mt_slots[slot] = (struct evdev_mt_slot) {
89 .ev_report = 0xFFFFFFFFFFFFFFFFULL,
90 .ev_mt_states[ABS_MT_INDEX(ABS_MT_TRACKING_ID)] = -1,
94 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
95 evdev_support_mt_compat(evdev);
99 evdev_mt_free(struct evdev_dev *evdev)
102 kfree(evdev->ev_mt, M_EVDEV);
106 evdev_get_last_mt_slot(struct evdev_dev *evdev)
109 return (evdev->ev_mt->ev_mt_last_reported_slot);
113 evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot)
116 evdev->ev_mt->ev_mt_slots[slot].ev_report = evdev->ev_report_count;
117 evdev->ev_mt->ev_mt_last_reported_slot = slot;
121 evdev_get_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code)
124 return (evdev->ev_mt->
125 ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)]);
129 evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code,
133 evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] =
138 evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
140 int32_t tr_id, slot, free_slot = -1;
142 for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
143 tr_id = evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID);
144 if (tr_id == tracking_id)
147 * Its possible that slot will be reassigned in a place of just
148 * released one within the same report. To avoid this compare
149 * report counter with slot`s report number updated with each
150 * ABS_MT_TRACKING_ID change.
152 if (free_slot == -1 && tr_id == -1 &&
153 evdev->ev_mt->ev_mt_slots[slot].ev_report !=
154 evdev->ev_report_count)
162 evdev_support_nfingers(struct evdev_dev *evdev, int32_t nfingers)
166 for (i = 0; i < MIN(nitems(evdev_fngmap), nfingers); i++)
167 evdev_support_key(evdev, evdev_fngmap[i]);
171 evdev_support_mt_compat(struct evdev_dev *evdev)
175 if (evdev->ev_absinfo == NULL)
178 evdev_support_event(evdev, EV_KEY);
179 evdev_support_key(evdev, BTN_TOUCH);
181 /* Touchscreens should not advertise tap tool capabilities */
182 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
183 evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
185 /* Echo 0-th MT-slot as ST-slot */
186 for (i = 0; i < nitems(evdev_mtstmap); i++)
187 if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0]))
188 evdev_support_abs(evdev, evdev_mtstmap[i][1],
189 evdev->ev_absinfo[evdev_mtstmap[i][0]].value,
190 evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum,
191 evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum,
192 evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz,
193 evdev->ev_absinfo[evdev_mtstmap[i][0]].flat,
194 evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
198 evdev_count_fingers(struct evdev_dev *evdev)
200 int32_t nfingers = 0, i;
202 for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
203 if (evdev_get_mt_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
210 evdev_send_nfingers(struct evdev_dev *evdev, int32_t nfingers)
214 EVDEV_LOCK_ASSERT(evdev);
216 if (nfingers > nitems(evdev_fngmap))
217 nfingers = nitems(evdev_fngmap);
219 for (i = 0; i < nitems(evdev_fngmap); i++)
220 evdev_send_event(evdev, EV_KEY, evdev_fngmap[i],
225 evdev_push_nfingers(struct evdev_dev *evdev, int32_t nfingers)
229 evdev_send_nfingers(evdev, nfingers);
234 evdev_send_mt_compat(struct evdev_dev *evdev)
238 EVDEV_LOCK_ASSERT(evdev);
240 nfingers = evdev_count_fingers(evdev);
241 evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
243 if (evdev_get_mt_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
244 /* Echo 0-th MT-slot as ST-slot */
245 for (i = 0; i < nitems(evdev_mtstmap); i++)
246 if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
247 evdev_send_event(evdev, EV_ABS,
249 evdev_get_mt_value(evdev, 0,
250 evdev_mtstmap[i][0]));
252 /* Touchscreens should not report tool taps */
253 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
254 evdev_send_nfingers(evdev, nfingers);
257 evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0);
261 evdev_push_mt_compat(struct evdev_dev *evdev)
265 evdev_send_mt_compat(evdev);
270 evdev_send_mt_autorel(struct evdev_dev *evdev)
274 EVDEV_LOCK_ASSERT(evdev);
276 for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
277 if (evdev->ev_mt->ev_mt_slots[slot].ev_report !=
278 evdev->ev_report_count &&
279 evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID) != -1){
280 evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
281 evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID,