diff mbox

[v2,1/3] input: add qemu_input_qcode_to_linux + qemu_input_linux_to_qcode

Message ID 1450102686-23855-1-git-send-email-kraxel@redhat.com
State New
Headers show

Commit Message

Gerd Hoffmann Dec. 14, 2015, 2:18 p.m. UTC
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/input.h |   3 ++
 ui/input-keymap.c  | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 148 insertions(+)

Comments

Jonathan Scruggs Jan. 4, 2016, 10:10 a.m. UTC | #1
Hi,

I tried these patches with qemu 2.5.0 on Gentoo and libvirt. I get the
following error:
Error starting domain: internal error: early end of file from monitor:
possible problem:
2015-12-22T21:51:20.659520Z qemu-system-x86_64: -input-linux
/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd,grab-all=on:
Could not open '/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd'

I also tried setting /dev/input/event9 to permissions of 666 to see if it
was a permission error, but the same thing happened. Any help would be
appreciated.


The way I pass it is with this:
  <qemu:commandline>
    <qemu:arg value='-input-linux'/>
    <qemu:arg
value='/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd,grab-all=on'/>
    <qemu:arg value='-input-linux'/>
    <qemu:arg
value='/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.1-event-mouse'/>
    <qemu:arg value='-input-linux'/>
    <qemu:arg
value='/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.2-event-joystick'/>
  </qemu:commandline>

Is there a way around this error?

Thanks,
Jon

On 14 December 2015 at 14:18, Gerd Hoffmann <kraxel@redhat.com> wrote:

> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  include/ui/input.h |   3 ++
>  ui/input-keymap.c  | 145
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 148 insertions(+)
>
> diff --git a/include/ui/input.h b/include/ui/input.h
> index d06a12d..d7afd80 100644
> --- a/include/ui/input.h
> +++ b/include/ui/input.h
> @@ -48,6 +48,9 @@ int qemu_input_key_value_to_qcode(const KeyValue *value);
>  int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
>                                       int *codes);
>
> +int qemu_input_qcode_to_linux(unsigned int qcode);
> +int qemu_input_linux_to_qcode(unsigned int lnx);
> +
>  InputEvent *qemu_input_event_new_btn(InputButton btn, bool down);
>  void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down);
>  void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
> diff --git a/ui/input-keymap.c b/ui/input-keymap.c
> index d36be4b..31f4daa 100644
> --- a/ui/input-keymap.c
> +++ b/ui/input-keymap.c
> @@ -2,6 +2,126 @@
>  #include "ui/keymaps.h"
>  #include "ui/input.h"
>
> +#include "standard-headers/linux/input.h"
> +
> +/* FIXME: duplicate, see hw/input/virtio-input-hid.c */
> +static const unsigned int qcode_to_linux[Q_KEY_CODE_MAX] = {
> +    [Q_KEY_CODE_ESC]                 = KEY_ESC,
> +    [Q_KEY_CODE_1]                   = KEY_1,
> +    [Q_KEY_CODE_2]                   = KEY_2,
> +    [Q_KEY_CODE_3]                   = KEY_3,
> +    [Q_KEY_CODE_4]                   = KEY_4,
> +    [Q_KEY_CODE_5]                   = KEY_5,
> +    [Q_KEY_CODE_6]                   = KEY_6,
> +    [Q_KEY_CODE_7]                   = KEY_7,
> +    [Q_KEY_CODE_8]                   = KEY_8,
> +    [Q_KEY_CODE_9]                   = KEY_9,
> +    [Q_KEY_CODE_0]                   = KEY_0,
> +    [Q_KEY_CODE_MINUS]               = KEY_MINUS,
> +    [Q_KEY_CODE_EQUAL]               = KEY_EQUAL,
> +    [Q_KEY_CODE_BACKSPACE]           = KEY_BACKSPACE,
> +
> +    [Q_KEY_CODE_TAB]                 = KEY_TAB,
> +    [Q_KEY_CODE_Q]                   = KEY_Q,
> +    [Q_KEY_CODE_W]                   = KEY_W,
> +    [Q_KEY_CODE_E]                   = KEY_E,
> +    [Q_KEY_CODE_R]                   = KEY_R,
> +    [Q_KEY_CODE_T]                   = KEY_T,
> +    [Q_KEY_CODE_Y]                   = KEY_Y,
> +    [Q_KEY_CODE_U]                   = KEY_U,
> +    [Q_KEY_CODE_I]                   = KEY_I,
> +    [Q_KEY_CODE_O]                   = KEY_O,
> +    [Q_KEY_CODE_P]                   = KEY_P,
> +    [Q_KEY_CODE_BRACKET_LEFT]        = KEY_LEFTBRACE,
> +    [Q_KEY_CODE_BRACKET_RIGHT]       = KEY_RIGHTBRACE,
> +    [Q_KEY_CODE_RET]                 = KEY_ENTER,
> +
> +    [Q_KEY_CODE_CTRL]                = KEY_LEFTCTRL,
> +    [Q_KEY_CODE_A]                   = KEY_A,
> +    [Q_KEY_CODE_S]                   = KEY_S,
> +    [Q_KEY_CODE_D]                   = KEY_D,
> +    [Q_KEY_CODE_F]                   = KEY_F,
> +    [Q_KEY_CODE_G]                   = KEY_G,
> +    [Q_KEY_CODE_H]                   = KEY_H,
> +    [Q_KEY_CODE_J]                   = KEY_J,
> +    [Q_KEY_CODE_K]                   = KEY_K,
> +    [Q_KEY_CODE_L]                   = KEY_L,
> +    [Q_KEY_CODE_SEMICOLON]           = KEY_SEMICOLON,
> +    [Q_KEY_CODE_APOSTROPHE]          = KEY_APOSTROPHE,
> +    [Q_KEY_CODE_GRAVE_ACCENT]        = KEY_GRAVE,
> +
> +    [Q_KEY_CODE_SHIFT]               = KEY_LEFTSHIFT,
> +    [Q_KEY_CODE_BACKSLASH]           = KEY_BACKSLASH,
> +    [Q_KEY_CODE_LESS]                = KEY_102ND,
> +    [Q_KEY_CODE_Z]                   = KEY_Z,
> +    [Q_KEY_CODE_X]                   = KEY_X,
> +    [Q_KEY_CODE_C]                   = KEY_C,
> +    [Q_KEY_CODE_V]                   = KEY_V,
> +    [Q_KEY_CODE_B]                   = KEY_B,
> +    [Q_KEY_CODE_N]                   = KEY_N,
> +    [Q_KEY_CODE_M]                   = KEY_M,
> +    [Q_KEY_CODE_COMMA]               = KEY_COMMA,
> +    [Q_KEY_CODE_DOT]                 = KEY_DOT,
> +    [Q_KEY_CODE_SLASH]               = KEY_SLASH,
> +    [Q_KEY_CODE_SHIFT_R]             = KEY_RIGHTSHIFT,
> +
> +    [Q_KEY_CODE_ALT]                 = KEY_LEFTALT,
> +    [Q_KEY_CODE_SPC]                 = KEY_SPACE,
> +    [Q_KEY_CODE_CAPS_LOCK]           = KEY_CAPSLOCK,
> +
> +    [Q_KEY_CODE_F1]                  = KEY_F1,
> +    [Q_KEY_CODE_F2]                  = KEY_F2,
> +    [Q_KEY_CODE_F3]                  = KEY_F3,
> +    [Q_KEY_CODE_F4]                  = KEY_F4,
> +    [Q_KEY_CODE_F5]                  = KEY_F5,
> +    [Q_KEY_CODE_F6]                  = KEY_F6,
> +    [Q_KEY_CODE_F7]                  = KEY_F7,
> +    [Q_KEY_CODE_F8]                  = KEY_F8,
> +    [Q_KEY_CODE_F9]                  = KEY_F9,
> +    [Q_KEY_CODE_F10]                 = KEY_F10,
> +    [Q_KEY_CODE_NUM_LOCK]            = KEY_NUMLOCK,
> +    [Q_KEY_CODE_SCROLL_LOCK]         = KEY_SCROLLLOCK,
> +
> +    [Q_KEY_CODE_KP_0]                = KEY_KP0,
> +    [Q_KEY_CODE_KP_1]                = KEY_KP1,
> +    [Q_KEY_CODE_KP_2]                = KEY_KP2,
> +    [Q_KEY_CODE_KP_3]                = KEY_KP3,
> +    [Q_KEY_CODE_KP_4]                = KEY_KP4,
> +    [Q_KEY_CODE_KP_5]                = KEY_KP5,
> +    [Q_KEY_CODE_KP_6]                = KEY_KP6,
> +    [Q_KEY_CODE_KP_7]                = KEY_KP7,
> +    [Q_KEY_CODE_KP_8]                = KEY_KP8,
> +    [Q_KEY_CODE_KP_9]                = KEY_KP9,
> +    [Q_KEY_CODE_KP_SUBTRACT]         = KEY_KPMINUS,
> +    [Q_KEY_CODE_KP_ADD]              = KEY_KPPLUS,
> +    [Q_KEY_CODE_KP_DECIMAL]          = KEY_KPDOT,
> +    [Q_KEY_CODE_KP_ENTER]            = KEY_KPENTER,
> +    [Q_KEY_CODE_KP_DIVIDE]           = KEY_KPSLASH,
> +    [Q_KEY_CODE_KP_MULTIPLY]         = KEY_KPASTERISK,
> +
> +    [Q_KEY_CODE_F11]                 = KEY_F11,
> +    [Q_KEY_CODE_F12]                 = KEY_F12,
> +
> +    [Q_KEY_CODE_CTRL_R]              = KEY_RIGHTCTRL,
> +    [Q_KEY_CODE_SYSRQ]               = KEY_SYSRQ,
> +    [Q_KEY_CODE_ALT_R]               = KEY_RIGHTALT,
> +
> +    [Q_KEY_CODE_HOME]                = KEY_HOME,
> +    [Q_KEY_CODE_UP]                  = KEY_UP,
> +    [Q_KEY_CODE_PGUP]                = KEY_PAGEUP,
> +    [Q_KEY_CODE_LEFT]                = KEY_LEFT,
> +    [Q_KEY_CODE_RIGHT]               = KEY_RIGHT,
> +    [Q_KEY_CODE_END]                 = KEY_END,
> +    [Q_KEY_CODE_DOWN]                = KEY_DOWN,
> +    [Q_KEY_CODE_PGDN]                = KEY_PAGEDOWN,
> +    [Q_KEY_CODE_INSERT]              = KEY_INSERT,
> +    [Q_KEY_CODE_DELETE]              = KEY_DELETE,
> +
> +    [Q_KEY_CODE_META_L]              = KEY_LEFTMETA,
> +    [Q_KEY_CODE_META_R]              = KEY_RIGHTMETA,
> +    [Q_KEY_CODE_MENU]                = KEY_MENU,
> +};
> +
>  static const int qcode_to_number[] = {
>      [Q_KEY_CODE_SHIFT] = 0x2a,
>      [Q_KEY_CODE_SHIFT_R] = 0x36,
> @@ -136,6 +256,7 @@ static const int qcode_to_number[] = {
>  };
>
>  static int number_to_qcode[0x100];
> +static int linux_to_qcode[KEY_CNT];
>
>  int qemu_input_key_value_to_number(const KeyValue *value)
>  {
> @@ -200,3 +321,27 @@ int qemu_input_key_value_to_scancode(const KeyValue
> *value, bool down,
>
>      return count;
>  }
> +
> +int qemu_input_qcode_to_linux(unsigned int qcode)
> +{
> +    assert(qcode < Q_KEY_CODE_MAX);
> +    return qcode_to_linux[qcode];
> +}
> +
> +int qemu_input_linux_to_qcode(unsigned int lnx)
> +{
> +    static int first = true;
> +
> +    if (first) {
> +        int qcode, number;
> +        first = false;
> +        for (qcode = 0; qcode < Q_KEY_CODE_MAX; qcode++) {
> +            number = qcode_to_linux[qcode];
> +            assert(number < KEY_CNT);
> +            linux_to_qcode[number] = qcode;
> +        }
> +    }
> +
> +    assert(lnx < KEY_CNT);
> +    return linux_to_qcode[lnx];
> +}
> --
> 1.8.3.1
>
> _______________________________________________
> vfio-users mailing list
> vfio-users@redhat.com
> https://www.redhat.com/mailman/listinfo/vfio-users
>
Gerd Hoffmann Jan. 4, 2016, 11:56 a.m. UTC | #2
On Mo, 2016-01-04 at 10:10 +0000, Jonathan Scruggs wrote:
> Hi,
> 
> 
> I tried these patches with qemu 2.5.0 on Gentoo and libvirt. I get the
> following error:
> Error starting domain: internal error: early end of file from monitor:
> possible problem:
> 2015-12-22T21:51:20.659520Z qemu-system-x86_64:
> -input-linux /dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd,grab-all=on: Could not open '/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd'
> 
> 
> I also tried setting /dev/input/event9 to permissions of 666 to see if
> it was a permission error, but the same thing happened. Any help would
> be appreciated.

libvirt uses cgroups to restrict qemu.  You can tweak cgroup_controllers
in /etc/libvirt/qemu.conf, when you remove "devices" controller it
should work (unless something else like selinux or apparmor applies
additional restrictions).

HTH,
  Gerd
Jonathan Scruggs Jan. 4, 2016, 1:13 p.m. UTC | #3
Hi,

Thanks for the reply.

I changed the conf to:
cgroup_controllers = [ "cpu", "memory", "cpuset", "cpuacct" ]
Also, cgroups are not mounted at /dev/cgroup
I don't have selinux or apparmor.

However, I still get this:
Error starting domain: internal error: early end of file from monitor,
possible problem: 2016-01-04T13:07:17.889701Z qemu-system-x86_64:
-input-linux
/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd,grab-all=on:
Could not open '/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd'

Thanks,
Jon

On 4 January 2016 at 11:56, Gerd Hoffmann <kraxel@redhat.com> wrote:

> On Mo, 2016-01-04 at 10:10 +0000, Jonathan Scruggs wrote:
> > Hi,
> >
> >
> > I tried these patches with qemu 2.5.0 on Gentoo and libvirt. I get the
> > following error:
> > Error starting domain: internal error: early end of file from monitor:
> > possible problem:
> > 2015-12-22T21:51:20.659520Z qemu-system-x86_64:
> > -input-linux
> /dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd,grab-all=on:
> Could not open '/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd'
> >
> >
> > I also tried setting /dev/input/event9 to permissions of 666 to see if
> > it was a permission error, but the same thing happened. Any help would
> > be appreciated.
>
> libvirt uses cgroups to restrict qemu.  You can tweak cgroup_controllers
> in /etc/libvirt/qemu.conf, when you remove "devices" controller it
> should work (unless something else like selinux or apparmor applies
> additional restrictions).
>
> HTH,
>   Gerd
>
>
Jonathan Scruggs Jan. 4, 2016, 1:19 p.m. UTC | #4
Oh. I just changed /dev/input/eventx (replace x with correct number for my
devices) to permissions of 666 and it worked. I guess I had to change the
conf file and change the permissions. Is there a way to make the devices
work with qemu? The permission user is root and group of input for all the
eventx devices. Do I need a udev script or is there a qemu user that can be
added to the group of input?

Thanks

On 4 January 2016 at 11:56, Gerd Hoffmann <kraxel@redhat.com> wrote:

> On Mo, 2016-01-04 at 10:10 +0000, Jonathan Scruggs wrote:
> > Hi,
> >
> >
> > I tried these patches with qemu 2.5.0 on Gentoo and libvirt. I get the
> > following error:
> > Error starting domain: internal error: early end of file from monitor:
> > possible problem:
> > 2015-12-22T21:51:20.659520Z qemu-system-x86_64:
> > -input-linux
> /dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd,grab-all=on:
> Could not open '/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd'
> >
> >
> > I also tried setting /dev/input/event9 to permissions of 666 to see if
> > it was a permission error, but the same thing happened. Any help would
> > be appreciated.
>
> libvirt uses cgroups to restrict qemu.  You can tweak cgroup_controllers
> in /etc/libvirt/qemu.conf, when you remove "devices" controller it
> should work (unless something else like selinux or apparmor applies
> additional restrictions).
>
> HTH,
>   Gerd
>
>
sL1pKn07 SpinFlo Jan. 5, 2016, 2:24 a.m. UTC | #5
2016-01-04 14:19 GMT+01:00 Jonathan Scruggs <j.scruggs@gmail.com>:
> Oh. I just changed /dev/input/eventx (replace x with correct number for my
> devices) to permissions of 666 and it worked. I guess I had to change the
> conf file and change the permissions. Is there a way to make the devices
> work with qemu? The permission user is root and group of input for all the
> eventx devices. Do I need a udev script or is there a qemu user that can be
> added to the group of input?
>
> Thanks
>
> On 4 January 2016 at 11:56, Gerd Hoffmann <kraxel@redhat.com> wrote:
>>
>> On Mo, 2016-01-04 at 10:10 +0000, Jonathan Scruggs wrote:
>> > Hi,
>> >
>> >
>> > I tried these patches with qemu 2.5.0 on Gentoo and libvirt. I get the
>> > following error:
>> > Error starting domain: internal error: early end of file from monitor:
>> > possible problem:
>> > 2015-12-22T21:51:20.659520Z qemu-system-x86_64:
>> > -input-linux
>> > /dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd,grab-all=on:
>> > Could not open '/dev/input/by-path/pci-0000:00:14.0-usb-0:12:1.0-event-kbd'
>> >
>> >
>> > I also tried setting /dev/input/event9 to permissions of 666 to see if
>> > it was a permission error, but the same thing happened. Any help would
>> > be appreciated.
>>
>> libvirt uses cgroups to restrict qemu.  You can tweak cgroup_controllers
>> in /etc/libvirt/qemu.conf, when you remove "devices" controller it
>> should work (unless something else like selinux or apparmor applies
>> additional restrictions).
>>
>> HTH,
>>   Gerd
>>

I tried add myself to input group. don't work.
not test if add root user to input group works


but can confirm if change all /dev/input/eventx to 0666 works the
keyboard/mouse on the guest

i have in the qemu.conf:

use r= root
group = kvm
cgroup_controllers = [ "cpu", "memory", "blkio", "cpuset", "cpuacct" ]

and add myself to groups libvirt (created by libvirt) and kvm (created by qemu)
sL1pKn07 SpinFlo Jan. 5, 2016, 2:26 a.m. UTC | #6
> libvirt uses cgroups to restrict qemu.  You can tweak cgroup_controllers
> in /etc/libvirt/qemu.conf, when you remove "devices" controller it
> should work (unless something else like selinux or apparmor applies
> additional restrictions).
>
> HTH,
>   Gerd

like this?

# What cgroup controllers to make use of with QEMU guests
#
#  - 'cpu' - use for schedular tunables
#  - 'devices' - use for device whitelisting
#  - 'memory' - use for memory tunables
#  - 'blkio' - use for block devices I/O tunables
#  - 'cpuset' - use for CPUs and memory nodes
#  - 'cpuacct' - use for CPUs statistics.
#
# NB, even if configured here, they won't be used unless
# the administrator has mounted cgroups, e.g.:
#
#  mkdir /dev/cgroup
#  mount -t cgroup -o devices,cpu,memory,blkio,cpuset none /dev/cgroup
#
# They can be mounted anywhere, and different controllers
# can be mounted in different locations. libvirt will detect
# where they are located.
#
cgroup_controllers = [ "cpu", "memory", "blkio", "cpuset", "cpuacct" ]

my original cgroup_controllers is commented

#cgroup_controllers = [ "cpu", "devices", "memory", "blkio", "cpuset",
"cpuacct" ]

greetings
Gerd Hoffmann Jan. 5, 2016, 7:05 a.m. UTC | #7
On Mo, 2016-01-04 at 13:19 +0000, Jonathan Scruggs wrote:
> Oh. I just changed /dev/input/eventx (replace x with correct number
> for my devices) to permissions of 666 and it worked. I guess I had to
> change the conf file and change the permissions. Is there a way to
> make the devices work with qemu? The permission user is root and group
> of input for all the eventx devices. Do I need a udev script or is
> there a qemu user that can be added to the group of input?

I'm using chmod 666, adding the qemu user to the input group should work
too.

cheers,
  Gerd
Gerd Hoffmann Jan. 5, 2016, 7:06 a.m. UTC | #8
Hi,

> like this?
> 
> cgroup_controllers = [ "cpu", "memory", "blkio", "cpuset", "cpuacct" ]

yes (+libvirtd restart so it re-reads the config).

cheers,
  Gerd
Jonathan Scruggs Jan. 5, 2016, 8:06 a.m. UTC | #9
I found the qemu user yesterday and added it to the input group. All is
good now. The patches work great! Are they being added to the main code
base soon? A small faq on the site detailing libvirt usage and adding qemu
to the input group would be needed though.

I notice no bugs as of yet. The mouse fully disengages from each system
unlike an earlier report I read in this mailing list. This is perfect and
precisely what I requested many months ago when vfio-users mailing list
first started. :)

