2 * Copyright © 2010 Intel Corporation
3 * Copyright © 2013 Jonas Ådahl
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 #include "linux/input.h"
32 #include <mtdev-plumbing.h>
40 #include "libinput-private.h"
42 #define DEFAULT_AXIS_STEP_DISTANCE 10
47 EVDEV_KEY_TYPE_BUTTON,
51 set_key_down(struct evdev_device *device, int code, int pressed)
53 long_set_bit_state(device->key_mask, code, pressed);
57 is_key_down(struct evdev_device *device, int code)
59 return long_bit_is_set(device->key_mask, code);
63 evdev_device_led_update(struct evdev_device *device, enum libinput_led leds)
66 enum libinput_led weston;
69 { LIBINPUT_LED_NUM_LOCK, LED_NUML },
70 { LIBINPUT_LED_CAPS_LOCK, LED_CAPSL },
71 { LIBINPUT_LED_SCROLL_LOCK, LED_SCROLLL },
73 struct input_event ev[ARRAY_LENGTH(map) + 1];
76 if (!(device->seat_caps & EVDEV_DEVICE_KEYBOARD))
79 memset(ev, 0, sizeof(ev));
80 for (i = 0; i < ARRAY_LENGTH(map); i++) {
82 ev[i].code = map[i].evdev;
83 ev[i].value = !!(leds & map[i].weston);
86 ev[i].code = SYN_REPORT;
88 i = write(device->fd, ev, sizeof ev);
89 (void)i; /* no, we really don't care about the return value */
93 transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y)
95 if (!device->abs.apply_calibration) {
100 *x = device->abs.x * device->abs.calibration[0] +
101 device->abs.y * device->abs.calibration[1] +
102 device->abs.calibration[2];
104 *y = device->abs.x * device->abs.calibration[3] +
105 device->abs.y * device->abs.calibration[4] +
106 device->abs.calibration[5];
111 scale_axis(const struct input_absinfo *absinfo, double val, double to_range)
113 return (val - absinfo->minimum) * to_range /
114 (absinfo->maximum - absinfo->minimum + 1);
118 evdev_device_transform_x(struct evdev_device *device,
122 return scale_axis(device->abs.absinfo_x, x, width);
126 evdev_device_transform_y(struct evdev_device *device,
130 return scale_axis(device->abs.absinfo_y, y, height);
134 evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
136 struct libinput *libinput = device->base.seat->libinput;
137 struct motion_params motion;
142 struct libinput_device *base = &device->base;
143 struct libinput_seat *seat = base->seat;
145 slot = device->mt.slot;
147 switch (device->pending_event) {
150 case EVDEV_RELATIVE_MOTION:
151 motion.dx = device->rel.dx;
152 motion.dy = device->rel.dy;
156 /* Apply pointer acceleration. */
157 filter_dispatch(device->pointer.filter, &motion, device, time);
159 if (motion.dx == 0.0 && motion.dy == 0.0)
162 pointer_notify_motion(base, time, motion.dx, motion.dy);
164 case EVDEV_ABSOLUTE_MT_DOWN:
165 if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
168 if (device->mt.slots[slot].seat_slot != -1) {
169 log_bug_kernel(libinput,
170 "%s: Driver sent multiple touch down for the "
171 "same slot", device->devnode);
175 seat_slot = ffs(~seat->slot_map) - 1;
176 device->mt.slots[slot].seat_slot = seat_slot;
181 seat->slot_map |= 1 << seat_slot;
182 x = device->mt.slots[slot].x;
183 y = device->mt.slots[slot].y;
185 touch_notify_touch_down(base, time, slot, seat_slot, x, y);
187 case EVDEV_ABSOLUTE_MT_MOTION:
188 if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
191 seat_slot = device->mt.slots[slot].seat_slot;
192 x = device->mt.slots[slot].x;
193 y = device->mt.slots[slot].y;
198 touch_notify_touch_motion(base, time, slot, seat_slot, x, y);
200 case EVDEV_ABSOLUTE_MT_UP:
201 if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
204 seat_slot = device->mt.slots[slot].seat_slot;
205 device->mt.slots[slot].seat_slot = -1;
210 seat->slot_map &= ~(1 << seat_slot);
212 touch_notify_touch_up(base, time, slot, seat_slot);
214 case EVDEV_ABSOLUTE_TOUCH_DOWN:
215 if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
218 if (device->abs.seat_slot != -1) {
219 log_bug_kernel(libinput,
220 "%s: Driver sent multiple touch down for the "
221 "same slot", device->devnode);
225 seat_slot = ffs(~seat->slot_map) - 1;
226 device->abs.seat_slot = seat_slot;
231 seat->slot_map |= 1 << seat_slot;
233 transform_absolute(device, &cx, &cy);
235 touch_notify_touch_down(base, time, -1, seat_slot, cx, cy);
237 case EVDEV_ABSOLUTE_MOTION:
238 transform_absolute(device, &cx, &cy);
242 if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
243 seat_slot = device->abs.seat_slot;
248 touch_notify_touch_motion(base, time, -1, seat_slot, x, y);
249 } else if (device->seat_caps & EVDEV_DEVICE_POINTER) {
250 pointer_notify_motion_absolute(base, time, x, y);
253 case EVDEV_ABSOLUTE_TOUCH_UP:
254 if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
257 seat_slot = device->abs.seat_slot;
258 device->abs.seat_slot = -1;
263 seat->slot_map &= ~(1 << seat_slot);
265 touch_notify_touch_up(base, time, -1, seat_slot);
268 assert(0 && "Unknown pending event type");
272 device->pending_event = EVDEV_NONE;
275 static enum evdev_key_type
276 get_key_type(uint16_t code)
278 if (code == BTN_TOUCH)
279 return EVDEV_KEY_TYPE_NONE;
281 if (code >= KEY_ESC && code <= KEY_MICMUTE)
282 return EVDEV_KEY_TYPE_KEY;
283 if (code >= BTN_MISC && code <= BTN_GEAR_UP)
284 return EVDEV_KEY_TYPE_BUTTON;
285 if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE)
286 return EVDEV_KEY_TYPE_KEY;
287 if (code >= BTN_DPAD_UP && code <= BTN_TRIGGER_HAPPY40)
288 return EVDEV_KEY_TYPE_BUTTON;
289 return EVDEV_KEY_TYPE_NONE;
293 evdev_process_touch_button(struct evdev_device *device,
294 uint64_t time, int value)
296 if (device->pending_event != EVDEV_NONE &&
297 device->pending_event != EVDEV_ABSOLUTE_MOTION)
298 evdev_flush_pending_event(device, time);
300 device->pending_event = (value ?
301 EVDEV_ABSOLUTE_TOUCH_DOWN :
302 EVDEV_ABSOLUTE_TOUCH_UP);
306 evdev_process_key(struct evdev_device *device,
307 struct input_event *e, uint64_t time)
309 enum evdev_key_type type;
311 /* ignore kernel key repeat */
315 if (e->code == BTN_TOUCH) {
317 evdev_process_touch_button(device, time, e->value);
321 evdev_flush_pending_event(device, time);
323 type = get_key_type(e->code);
325 /* Ignore key release events from the kernel for keys that libinput
326 * never got a pressed event for. */
329 case EVDEV_KEY_TYPE_NONE:
331 case EVDEV_KEY_TYPE_KEY:
332 case EVDEV_KEY_TYPE_BUTTON:
333 if (!is_key_down(device, e->code))
338 set_key_down(device, e->code, e->value);
341 case EVDEV_KEY_TYPE_NONE:
343 case EVDEV_KEY_TYPE_KEY:
348 e->value ? LIBINPUT_KEY_STATE_PRESSED :
349 LIBINPUT_KEY_STATE_RELEASED);
351 case EVDEV_KEY_TYPE_BUTTON:
352 pointer_notify_button(
356 e->value ? LIBINPUT_BUTTON_STATE_PRESSED :
357 LIBINPUT_BUTTON_STATE_RELEASED);
363 evdev_process_touch(struct evdev_device *device,
364 struct input_event *e,
369 evdev_flush_pending_event(device, time);
370 device->mt.slot = e->value;
372 case ABS_MT_TRACKING_ID:
373 if (device->pending_event != EVDEV_NONE &&
374 device->pending_event != EVDEV_ABSOLUTE_MT_MOTION)
375 evdev_flush_pending_event(device, time);
377 device->pending_event = EVDEV_ABSOLUTE_MT_DOWN;
379 device->pending_event = EVDEV_ABSOLUTE_MT_UP;
381 case ABS_MT_POSITION_X:
382 device->mt.slots[device->mt.slot].x = e->value;
383 if (device->pending_event == EVDEV_NONE)
384 device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
386 case ABS_MT_POSITION_Y:
387 device->mt.slots[device->mt.slot].y = e->value;
388 if (device->pending_event == EVDEV_NONE)
389 device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
395 evdev_process_absolute_motion(struct evdev_device *device,
396 struct input_event *e)
400 device->abs.x = e->value;
401 if (device->pending_event == EVDEV_NONE)
402 device->pending_event = EVDEV_ABSOLUTE_MOTION;
405 device->abs.y = e->value;
406 if (device->pending_event == EVDEV_NONE)
407 device->pending_event = EVDEV_ABSOLUTE_MOTION;
413 evdev_process_relative(struct evdev_device *device,
414 struct input_event *e, uint64_t time)
416 struct libinput_device *base = &device->base;
420 if (device->pending_event != EVDEV_RELATIVE_MOTION)
421 evdev_flush_pending_event(device, time);
422 device->rel.dx += e->value;
423 device->pending_event = EVDEV_RELATIVE_MOTION;
426 if (device->pending_event != EVDEV_RELATIVE_MOTION)
427 evdev_flush_pending_event(device, time);
428 device->rel.dy += e->value;
429 device->pending_event = EVDEV_RELATIVE_MOTION;
432 evdev_flush_pending_event(device, time);
436 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
437 -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE);
440 evdev_flush_pending_event(device, time);
449 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
450 e->value * DEFAULT_AXIS_STEP_DISTANCE);
460 evdev_process_absolute(struct evdev_device *device,
461 struct input_event *e,
465 evdev_process_touch(device, e, time);
467 evdev_process_absolute_motion(device, e);
472 evdev_need_touch_frame(struct evdev_device *device)
474 if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
477 switch (device->pending_event) {
479 case EVDEV_RELATIVE_MOTION:
481 case EVDEV_ABSOLUTE_MT_DOWN:
482 case EVDEV_ABSOLUTE_MT_MOTION:
483 case EVDEV_ABSOLUTE_MT_UP:
484 case EVDEV_ABSOLUTE_TOUCH_DOWN:
485 case EVDEV_ABSOLUTE_TOUCH_UP:
486 case EVDEV_ABSOLUTE_MOTION:
494 fallback_process(struct evdev_dispatch *dispatch,
495 struct evdev_device *device,
496 struct input_event *event,
501 switch (event->type) {
503 evdev_process_relative(device, event, time);
506 evdev_process_absolute(device, event, time);
509 evdev_process_key(device, event, time);
512 need_frame = evdev_need_touch_frame(device);
513 evdev_flush_pending_event(device, time);
515 touch_notify_frame(&device->base, time);
521 fallback_destroy(struct evdev_dispatch *dispatch)
526 struct evdev_dispatch_interface fallback_interface = {
531 static struct evdev_dispatch *
532 fallback_dispatch_create(void)
534 struct evdev_dispatch *dispatch = malloc(sizeof *dispatch);
535 if (dispatch == NULL)
538 dispatch->interface = &fallback_interface;
544 evdev_process_event(struct evdev_device *device, struct input_event *e)
546 struct evdev_dispatch *dispatch = device->dispatch;
547 uint64_t time = e->time.tv_sec * 1000ULL + e->time.tv_usec / 1000;
549 dispatch->interface->process(dispatch, device, e, time);
553 evdev_device_dispatch_one(struct evdev_device *device,
554 struct input_event *ev)
556 if (!device->mtdev) {
557 evdev_process_event(device, ev);
559 mtdev_put_event(device->mtdev, ev);
560 if (libevdev_event_is_code(ev, EV_SYN, SYN_REPORT)) {
561 while (!mtdev_empty(device->mtdev)) {
562 struct input_event e;
563 mtdev_get_event(device->mtdev, &e);
564 evdev_process_event(device, &e);
571 evdev_sync_device(struct evdev_device *device)
573 struct input_event ev;
577 rc = libevdev_next_event(device->evdev,
578 LIBEVDEV_READ_FLAG_SYNC, &ev);
581 evdev_device_dispatch_one(device, &ev);
582 } while (rc == LIBEVDEV_READ_STATUS_SYNC);
584 return rc == -EAGAIN ? 0 : rc;
588 evdev_device_dispatch(void *data)
590 struct evdev_device *device = data;
591 struct libinput *libinput = device->base.seat->libinput;
592 struct input_event ev;
595 /* If the compositor is repainting, this function is called only once
596 * per frame and we have to process all the events available on the
597 * fd, otherwise there will be input lag. */
599 rc = libevdev_next_event(device->evdev,
600 LIBEVDEV_READ_FLAG_NORMAL, &ev);
601 if (rc == LIBEVDEV_READ_STATUS_SYNC) {
602 /* send one more sync event so we handle all
603 currently pending events before we sync up
604 to the current state */
605 ev.code = SYN_REPORT;
606 evdev_device_dispatch_one(device, &ev);
608 rc = evdev_sync_device(device);
610 rc = LIBEVDEV_READ_STATUS_SUCCESS;
611 } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
612 evdev_device_dispatch_one(device, &ev);
614 } while (rc == LIBEVDEV_READ_STATUS_SUCCESS);
616 if (rc != -EAGAIN && rc != -EINTR) {
617 libinput_remove_source(libinput, device->source);
618 device->source = NULL;
623 configure_pointer_acceleration(struct evdev_device *device)
625 device->pointer.filter =
626 create_pointer_accelator_filter(
627 pointer_accel_profile_smooth_simple);
628 if (!device->pointer.filter)
635 evdev_configure_device(struct evdev_device *device)
637 struct libinput *libinput = device->base.seat->libinput;
638 struct libevdev *evdev = device->evdev;
639 const struct input_absinfo *absinfo;
640 struct input_absinfo fixed;
641 int has_abs, has_rel, has_mt;
642 int has_button, has_keyboard, has_touch;
643 struct mt_slot *slots;
656 if (libevdev_has_event_type(evdev, EV_ABS)) {
658 if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) {
659 if (absinfo->resolution == 0) {
661 fixed.resolution = 1;
662 libevdev_set_abs_info(evdev, ABS_X, &fixed);
663 device->abs.fake_resolution = 1;
665 device->abs.absinfo_x = absinfo;
668 if ((absinfo = libevdev_get_abs_info(evdev, ABS_Y))) {
669 if (absinfo->resolution == 0) {
671 fixed.resolution = 1;
672 libevdev_set_abs_info(evdev, ABS_Y, &fixed);
673 device->abs.fake_resolution = 1;
675 device->abs.absinfo_y = absinfo;
678 /* We only handle the slotted Protocol B in weston.
679 Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT
680 require mtdev for conversion. */
681 if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) &&
682 libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) {
683 absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
684 if (absinfo->resolution == 0) {
686 fixed.resolution = 1;
687 libevdev_set_abs_info(evdev,
690 device->abs.fake_resolution = 1;
692 device->abs.absinfo_x = absinfo;
693 absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
694 if (absinfo->resolution == 0) {
696 fixed.resolution = 1;
697 libevdev_set_abs_info(evdev,
700 device->abs.fake_resolution = 1;
702 device->abs.absinfo_y = absinfo;
707 if (!libevdev_has_event_code(evdev,
708 EV_ABS, ABS_MT_SLOT)) {
709 device->mtdev = mtdev_new_open(device->fd);
713 num_slots = device->mtdev->caps.slot.maximum;
714 if (device->mtdev->caps.slot.minimum < 0 ||
717 active_slot = device->mtdev->caps.slot.value;
719 num_slots = libevdev_get_num_slots(device->evdev);
720 active_slot = libevdev_get_current_slot(evdev);
723 slots = calloc(num_slots, sizeof(struct mt_slot));
727 for (slot = 0; slot < num_slots; ++slot) {
728 slots[slot].seat_slot = -1;
732 device->mt.slots = slots;
733 device->mt.slots_len = num_slots;
734 device->mt.slot = active_slot;
737 if (libevdev_has_event_code(evdev, EV_REL, REL_X) ||
738 libevdev_has_event_code(evdev, EV_REL, REL_Y))
741 if (libevdev_has_event_type(evdev, EV_KEY)) {
742 if (!libevdev_has_property(evdev, INPUT_PROP_DIRECT) &&
743 libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER) &&
744 !libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN) &&
745 (has_abs || has_mt)) {
746 device->dispatch = evdev_mt_touchpad_create(device);
748 "input device '%s', %s is a touchpad\n",
749 device->devname, device->devnode);
750 return device->dispatch == NULL ? -1 : 0;
753 for (i = 0; i < KEY_MAX; i++) {
754 if (libevdev_has_event_code(evdev, EV_KEY, i)) {
755 switch (get_key_type(i)) {
756 case EVDEV_KEY_TYPE_NONE:
758 case EVDEV_KEY_TYPE_KEY:
761 case EVDEV_KEY_TYPE_BUTTON:
768 if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOUCH))
771 if (libevdev_has_event_type(evdev, EV_LED))
774 if ((has_abs || has_rel) && has_button) {
775 if (configure_pointer_acceleration(device) == -1)
778 device->seat_caps |= EVDEV_DEVICE_POINTER;
781 "input device '%s', %s is a pointer caps =%s%s%s\n",
782 device->devname, device->devnode,
783 has_abs ? " absolute-motion" : "",
784 has_rel ? " relative-motion": "",
785 has_button ? " button" : "");
788 device->seat_caps |= EVDEV_DEVICE_KEYBOARD;
790 "input device '%s', %s is a keyboard\n",
791 device->devname, device->devnode);
793 if (has_touch && !has_button) {
794 device->seat_caps |= EVDEV_DEVICE_TOUCH;
796 "input device '%s', %s is a touch device\n",
797 device->devname, device->devnode);
803 struct evdev_device *
804 evdev_device_create(struct libinput_seat *seat,
808 struct libinput *libinput = seat->libinput;
809 struct evdev_device *device;
812 int unhandled_device = 0;
814 /* Use non-blocking mode so that we can loop on read on
815 * evdev_device_data() until all events on the fd are
816 * read. mtdev_get() also expects this. */
817 fd = open_restricted(libinput, devnode, O_RDWR | O_NONBLOCK);
820 "opening input device '%s' failed (%s).\n",
821 devnode, strerror(-fd));
825 device = zalloc(sizeof *device);
829 libinput_device_init(&device->base, seat);
831 rc = libevdev_new_from_fd(fd, &device->evdev);
835 libevdev_set_clock_id(device->evdev, CLOCK_MONOTONIC);
837 device->seat_caps = 0;
839 device->mtdev = NULL;
840 device->devnode = strdup(devnode);
841 device->sysname = strdup(sysname);
844 device->abs.seat_slot = -1;
845 device->dispatch = NULL;
847 device->pending_event = EVDEV_NONE;
848 device->devname = libevdev_get_name(device->evdev);
850 libinput_seat_ref(seat);
852 if (evdev_configure_device(device) == -1)
855 if (device->seat_caps == 0) {
856 unhandled_device = 1;
860 /* If the dispatch was not set up use the fallback. */
861 if (device->dispatch == NULL)
862 device->dispatch = fallback_dispatch_create();
863 if (device->dispatch == NULL)
867 libinput_add_fd(libinput, fd, evdev_device_dispatch, device);
871 list_insert(seat->devices_list.prev, &device->base.link);
872 notify_added_device(&device->base);
878 close_restricted(libinput, fd);
879 evdev_device_destroy(device);
881 return unhandled_device ? EVDEV_UNHANDLED_DEVICE : NULL;
885 evdev_device_get_keys(struct evdev_device *device, char *keys, size_t size)
887 memset(keys, 0, size);
892 evdev_device_get_output(struct evdev_device *device)
894 return device->output_name;
898 evdev_device_get_sysname(struct evdev_device *device)
900 return device->sysname;
904 evdev_device_get_name(struct evdev_device *device)
906 return device->devname;
910 evdev_device_get_id_product(struct evdev_device *device)
912 return libevdev_get_id_product(device->evdev);
916 evdev_device_get_id_vendor(struct evdev_device *device)
918 return libevdev_get_id_vendor(device->evdev);
922 evdev_device_calibrate(struct evdev_device *device, float calibration[6])
924 device->abs.apply_calibration = 1;
925 memcpy(device->abs.calibration, calibration, sizeof device->abs.calibration);
929 evdev_device_has_capability(struct evdev_device *device,
930 enum libinput_device_capability capability)
932 switch (capability) {
933 case LIBINPUT_DEVICE_CAP_POINTER:
934 return !!(device->seat_caps & EVDEV_DEVICE_POINTER);
935 case LIBINPUT_DEVICE_CAP_KEYBOARD:
936 return !!(device->seat_caps & EVDEV_DEVICE_KEYBOARD);
937 case LIBINPUT_DEVICE_CAP_TOUCH:
938 return !!(device->seat_caps & EVDEV_DEVICE_TOUCH);
945 evdev_device_get_size(struct evdev_device *device,
949 const struct input_absinfo *x, *y;
951 x = libevdev_get_abs_info(device->evdev, ABS_X);
952 y = libevdev_get_abs_info(device->evdev, ABS_Y);
954 if (!x || !y || device->abs.fake_resolution ||
955 !x->resolution || !y->resolution)
958 *width = evdev_convert_to_mm(x, x->maximum);
959 *height = evdev_convert_to_mm(y, y->maximum);
965 evdev_device_remove(struct evdev_device *device)
968 libinput_remove_source(device->base.seat->libinput,
972 mtdev_close_delete(device->mtdev);
973 close_restricted(device->base.seat->libinput, device->fd);
975 list_remove(&device->base.link);
977 notify_removed_device(&device->base);
978 libinput_device_unref(&device->base);
982 evdev_device_destroy(struct evdev_device *device)
984 struct evdev_dispatch *dispatch;
986 dispatch = device->dispatch;
988 dispatch->interface->destroy(dispatch);
990 filter_destroy(device->pointer.filter);
991 libinput_seat_unref(device->base.seat);
992 libevdev_free(device->evdev);
993 free(device->mt.slots);
994 free(device->devnode);
995 free(device->sysname);