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