Thanks for all your work on this,
Jon

On 5 January 2016 at 07:05, Gerd Hoffmann <kraxel@redhat.com> wrote:

> On Mo, 2016-01-04 at 13:19 +0000, Jonathan Scruggs wrote:
> > Oh. I just changed /dev/input/eventx (replace x with correct number
> > for my devices) to permissions of 666 and it worked. I guess I had to
> > change the conf file and change the permissions. Is there a way to
> > make the devices work with qemu? The permission user is root and group
> > of input for all the eventx devices. Do I need a udev script or is
> > there a qemu user that can be added to the group of input?
>
> I'm using chmod 666, adding the qemu user to the input group should work
> too.
>
> cheers,
>   Gerd
>
>
>
sL1pKn07 SpinFlo Jan. 5, 2016, 2:44 p.m. UTC | #10
2016-01-05 9:06 GMT+01:00 Jonathan Scruggs <j.scruggs@gmail.com>:
> I notice no bugs as of yet.

Hi
I found one (if can call that) bug

I use a physical USB switch for share the K/M with other PC
when switch to other pc, lost the signal. this is ok. but the VM start
stutter (the sounds and videos), and when is back, can't recover the
signal in the VM. requiring restart the guest

This is expected?

btw. I found solution for the kb/mouse permissions on my setup. qemu
is launched with root user. Then I added the root to group input. now
no need set 0666 to /dev/input/eventX and can use the keyboard/mouse
without apparent problems (better than passthrough (need use other
keyboard for host)) and synergy (in games can't rotate the camera in
all degrees).

