xref: /openbmc/qemu/ui/input.c (revision 87c9b5e0)
1 #include "qemu/osdep.h"
2 #include "hw/qdev.h"
3 #include "sysemu/sysemu.h"
4 #include "qapi-types.h"
5 #include "qemu/error-report.h"
6 #include "qmp-commands.h"
7 #include "trace.h"
8 #include "ui/input.h"
9 #include "ui/console.h"
10 #include "sysemu/replay.h"
11 
12 struct QemuInputHandlerState {
13     DeviceState       *dev;
14     QemuInputHandler  *handler;
15     int               id;
16     int               events;
17     QemuConsole       *con;
18     QTAILQ_ENTRY(QemuInputHandlerState) node;
19 };
20 
21 typedef struct QemuInputEventQueue QemuInputEventQueue;
22 struct QemuInputEventQueue {
23     enum {
24         QEMU_INPUT_QUEUE_DELAY = 1,
25         QEMU_INPUT_QUEUE_EVENT,
26         QEMU_INPUT_QUEUE_SYNC,
27     } type;
28     QEMUTimer *timer;
29     uint32_t delay_ms;
30     QemuConsole *src;
31     InputEvent *evt;
32     QTAILQ_ENTRY(QemuInputEventQueue) node;
33 };
34 
35 static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
36     QTAILQ_HEAD_INITIALIZER(handlers);
37 static NotifierList mouse_mode_notifiers =
38     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
39 
40 static QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue) kbd_queue =
41     QTAILQ_HEAD_INITIALIZER(kbd_queue);
42 static QEMUTimer *kbd_timer;
43 static uint32_t kbd_default_delay_ms = 10;
44 
45 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
46                                                    QemuInputHandler *handler)
47 {
48     QemuInputHandlerState *s = g_new0(QemuInputHandlerState, 1);
49     static int id = 1;
50 
51     s->dev = dev;
52     s->handler = handler;
53     s->id = id++;
54     QTAILQ_INSERT_TAIL(&handlers, s, node);
55 
56     qemu_input_check_mode_change();
57     return s;
58 }
59 
60 void qemu_input_handler_activate(QemuInputHandlerState *s)
61 {
62     QTAILQ_REMOVE(&handlers, s, node);
63     QTAILQ_INSERT_HEAD(&handlers, s, node);
64     qemu_input_check_mode_change();
65 }
66 
67 void qemu_input_handler_deactivate(QemuInputHandlerState *s)
68 {
69     QTAILQ_REMOVE(&handlers, s, node);
70     QTAILQ_INSERT_TAIL(&handlers, s, node);
71     qemu_input_check_mode_change();
72 }
73 
74 void qemu_input_handler_unregister(QemuInputHandlerState *s)
75 {
76     QTAILQ_REMOVE(&handlers, s, node);
77     g_free(s);
78     qemu_input_check_mode_change();
79 }
80 
81 void qemu_input_handler_bind(QemuInputHandlerState *s,
82                              const char *device_id, int head,
83                              Error **errp)
84 {
85     DeviceState *dev;
86     QemuConsole *con;
87 
88     dev = qdev_find_recursive(sysbus_get_default(), device_id);
89     if (dev == NULL) {
90         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
91                   "Device '%s' not found", device_id);
92         return;
93     }
94 
95     con = qemu_console_lookup_by_device(dev, head);
96     if (con == NULL) {
97         error_setg(errp, "Device %s is not bound to a QemuConsole", device_id);
98         return;
99     }
100 
101     s->con = con;
102 }
103 
104 static QemuInputHandlerState*
105 qemu_input_find_handler(uint32_t mask, QemuConsole *con)
106 {
107     QemuInputHandlerState *s;
108 
109     QTAILQ_FOREACH(s, &handlers, node) {
110         if (s->con == NULL || s->con != con) {
111             continue;
112         }
113         if (mask & s->handler->mask) {
114             return s;
115         }
116     }
117 
118     QTAILQ_FOREACH(s, &handlers, node) {
119         if (s->con != NULL) {
120             continue;
121         }
122         if (mask & s->handler->mask) {
123             return s;
124         }
125     }
126     return NULL;
127 }
128 
129 void qmp_x_input_send_event(bool has_console, int64_t console,
130                             InputEventList *events, Error **errp)
131 {
132     InputEventList *e;
133     QemuConsole *con;
134 
135     con = NULL;
136     if (has_console) {
137         con = qemu_console_lookup_by_index(console);
138         if (!con) {
139             error_setg(errp, "console %" PRId64 " not found", console);
140             return;
141         }
142     }
143 
144     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
145         error_setg(errp, "VM not running");
146         return;
147     }
148 
149     for (e = events; e != NULL; e = e->next) {
150         InputEvent *event = e->value;
151 
152         if (!qemu_input_find_handler(1 << event->type, con)) {
153             error_setg(errp, "Input handler not found for "
154                              "event type %s",
155                             InputEventKind_lookup[event->type]);
156             return;
157         }
158     }
159 
160     for (e = events; e != NULL; e = e->next) {
161         InputEvent *event = e->value;
162 
163         qemu_input_event_send(con, event);
164     }
165 
166     qemu_input_event_sync();
167 }
168 
169 static void qemu_input_transform_abs_rotate(InputEvent *evt)
170 {
171     switch (graphic_rotate) {
172     case 90:
173         if (evt->u.abs->axis == INPUT_AXIS_X) {
174             evt->u.abs->axis = INPUT_AXIS_Y;
175         } else if (evt->u.abs->axis == INPUT_AXIS_Y) {
176             evt->u.abs->axis = INPUT_AXIS_X;
177             evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
178         }
179         break;
180     case 180:
181         evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
182         break;
183     case 270:
184         if (evt->u.abs->axis == INPUT_AXIS_X) {
185             evt->u.abs->axis = INPUT_AXIS_Y;
186             evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
187         } else if (evt->u.abs->axis == INPUT_AXIS_Y) {
188             evt->u.abs->axis = INPUT_AXIS_X;
189         }
190         break;
191     }
192 }
193 
194 static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
195 {
196     const char *name;
197     int qcode, idx = -1;
198 
199     if (src) {
200         idx = qemu_console_get_index(src);
201     }
202     switch (evt->type) {
203     case INPUT_EVENT_KIND_KEY:
204         switch (evt->u.key->key->type) {
205         case KEY_VALUE_KIND_NUMBER:
206             qcode = qemu_input_key_number_to_qcode(evt->u.key->key->u.number);
207             name = QKeyCode_lookup[qcode];
208             trace_input_event_key_number(idx, evt->u.key->key->u.number,
209                                          name, evt->u.key->down);
210             break;
211         case KEY_VALUE_KIND_QCODE:
212             name = QKeyCode_lookup[evt->u.key->key->u.qcode];
213             trace_input_event_key_qcode(idx, name, evt->u.key->down);
214             break;
215         case KEY_VALUE_KIND__MAX:
216             /* keep gcc happy */
217             break;
218         }
219         break;
220     case INPUT_EVENT_KIND_BTN:
221         name = InputButton_lookup[evt->u.btn->button];
222         trace_input_event_btn(idx, name, evt->u.btn->down);
223         break;
224     case INPUT_EVENT_KIND_REL:
225         name = InputAxis_lookup[evt->u.rel->axis];
226         trace_input_event_rel(idx, name, evt->u.rel->value);
227         break;
228     case INPUT_EVENT_KIND_ABS:
229         name = InputAxis_lookup[evt->u.abs->axis];
230         trace_input_event_abs(idx, name, evt->u.abs->value);
231         break;
232     case INPUT_EVENT_KIND__MAX:
233         /* keep gcc happy */
234         break;
235     }
236 }
237 
238 static void qemu_input_queue_process(void *opaque)
239 {
240     struct QemuInputEventQueueHead *queue = opaque;
241     QemuInputEventQueue *item;
242 
243     g_assert(!QTAILQ_EMPTY(queue));
244     item = QTAILQ_FIRST(queue);
245     g_assert(item->type == QEMU_INPUT_QUEUE_DELAY);
246     QTAILQ_REMOVE(queue, item, node);
247     g_free(item);
248 
249     while (!QTAILQ_EMPTY(queue)) {
250         item = QTAILQ_FIRST(queue);
251         switch (item->type) {
252         case QEMU_INPUT_QUEUE_DELAY:
253             timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
254                       + item->delay_ms);
255             return;
256         case QEMU_INPUT_QUEUE_EVENT:
257             qemu_input_event_send(item->src, item->evt);
258             qapi_free_InputEvent(item->evt);
259             break;
260         case QEMU_INPUT_QUEUE_SYNC:
261             qemu_input_event_sync();
262             break;
263         }
264         QTAILQ_REMOVE(queue, item, node);
265         g_free(item);
266     }
267 }
268 
269 static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue,
270                                    QEMUTimer *timer, uint32_t delay_ms)
271 {
272     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
273     bool start_timer = QTAILQ_EMPTY(queue);
274 
275     item->type = QEMU_INPUT_QUEUE_DELAY;
276     item->delay_ms = delay_ms;
277     item->timer = timer;
278     QTAILQ_INSERT_TAIL(queue, item, node);
279 
280     if (start_timer) {
281         timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
282                   + item->delay_ms);
283     }
284 }
285 
286 static void qemu_input_queue_event(struct QemuInputEventQueueHead *queue,
287                                    QemuConsole *src, InputEvent *evt)
288 {
289     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
290 
291     item->type = QEMU_INPUT_QUEUE_EVENT;
292     item->src = src;
293     item->evt = evt;
294     QTAILQ_INSERT_TAIL(queue, item, node);
295 }
296 
297 static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
298 {
299     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
300 
301     item->type = QEMU_INPUT_QUEUE_SYNC;
302     QTAILQ_INSERT_TAIL(queue, item, node);
303 }
304 
305 void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
306 {
307     QemuInputHandlerState *s;
308 
309     qemu_input_event_trace(src, evt);
310 
311     /* pre processing */
312     if (graphic_rotate && (evt->type == INPUT_EVENT_KIND_ABS)) {
313             qemu_input_transform_abs_rotate(evt);
314     }
315 
316     /* send event */
317     s = qemu_input_find_handler(1 << evt->type, src);
318     if (!s) {
319         return;
320     }
321     s->handler->event(s->dev, src, evt);
322     s->events++;
323 }
324 
325 void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
326 {
327     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
328         return;
329     }
330 
331     replay_input_event(src, evt);
332 }
333 
334 void qemu_input_event_sync_impl(void)
335 {
336     QemuInputHandlerState *s;
337 
338     trace_input_event_sync();
339 
340     QTAILQ_FOREACH(s, &handlers, node) {
341         if (!s->events) {
342             continue;
343         }
344         if (s->handler->sync) {
345             s->handler->sync(s->dev);
346         }
347         s->events = 0;
348     }
349 }
350 
351 void qemu_input_event_sync(void)
352 {
353     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
354         return;
355     }
356 
357     replay_input_sync_event();
358 }
359 
360 InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
361 {
362     InputEvent *evt = g_new0(InputEvent, 1);
363     evt->u.key = g_new0(InputKeyEvent, 1);
364     evt->type = INPUT_EVENT_KIND_KEY;
365     evt->u.key->key = key;
366     evt->u.key->down = down;
367     return evt;
368 }
369 
370 void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
371 {
372     InputEvent *evt;
373     evt = qemu_input_event_new_key(key, down);
374     if (QTAILQ_EMPTY(&kbd_queue)) {
375         qemu_input_event_send(src, evt);
376         qemu_input_event_sync();
377         qapi_free_InputEvent(evt);
378     } else {
379         qemu_input_queue_event(&kbd_queue, src, evt);
380         qemu_input_queue_sync(&kbd_queue);
381     }
382 }
383 
384 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
385 {
386     KeyValue *key = g_new0(KeyValue, 1);
387     key->type = KEY_VALUE_KIND_NUMBER;
388     key->u.number = num;
389     qemu_input_event_send_key(src, key, down);
390 }
391 
392 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
393 {
394     KeyValue *key = g_new0(KeyValue, 1);
395     key->type = KEY_VALUE_KIND_QCODE;
396     key->u.qcode = q;
397     qemu_input_event_send_key(src, key, down);
398 }
399 
400 void qemu_input_event_send_key_delay(uint32_t delay_ms)
401 {
402     if (!kbd_timer) {
403         kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process,
404                                  &kbd_queue);
405     }
406     qemu_input_queue_delay(&kbd_queue, kbd_timer,
407                            delay_ms ? delay_ms : kbd_default_delay_ms);
408 }
409 
410 InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
411 {
412     InputEvent *evt = g_new0(InputEvent, 1);
413     evt->u.btn = g_new0(InputBtnEvent, 1);
414     evt->type = INPUT_EVENT_KIND_BTN;
415     evt->u.btn->button = btn;
416     evt->u.btn->down = down;
417     return evt;
418 }
419 
420 void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)
421 {
422     InputEvent *evt;
423     evt = qemu_input_event_new_btn(btn, down);
424     qemu_input_event_send(src, evt);
425     qapi_free_InputEvent(evt);
426 }
427 
428 void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
429                                uint32_t button_old, uint32_t button_new)
430 {
431     InputButton btn;
432     uint32_t mask;
433 
434     for (btn = 0; btn < INPUT_BUTTON__MAX; btn++) {
435         mask = button_map[btn];
436         if ((button_old & mask) == (button_new & mask)) {
437             continue;
438         }
439         qemu_input_queue_btn(src, btn, button_new & mask);
440     }
441 }
442 
443 bool qemu_input_is_absolute(void)
444 {
445     QemuInputHandlerState *s;
446 
447     s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS,
448                                 NULL);
449     return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
450 }
451 
452 int qemu_input_scale_axis(int value, int size_in, int size_out)
453 {
454     if (size_in < 2) {
455         return size_out / 2;
456     }
457     return (int64_t)value * (size_out - 1) / (size_in - 1);
458 }
459 
460 InputEvent *qemu_input_event_new_move(InputEventKind kind,
461                                       InputAxis axis, int value)
462 {
463     InputEvent *evt = g_new0(InputEvent, 1);
464     InputMoveEvent *move = g_new0(InputMoveEvent, 1);
465 
466     evt->type = kind;
467     evt->u.data = move;
468     move->axis = axis;
469     move->value = value;
470     return evt;
471 }
472 
473 void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
474 {
475     InputEvent *evt;
476     evt = qemu_input_event_new_move(INPUT_EVENT_KIND_REL, axis, value);
477     qemu_input_event_send(src, evt);
478     qapi_free_InputEvent(evt);
479 }
480 
481 void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size)
482 {
483     InputEvent *evt;
484     int scaled = qemu_input_scale_axis(value, size, INPUT_EVENT_ABS_SIZE);
485     evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled);
486     qemu_input_event_send(src, evt);
487     qapi_free_InputEvent(evt);
488 }
489 
490 void qemu_input_check_mode_change(void)
491 {
492     static int current_is_absolute;
493     int is_absolute;
494 
495     is_absolute = qemu_input_is_absolute();
496 
497     if (is_absolute != current_is_absolute) {
498         trace_input_mouse_mode(is_absolute);
499         notifier_list_notify(&mouse_mode_notifiers, NULL);
500     }
501 
502     current_is_absolute = is_absolute;
503 }
504 
505 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
506 {
507     notifier_list_add(&mouse_mode_notifiers, notify);
508 }
509 
510 void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
511 {
512     notifier_remove(notify);
513 }
514 
515 MouseInfoList *qmp_query_mice(Error **errp)
516 {
517     MouseInfoList *mice_list = NULL;
518     MouseInfoList *info;
519     QemuInputHandlerState *s;
520     bool current = true;
521 
522     QTAILQ_FOREACH(s, &handlers, node) {
523         if (!(s->handler->mask &
524               (INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS))) {
525             continue;
526         }
527 
528         info = g_new0(MouseInfoList, 1);
529         info->value = g_new0(MouseInfo, 1);
530         info->value->index = s->id;
531         info->value->name = g_strdup(s->handler->name);
532         info->value->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS;
533         info->value->current = current;
534 
535         current = false;
536         info->next = mice_list;
537         mice_list = info;
538     }
539 
540     return mice_list;
541 }
542 
543 void hmp_mouse_set(Monitor *mon, const QDict *qdict)
544 {
545     QemuInputHandlerState *s;
546     int index = qdict_get_int(qdict, "index");
547     int found = 0;
548 
549     QTAILQ_FOREACH(s, &handlers, node) {
550         if (s->id != index) {
551             continue;
552         }
553         if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
554                                   INPUT_EVENT_MASK_ABS))) {
555             error_report("Input device '%s' is not a mouse", s->handler->name);
556             return;
557         }
558         found = 1;
559         qemu_input_handler_activate(s);
560         break;
561     }
562 
563     if (!found) {
564         error_report("Mouse at index '%d' not found", index);
565     }
566 
567     qemu_input_check_mode_change();
568 }
569