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