Greetings
Gerd Hoffmann Jan. 6, 2016, 7:53 a.m. UTC | #11
On Di, 2016-01-05 at 15:44 +0100, sL1pKn07 SpinFlo wrote:
> 2016-01-05 9:06 GMT+01:00 Jonathan Scruggs <j.scruggs@gmail.com>:
> > I notice no bugs as of yet.
> 
> Hi
> I found one (if can call that) bug
> 
> I use a physical USB switch for share the K/M with other PC
> when switch to other pc, lost the signal.

How does the switch work?  Disconnect the usb devices (i.e. they are
gone from lsusb output)?

cheers,
  Gerd
sL1pKn07 SpinFlo Jan. 7, 2016, 4:55 a.m. UTC | #12
Yes, is like disconect the cable of USB.
http://sl1pkn07.wtf/imagenes/kvm01.jpg
http://sl1pkn07.wtf/imagenes/kvm04.jpg

Greetings.

El 06/01/2016 08:53, "Gerd Hoffmann" <kraxel@redhat.com> escribió:
>
> On Di, 2016-01-05 at 15:44 +0100, sL1pKn07 SpinFlo wrote:
> > 2016-01-05 9:06 GMT+01:00 Jonathan Scruggs <j.scruggs@gmail.com>:
> > > I notice no bugs as of yet.
> >
> > Hi
> > I found one (if can call that) bug
> >
> > I use a physical USB switch for share the K/M with other PC
> > when switch to other pc, lost the signal.
>
> How does the switch work?  Disconnect the usb devices (i.e. they are
> gone from lsusb output)?
>
> cheers,
>   Gerd
>
sL1pKn07 SpinFlo Jan. 7, 2016, 4:57 a.m. UTC | #13
On Mi, 2016-01-06 at 13:42 +0100, sL1pKn07 SpinFlo wrote:
> Yes, is like disconect the cable of USB.

Ok.  That is not so easy.  Well, the first part (switch away) is easy,
it is just a matter of catching read errors, so the device going away
(unplug) doesn't screw up things.  But when it comes to reconnect after
switching back it'll quickly becomes quite messy ...

cheers,
  Gerd
sL1pKn07 SpinFlo Jan. 13, 2016, 8:34 p.m. UTC | #14
Today have notice the patch stop working on my VM

input_linux_event_mouse: read: Resource temporarily unavailable
input_linux_event_keyboard: read: Resource temporarily unavailable

