[libvirt] [PATCH 13/13] virsh, send-key: add --codeset xt:keystring support

Daniel P. Berrange berrange at redhat.com
Wed May 25 20:32:43 UTC 2011


On Wed, May 25, 2011 at 05:37:55PM +0800, Lai Jiangshan wrote:
> It make send-key command more friendly for user.
> 
> Signed-off-by: Lai Jiangshan <laijs at fujitsu.com>
> ---
>  tools/virsh.c |  224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 221 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/virsh.c b/tools/virsh.c
> index 3bccc08..18ef4bb 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -3017,11 +3017,24 @@ cmdInjectNMI(vshControl *ctl, const vshCmd *cmd)
>  static const vshCmdInfo info_send_key[] = {
>      {"help", N_("Send keycodes to the guest")},
>      {"desc", N_("Send keycodes to the guest, the keycodes must be integers\n"
> +                "    or the qemu-style key strings for the \"xt:keystring\" codeset\n"
>                  "    or the KEY_* strings listed below for the \"linux\" codeset.\n\n"
> +                "    Available codeset:\n"
> +                "        linux          the keycodes specified in \n"
> +                "                        /usr/include/linux/input.h(default)\n"
> +                "        default        linux codeset will be used\n"
> +                "        driver_default the hypervisor default codeset will be used\n"
> +                "        xt             XT(set1) scancode of standard AT keyboards and PS/2 keyboards\n"
> +                "        atset1         set1 scancode of standard AT keyboards and PS/2 keyboards\n"
> +                "        atset2         set2 scancode of standard AT keyboards and PS/2 keyboards\n"
> +                "        atset3         set3 scancode of standard AT keyboards and PS/2 keyboards\n"
> +                "        xt:keystring   XT scancode, but <keycode>... must be the qemu-style key strings\n"
> +                "\n"
>                  "    Examples:\n\n"
>                  "        virsh # send-key <domain> 37 18 21\n"
>                  "        virsh # send-key <domain> --holdtime 1000 0x15 18 0xf\n"
> -                "        virsh # send-eky <domain> KEY_LEFTCTRL KEY_LEFTALT KEY_F1\n"
> +                "        virsh # send-key <domain> KEY_LEFTCTRL KEY_LEFTALT KEY_F1\n"
> +                "        virsh # send-key <domain> --codeset xt:keystring alt-sysrq h\n"
>                  "\n"
>                  "    KEY_XXX strings for the \"linux\" codeset:\n"
>  #define keycode(var, value) "    "  #var " = " #value "\n"
> @@ -3062,6 +3075,178 @@ static int get_integer_keycode(const char *key_name)
>      return val;
>  }
>  
> +
> +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, "<" },
> +
> +    { 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" },
> +
> +    { 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" },
> +
> +    { 0, NULL },
> +};


If we add a 2nd public API which takes a list of keycode strings,
then this mapping table can be kept in the QEMU driver source,
instead of in virsh. Again, we can use my keymap-gen.pl script
to automatically generate the mapping table.

> +
> +static int get_xtkeystr_keycode(const char *key_name, unsigned int keyname_len)
> +{
> +    const KeyDef *p;
> +    char *endp;
> +    int ret;
> +
> +    if (keyname_len == 0)
> +        return -1;
> +
> +    for(p = key_defs; p->name != NULL; p++) {
> +        if (!strncmp(key_name, p->name, keyname_len))
> +            return p->keycode;
> +    }
> +    if (key_name[0] == '0' && (key_name[1] == 'x' || key_name[1] == 'X')) {
> +        ret = strtoul(key_name, &endp, 0);
> +        if (endp - key_name == keyname_len && ret >= 0x01 && ret <= 0xff)
> +            return ret;
> +    }
> +    return -1;
> +}
> +
> +
>  static bool
>  cmdSendKey(vshControl *ctl, const vshCmd *cmd)
>  {
> @@ -3073,6 +3258,7 @@ cmdSendKey(vshControl *ctl, const vshCmd *cmd)
>      int count = 0;
>      const vshCmdOpt *opt;
>      int keycode;
> +    int xt_keystring = 0;
>      unsigned int keycodes[MAX_SEND_KEY];
>  
>      if (!vshConnectionUsability(ctl, ctl->conn))
> @@ -3099,6 +3285,9 @@ cmdSendKey(vshControl *ctl, const vshCmd *cmd)
>          codeset = LIBVIRT_KEYCODE_ATSET2;
>      } else if (STREQ(codeset_option, "atset3")) {
>          codeset = LIBVIRT_KEYCODE_ATSET3;
> +    } else if (STREQ(codeset_option, "xt:keystring")) {
> +        codeset = LIBVIRT_KEYCODE_XT;
> +        xt_keystring = 1;
>      } else {
>          vshError(ctl, _("unknown codeset: '%s'"), codeset_option);
>          goto free_domain;
> @@ -3106,11 +3295,40 @@ cmdSendKey(vshControl *ctl, const vshCmd *cmd)
>  
>      for_each_variable_arg(cmd, opt) {
>          if (count == MAX_SEND_KEY) {
> -            vshError(ctl, _("too many keycode"));
> +            vshError(ctl, _("too many keycodes"));
>              goto free_domain;
>          }
>  
> -        if ((keycode = get_linux_keycode(opt->data)) > 0)
> +        if (codeset == LIBVIRT_KEYCODE_XT && xt_keystring == 1) {
> +            const char *sep, *key_string = opt->data;
> +            unsigned int keyname_len;
> +
> +            for (;;) {
> +                if (count == MAX_SEND_KEY) {
> +                    vshError(ctl, _("too many keycodes"));
> +                    goto free_domain;
> +                }
> +
> +                sep = strchr(key_string, '-');
> +                keyname_len = sep ? sep - key_string : strlen(key_string);
> +
> +                keycode = get_xtkeystr_keycode(key_string, keyname_len);
> +                if (keycode < 0) {
> +                    vshError(ctl, _("invalid keycode: '%s'"), opt->data);
> +                    goto free_domain;
> +                }
> +
> +                keycodes[count] = keycode;
> +                count++;
> +                if (!sep)
> +                    break;
> +                key_string += keyname_len + 1;
> +            }
> +            continue;
> +        }
> +
> +        if (codeset == LIBVIRT_KEYCODE_LINUX &&
> +            (keycode = get_linux_keycode(opt->data)) > 0)
>              goto get_keycode;
>  
>          if ((keycode = get_integer_keycode(opt->data)) > 0)

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list