xref: /openbmc/qemu/ui/input.c (revision d0bf492f)
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     InputMultiTouchEvent *mtt;
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_MTT:
255         mtt = evt->u.mtt.data;
256         name = InputAxis_str(mtt->axis);
257         trace_input_event_mtt(idx, name, mtt->value);
258         break;
259     case INPUT_EVENT_KIND__MAX:
260         /* keep gcc happy */
261         break;
262     }
263 }
264 
265 static void qemu_input_queue_process(void *opaque)
266 {
267     QemuInputEventQueueHead *queue = opaque;
268     QemuInputEventQueue *item;
269 
270     g_assert(!QTAILQ_EMPTY(queue));
271     item = QTAILQ_FIRST(queue);
272     g_assert(item->type == QEMU_INPUT_QUEUE_DELAY);
273     QTAILQ_REMOVE(queue, item, node);
274     queue_count--;
275     g_free(item);
276 
277     while (!QTAILQ_EMPTY(queue)) {
278         item = QTAILQ_FIRST(queue);
279         switch (item->type) {
280         case QEMU_INPUT_QUEUE_DELAY:
281             timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
282                       + item->delay_ms);
283             return;
284         case QEMU_INPUT_QUEUE_EVENT:
285             qemu_input_event_send(item->src, item->evt);
286             qapi_free_InputEvent(item->evt);
287             break;
288         case QEMU_INPUT_QUEUE_SYNC:
289             qemu_input_event_sync();
290             break;
291         }
292         QTAILQ_REMOVE(queue, item, node);
293         queue_count--;
294         g_free(item);
295     }
296 }
297 
298 static void qemu_input_queue_delay(QemuInputEventQueueHead *queue,
299                                    QEMUTimer *timer, uint32_t delay_ms)
300 {
301     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
302     bool start_timer = QTAILQ_EMPTY(queue);
303 
304     item->type = QEMU_INPUT_QUEUE_DELAY;
305     item->delay_ms = delay_ms;
306     item->timer = timer;
307     QTAILQ_INSERT_TAIL(queue, item, node);
308     queue_count++;
309 
310     if (start_timer) {
311         timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
312                   + item->delay_ms);
313     }
314 }
315 
316 static void qemu_input_queue_event(QemuInputEventQueueHead *queue,
317                                    QemuConsole *src, InputEvent *evt)
318 {
319     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
320 
321     item->type = QEMU_INPUT_QUEUE_EVENT;
322     item->src = src;
323     item->evt = evt;
324     QTAILQ_INSERT_TAIL(queue, item, node);
325     queue_count++;
326 }
327 
328 static void qemu_input_queue_sync(QemuInputEventQueueHead *queue)
329 {
330     QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
331 
332     item->type = QEMU_INPUT_QUEUE_SYNC;
333     QTAILQ_INSERT_TAIL(queue, item, node);
334     queue_count++;
335 }
336 
337 void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
338 {
339     QemuInputHandlerState *s;
340 
341     qemu_input_event_trace(src, evt);
342 
343     /* pre processing */
344     if (graphic_rotate && (evt->type == INPUT_EVENT_KIND_ABS)) {
345             qemu_input_transform_abs_rotate(evt);
346     }
347 
348     /* send event */
349     s = qemu_input_find_handler(1 << evt->type, src);
350     if (!s) {
351         return;
352     }
353     s->handler->event(s->dev, src, evt);
354     s->events++;
355 }
356 
357 void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
358 {
359     /* Expect all parts of QEMU to send events with QCodes exclusively.
360      * Key numbers are only supported as end-user input via QMP */
361     assert(!(evt->type == INPUT_EVENT_KIND_KEY &&
362              evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER));
363 
364 
365     /*
366      * 'sysrq' was mistakenly added to hack around the fact that
367      * the ps2 driver was not generating correct scancodes sequences
368      * when 'alt+print' was pressed. This flaw is now fixed and the
369      * 'sysrq' key serves no further purpose. We normalize it to
370      * 'print', so that downstream receivers of the event don't
371      * need to deal with this mistake
372      */
373     if (evt->type == INPUT_EVENT_KIND_KEY &&
374         evt->u.key.data->key->u.qcode.data == Q_KEY_CODE_SYSRQ) {
375         evt->u.key.data->key->u.qcode.data = Q_KEY_CODE_PRINT;
376     }
377 
378     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
379         return;
380     }
381 
382     replay_input_event(src, evt);
383 }
384 
385 void qemu_input_event_sync_impl(void)
386 {
387     QemuInputHandlerState *s;
388 
389     trace_input_event_sync();
390 
391     QTAILQ_FOREACH(s, &handlers, node) {
392         if (!s->events) {
393             continue;
394         }
395         if (s->handler->sync) {
396             s->handler->sync(s->dev);
397         }
398         s->events = 0;
399     }
400 }
401 
402 void qemu_input_event_sync(void)
403 {
404     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
405         return;
406     }
407 
408     replay_input_sync_event();
409 }
410 
411 static InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
412 {
413     InputEvent *evt = g_new0(InputEvent, 1);
414     evt->u.key.data = g_new0(InputKeyEvent, 1);
415     evt->type = INPUT_EVENT_KIND_KEY;
416     evt->u.key.data->key = key;
417     evt->u.key.data->down = down;
418     return evt;
419 }
420 
421 void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
422 {
423     InputEvent *evt;
424     evt = qemu_input_event_new_key(key, down);
425     if (QTAILQ_EMPTY(&kbd_queue)) {
426         qemu_input_event_send(src, evt);
427         qemu_input_event_sync();
428         qapi_free_InputEvent(evt);
429     } else if (queue_count < queue_limit) {
430         qemu_input_queue_event(&kbd_queue, src, evt);
431         qemu_input_queue_sync(&kbd_queue);
432     } else {
433         qapi_free_InputEvent(evt);
434     }
435 }
436 
437 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
438 {
439     QKeyCode code = qemu_input_key_number_to_qcode(num);
440     qemu_input_event_send_key_qcode(src, code, down);
441 }
442 
443 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
444 {
445     KeyValue *key = g_new0(KeyValue, 1);
446     key->type = KEY_VALUE_KIND_QCODE;
447     key->u.qcode.data = q;
448     qemu_input_event_send_key(src, key, down);
449 }
450 
451 void qemu_input_event_send_key_delay(uint32_t delay_ms)
452 {
453     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
454         return;
455     }
456 
457     if (!kbd_timer) {
458         kbd_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
459                                    SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
460                                    qemu_input_queue_process, &kbd_queue);
461     }
462     if (queue_count < queue_limit) {
463         qemu_input_queue_delay(&kbd_queue, kbd_timer,
464                                delay_ms ? delay_ms : kbd_default_delay_ms);
465     }
466 }
467 
468 void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)
469 {
470     InputBtnEvent bevt = {
471         .button = btn,
472         .down = down,
473     };
474     InputEvent evt = {
475         .type = INPUT_EVENT_KIND_BTN,
476         .u.btn.data = &bevt,
477     };
478 
479     qemu_input_event_send(src, &evt);
480 }
481 
482 void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
483                                uint32_t button_old, uint32_t button_new)
484 {
485     InputButton btn;
486     uint32_t mask;
487 
488     for (btn = 0; btn < INPUT_BUTTON__MAX; btn++) {
489         mask = button_map[btn];
490         if ((button_old & mask) == (button_new & mask)) {
491             continue;
492         }
493         qemu_input_queue_btn(src, btn, button_new & mask);
494     }
495 }
496 
497 bool qemu_input_is_absolute(void)
498 {
499     QemuInputHandlerState *s;
500 
501     s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS,
502                                 NULL);
503     return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
504 }
505 
506 int qemu_input_scale_axis(int value,
507                           int min_in, int max_in,
508                           int min_out, int max_out)
509 {
510     int64_t range_in = (int64_t)max_in - min_in;
511     int64_t range_out = (int64_t)max_out - min_out;
512 
513     if (range_in < 1) {
514         return min_out + range_out / 2;
515     }
516     return ((int64_t)value - min_in) * range_out / range_in + min_out;
517 }
518 
519 void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
520 {
521     InputMoveEvent move = {
522         .axis = axis,
523         .value = value,
524     };
525     InputEvent evt = {
526         .type = INPUT_EVENT_KIND_REL,
527         .u.rel.data = &move,
528     };
529 
530     qemu_input_event_send(src, &evt);
531 }
532 
533 void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
534                           int min_in, int max_in)
535 {
536     InputMoveEvent move = {
537         .axis = axis,
538         .value = qemu_input_scale_axis(value, min_in, max_in,
539                                        INPUT_EVENT_ABS_MIN,
540                                        INPUT_EVENT_ABS_MAX),
541     };
542     InputEvent evt = {
543         .type = INPUT_EVENT_KIND_ABS,
544         .u.abs.data = &move,
545     };
546 
547     qemu_input_event_send(src, &evt);
548 }
549 
550 void qemu_input_queue_mtt(QemuConsole *src, InputMultiTouchType type,
551                           int slot, int tracking_id)
552 {
553     InputMultiTouchEvent mtt = {
554         .type = type,
555         .slot = slot,
556         .tracking_id = tracking_id,
557     };
558     InputEvent evt = {
559         .type = INPUT_EVENT_KIND_MTT,
560         .u.mtt.data = &mtt,
561     };
562 
563     qemu_input_event_send(src, &evt);
564 }
565 
566 void qemu_input_queue_mtt_abs(QemuConsole *src, InputAxis axis, int value,
567                               int min_in, int max_in, int slot, int tracking_id)
568 {
569     InputMultiTouchEvent mtt = {
570         .type = INPUT_MULTI_TOUCH_TYPE_DATA,
571         .slot = slot,
572         .tracking_id = tracking_id,
573         .axis = axis,
574         .value = qemu_input_scale_axis(value, min_in, max_in,
575                                        INPUT_EVENT_ABS_MIN,
576                                        INPUT_EVENT_ABS_MAX),
577     };
578     InputEvent evt = {
579         .type = INPUT_EVENT_KIND_MTT,
580         .u.mtt.data = &mtt,
581     };
582 
583     qemu_input_event_send(src, &evt);
584 }
585 
586 void qemu_input_check_mode_change(void)
587 {
588     static int current_is_absolute;
589     int is_absolute;
590 
591     is_absolute = qemu_input_is_absolute();
592 
593     if (is_absolute != current_is_absolute) {
594         trace_input_mouse_mode(is_absolute);
595         notifier_list_notify(&mouse_mode_notifiers, NULL);
596     }
597 
598     current_is_absolute = is_absolute;
599 }
600 
601 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
602 {
603     notifier_list_add(&mouse_mode_notifiers, notify);
604 }
605 
606 void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
607 {
608     notifier_remove(notify);
609 }
610 
611 MouseInfoList *qmp_query_mice(Error **errp)
612 {
613     MouseInfoList *mice_list = NULL;
614     MouseInfo *info;
615     QemuInputHandlerState *s;
616     bool current = true;
617 
618     QTAILQ_FOREACH(s, &handlers, node) {
619         if (!(s->handler->mask &
620               (INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS))) {
621             continue;
622         }
623 
624         info = g_new0(MouseInfo, 1);
625         info->index = s->id;
626         info->name = g_strdup(s->handler->name);
627         info->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS;
628         info->current = current;
629 
630         current = false;
631         QAPI_LIST_PREPEND(mice_list, info);
632     }
633 
634     return mice_list;
635 }
636 
637 bool qemu_mouse_set(int index, Error **errp)
638 {
639     QemuInputHandlerState *s;
640 
641     QTAILQ_FOREACH(s, &handlers, node) {
642         if (s->id == index) {
643             break;
644         }
645     }
646 
647     if (!s) {
648         error_setg(errp, "Mouse at index '%d' not found", index);
649         return false;
650     }
651 
652     if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
653                               INPUT_EVENT_MASK_ABS))) {
654         error_setg(errp, "Input device '%s' is not a mouse",
655                    s->handler->name);
656         return false;
657     }
658 
659     qemu_input_handler_activate(s);
660     qemu_input_check_mode_change();
661     return true;
662 }
663