i only rebuild qemu (from Gerd Hoffmann's input-dev-event barnch) with
some changes.

this is my options:

  ./configure \
    --python=/usr/bin/python2 \
    --prefix=/usr \
    --sysconfdir=/etc \
    --audio-drv-list='pa alsa sdl' \
    --localstatedir=/var \
    --libexecdir=/usr/lib/qemu \
    --enable-sdl \
    --with-sdlabi=2.0 \
    --enable-linux-aio \
    --enable-seccomp \
    --enable-tpm \
    --enable-modules \
    --disable-gtk \
    --disable-spice \
    --disable-rbd \
    --disable-libiscsi \
    --disable-libnfs \
    --disable-smartcard \
    --disable-glusterfs \
    --disable-docs \
    --disable-vnc{,-sasl,-jpeg,-png}

I only disable spice,vnc,smartcard,glusterfs,iscsi,rbd,docs,libnfs and
add sdlabi=2.0

is a regression or one of the disable components is necessary to run the patch?

greetings

2016-01-07 5:57 GMT+01:00 sL1pKn07 SpinFlo <sl1pkn07@gmail.com>:
> On Mi, 2016-01-06 at 13:42 +0100, sL1pKn07 SpinFlo wrote:
>> Yes, is like disconect the cable of USB.
>
> Ok.  That is not so easy.  Well, the first part (switch away) is easy,
> it is just a matter of catching read errors, so the device going away
> (unplug) doesn't screw up things.  But when it comes to reconnect after
> switching back it'll quickly becomes quite messy ...
>
> cheers,
>   Gerd
sL1pKn07 SpinFlo Jan. 14, 2016, 11:19 p.m. UTC | #15
ok, now works tnx Gerd!


but i found 2 problems, one with keyboard and other with the mouse

Keyboard:

the repetition (hold the key) don't work.

Mouse:

only detect 3 buttons (my Logitech G5 Laser Have 7)

this is spected?

greetings
Gerd Hoffmann Jan. 15, 2016, 8:50 a.m. UTC | #16
On Fr, 2016-01-15 at 00:19 +0100, sL1pKn07 SpinFlo wrote:
> ok, now works tnx Gerd!
> 
> 
> but i found 2 problems, one with keyboard and other with the mouse
> 
> Keyboard:
> 
> the repetition (hold the key) don't work.

Support used to be there, but the constant flow of key repeat events in
case you hold down a key longer (like you do with shift or ctrl in some
games) made things unstable so I turned that off.

> Mouse:
> 
> only detect 3 buttons (my Logitech G5 Laser Have 7)

The mouse emulated by qemu has only three buttons.

cheers,
  Gerd
sL1pKn07 SpinFlo Jan. 15, 2016, 6:06 p.m. UTC | #17
---------- Forwarded message ----------
From: Gerd Hoffmann <kraxel@redhat.com>
Date: 2016-01-15 14:24 GMT+01:00
Subject: Re: [vfio-users] [PATCH v2 1/3] input: add
qemu_input_qcode_to_linux + qemu_input_linux_to_qcode
To: sL1pKn07 SpinFlo <sl1pkn07@gmail.com>


> --- a/include/standard-headers/linux/input-event-codes.h
> +++ b/include/standard-headers/linux/input-event-codes.h
> @@ -416,6 +416,11 @@
>  #define BTN_WHEEL 0x150
>  #define BTN_GEAR_DOWN 0x150
>  #define BTN_GEAR_UP 0x151
> +#define BTN_GEAR_LEFT 0x???   /* FIXME! */
> +#define BTN_GEAR_RIGHT 0x???   /* FIXME! */
> +#define BTN_FUNCTION_1 0x???   /* FIXME! */
> +#define BTN_FUNCTION_2 0x???   /* FIXME! */

The ones sent by your mouse most likely already in the list.

Add "log=on" to the mouse, then qemu will log all mouse events it gets
from the kernel to stderr, including the ones it doesn't handle.  That
should show which wheel and button events the mouse sends.  Lets
continue from there.

More buttons can be defined by adding them to InputButton in
qapi-schema.json

Most tricky part is probably getting the mouse events to the guest os.
quick look as the ps/2 emulation looks like there are no unused bits for
more buttons.  Possibly we have to extend the usb mouse emulation for
that.  Need to google a bit on that (any hints are welcome ;) ...

cheers,
  Gerd
Jonathan Scruggs Jan. 18, 2016, 11:47 a.m. UTC | #18
Hi Gerd,

Would there be a way to add repeating keys back in that doesn't cause
issues? Maybe slow down the repeat cycle? Or is this strictly a issue with
how the actual event drivers or the buffers work and would need changing to
that on the host side? In my mind it seams fairly straightforward in just
forwarding these events to the VM.

Would it be different if the keyboard was using the PS/2 versus the USB
interface on the guest? I have a USB controller added for the guest but the
keyboard and mouse are on PS/2 interfaces.

A second thought. What if you made the keyboard and mouse USB only, then on
the guest, make sure the USB controller is using Message Signal-Based
interrupts. On Windows, the controller was set to the old style Line-Based.
The slow downs could be caused by a lake in speed with he interrupts and
USB polling speed.

Would you be able to tell me how to make the keyboard/mouse USB only and
enable repeat keys, so I can investigate this option? If it works like this
then a good set of instructions will need to be done to enable all this and
solve an issue. :-) Also, I would need to know the cases where the slow
downs happen to test.

What do you think?

-Jon
On 15 Jan 2016 08:50, "Gerd Hoffmann" <kraxel@redhat.com> wrote:

> On Fr, 2016-01-15 at 00:19 +0100, sL1pKn07 SpinFlo wrote:
> > ok, now works tnx Gerd!
> >
> >
> > but i found 2 problems, one with keyboard and other with the mouse
> >
> > Keyboard:
> >
> > the repetition (hold the key) don't work.
>
> Support used to be there, but the constant flow of key repeat events in
> case you hold down a key longer (like you do with shift or ctrl in some
> games) made things unstable so I turned that off.
>
> > Mouse:
> >
> > only detect 3 buttons (my Logitech G5 Laser Have 7)
>
> The mouse emulated by qemu has only three buttons.
>
> cheers,
>   Gerd
>
>
> _______________________________________________
> vfio-users mailing list
> vfio-users@redhat.com
> https://www.redhat.com/mailman/listinfo/vfio-users
>
Gerd Hoffmann Jan. 18, 2016, 2:13 p.m. UTC | #19
On Mo, 2016-01-18 at 11:47 +0000, Jonathan Scruggs wrote:
> Hi Gerd,
> 
> Would there be a way to add repeating keys back in that doesn't cause
> issues? Maybe slow down the repeat cycle? Or is this strictly a issue
> with how the actual event drivers or the buffers work and would need
> changing to that on the host side?

