qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

input.c (17105B)


      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      * need 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     MouseInfo *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(MouseInfo, 1);
    585         info->index = s->id;
    586         info->name = g_strdup(s->handler->name);
    587         info->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS;
    588         info->current = current;
    589 
    590         current = false;
    591         QAPI_LIST_PREPEND(mice_list, info);
    592     }
    593 
    594     return mice_list;
    595 }
    596 
    597 void hmp_mouse_set(Monitor *mon, const QDict *qdict)
    598 {
    599     QemuInputHandlerState *s;
    600     int index = qdict_get_int(qdict, "index");
    601     int found = 0;
    602 
    603     QTAILQ_FOREACH(s, &handlers, node) {
    604         if (s->id != index) {
    605             continue;
    606         }
    607         if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
    608                                   INPUT_EVENT_MASK_ABS))) {
    609             error_report("Input device '%s' is not a mouse", s->handler->name);
    610             return;
    611         }
    612         found = 1;
    613         qemu_input_handler_activate(s);
    614         break;
    615     }
    616 
    617     if (!found) {
    618         error_report("Mouse at index '%d' not found", index);
    619     }
    620 
    621     qemu_input_check_mode_change();
    622 }