2 * This work is licensed under the terms of the GNU GPL, version 2 or
3 * (at your option) any later version. See the COPYING file in the
7 #include "qemu/osdep.h"
8 #include "qapi/error.h"
9 #include "qemu/config-file.h"
10 #include "qemu/main-loop.h"
11 #include "qemu/module.h"
12 #include "qemu/sockets.h"
13 #include "sysemu/sysemu.h"
15 #include "qom/object_interfaces.h"
16 #include "sysemu/iothread.h"
17 #include "block/aio.h"
19 #include <sys/ioctl.h>
20 #include "standard-headers/linux/input.h"
22 static bool linux_is_button(unsigned int lnx)
27 if (lnx >= 0x160 && lnx < 0x2c0) {
33 #define TYPE_INPUT_LINUX "input-linux"
34 #define INPUT_LINUX(obj) \
35 OBJECT_CHECK(InputLinux, (obj), TYPE_INPUT_LINUX)
36 #define INPUT_LINUX_GET_CLASS(obj) \
37 OBJECT_GET_CLASS(InputLinuxClass, (obj), TYPE_INPUT_LINUX)
38 #define INPUT_LINUX_CLASS(klass) \
39 OBJECT_CLASS_CHECK(InputLinuxClass, (klass), TYPE_INPUT_LINUX)
41 typedef struct InputLinux InputLinux;
42 typedef struct InputLinuxClass InputLinuxClass;
53 bool keydown[KEY_CNT];
66 struct input_event event;
69 enum GrabToggleKeys grab_toggle;
71 QTAILQ_ENTRY(InputLinux) next;
74 struct InputLinuxClass {
75 ObjectClass parent_class;
78 static QTAILQ_HEAD(, InputLinux) inputs = QTAILQ_HEAD_INITIALIZER(inputs);
80 static void input_linux_toggle_grab(InputLinux *il)
82 intptr_t request = !il->grab_active;
86 rc = ioctl(il->fd, EVIOCGRAB, request);
90 il->grab_active = !il->grab_active;
95 QTAILQ_FOREACH(item, &inputs, next) {
96 if (item == il || item->grab_all) {
97 /* avoid endless loops */
100 if (item->grab_active != il->grab_active) {
101 input_linux_toggle_grab(item);
106 static bool input_linux_check_toggle(InputLinux *il)
108 switch (il->grab_toggle) {
109 case GRAB_TOGGLE_KEYS_CTRL_CTRL:
110 return il->keydown[KEY_LEFTCTRL] &&
111 il->keydown[KEY_RIGHTCTRL];
113 case GRAB_TOGGLE_KEYS_ALT_ALT:
114 return il->keydown[KEY_LEFTALT] &&
115 il->keydown[KEY_RIGHTALT];
117 case GRAB_TOGGLE_KEYS_META_META:
118 return il->keydown[KEY_LEFTMETA] &&
119 il->keydown[KEY_RIGHTMETA];
121 case GRAB_TOGGLE_KEYS_SCROLLLOCK:
122 return il->keydown[KEY_SCROLLLOCK];
124 case GRAB_TOGGLE_KEYS_CTRL_SCROLLLOCK:
125 return (il->keydown[KEY_LEFTCTRL] ||
126 il->keydown[KEY_RIGHTCTRL]) &&
127 il->keydown[KEY_SCROLLLOCK];
129 case GRAB_TOGGLE_KEYS__MAX:
130 /* avoid gcc error */
136 static bool input_linux_should_skip(InputLinux *il,
137 struct input_event *event)
139 return (il->grab_toggle == GRAB_TOGGLE_KEYS_SCROLLLOCK ||
140 il->grab_toggle == GRAB_TOGGLE_KEYS_CTRL_SCROLLLOCK) &&
141 event->code == KEY_SCROLLLOCK;
144 static void input_linux_handle_keyboard(InputLinux *il,
145 struct input_event *event)
147 if (event->type == EV_KEY) {
148 if (event->value > 2 || (event->value > 1 && !il->repeat)) {
150 * ignore autorepeat + unknown key events
151 * 0 == up, 1 == down, 2 == autorepeat, other == undefined
155 if (event->code >= KEY_CNT) {
157 * Should not happen. But better safe than sorry,
158 * and we make Coverity happy too.
163 /* keep track of key state */
164 if (!il->keydown[event->code] && event->value) {
165 il->keydown[event->code] = true;
168 if (il->keydown[event->code] && !event->value) {
169 il->keydown[event->code] = false;
173 /* send event to guest when grab is active */
174 if (il->grab_active && !input_linux_should_skip(il, event)) {
175 int qcode = qemu_input_linux_to_qcode(event->code);
176 qemu_input_event_send_key_qcode(NULL, qcode, event->value);
179 /* hotkey -> record switch request ... */
180 if (input_linux_check_toggle(il)) {
181 il->grab_request = true;
185 * ... and do the switch when all keys are lifted, so we
186 * confuse neither guest nor host with keys which seem to
187 * be stuck due to missing key-up events.
189 if (il->grab_request && !il->keycount) {
190 il->grab_request = false;
191 input_linux_toggle_grab(il);
196 static void input_linux_event_mouse_button(int button)
198 qemu_input_queue_btn(NULL, button, true);
199 qemu_input_event_sync();
200 qemu_input_queue_btn(NULL, button, false);
201 qemu_input_event_sync();
204 static void input_linux_handle_mouse(InputLinux *il, struct input_event *event)
206 if (!il->grab_active) {
210 switch (event->type) {
212 switch (event->code) {
214 qemu_input_queue_btn(NULL, INPUT_BUTTON_LEFT, event->value);
217 qemu_input_queue_btn(NULL, INPUT_BUTTON_RIGHT, event->value);
220 qemu_input_queue_btn(NULL, INPUT_BUTTON_MIDDLE, event->value);
223 qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_UP, event->value);
226 qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_DOWN,
230 qemu_input_queue_btn(NULL, INPUT_BUTTON_SIDE, event->value);
233 qemu_input_queue_btn(NULL, INPUT_BUTTON_EXTRA, event->value);
238 switch (event->code) {
240 qemu_input_queue_rel(NULL, INPUT_AXIS_X, event->value);
243 qemu_input_queue_rel(NULL, INPUT_AXIS_Y, event->value);
246 il->wheel = event->value;
251 switch (event->code) {
253 qemu_input_queue_abs(NULL, INPUT_AXIS_X, event->value,
254 il->abs_x_min, il->abs_x_max);
257 qemu_input_queue_abs(NULL, INPUT_AXIS_Y, event->value,
258 il->abs_y_min, il->abs_y_max);
263 qemu_input_event_sync();
264 if (il->wheel != 0) {
265 input_linux_event_mouse_button((il->wheel > 0)
266 ? INPUT_BUTTON_WHEEL_UP
267 : INPUT_BUTTON_WHEEL_DOWN);
274 static void input_linux_event(void *opaque)
276 InputLinux *il = opaque;
279 uint8_t *p = (uint8_t *)&il->event;
282 read_size = sizeof(il->event) - il->read_offset;
283 rc = read(il->fd, &p[il->read_offset], read_size);
284 if (rc != read_size) {
285 if (rc < 0 && errno != EAGAIN) {
286 fprintf(stderr, "%s: read: %s\n", __func__, strerror(errno));
287 qemu_set_fd_handler(il->fd, NULL, NULL, NULL);
290 il->read_offset += rc;
297 input_linux_handle_keyboard(il, &il->event);
299 if ((il->has_rel_x || il->has_abs_x) && il->num_btns) {
300 input_linux_handle_mouse(il, &il->event);
305 static void input_linux_complete(UserCreatable *uc, Error **errp)
307 InputLinux *il = INPUT_LINUX(uc);
308 uint8_t evtmap, relmap, absmap;
309 uint8_t keymap[KEY_CNT / 8], keystate[KEY_CNT / 8];
312 struct input_absinfo absinfo;
315 error_setg(errp, "no input device specified");
319 il->fd = open(il->evdev, O_RDWR);
321 error_setg_file_open(errp, errno, il->evdev);
324 qemu_set_nonblock(il->fd);
326 rc = ioctl(il->fd, EVIOCGVERSION, &ver);
328 error_setg(errp, "%s: is not an evdev device", il->evdev);
332 rc = ioctl(il->fd, EVIOCGBIT(0, sizeof(evtmap)), &evtmap);
334 error_setg(errp, "%s: failed to read event bits", il->evdev);
338 if (evtmap & (1 << EV_REL)) {
340 rc = ioctl(il->fd, EVIOCGBIT(EV_REL, sizeof(relmap)), &relmap);
341 if (relmap & (1 << REL_X)) {
342 il->has_rel_x = true;
346 if (evtmap & (1 << EV_ABS)) {
348 rc = ioctl(il->fd, EVIOCGBIT(EV_ABS, sizeof(absmap)), &absmap);
349 if (absmap & (1 << ABS_X)) {
350 il->has_abs_x = true;
351 rc = ioctl(il->fd, EVIOCGABS(ABS_X), &absinfo);
352 il->abs_x_min = absinfo.minimum;
353 il->abs_x_max = absinfo.maximum;
354 rc = ioctl(il->fd, EVIOCGABS(ABS_Y), &absinfo);
355 il->abs_y_min = absinfo.minimum;
356 il->abs_y_max = absinfo.maximum;
360 if (evtmap & (1 << EV_KEY)) {
361 memset(keymap, 0, sizeof(keymap));
362 rc = ioctl(il->fd, EVIOCGBIT(EV_KEY, sizeof(keymap)), keymap);
363 rc = ioctl(il->fd, EVIOCGKEY(sizeof(keystate)), keystate);
364 for (i = 0; i < KEY_CNT; i++) {
365 if (keymap[i / 8] & (1 << (i % 8))) {
366 if (linux_is_button(i)) {
371 if (keystate[i / 8] & (1 << (i % 8))) {
372 il->keydown[i] = true;
379 qemu_set_fd_handler(il->fd, input_linux_event, NULL, il);
381 /* delay grab until all keys are released */
382 il->grab_request = true;
384 input_linux_toggle_grab(il);
386 QTAILQ_INSERT_TAIL(&inputs, il, next);
387 il->initialized = true;
395 static void input_linux_instance_finalize(Object *obj)
397 InputLinux *il = INPUT_LINUX(obj);
399 if (il->initialized) {
400 QTAILQ_REMOVE(&inputs, il, next);
406 static char *input_linux_get_evdev(Object *obj, Error **errp)
408 InputLinux *il = INPUT_LINUX(obj);
410 return g_strdup(il->evdev);
413 static void input_linux_set_evdev(Object *obj, const char *value,
416 InputLinux *il = INPUT_LINUX(obj);
419 error_setg(errp, "evdev property already set");
422 il->evdev = g_strdup(value);
425 static bool input_linux_get_grab_all(Object *obj, Error **errp)
427 InputLinux *il = INPUT_LINUX(obj);
432 static void input_linux_set_grab_all(Object *obj, bool value,
435 InputLinux *il = INPUT_LINUX(obj);
437 il->grab_all = value;
440 static bool input_linux_get_repeat(Object *obj, Error **errp)
442 InputLinux *il = INPUT_LINUX(obj);
447 static void input_linux_set_repeat(Object *obj, bool value,
450 InputLinux *il = INPUT_LINUX(obj);
455 static int input_linux_get_grab_toggle(Object *obj, Error **errp)
457 InputLinux *il = INPUT_LINUX(obj);
459 return il->grab_toggle;
462 static void input_linux_set_grab_toggle(Object *obj, int value,
465 InputLinux *il = INPUT_LINUX(obj);
467 il->grab_toggle = value;
470 static void input_linux_instance_init(Object *obj)
472 object_property_add_str(obj, "evdev",
473 input_linux_get_evdev,
474 input_linux_set_evdev, NULL);
475 object_property_add_bool(obj, "grab_all",
476 input_linux_get_grab_all,
477 input_linux_set_grab_all, NULL);
478 object_property_add_bool(obj, "repeat",
479 input_linux_get_repeat,
480 input_linux_set_repeat, NULL);
481 object_property_add_enum(obj, "grab-toggle", "GrabToggleKeys",
482 &GrabToggleKeys_lookup,
483 input_linux_get_grab_toggle,
484 input_linux_set_grab_toggle, NULL);
487 static void input_linux_class_init(ObjectClass *oc, void *data)
489 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
491 ucc->complete = input_linux_complete;
494 static const TypeInfo input_linux_info = {
495 .name = TYPE_INPUT_LINUX,
496 .parent = TYPE_OBJECT,
497 .class_size = sizeof(InputLinuxClass),
498 .class_init = input_linux_class_init,
499 .instance_size = sizeof(InputLinux),
500 .instance_init = input_linux_instance_init,
501 .instance_finalize = input_linux_instance_finalize,
502 .interfaces = (InterfaceInfo[]) {
503 { TYPE_USER_CREATABLE },
508 static void register_types(void)
510 type_register_static(&input_linux_info);
513 type_init(register_types);