I don't know ...

> In my mind it seams fairly straightforward in just forwarding these
> events to the VM.

I assumed that as well, it was there initially and only removed after it
turned out to cause problems.

I've added a patch to the git branch bringing it back, but guarded with
a new config option (repeat={on,off}) and turned off by default.

> Would it be different if the keyboard was using the PS/2 versus the
> USB interface on the guest? I have a USB controller added for the
> guest but the keyboard and mouse are on PS/2 interfaces.

Worth testing.  Just add "-device usb-kbd" to the qemu command line and
see what happens ...

> A second thought. What if you made the keyboard and mouse USB only,
> then on the guest, make sure the USB controller is using Message
> Signal-Based interrupts. On Windows, the controller was set to the old
> style Line-Based. The slow downs could be caused by a lake in speed
> with he interrupts and USB polling speed.

In case windows is new enough to have xhci support (win8+) you can try
using a xhci hostadapter, which supports MSI (uhci and ehci don't), then
hook up the usb keyboard to it.

"-device nec-usb-xhci,id=xhci -device usb-kbd,bus=xhci.0"

cheers,
  Gerd
Jonathan Scruggs Jan. 23, 2016, 9:51 p.m. UTC | #20
Hi Gerd,

I am using qemu 2.5.0 source code and applied all the patches on your git
server. This one:
https://www.kraxel.org/cgit/qemu/commit/?h=work/input-dev-event&id=b52110d4f22e99953ac5195a90988a253e3e2f90
causes the build to fail with this:
error: array index in non-array initializer
It happens on all the key binding assignments. Are there changes in the
code elsewhere that this patch is for? It compiles just fine without it on
the 2.5.0 sources with the latest CVE bug patches.

Jon

On 18 January 2016 at 14:13, Gerd Hoffmann <kraxel@redhat.com> wrote:

> On Mo, 2016-01-18 at 11:47 +0000, Jonathan Scruggs wrote:
> > Hi Gerd,
> >
> > Would there be a way to add repeating keys back in that doesn't cause
> > issues? Maybe slow down the repeat cycle? Or is this strictly a issue
> > with how the actual event drivers or the buffers work and would need
> > changing to that on the host side?
>
> I don't know ...
>
> > In my mind it seams fairly straightforward in just forwarding these
> > events to the VM.
>
> I assumed that as well, it was there initially and only removed after it
> turned out to cause problems.
>
> I've added a patch to the git branch bringing it back, but guarded with
> a new config option (repeat={on,off}) and turned off by default.
>
> > Would it be different if the keyboard was using the PS/2 versus the
> > USB interface on the guest? I have a USB controller added for the
> > guest but the keyboard and mouse are on PS/2 interfaces.
>
> Worth testing.  Just add "-device usb-kbd" to the qemu command line and
> see what happens ...
>
> > A second thought. What if you made the keyboard and mouse USB only,
> > then on the guest, make sure the USB controller is using Message
> > Signal-Based interrupts. On Windows, the controller was set to the old
> > style Line-Based. The slow downs could be caused by a lake in speed
> > with he interrupts and USB polling speed.
>
> In case windows is new enough to have xhci support (win8+) you can try
> using a xhci hostadapter, which supports MSI (uhci and ehci don't), then
> hook up the usb keyboard to it.
>
> "-device nec-usb-xhci,id=xhci -device usb-kbd,bus=xhci.0"
>
> cheers,
>   Gerd
>
>
Jonathan Scruggs Jan. 24, 2016, 3:06 p.m. UTC | #21
Hi Gerd,

A couple of options I have been wondering about.

1)
Is it possible to have an option that would enable running a program on the
host on switching, IE when both CRTL keys are pressed. It would run on the
host regardless if it was on the guest machine when the keys pressed.
An option like 'onswitchexecute=/usr/bin/monitorswitch'

Something like that. I have a small program that switches the monitor input
via I2C direct (if interested: http://pastebin.com/6Hd0pafF). The program
would need to be modified a little bit to not use a variable input. but to
somehow detect what it's currently at and then switch to the opposite --
shouldn't be too hard.

2)
This would be useful for number idea one.
Instead of both CTRL keys, could the hotkey be something like
CTRL+SHIFT+ALT+1 for the host, and then each guest would set an option of 2
through 9. Since this is really only good for dedicated graphics cards, the
most I've heard of is 7 in one machine and that was a crazy build. A normal
person would have two cards, namely MS Windows Gaming Rig and GNU/Linux.
However, some may want three, which is very doable on most systems. So,
CTRL+SHIFT+ALT+2 or +3 to get to the other systems.

It can connect into point one, as the cheap and dirty monitor switcher code
takes an input and my monitor has three inputs, so a person could write
code to switch anything to anything. The option could have a variable
string that when called by your Input patches, would replace the variable
place holder with the machine being called, IE:
'execonswitch=/usr/bin/monitorswitch %COMPNUM'
Or something like that.

Hope you like the ideas.
Jon

On 18 January 2016 at 14:13, Gerd Hoffmann <kraxel@redhat.com> wrote:

> On Mo, 2016-01-18 at 11:47 +0000, Jonathan Scruggs wrote:
> > Hi Gerd,
> >
> > Would there be a way to add repeating keys back in that doesn't cause
> > issues? Maybe slow down the repeat cycle? Or is this strictly a issue
> > with how the actual event drivers or the buffers work and would need
> > changing to that on the host side?
>
> I don't know ...
>
> > In my mind it seams fairly straightforward in just forwarding these
> > events to the VM.
>
> I assumed that as well, it was there initially and only removed after it
> turned out to cause problems.
>
> I've added a patch to the git branch bringing it back, but guarded with
> a new config option (repeat={on,off}) and turned off by default.
>
> > Would it be different if the keyboard was using the PS/2 versus the
> > USB interface on the guest? I have a USB controller added for the
> > guest but the keyboard and mouse are on PS/2 interfaces.
>
> Worth testing.  Just add "-device usb-kbd" to the qemu command line and
> see what happens ...
>
> > A second thought. What if you made the keyboard and mouse USB only,
> > then on the guest, make sure the USB controller is using Message
> > Signal-Based interrupts. On Windows, the controller was set to the old
> > style Line-Based. The slow downs could be caused by a lake in speed
> > with he interrupts and USB polling speed.
>
> In case windows is new enough to have xhci support (win8+) you can try
> using a xhci hostadapter, which supports MSI (uhci and ehci don't), then
> hook up the usb keyboard to it.
>
> "-device nec-usb-xhci,id=xhci -device usb-kbd,bus=xhci.0"
>
> cheers,
>   Gerd
>
>
Gerd Hoffmann Jan. 25, 2016, 8:13 a.m. UTC | #22
On Sa, 2016-01-23 at 21:51 +0000, Jonathan Scruggs wrote:
> Hi Gerd,
> 
> 
> I am using qemu 2.5.0 source code and applied all the patches on your
> git server. This one:
> https://www.kraxel.org/cgit/qemu/commit/?h=work/input-dev-event&id=b52110d4f22e99953ac5195a90988a253e3e2f90
> causes the build to fail with this:
> error: array index in non-array initializer

There have been some incompatible changes between 2.5.0 and master ...

Dropping the "input-linux: adapt to qapi changes" patch might get things
build on 2.5.0, didn't test that though ...

HTH,
  Gerd
Gerd Hoffmann Jan. 25, 2016, 8:29 a.m. UTC | #23
Hi,

> 1)
> Is it possible to have an option that would enable running a program
> on the host on switching, IE when both CRTL keys are pressed. It would
> run on the host regardless if it was on the guest machine when the
> keys pressed.
> An option like 'onswitchexecute=/usr/bin/monitorswitch'

Should be doable.  We have other places with simliar things already
(network setup for example).

> Something like that. I have a small program that switches the monitor
> input via I2C direct (if interested: http://pastebin.com/6Hd0pafF).
> The program would need to be modified a little bit to not use a
> variable input. but to somehow detect what it's currently at and then
> switch to the opposite -- shouldn't be too hard.

Calling the thing with "host" or "guest" as argument should be easy too.

> This would be useful for number idea one.
> Instead of both CTRL keys, could the hotkey be something like CTRL
> +SHIFT+ALT+1 for the host, and then each guest would set an option of
> 2 through 9.

Not going to work.  At least not a direct guest -> guest switch, only
guest1 -> host -> guest2.

cheers,
  Gerd
diff mbox

Patch

diff --git a/include/ui/input.h b/include/ui/input.h
index d06a12d..d7afd80 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -48,6 +48,9 @@  int qemu_input_key_value_to_qcode(const KeyValue *value);
 int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
                                      int *codes);
 
+int qemu_input_qcode_to_linux(unsigned int qcode);
+int qemu_input_linux_to_qcode(unsigned int lnx);
+
 InputEvent *qemu_input_event_new_btn(InputButton btn, bool down);
 void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down);
 void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
