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