SuperHID

Copyright 2015 by Assured Information Security, Inc. Created by Jean-Edouard Lejosne <lejosnej@ainfosec.com>. This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/.

SuperHID v2

Downsides of SuperHID v1

SuperHID v1 extends the Linux HID gadget with multitouch stuff.
Using the gadget subsystem, originally designed for real hardware, implies having to simulate and drive a ton of hardware:

  • A USB host controller (HCD)
  • A USB device controller (UCD), along with its endpoints and the glue to the HCD
  • A USB device that "plugs" to a UCD

The resulting fake device is then passed to a guest using the PV USB backend/frontend.

In the proof-of-concept, the dummy_hcd kernel module is used as an HCD+UCD, with the critical limitation that it supports only 1 USB device, with no easy way to extend to multiple devices.

In general, the gadget subsystem is not meant to be used like that. Gadgets are for "slave" USB devices, not hosts...

New ideas

In the current scheme, we spend a lot of effort and resource to simulate a "real" device, when in the end it gets "virtualized"...

The main idea for making it simpler would be to stop using the gadget subsystem, and just plug SuperHID somewhere in the PV USB mechanism. The frontends just bring up "fake" devices anyway!

I see two ways of doing this:

  • usbback could be modified to be able to use a special kernel module in place of real USB devices. That way, the frontends would need no modification, but that implies understanding and modifying the huge mess that is usbback...
  • A separate USB backend could be written, using some of the guts of usbback as a starting point. That new backend would talk to SuperHID instead of real devices. That means not having to mess with usbback, but the frontends may have to be modified to be able to deal with multiple PV USB backends...

The second approach seems to make the most sense to me, so that's what I'm looking at.

Here's a picture that compares the two designs:

SuperHID v1

Introduction

Some HID background could be useful to understand the core of SuperHID.

When using SuperHID, the input follows that path:

Device (HID)
  v
Linux (HID->Event)
  v
input_server (Event)
  v
SuperHID plugin (Event->HID)
  v
SuperHID driver (HID)
  v
SuperHID fake device (HID->USB)

Then, passing the superhid fake device through to any guest gives it all the input we want.

Highlights

  • No code needed in the guest VM
  • Multi-touch works in Microsoft Windows 8, and any other pv-usb-enabled guest
  • All the input still goes through input_server, which gives total control over what event goes to which VM

Downsides

  • The input events follow a long path, as illustrated above

To do

  • Implement the plugin directly in input_server, to reduce the packets journey.
  • Implement a way to skip the relative-to-absolute translation that happens in input_server, to make input faster and more reliable (but potentially breaking other input features).
  • Enhance the superhid gadget driver (and/or the virtual USB controller) to be able to create multiple devices (right now we get only one).
  • Get the toolstack and the USB subsystem to automatically pass the right SuperHID fake input device to the right guest.

The USB controller

The superhid proof-of-concept is now functionnal, and the superhid device itself can be used as-is.

However, the USB controller needs a lot of work. Right now, we use dummy_hcd, which simulates a real life controller, with power, latency and ports limitations. This module has been created only for development purposes, to simulate devices before actually getting access to the real hardware. The problem of that module is that is requires the clock to be set to 1000HZ, and it probably uses too much resources.

What SuperHID needs is something that would be more of a "fake USB controller", that would be dummy-er than dummy_hcd. Like just enough code to create a fake controller and pipe the packets to the fake devices (gadgets).

How to build and use SuperHID

  • Make sure the dom0 Linux kernel has been (re)compiled with an HZ value of 1000 and gadget support.
  • In OE: ./bb xenclient-superhid
  • Send and install the resulting module to the (OpenXT) test machine (superhid.ko)
  • In input.git/superhid (with a 32 bits compiler): gcc -o shp -lpthread -levent superhidplugin.c
  • Send shp to the test machine
  • On the test machine:

    # cat > /etc/modprobe.d/superhid.conf <<EOF
    options superhid idVendor=0x03eb idProduct=0x211c bcdDevice=0x0001 iManufacturer=jed iProduct=superhid
    EOF
    # modprobe dummy_hcd
    # modprobe superhid
    # ./shp <domid>
    

Note: idVendor and idProduct are set to an existing input device to make some guests recognise it. Ideally, those values could be anything, as the device is just a standard HID device.

  • Pass the superhid device to the (Windows/Linux) guest

At that point, the guest should see a new multitouch HID device and should be able to use it.