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