Commit e4c8f004 authored by Amos Kong's avatar Amos Kong Committed by Luiz Capitulino
Browse files

qapi: convert sendkey



Convert 'sendkey' to use QAPI.

QAPI passes key's index of mapping table to qmp_send_key(),
not keycode. So we use help functions to convert key/code to
index of key_defs, and 'index' will be converted to 'keycode'
inside qmp_send_key().

For qmp, QAPI would check invalid key and raise error.
For hmp, invalid key is checked in hmp_send_key().

'send-key' of QMP doesn't support key in hexadecimal format.

Signed-off-by: default avatarAmos Kong <akong@redhat.com>
Signed-off-by: default avatarLuiz Capitulino <lcapitulino@redhat.com>
parent 1048c88f
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -399,7 +399,6 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires)
void curses_display_init(DisplayState *ds, int full_screen);

/* input.c */
extern const int key_defs[];
int index_from_key(const char *key);
int index_from_keycode(int code);

+1 −1
Original line number Diff line number Diff line
@@ -505,7 +505,7 @@ ETEXI
        .args_type  = "keys:s,hold-time:i?",
        .params     = "keys [hold_ms]",
        .help       = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
        .mhandler.cmd = do_sendkey,
        .mhandler.cmd = hmp_send_key,
    },

STEXI
+55 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "qemu-timer.h"
#include "qmp-commands.h"
#include "monitor.h"
#include "console.h"

static void hmp_handle_error(Monitor *mon, Error **errp)
{
@@ -1102,3 +1103,57 @@ void hmp_closefd(Monitor *mon, const QDict *qdict)
    qmp_closefd(fdname, &errp);
    hmp_handle_error(mon, &errp);
}

void hmp_send_key(Monitor *mon, const QDict *qdict)
{
    const char *keys = qdict_get_str(qdict, "keys");
    QKeyCodeList *keylist, *head = NULL, *tmp = NULL;
    int has_hold_time = qdict_haskey(qdict, "hold-time");
    int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
    Error *err = NULL;
    char keyname_buf[16];
    char *separator;
    int keyname_len, idx;

    while (1) {
        separator = strchr(keys, '-');
        keyname_len = separator ? separator - keys : strlen(keys);
        pstrcpy(keyname_buf, sizeof(keyname_buf), keys);

        /* Be compatible with old interface, convert user inputted "<" */
        if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) {
            pstrcpy(keyname_buf, sizeof(keyname_buf), "less");
            keyname_len = 4;
        }
        keyname_buf[keyname_len] = 0;

        idx = index_from_key(keyname_buf);
        if (idx == Q_KEY_CODE_MAX) {
            monitor_printf(mon, "invalid parameter: %s\n", keyname_buf);
            break;
        }

        keylist = g_malloc0(sizeof(*keylist));
        keylist->value = idx;
        keylist->next = NULL;

        if (!head) {
            head = keylist;
        }
        if (tmp) {
            tmp->next = keylist;
        }
        tmp = keylist;

        if (!separator) {
            break;
        }
        keys = separator + 1;
    }

    if (idx != Q_KEY_CODE_MAX) {
        qmp_send_key(head, has_hold_time, hold_time, &err);
    }
    hmp_handle_error(mon, &err);
    qapi_free_QKeyCodeList(head);
}
+1 −0
Original line number Diff line number Diff line
@@ -71,5 +71,6 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
void hmp_netdev_del(Monitor *mon, const QDict *qdict);
void hmp_getfd(Monitor *mon, const QDict *qdict);
void hmp_closefd(Monitor *mon, const QDict *qdict);
void hmp_send_key(Monitor *mon, const QDict *qdict);

#endif
+66 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "console.h"
#include "error.h"
#include "qmp-commands.h"
#include "qapi-types.h"

static QEMUPutKBDEvent *qemu_put_kbd_event;
static void *qemu_put_kbd_event_opaque;
@@ -37,7 +38,7 @@ static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
static NotifierList mouse_mode_notifiers = 
    NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);

const int key_defs[] = {
static const int key_defs[] = {
    [Q_KEY_CODE_SHIFT] = 0x2a,
    [Q_KEY_CODE_SHIFT_R] = 0x36,

@@ -223,6 +224,70 @@ int index_from_keycode(int code)
    return i;
}

static QKeyCodeList *keycodes;
static QEMUTimer *key_timer;

static void release_keys(void *opaque)
{
    int keycode;
    QKeyCodeList *p;

    for (p = keycodes; p != NULL; p = p->next) {
        keycode = key_defs[p->value];
        if (keycode & 0x80) {
            kbd_put_keycode(0xe0);
        }
        kbd_put_keycode(keycode | 0x80);
    }
    qapi_free_QKeyCodeList(keycodes);
    keycodes = NULL;
}

void qmp_send_key(QKeyCodeList *keys, bool has_hold_time, int64_t hold_time,
                  Error **errp)
{
    int keycode;
    QKeyCodeList *p, *keylist, *head = NULL, *tmp = NULL;

    if (!key_timer) {
        key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
    }

    if (keycodes != NULL) {
        qemu_del_timer(key_timer);
        release_keys(NULL);
    }
    if (!has_hold_time) {
        hold_time = 100;
    }

    for (p = keys; p != NULL; p = p->next) {
        keylist = g_malloc0(sizeof(*keylist));
        keylist->value = p->value;
        keylist->next = NULL;

        if (!head) {
            head = keylist;
        }
        if (tmp) {
            tmp->next = keylist;
        }
        tmp = keylist;

        /* key down events */
        keycode = key_defs[p->value];
        if (keycode & 0x80) {
            kbd_put_keycode(0xe0);
        }
        kbd_put_keycode(keycode & 0x7f);
    }
    keycodes = head;

    /* delayed key up events */
    qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
                   muldiv64(get_ticks_per_sec(), hold_time, 1000));
}

void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
{
    qemu_put_kbd_event_opaque = opaque;
Loading