diff --git a/ui/input-keymap.c b/ui/input-keymap.c
index d36be4b..31f4daa 100644
--- a/ui/input-keymap.c
+++ b/ui/input-keymap.c
@@ -2,6 +2,126 @@ 
 #include "ui/keymaps.h"
 #include "ui/input.h"
 
+#include "standard-headers/linux/input.h"
+
+/* FIXME: duplicate, see hw/input/virtio-input-hid.c */
+static const unsigned int qcode_to_linux[Q_KEY_CODE_MAX] = {
+    [Q_KEY_CODE_ESC]                 = KEY_ESC,
+    [Q_KEY_CODE_1]                   = KEY_1,
+    [Q_KEY_CODE_2]                   = KEY_2,
+    [Q_KEY_CODE_3]                   = KEY_3,
+    [Q_KEY_CODE_4]                   = KEY_4,
+    [Q_KEY_CODE_5]                   = KEY_5,
+    [Q_KEY_CODE_6]                   = KEY_6,
+    [Q_KEY_CODE_7]                   = KEY_7,
+    [Q_KEY_CODE_8]                   = KEY_8,
+    [Q_KEY_CODE_9]                   = KEY_9,
+    [Q_KEY_CODE_0]                   = KEY_0,
+    [Q_KEY_CODE_MINUS]               = KEY_MINUS,
+    [Q_KEY_CODE_EQUAL]               = KEY_EQUAL,
+    [Q_KEY_CODE_BACKSPACE]           = KEY_BACKSPACE,
+
+    [Q_KEY_CODE_TAB]                 = KEY_TAB,
+    [Q_KEY_CODE_Q]                   = KEY_Q,
+    [Q_KEY_CODE_W]                   = KEY_W,
+    [Q_KEY_CODE_E]                   = KEY_E,
+    [Q_KEY_CODE_R]                   = KEY_R,
+    [Q_KEY_CODE_T]                   = KEY_T,
+    [Q_KEY_CODE_Y]                   = KEY_Y,
+    [Q_KEY_CODE_U]                   = KEY_U,
+    [Q_KEY_CODE_I]                   = KEY_I,
+    [Q_KEY_CODE_O]                   = KEY_O,
+    [Q_KEY_CODE_P]                   = KEY_P,
+    [Q_KEY_CODE_BRACKET_LEFT]        = KEY_LEFTBRACE,
+    [Q_KEY_CODE_BRACKET_RIGHT]       = KEY_RIGHTBRACE,
+    [Q_KEY_CODE_RET]                 = KEY_ENTER,
+
+    [Q_KEY_CODE_CTRL]                = KEY_LEFTCTRL,
+    [Q_KEY_CODE_A]                   = KEY_A,
+    [Q_KEY_CODE_S]                   = KEY_S,
+    [Q_KEY_CODE_D]                   = KEY_D,
+    [Q_KEY_CODE_F]                   = KEY_F,
+    [Q_KEY_CODE_G]                   = KEY_G,
+    [Q_KEY_CODE_H]                   = KEY_H,
+    [Q_KEY_CODE_J]                   = KEY_J,
+    [Q_KEY_CODE_K]                   = KEY_K,
+    [Q_KEY_CODE_L]                   = KEY_L,
+    [Q_KEY_CODE_SEMICOLON]           = KEY_SEMICOLON,
+    [Q_KEY_CODE_APOSTROPHE]          = KEY_APOSTROPHE,
+    [Q_KEY_CODE_GRAVE_ACCENT]        = KEY_GRAVE,
+
+    [Q_KEY_CODE_SHIFT]               = KEY_LEFTSHIFT,
+    [Q_KEY_CODE_BACKSLASH]           = KEY_BACKSLASH,
+    [Q_KEY_CODE_LESS]                = KEY_102ND,
+    [Q_KEY_CODE_Z]                   = KEY_Z,
+    [Q_KEY_CODE_X]                   = KEY_X,
+    [Q_KEY_CODE_C]                   = KEY_C,
+    [Q_KEY_CODE_V]                   = KEY_V,
+    [Q_KEY_CODE_B]                   = KEY_B,
+    [Q_KEY_CODE_N]                   = KEY_N,
+    [Q_KEY_CODE_M]                   = KEY_M,
+    [Q_KEY_CODE_COMMA]               = KEY_COMMA,
+    [Q_KEY_CODE_DOT]                 = KEY_DOT,
+    [Q_KEY_CODE_SLASH]               = KEY_SLASH,
+    [Q_KEY_CODE_SHIFT_R]             = KEY_RIGHTSHIFT,
+
+    [Q_KEY_CODE_ALT]                 = KEY_LEFTALT,
+    [Q_KEY_CODE_SPC]                 = KEY_SPACE,
+    [Q_KEY_CODE_CAPS_LOCK]           = KEY_CAPSLOCK,
+
+    [Q_KEY_CODE_F1]                  = KEY_F1,
+    [Q_KEY_CODE_F2]                  = KEY_F2,
+    [Q_KEY_CODE_F3]                  = KEY_F3,
+    [Q_KEY_CODE_F4]                  = KEY_F4,
+    [Q_KEY_CODE_F5]                  = KEY_F5,
+    [Q_KEY_CODE_F6]                  = KEY_F6,
+    [Q_KEY_CODE_F7]                  = KEY_F7,
+    [Q_KEY_CODE_F8]                  = KEY_F8,
+    [Q_KEY_CODE_F9]                  = KEY_F9,
+    [Q_KEY_CODE_F10]                 = KEY_F10,
+    [Q_KEY_CODE_NUM_LOCK]            = KEY_NUMLOCK,
+    [Q_KEY_CODE_SCROLL_LOCK]         = KEY_SCROLLLOCK,
+
+    [Q_KEY_CODE_KP_0]                = KEY_KP0,
+    [Q_KEY_CODE_KP_1]                = KEY_KP1,
+    [Q_KEY_CODE_KP_2]                = KEY_KP2,
+    [Q_KEY_CODE_KP_3]                = KEY_KP3,
+    [Q_KEY_CODE_KP_4]                = KEY_KP4,
+    [Q_KEY_CODE_KP_5]                = KEY_KP5,
+    [Q_KEY_CODE_KP_6]                = KEY_KP6,
+    [Q_KEY_CODE_KP_7]                = KEY_KP7,
+    [Q_KEY_CODE_KP_8]                = KEY_KP8,
+    [Q_KEY_CODE_KP_9]                = KEY_KP9,
+    [Q_KEY_CODE_KP_SUBTRACT]         = KEY_KPMINUS,
+    [Q_KEY_CODE_KP_ADD]              = KEY_KPPLUS,
+    [Q_KEY_CODE_KP_DECIMAL]          = KEY_KPDOT,
+    [Q_KEY_CODE_KP_ENTER]            = KEY_KPENTER,
+    [Q_KEY_CODE_KP_DIVIDE]           = KEY_KPSLASH,
+    [Q_KEY_CODE_KP_MULTIPLY]         = KEY_KPASTERISK,
+
+    [Q_KEY_CODE_F11]                 = KEY_F11,
+    [Q_KEY_CODE_F12]                 = KEY_F12,
+
+    [Q_KEY_CODE_CTRL_R]              = KEY_RIGHTCTRL,
+    [Q_KEY_CODE_SYSRQ]               = KEY_SYSRQ,
+    [Q_KEY_CODE_ALT_R]               = KEY_RIGHTALT,
+
+    [Q_KEY_CODE_HOME]                = KEY_HOME,
+    [Q_KEY_CODE_UP]                  = KEY_UP,
+    [Q_KEY_CODE_PGUP]                = KEY_PAGEUP,
+    [Q_KEY_CODE_LEFT]                = KEY_LEFT,
+    [Q_KEY_CODE_RIGHT]               = KEY_RIGHT,
+    [Q_KEY_CODE_END]                 = KEY_END,
+    [Q_KEY_CODE_DOWN]                = KEY_DOWN,
+    [Q_KEY_CODE_PGDN]                = KEY_PAGEDOWN,
+    [Q_KEY_CODE_INSERT]              = KEY_INSERT,
+    [Q_KEY_CODE_DELETE]              = KEY_DELETE,
+
+    [Q_KEY_CODE_META_L]              = KEY_LEFTMETA,
+    [Q_KEY_CODE_META_R]              = KEY_RIGHTMETA,
+    [Q_KEY_CODE_MENU]                = KEY_MENU,
+};
+
 static const int qcode_to_number[] = {
     [Q_KEY_CODE_SHIFT] = 0x2a,
     [Q_KEY_CODE_SHIFT_R] = 0x36,
@@ -136,6 +256,7 @@  static const int qcode_to_number[] = {
 };
 
 static int number_to_qcode[0x100];
+static int linux_to_qcode[KEY_CNT];
 
 int qemu_input_key_value_to_number(const KeyValue *value)
 {
@@ -200,3 +321,27 @@  int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
 
     return count;
 }
+
+int qemu_input_qcode_to_linux(unsigned int qcode)
+{
+    assert(qcode < Q_KEY_CODE_MAX);
+    return qcode_to_linux[qcode];
+}
+
+int qemu_input_linux_to_qcode(unsigned int lnx)
+{
+    static int first = true;
+
+    if (first) {
+        int qcode, number;
+        first = false;
+        for (qcode = 0; qcode < Q_KEY_CODE_MAX; qcode++) {
+            number = qcode_to_linux[qcode];
+            assert(number < KEY_CNT);
+            linux_to_qcode[number] = qcode;
+        }
+    }
+
+    assert(lnx < KEY_CNT);
+    return linux_to_qcode[lnx];
+}