All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amos Kong <akong@redhat.com>
To: Luiz Capitulino <lcapitulino@redhat.com>
Cc: aliguori@us.ibm.com, eblake@redhat.com, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v5 6/6] qapi: convert sendkey
Date: Thu, 2 Aug 2012 21:38:00 -0400 (EDT)	[thread overview]
Message-ID: <857705732.7437537.1343957880905.JavaMail.root@redhat.com> (raw)
In-Reply-To: <20120802165729.7eafbee0@doriath.home>

----- Original Message -----
> On Thu, 26 Jul 2012 12:49:01 +0800
> Amos Kong <akong@redhat.com> wrote:
> 
> > Convert 'sendkey' to use QAPI.
> > 
> > Keys' indexes in the enmu are same as keycodes' indexes in the
> > key_defs[], index_from_code() and index_from_key() will return
> > Q_KEY_CODE_MAX if the code/key is invalid.
> > 
> > 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: Amos Kong <akong@redhat.com>
> 
> I've some review comments below, besides I'd like to ask you to split
> the addition of the QKeyCode enum and the key_defs table moving to a
> different patch.

Ok.

> Other than that this looks quite better, hopefully v6 will be the
> last one.

Thanks for your time :)

> > ---
> >  console.h        |    5 +
> >  hmp-commands.hx  |    2 +-
> >  hmp.c            |   55 ++++++++++++
> >  hmp.h            |    1 +
> >  input.c          |  249
> >  ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  monitor.c        |  258
> >  ++----------------------------------------------------
> >  qapi-schema.json |   46 ++++++++++
> >  qmp-commands.hx  |   28 ++++++
> >  8 files changed, 393 insertions(+), 251 deletions(-)
> > 
> > diff --git a/console.h b/console.h
> > index 4334db5..b2d7af6 100644
> > --- a/console.h
> > +++ b/console.h
> > @@ -6,6 +6,7 @@
> >  #include "notify.h"
> >  #include "monitor.h"
> >  #include "trace.h"
> > +#include "qapi-types.h"
> >  
> >  /* keyboard/mouse support */
> >  
> > @@ -397,4 +398,8 @@ static inline int
> > vnc_display_pw_expire(DisplayState *ds, time_t expires)
> >  /* curses.c */
> >  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);
> >  #endif
> > diff --git a/hmp-commands.hx b/hmp-commands.hx
> > index 2891d48..8c2be24 100644
> > --- a/hmp-commands.hx
> > +++ b/hmp-commands.hx
> > @@ -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
> > diff --git a/hmp.c b/hmp.c
> > index 6b72a64..041555a 100644
> > --- a/hmp.c
> > +++ b/hmp.c
> > @@ -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)
> >  {
> > @@ -1020,3 +1021,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) {
> > +            error_set(&err, QERR_INVALID_PARAMETER, keyname_buf);
> 
> No need to use error_set(), you can call monitor_printf() directly.

Nod.

> > +            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);
> > +}
> > diff --git a/hmp.h b/hmp.h
> > index 8d2b0d7..56d67a3 100644
> > --- a/hmp.h
> > +++ b/hmp.h
> > @@ -66,5 +66,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
> > diff --git a/input.c b/input.c
> > index 6968b31..2286581 100644
> > --- a/input.c
> > +++ b/input.c
> > @@ -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,6 +38,254 @@ static QTAILQ_HEAD(, QEMUPutMouseEntry)
> > mouse_handlers =
> >  static NotifierList mouse_mode_notifiers =
> >      NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
> >  
> > +const int key_defs[] = {
> 
> Please, make key_defs static.



> > +    [Q_KEY_CODE_SHIFT] = 0x2a,
> > +    [Q_KEY_CODE_SHIFT_R] = 0x36,
> > +
> > +    [Q_KEY_CODE_ALT] = 0x38,
> > +    [Q_KEY_CODE_ALT_R] = 0xb8,
> > +    [Q_KEY_CODE_ALTGR] = 0x64,
> > +    [Q_KEY_CODE_ALTGR_R] = 0xe4,
> > +    [Q_KEY_CODE_CTRL] = 0x1d,
> > +    [Q_KEY_CODE_CTRL_R] = 0x9d,
> > +
> > +    [Q_KEY_CODE_MENU] = 0xdd,
> > +
> > +    [Q_KEY_CODE_ESC] = 0x01,
> > +
> > +    [Q_KEY_CODE_1] = 0x02,
> > +    [Q_KEY_CODE_2] = 0x03,
> > +    [Q_KEY_CODE_3] = 0x04,
> > +    [Q_KEY_CODE_4] = 0x05,
> > +    [Q_KEY_CODE_5] = 0x06,
> > +    [Q_KEY_CODE_6] = 0x07,
> > +    [Q_KEY_CODE_7] = 0x08,
> > +    [Q_KEY_CODE_8] = 0x09,
> > +    [Q_KEY_CODE_9] = 0x0a,
> > +    [Q_KEY_CODE_0] = 0x0b,
> > +    [Q_KEY_CODE_MINUS] = 0x0c,
> > +    [Q_KEY_CODE_EQUAL] = 0x0d,
> > +    [Q_KEY_CODE_BACKSPACE] = 0x0e,
> > +
> > +    [Q_KEY_CODE_TAB] = 0x0f,
> > +    [Q_KEY_CODE_Q] = 0x10,
> > +    [Q_KEY_CODE_W] = 0x11,
> > +    [Q_KEY_CODE_E] = 0x12,
> > +    [Q_KEY_CODE_R] = 0x13,
> > +    [Q_KEY_CODE_T] = 0x14,
> > +    [Q_KEY_CODE_Y] = 0x15,
> > +    [Q_KEY_CODE_U] = 0x16,
> > +    [Q_KEY_CODE_I] = 0x17,
> > +    [Q_KEY_CODE_O] = 0x18,
> > +    [Q_KEY_CODE_P] = 0x19,
> > +    [Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
> > +    [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
> > +    [Q_KEY_CODE_RET] = 0x1c,
> > +
> > +    [Q_KEY_CODE_A] = 0x1e,
> > +    [Q_KEY_CODE_S] = 0x1f,
> > +    [Q_KEY_CODE_D] = 0x20,
> > +    [Q_KEY_CODE_F] = 0x21,
> > +    [Q_KEY_CODE_G] = 0x22,
> > +    [Q_KEY_CODE_H] = 0x23,
> > +    [Q_KEY_CODE_J] = 0x24,
> > +    [Q_KEY_CODE_K] = 0x25,
> > +    [Q_KEY_CODE_L] = 0x26,
> > +    [Q_KEY_CODE_SEMICOLON] = 0x27,
> > +    [Q_KEY_CODE_APOSTROPHE] = 0x28,
> > +    [Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
> > +
> > +    [Q_KEY_CODE_BACKSLASH] = 0x2b,
> > +    [Q_KEY_CODE_Z] = 0x2c,
> > +    [Q_KEY_CODE_X] = 0x2d,
> > +    [Q_KEY_CODE_C] = 0x2e,
> > +    [Q_KEY_CODE_V] = 0x2f,
> > +    [Q_KEY_CODE_B] = 0x30,
> > +    [Q_KEY_CODE_N] = 0x31,
> > +    [Q_KEY_CODE_M] = 0x32,
> > +    [Q_KEY_CODE_COMMA] = 0x33,
> > +    [Q_KEY_CODE_DOT] = 0x34,
> > +    [Q_KEY_CODE_SLASH] = 0x35,
> > +
> > +    [Q_KEY_CODE_ASTERISK] = 0x37,
> > +
> > +    [Q_KEY_CODE_SPC] = 0x39,
> > +    [Q_KEY_CODE_CAPS_LOCK] = 0x3a,
> > +    [Q_KEY_CODE_F1] = 0x3b,
> > +    [Q_KEY_CODE_F2] = 0x3c,
> > +    [Q_KEY_CODE_F3] = 0x3d,
> > +    [Q_KEY_CODE_F4] = 0x3e,
> > +    [Q_KEY_CODE_F5] = 0x3f,
> > +    [Q_KEY_CODE_F6] = 0x40,
> > +    [Q_KEY_CODE_F7] = 0x41,
> > +    [Q_KEY_CODE_F8] = 0x42,
> > +    [Q_KEY_CODE_F9] = 0x43,
> > +    [Q_KEY_CODE_F10] = 0x44,
> > +    [Q_KEY_CODE_NUM_LOCK] = 0x45,
> > +    [Q_KEY_CODE_SCROLL_LOCK] = 0x46,
> > +
> > +    [Q_KEY_CODE_KP_DIVIDE] = 0xb5,
> > +    [Q_KEY_CODE_KP_MULTIPLY] = 0x37,
> > +    [Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
> > +    [Q_KEY_CODE_KP_ADD] = 0x4e,
> > +    [Q_KEY_CODE_KP_ENTER] = 0x9c,
> > +    [Q_KEY_CODE_KP_DECIMAL] = 0x53,
> > +    [Q_KEY_CODE_SYSRQ] = 0x54,
> > +
> > +    [Q_KEY_CODE_KP_0] = 0x52,
> > +    [Q_KEY_CODE_KP_1] = 0x4f,
> > +    [Q_KEY_CODE_KP_2] = 0x50,
> > +    [Q_KEY_CODE_KP_3] = 0x51,
> > +    [Q_KEY_CODE_KP_4] = 0x4b,
> > +    [Q_KEY_CODE_KP_5] = 0x4c,
> > +    [Q_KEY_CODE_KP_6] = 0x4d,
> > +    [Q_KEY_CODE_KP_7] = 0x47,
> > +    [Q_KEY_CODE_KP_8] = 0x48,
> > +    [Q_KEY_CODE_KP_9] = 0x49,
> > +
> > +    [Q_KEY_CODE_LESS] = 0x56,
> > +
> > +    [Q_KEY_CODE_F11] = 0x57,
> > +    [Q_KEY_CODE_F12] = 0x58,
> > +
> > +    [Q_KEY_CODE_PRINT] = 0xb7,
> > +
> > +    [Q_KEY_CODE_HOME] = 0xc7,
> > +    [Q_KEY_CODE_PGUP] = 0xc9,
> > +    [Q_KEY_CODE_PGDN] = 0xd1,
> > +    [Q_KEY_CODE_END] = 0xcf,
> > +
> > +    [Q_KEY_CODE_LEFT] = 0xcb,
> > +    [Q_KEY_CODE_UP] = 0xc8,
> > +    [Q_KEY_CODE_DOWN] = 0xd0,
> > +    [Q_KEY_CODE_RIGHT] = 0xcd,
> > +
> > +    [Q_KEY_CODE_INSERT] = 0xd2,
> > +    [Q_KEY_CODE_DELETE] = 0xd3,
> > +#ifdef NEED_CPU_H
> > +#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
> > +    [Q_KEY_CODE_STOP] = 0xf0,
> > +    [Q_KEY_CODE_AGAIN] = 0xf1,
> > +    [Q_KEY_CODE_PROPS] = 0xf2,
> > +    [Q_KEY_CODE_UNDO] = 0xf3,
> > +    [Q_KEY_CODE_FRONT] = 0xf4,
> > +    [Q_KEY_CODE_COPY] = 0xf5,
> > +    [Q_KEY_CODE_OPEN] = 0xf6,
> > +    [Q_KEY_CODE_PASTE] = 0xf7,
> > +    [Q_KEY_CODE_FIND] = 0xf8,
> > +    [Q_KEY_CODE_CUT] = 0xf9,
> > +    [Q_KEY_CODE_LF] = 0xfa,
> > +    [Q_KEY_CODE_HELP] = 0xfb,
> > +    [Q_KEY_CODE_META_L] = 0xfc,
> > +    [Q_KEY_CODE_META_R] = 0xfd,
> > +    [Q_KEY_CODE_COMPOSE] = 0xfe,
> > +#endif
> > +#endif
> > +    [Q_KEY_CODE_MAX] = 0,
> > +};
> > +
> > +int index_from_key(const char *key)
> 
> keycode_from_key() is better.

QAPI passes 'index' to qmp_send_key(), not value (keycode)
So what those two functions return should be the 'index' of key_defs,
not the value (keycode).

'Index' will be converted to 'keycode' insider qmp_send_key()
 
> > +{
> > +    int i, keycode;
> > +    char *endp;
> > +
> > +    for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
> > +        if (!strcmp(key, QKeyCode_lookup[i])) {
> > +            break;
> > +        }
> > +    }
> > +
> > +    if (strstart(key, "0x", NULL)) {
> > +        keycode = strtoul(key, &endp, 0);
> > +        if (*endp == '\0' && keycode >= 0x01 && keycode <= 0xff) {
> > +            for (i = 0; i < Q_KEY_CODE_MAX; i++) {
> > +                if (keycode == key_defs[i]) {
> > +                    break;
> > +                }
> > +            }
> > +        }
> > +    }
> > +
> > +    /* Return Q_KEY_CODE_MAX if the key is invalid */
> > +    return i;
> > +}
> > +
> > +int index_from_keycode(int code)
> 
> keycode_from_code()
> 
> > +{
> > +    int i;
> > +    for (i = 0; i < Q_KEY_CODE_MAX; i++) {
> > +        if (key_defs[i] == code) {
> > +            break;
> > +        }
> > +    }
> > +    /* Return Q_KEY_CODE_MAX if the code is invalid */
> > +    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;
> > diff --git a/monitor.c b/monitor.c
> > index 4db0c1e..e3a2023 100644
> > --- a/monitor.c
> > +++ b/monitor.c
> > @@ -1293,252 +1293,6 @@ static void do_sum(Monitor *mon, const
> > QDict *qdict)
> >      monitor_printf(mon, "%05d\n", sum);
> >  }
> >  
> > -typedef struct {
> > -    int keycode;
> > -    const char *name;
> > -} KeyDef;
> > -
> > -static const KeyDef key_defs[] = {
> > -    { 0x2a, "shift" },
> > -    { 0x36, "shift_r" },
> > -
> > -    { 0x38, "alt" },
> > -    { 0xb8, "alt_r" },
> > -    { 0x64, "altgr" },
> > -    { 0xe4, "altgr_r" },
> > -    { 0x1d, "ctrl" },
> > -    { 0x9d, "ctrl_r" },
> > -
> > -    { 0xdd, "menu" },
> > -
> > -    { 0x01, "esc" },
> > -
> > -    { 0x02, "1" },
> > -    { 0x03, "2" },
> > -    { 0x04, "3" },
> > -    { 0x05, "4" },
> > -    { 0x06, "5" },
> > -    { 0x07, "6" },
> > -    { 0x08, "7" },
> > -    { 0x09, "8" },
> > -    { 0x0a, "9" },
> > -    { 0x0b, "0" },
> > -    { 0x0c, "minus" },
> > -    { 0x0d, "equal" },
> > -    { 0x0e, "backspace" },
> > -
> > -    { 0x0f, "tab" },
> > -    { 0x10, "q" },
> > -    { 0x11, "w" },
> > -    { 0x12, "e" },
> > -    { 0x13, "r" },
> > -    { 0x14, "t" },
> > -    { 0x15, "y" },
> > -    { 0x16, "u" },
> > -    { 0x17, "i" },
> > -    { 0x18, "o" },
> > -    { 0x19, "p" },
> > -    { 0x1a, "bracket_left" },
> > -    { 0x1b, "bracket_right" },
> > -    { 0x1c, "ret" },
> > -
> > -    { 0x1e, "a" },
> > -    { 0x1f, "s" },
> > -    { 0x20, "d" },
> > -    { 0x21, "f" },
> > -    { 0x22, "g" },
> > -    { 0x23, "h" },
> > -    { 0x24, "j" },
> > -    { 0x25, "k" },
> > -    { 0x26, "l" },
> > -    { 0x27, "semicolon" },
> > -    { 0x28, "apostrophe" },
> > -    { 0x29, "grave_accent" },
> > -
> > -    { 0x2b, "backslash" },
> > -    { 0x2c, "z" },
> > -    { 0x2d, "x" },
> > -    { 0x2e, "c" },
> > -    { 0x2f, "v" },
> > -    { 0x30, "b" },
> > -    { 0x31, "n" },
> > -    { 0x32, "m" },
> > -    { 0x33, "comma" },
> > -    { 0x34, "dot" },
> > -    { 0x35, "slash" },
> > -
> > -    { 0x37, "asterisk" },
> > -
> > -    { 0x39, "spc" },
> > -    { 0x3a, "caps_lock" },
> > -    { 0x3b, "f1" },
> > -    { 0x3c, "f2" },
> > -    { 0x3d, "f3" },
> > -    { 0x3e, "f4" },
> > -    { 0x3f, "f5" },
> > -    { 0x40, "f6" },
> > -    { 0x41, "f7" },
> > -    { 0x42, "f8" },
> > -    { 0x43, "f9" },
> > -    { 0x44, "f10" },
> > -    { 0x45, "num_lock" },
> > -    { 0x46, "scroll_lock" },
> > -
> > -    { 0xb5, "kp_divide" },
> > -    { 0x37, "kp_multiply" },
> > -    { 0x4a, "kp_subtract" },
> > -    { 0x4e, "kp_add" },
> > -    { 0x9c, "kp_enter" },
> > -    { 0x53, "kp_decimal" },
> > -    { 0x54, "sysrq" },
> > -
> > -    { 0x52, "kp_0" },
> > -    { 0x4f, "kp_1" },
> > -    { 0x50, "kp_2" },
> > -    { 0x51, "kp_3" },
> > -    { 0x4b, "kp_4" },
> > -    { 0x4c, "kp_5" },
> > -    { 0x4d, "kp_6" },
> > -    { 0x47, "kp_7" },
> > -    { 0x48, "kp_8" },
> > -    { 0x49, "kp_9" },
> > -
> > -    { 0x56, "less" },
> > -
> > -    { 0x57, "f11" },
> > -    { 0x58, "f12" },
> > -
> > -    { 0xb7, "print" },
> > -
> > -    { 0xc7, "home" },
> > -    { 0xc9, "pgup" },
> > -    { 0xd1, "pgdn" },
> > -    { 0xcf, "end" },
> > -
> > -    { 0xcb, "left" },
> > -    { 0xc8, "up" },
> > -    { 0xd0, "down" },
> > -    { 0xcd, "right" },
> > -
> > -    { 0xd2, "insert" },
> > -    { 0xd3, "delete" },
> > -#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
> > -    { 0xf0, "stop" },
> > -    { 0xf1, "again" },
> > -    { 0xf2, "props" },
> > -    { 0xf3, "undo" },
> > -    { 0xf4, "front" },
> > -    { 0xf5, "copy" },
> > -    { 0xf6, "open" },
> > -    { 0xf7, "paste" },
> > -    { 0xf8, "find" },
> > -    { 0xf9, "cut" },
> > -    { 0xfa, "lf" },
> > -    { 0xfb, "help" },
> > -    { 0xfc, "meta_l" },
> > -    { 0xfd, "meta_r" },
> > -    { 0xfe, "compose" },
> > -#endif
> > -    { 0, NULL },
> > -};
> > -
> > -static int get_keycode(const char *key)
> > -{
> > -    const KeyDef *p;
> > -    char *endp;
> > -    int ret;
> > -
> > -    for(p = key_defs; p->name != NULL; p++) {
> > -        if (!strcmp(key, p->name))
> > -            return p->keycode;
> > -    }
> > -    if (strstart(key, "0x", NULL)) {
> > -        ret = strtoul(key, &endp, 0);
> > -        if (*endp == '\0' && ret >= 0x01 && ret <= 0xff)
> > -            return ret;
> > -    }
> > -    return -1;
> > -}
> > -
> > -#define MAX_KEYCODES 16
> > -static uint8_t keycodes[MAX_KEYCODES];
> > -static int nb_pending_keycodes;
> > -static QEMUTimer *key_timer;
> > -
> > -static void release_keys(void *opaque)
> > -{
> > -    int keycode;
> > -
> > -    while (nb_pending_keycodes > 0) {
> > -        nb_pending_keycodes--;
> > -        keycode = keycodes[nb_pending_keycodes];
> > -        if (keycode & 0x80)
> > -            kbd_put_keycode(0xe0);
> > -        kbd_put_keycode(keycode | 0x80);
> > -    }
> > -}
> > -
> > -static void do_sendkey(Monitor *mon, const QDict *qdict)
> > -{
> > -    char keyname_buf[16];
> > -    char *separator;
> > -    int keyname_len, keycode, i;
> > -    const char *keys = qdict_get_str(qdict, "keys");
> > -    int has_hold_time = qdict_haskey(qdict, "hold-time");
> > -    int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
> > -
> > -    if (nb_pending_keycodes > 0) {
> > -        qemu_del_timer(key_timer);
> > -        release_keys(NULL);
> > -    }
> > -    if (!has_hold_time)
> > -        hold_time = 100;
> > -    i = 0;
> > -    while (1) {
> > -        separator = strchr(keys, '-');
> > -        keyname_len = separator ? separator - keys : strlen(keys);
> > -        if (keyname_len > 0) {
> > -            pstrcpy(keyname_buf, sizeof(keyname_buf), keys);
> > -            if (keyname_len > sizeof(keyname_buf) - 1) {
> > -                monitor_printf(mon, "invalid key: '%s...'\n",
> > keyname_buf);
> > -                return;
> > -            }
> > -            if (i == MAX_KEYCODES) {
> > -                monitor_printf(mon, "too many keys\n");
> > -                return;
> > -            }
> > -
> > -            /* 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;
> > -            keycode = get_keycode(keyname_buf);
> > -            if (keycode < 0) {
> > -                monitor_printf(mon, "unknown key: '%s'\n",
> > keyname_buf);
> > -                return;
> > -            }
> > -            keycodes[i++] = keycode;
> > -        }
> > -        if (!separator)
> > -            break;
> > -        keys = separator + 1;
> > -    }
> > -    nb_pending_keycodes = i;
> > -    /* key down events */
> > -    for (i = 0; i < nb_pending_keycodes; i++) {
> > -        keycode = keycodes[i];
> > -        if (keycode & 0x80)
> > -            kbd_put_keycode(0xe0);
> > -        kbd_put_keycode(keycode & 0x7f);
> > -    }
> > -    /* delayed key up events */
> > -    qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
> > -                   muldiv64(get_ticks_per_sec(), hold_time,
> > 1000));
> > -}
> > -
> >  static int mouse_button_state;
> >  
> >  static void do_mouse_move(Monitor *mon, const QDict *qdict)
> > @@ -4077,7 +3831,7 @@ static void monitor_find_completion(const
> > char *cmdline)
> >      int nb_args, i, len;
> >      const char *ptype, *str;
> >      const mon_cmd_t *cmd;
> > -    const KeyDef *key;
> > +    const int *code;
> >  
> >      parse_cmdline(cmdline, &nb_args, args);
> >  #ifdef DEBUG_COMPLETION
> > @@ -4151,9 +3905,14 @@ static void monitor_find_completion(const
> > char *cmdline)
> >                  if (sep)
> >                      str = sep + 1;
> >                  readline_set_completion_index(cur_mon->rs,
> >                  strlen(str));
> > -                for(key = key_defs; key->name != NULL; key++) {
> > -                    cmd_completion(str, key->name);
> 
> You can do:
> 
> cmd_completion(str, KeyCodes_lookup[i]);
> 
> The loop below is not needed.

This is enough, then we can make key_defs static.

                for (i = 0; i < Q_KEY_CODE_MAX; i++) {
                    cmd_completion(str, QKeyCode_lookup[i]);
                }

 
> > +                for (code = key_defs; code != NULL; code++) {
> > +                    int idx;
> > +                    idx = index_from_keycode(*code);
> > +                    if (idx != Q_KEY_CODE_MAX) {
> > +                        cmd_completion(str, QKeyCode_lookup[idx]);
> > +                    }
> >                  }
> > +
> >              } else if (!strcmp(cmd->name, "help|?")) {
> >                  readline_set_completion_index(cur_mon->rs,
> >                  strlen(str));
> >                  for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
> > @@ -4681,7 +4440,6 @@ void monitor_init(CharDriverState *chr, int
> > flags)
> >      Monitor *mon;
> >  
> >      if (is_first_init) {
> > -        key_timer = qemu_new_timer_ns(vm_clock, release_keys,
> > NULL);
> >          monitor_protocol_event_init();
> >          is_first_init = 0;
> >      }
> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index bc55ed2..3a562d8 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -2183,3 +2183,49 @@
> >  # Since: 0.14.0
> >  ##
> >  { 'command': 'closefd', 'data': {'fdname': 'str'} }
> > +
> > +##
> > +# @QKeyCode:
> > +#
> > +# An enumeration of key name.
> > +#
> > +# This is used by the send-key command.
> > +#
> > +# Since: 1.2
> > +##
> > +{ 'enum': 'QKeyCode',
> > +  'data': [ 'shift', 'shift_r', 'alt', 'alt_r', 'altgr',
> > 'altgr_r', 'ctrl',
> > +            'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6',
> > '7', '8',
> > +            '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q',
> > 'w', 'e',
> > +            'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left',
> > 'bracket_right',
> > +            'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
> > 'semicolon',
> > +            'apostrophe', 'grave_accent', 'backslash', 'z', 'x',
> > 'c', 'v', 'b',
> > +            'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc',
> > 'caps_lock',
> > +            'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9',
> > 'f10',
> > +            'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply',
> > +            'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal',
> > 'sysrq', 'kp_0',
> > +            'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6',
> > 'kp_7', 'kp_8',
> > +            'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup',
> > 'pgdn', 'end',
> > +            'left', 'up', 'down', 'right', 'insert', 'delete',
> > 'stop', 'again',
> > +            'props', 'undo', 'front', 'copy', 'open', 'paste',
> > 'find', 'cut',
> > +             'lf', 'help', 'meta_l', 'meta_r', 'compose' ] }
> > +
> > +##
> > +# @send-key:
> > +#
> > +# Send keys to guest.
> > +#
> > +# @keys: key sequence. 'keys' is the name of the key. Use a JSON
> > array to
> > +#        press several keys simultaneously.
> > +#
> > +# @hold-time: #optional time to delay key up events, milliseconds.
> > Defaults
> > +#             to 100
> > +#
> > +# Returns: Nothing on success
> > +#          If key is unknown or redundant, InvalidParameter
> > +#
> > +# Since: 1.2
> > +#
> > +##
> > +{ 'command': 'send-key',
> > +  'data': { 'keys': ['QKeyCode'], '*hold-time': 'int' } }
> > diff --git a/qmp-commands.hx b/qmp-commands.hx
> > index e3cf3c5..3c1e646 100644
> > --- a/qmp-commands.hx
> > +++ b/qmp-commands.hx
> > @@ -335,6 +335,34 @@ Example:
> >  EQMP
> >  
> >      {
> > +        .name       = "send-key",
> > +        .args_type  = "keys:O,hold-time:i?",
> > +        .mhandler.cmd_new = qmp_marshal_input_send_key,
> > +    },
> > +
> > +SQMP
> > +send-key
> > +----------
> > +
> > +Send keys to VM.
> > +
> > +Arguments:
> > +
> > +keys array:
> > +    - "key": key sequence (a json-array of key enum values)
> > +
> > +- hold-time: time to delay key up events, milliseconds. Defaults
> > to 100
> > +             (json-int, optional)
> > +
> > +Example:
> > +
> > +-> { "execute": "send-key",
> > +     "arguments": { 'keys': [ 'ctrl', 'alt', 'delete' ] } }
> > +<- { "return": {} }
> > +
> > +EQMP
> > +
> > +    {
> >          .name       = "cpu",
> >          .args_type  = "index:i",
> >          .mhandler.cmd_new = qmp_marshal_input_cpu,
> 
> 
> 

  reply	other threads:[~2012-08-03  1:38 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-26  4:48 [Qemu-devel] [PATCH v5 0/6] convert sendkey to qapi Amos Kong
2012-07-26  4:48 ` [Qemu-devel] [PATCH v5 1/6] fix doc of using raw values with sendkey Amos Kong
2012-07-26  4:48 ` [Qemu-devel] [PATCH v5 2/6] monitor: rename keyname '<' to 'less' Amos Kong
2012-07-26  4:48 ` [Qemu-devel] [PATCH v5 3/6] hmp: rename arguments Amos Kong
2012-07-26  4:48 ` [Qemu-devel] [PATCH v5 4/6] qapi: generate list struct and visit_list for enum Amos Kong
2012-07-26  4:49 ` [Qemu-devel] [PATCH v5 5/6] ps2: output warning when event queue full Amos Kong
2012-07-27 19:24   ` Blue Swirl
2012-07-26  4:49 ` [Qemu-devel] [PATCH v5 6/6] qapi: convert sendkey Amos Kong
2012-07-26 21:22   ` Eric Blake
2012-08-02 19:57   ` Luiz Capitulino
2012-08-03  1:38     ` Amos Kong [this message]
2012-08-03 13:23       ` Luiz Capitulino

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=857705732.7437537.1343957880905.JavaMail.root@redhat.com \
    --to=akong@redhat.com \
    --cc=aliguori@us.ibm.com \
    --cc=eblake@redhat.com \
    --cc=lcapitulino@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.