xref: /openbmc/qemu/ui/input.c (revision 7ae71462)
1 #include "qemu/osdep.h"
2 #include "sysemu/sysemu.h"
3 #include "qapi/error.h"
4 #include "qapi/qapi-commands-ui.h"
5 #include "trace.h"
6 #include "ui/input.h"
7 #include "ui/console.h"
8 #include "sysemu/replay.h"
9 #include "sysemu/runstate.h"
10 
11 struct QemuInputHandlerState {
12     DeviceState       *dev;
13     QemuInputHandler  *handler;
14     int               id;
15     int               events;
16     QemuConsole       *con;
17     QTAILQ_ENTRY(QemuInputHandlerState) node;
18 };
19 
20 typedef struct QemuInputEventQueue QemuInputEventQueue;
21 typedef QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue)
22     QemuInputEventQueueHead;
23 
24 struct QemuInputEventQueue {
25     enum {
26         QEMU_INPUT_QUEUE_DELAY = 1,
27         QEMU_INPUT_QUEUE_EVENT,
28         QEMU_INPUT_QUEUE_SYNC,
29     } type;
30     QEMUTimer *timer;
31     uint32_t delay_ms;
32     QemuConsole *src;
33     InputEvent *evt;
34     QTAILQ_ENTRY(QemuInputEventQueue) node;
35 };
36 
37 static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
38     QTAILQ_HEAD_INITIALIZER(handlers);
39 static NotifierList mouse_mode_notifiers =
40     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
41 
42 static QemuInputEventQueueHead kbd_queue = QTAILQ_HEAD_INITIALIZER(kbd_queue);
43 static QEMUTimer *kbd_timer;
44 static uint32_t kbd_default_delay_ms = 10;
45 static uint32_t queue_count;
46 static uint32_t queue_limit = 1024;
47 
48 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
49                                                    QemuInputHandler *handler)
50 {
51     QemuInputHandlerState *s = g_new0(QemuInputHandlerState, 1);
52     static int id = 1;
53 
54     s->dev = dev;
55     s->handler = handler;
56     s->id = id++;
57     QTAILQ_INSERT_TAIL(&handlers, s, node);
58 
59     qemu_input_check_mode_change();
60     return s;
61 }
62 
63 void qemu_input_handler_activate(QemuInputHandlerState *s)
64 {
65     QTAILQ_REMOVE(&handlers, s, node);
66     QTAILQ_INSERT_HEAD(&handlers, s, node);
67     qemu_input_check_mode_change();
68 }
69 
70 void qemu_input_handler_deactivate(QemuInputHandlerState *s)
71 {
72     QTAILQ_REMOVE(&handlers, s, node);
73     QTAILQ_INSERT_TAIL(&handlers, s, node);
74     qemu_input_check_mode_change();
75 }
76 
77 void qemu_input_handler_unregister(QemuInputHandlerState *s)
78 {
79     QTAILQ_REMOVE(&handlers, s, node);
80     g_free(s);
81     qemu_input_check_mode_change();
82 }
83 
84 void qemu_input_handler_bind(QemuInputHandlerState *s,
85                              const char *device_id, int head,
86                              Error **errp)
87 {
88     QemuConsole *con;
89     Error *err = NULL;
90 
91     con = qemu_console_lookup_by_device_name(device_id, head, &err);
92     if (err) {
93         error_propagate(errp, err);
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(const char *device,
126                           bool has_head, int64_t head,
127                           InputEventList *events, Error **errp)
128 {
129     InputEventList *e;
130     QemuConsole *con;
131     Error *err = NULL;
132 
133     con = NULL;
134     if (device) {
135         if (!has_head) {
136             head = 0;
137         }
138         con = qemu_console_lookup_by_device_name(device, head, &err);
139         if (err) {
140             error_propagate(errp, err);
141             return;
142         }
143     }
144 
145     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
146         error_setg(errp, "VM not running");
147         return;
148     }
149 
150     for (e = events; e != NULL; e = e->next) {
151         InputEvent *event = e->value;
152 
153         if (!qemu_input_find_handler(1 << event->type, con)) {
154             error_setg(errp, "Input handler not found for "
155                              "event type %s",
156                             InputEventKind_str(event->type));
157             return;
158         }
159     }
160 
161     for (e = events; e != NULL; e = e->next) {
162         InputEvent *evt = e->value;
163 
164         if (evt->type == INPUT_EVENT_KIND_KEY &&
165             evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER) {
166             KeyValue *key = evt->u.key.data->key;
167             QKeyCode code = qemu_input_key_number_to_qcode(key->u.number.data);
168             qemu_input_event_send_key_qcode(con, code, evt->u.key.data->down);
169         } else {
170             qemu_input_event_send(con, evt);
171         }
172     }
173 
174     qemu_input_event_sync();
175 }
176 
177 static int qemu_input_transform_invert_abs_value(int value)
178 {
179   return (int64_t)INPUT_EVENT_ABS_MAX - value + INPUT_EVENT_ABS_MIN;
180 }
181 
182 static void qemu_input_transform_abs_rotate(InputEvent *evt)
183 {
184     InputMoveEvent *move = evt->u.abs.data;
185     switch (graphic_rotate) {
186     case 90:
187         if (move->axis == INPUT_AXIS_X) {
188             move->axis = INPUT_AXIS_Y;
189         } else if (move->axis == INPUT_AXIS_Y) {
190             move->axis = INPUT_AXIS_X;
191             move->value = qemu_input_transform_invert_abs_value(move->value);
192         }
193         break;
194     case 180:
195         move->value = qemu_input_transform_invert_abs_value(move->value);
196         break;
197     case 270:
198         if (move->axis == INPUT_AXIS_X) {
199             move->axis = INPUT_AXIS_Y;
200             move->value = qemu_input_transform_invert_abs_value(move->value);
201         } else if (move->axis == INPUT_AXIS_Y) {
202             move->axis = INPUT_AXIS_X;
203         }
204         break;
205     }
206 }
207 
208 static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
209 {
210     const char *name;
211     int qcode, idx = -1;
212     InputKeyEvent *key;
213     InputBtnEvent *btn;
214     InputMoveEvent *move;
215 
216     if (src) {
217         idx = qemu_console_get_index(src);
218     }
219     switch (evt->type) {
220     case INPUT_EVENT_KIND_KEY:
221         key = evt->u.key.data;
222         switch (key->key->type) {
223         case KEY_VALUE_KIND_NUMBER:
224             qcode = qemu_input_key_number_to_qcode(key->key->u.number.data);
225             name = QKeyCode_str(qcode);
226             trace_input_event_key_number(idx, key->key->u.number.data,
227                                          name, key->down);
228             break;
229         case KEY_VALUE_KIND_QCODE:
230             name = QKeyCode_str(key->key->u.qcode.data);
231             trace_input_event_key_qcode(idx, name, key->down);
232             break;
233         case KEY_VALUE_KIND__MAX:
234             /* keep gcc happy */
235             break;
236         }
237         break;
238     case INPUT_EVENT_KIND_BTN:
239         btn = evt->u.btn.data;
240         name = InputButton_str(btn->button);
241         trace_input_event_btn(idx, name, btn->down);
242         break;
243     case INPUT_EVENT_KIND_REL:
244         move = evt->u.rel.data;
245         name = InputAxis_str(move->axis);
246         trace_input_event_rel(idx, name, move->value);
247         break;
248     case INPUT_EVENT_KIND_ABS:
249         move = evt->u.abs.data;
250         name = InputAxis_str(move->axis);
251         trace_input_event_abs(idx, name, move->value);
252         break;
253     case INPUT_EVENT_KIND__MAX:
254         /* keep gcc happy */
255         break;
256     }
257 }
258 
259 static void qemu_input_queue_process(void *opaque)
260 {
261     QemuInputEventQueueHead *queue = opaque;
262     QemuInputEventQueue *item;
263 
264     g_assert(!QTAILQ_EMPTY(queue));
265     item = QTAILQ_FIRST(queue);
266     g_assert(item->type == QEMU_INPUT_QUEUE_DELAY);
267     QTAILQ_REMOVE(queue, item, node);
268     queue_count--;
269     g_free(item);
270 
271     while (!QTAILQ_EMPTY(queue)) {
272         item = QTAILQ_FIRST(queue);
273         switch (item->type) {
274         case QEMU_INPUT_QUEUE_DELAY:
275             timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
276                       + item->delay_ms);
277             return;
278         case QEMU_INPUT_QUEUE_EVENT:
279             qemu_input_event_send(item->src, item->evt);
280             qapi_free_InputEvent(item->evt);
281             break;
282         case QEMU_INPUT_QUEUE_SYNC:
283             qemu_input_event_sync();
284             break;
285         }
286         QTAILQ_REMOVE(queue, item, node);
287         queue_count--;
288         g_free(item);
289     }
290 }
291 
292 static void qemu_input_queue_delay(QemuInputEventQueueHead *queue,
293                                    QEMUTimer *timer, uint32_t delay_ms)
294 {
295     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
296     bool start_timer = QTAILQ_EMPTY(queue);
297 
298     item->type = QEMU_INPUT_QUEUE_DELAY;
299     item->delay_ms = delay_ms;
300     item->timer = timer;
301     QTAILQ_INSERT_TAIL(queue, item, node);
302     queue_count++;
303 
304     if (start_timer) {
305         timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
306                   + item->delay_ms);
307     }
308 }
309 
310 static void qemu_input_queue_event(QemuInputEventQueueHead *queue,
311                                    QemuConsole *src, InputEvent *evt)
312 {
313     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
314 
315     item->type = QEMU_INPUT_QUEUE_EVENT;
316     item->src = src;
317     item->evt = evt;
318     QTAILQ_INSERT_TAIL(queue, item, node);
319     queue_count++;
320 }
321 
322 static void qemu_input_queue_sync(QemuInputEventQueueHead *queue)
323 {
324     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
325 
326     item->type = QEMU_INPUT_QUEUE_SYNC;
327     QTAILQ_INSERT_TAIL(queue, item, node);
328     queue_count++;
329 }
330 
331 void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
332 {
333     QemuInputHandlerState *s;
334 
335     qemu_input_event_trace(src, evt);
336 
337     /* pre processing */
338     if (graphic_rotate && (evt->type == INPUT_EVENT_KIND_ABS)) {
339             qemu_input_transform_abs_rotate(evt);
340     }
341 
342     /* send event */
343     s = qemu_input_find_handler(1 << evt->type, src);
344     if (!s) {
345         return;
346     }
347     s->handler->event(s->dev, src, evt);
348     s->events++;
349 }
350 
351 void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
352 {
353     /* Expect all parts of QEMU to send events with QCodes exclusively.
354      * Key numbers are only supported as end-user input via QMP */
355     assert(!(evt->type == INPUT_EVENT_KIND_KEY &&
356              evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER));
357 
358 
359     /*
360      * 'sysrq' was mistakenly added to hack around the fact that
361      * the ps2 driver was not generating correct scancodes sequences
362      * when 'alt+print' was pressed. This flaw is now fixed and the
363      * 'sysrq' key serves no further purpose. We normalize it to
364      * 'print', so that downstream receivers of the event don't
365      * need to deal with this mistake
366      */
367     if (evt->type == INPUT_EVENT_KIND_KEY &&
368         evt->u.key.data->key->u.qcode.data == Q_KEY_CODE_SYSRQ) {
369         evt->u.key.data->key->u.qcode.data = Q_KEY_CODE_PRINT;
370     }
371 
372     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
373         return;
374     }
375 
376     replay_input_event(src, evt);
377 }
378 
379 void qemu_input_event_sync_impl(void)
380 {
381     QemuInputHandlerState *s;
382 
383     trace_input_event_sync();
384 
385     QTAILQ_FOREACH(s, &handlers, node) {
386         if (!s->events) {
387             continue;
388         }
389         if (s->handler->sync) {
390             s->handler->sync(s->dev);
391         }
392         s->events = 0;
393     }
394 }
395 
396 void qemu_input_event_sync(void)
397 {
398     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
399         return;
400     }
401 
402     replay_input_sync_event();
403 }
404 
405 static InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
406 {
407     InputEvent *evt = g_new0(InputEvent, 1);
408     evt->u.key.data = g_new0(InputKeyEvent, 1);
409     evt->type = INPUT_EVENT_KIND_KEY;
410     evt->u.key.data->key = key;
411     evt->u.key.data->down = down;
412     return evt;
413 }
414 
415 void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
416 {
417     InputEvent *evt;
418     evt = qemu_input_event_new_key(key, down);
419     if (QTAILQ_EMPTY(&kbd_queue)) {
420         qemu_input_event_send(src, evt);
421         qemu_input_event_sync();
422         qapi_free_InputEvent(evt);
423     } else if (queue_count < queue_limit) {
424         qemu_input_queue_event(&kbd_queue, src, evt);
425         qemu_input_queue_sync(&kbd_queue);
426     } else {
427         qapi_free_InputEvent(evt);
428     }
429 }
430 
431 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
432 {
433     QKeyCode code = qemu_input_key_number_to_qcode(num);
434     qemu_input_event_send_key_qcode(src, code, down);
435 }
436 
437 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
438 {
439     KeyValue *key = g_new0(KeyValue, 1);
440     key->type = KEY_VALUE_KIND_QCODE;
441     key->u.qcode.data = q;
442     qemu_input_event_send_key(src, key, down);
443 }
444 
445 void qemu_input_event_send_key_delay(uint32_t delay_ms)
446 {
447     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
448         return;
449     }
450 
451     if (!kbd_timer) {
452         kbd_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
453                                    SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
454                                    qemu_input_queue_process, &kbd_queue);
455     }
456     if (queue_count < queue_limit) {
457         qemu_input_queue_delay(&kbd_queue, kbd_timer,
458                                delay_ms ? delay_ms : kbd_default_delay_ms);
459     }
460 }
461 
462 void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)
463 {
464     InputBtnEvent bevt = {
465         .button = btn,
466         .down = down,
467     };
468     InputEvent evt = {
469         .type = INPUT_EVENT_KIND_BTN,
470         .u.btn.data = &bevt,
471     };
472 
473     qemu_input_event_send(src, &evt);
474 }
475 
476 void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
477                                uint32_t button_old, uint32_t button_new)
478 {
479     InputButton btn;
480     uint32_t mask;
481 
482     for (btn = 0; btn < INPUT_BUTTON__MAX; btn++) {
483         mask = button_map[btn];
484         if ((button_old & mask) == (button_new & mask)) {
485             continue;
486         }
487         qemu_input_queue_btn(src, btn, button_new & mask);
488     }
489 }
490 
491 bool qemu_input_is_absolute(void)
492 {
493     QemuInputHandlerState *s;
494 
495     s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS,
496                                 NULL);
497     return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
498 }
499 
500 int qemu_input_scale_axis(int value,
501                           int min_in, int max_in,
502                           int min_out, int max_out)
503 {
504     int64_t range_in = (int64_t)max_in - min_in;
505     int64_t range_out = (int64_t)max_out - min_out;
506 
507     if (range_in < 1) {
508         return min_out + range_out / 2;
509     }
510     return ((int64_t)value - min_in) * range_out / range_in + min_out;
511 }
512 
513 void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
514 {
515     InputMoveEvent move = {
516         .axis = axis,
517         .value = value,
518     };
519     InputEvent evt = {
520         .type = INPUT_EVENT_KIND_REL,
521         .u.rel.data = &move,
522     };
523 
524     qemu_input_event_send(src, &evt);
525 }
526 
527 void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
528                           int min_in, int max_in)
529 {
530     InputMoveEvent move = {
531         .axis = axis,
532         .value = qemu_input_scale_axis(value, min_in, max_in,
533                                        INPUT_EVENT_ABS_MIN,
534                                        INPUT_EVENT_ABS_MAX),
535     };
536     InputEvent evt = {
537         .type = INPUT_EVENT_KIND_ABS,
538         .u.abs.data = &move,
539     };
540 
541     qemu_input_event_send(src, &evt);
542 }
543 
544 void qemu_input_check_mode_change(void)
545 {
546     static int current_is_absolute;
547     int is_absolute;
548 
549     is_absolute = qemu_input_is_absolute();
550 
551     if (is_absolute != current_is_absolute) {
552         trace_input_mouse_mode(is_absolute);
553         notifier_list_notify(&mouse_mode_notifiers, NULL);
554     }
555 
556     current_is_absolute = is_absolute;
557 }
558 
559 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
560 {
561     notifier_list_add(&mouse_mode_notifiers, notify);
562 }
563 
564 void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
565 {
566     notifier_remove(notify);
567 }
568 
569 MouseInfoList *qmp_query_mice(Error **errp)
570 {
571     MouseInfoList *mice_list = NULL;
572     MouseInfo *info;
573     QemuInputHandlerState *s;
574     bool current = true;
575 
576     QTAILQ_FOREACH(s, &handlers, node) {
577         if (!(s->handler->mask &
578               (INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS))) {
579             continue;
580         }
581 
582         info = g_new0(MouseInfo, 1);
583         info->index = s->id;
584         info->name = g_strdup(s->handler->name);
585         info->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS;
586         info->current = current;
587 
588         current = false;
589         QAPI_LIST_PREPEND(mice_list, info);
590     }
591 
592     return mice_list;
593 }
594 
595 bool qemu_mouse_set(int index, Error **errp)
596 {
597     QemuInputHandlerState *s;
598 
599     QTAILQ_FOREACH(s, &handlers, node) {
600         if (s->id == index) {
601             break;
602         }
603     }
604 
605     if (!s) {
606         error_setg(errp, "Mouse at index '%d' not found", index);
607         return false;
608     }
609 
610     if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
611                               INPUT_EVENT_MASK_ABS))) {
612         error_setg(errp, "Input device '%s' is not a mouse",
613                    s->handler->name);
614         return false;
615     }
616 
617     qemu_input_handler_activate(s);
618     qemu_input_check_mode_change();
619     return true;
620 }
621