Wednesday, 2 June 2010

Towards a more general solution

I spent the last few days generalizing my proxy driver, in such a way that most HID devices (mice, keyboards), should now be working. Actually, any device that uses only endpoint 1 in interrupt mode and IN direction should be supported by the current implementation.

There are no static descriptors hard-coded in the driver anymore, so GET_DESCRIPTOR requests are intercepted, and the configuration descriptors are parsed and cached (using functions found in the kernel). Also, the descriptors are modified on the fly, to compensate for the fact that the communication between the PC and the BeagleBoard happens in Full Speed, while the BeagleBoard-device communication uses Low Speed.

Two fields are dynamically modified:
  • bMaxPacketSize0 in the device descriptor. It seems like the MUSB driver only support 64 bytes as maximum packet size (which is what is mandated by the High Speed mode), while the mouse uses 8 bytes (the only possible value for Low Speed devices). In theory, Full Speed devices can advertise a maximum packet size between 8 and 64 bytes, but the MUSB driver does not seem to support that.
  • bInterval in endpoints descriptors. As mentionned before, the meaning of that field varies with the device speed.
To get the proxy driver to work, you need to follow these steps:
  • Clone my kernel git tree. Use the backup-20100602 branch.
  • Compile the kernel with the default beagleboard configuration (see here). You just need to add CONFIG_USB_G_PROXY=m. I also disabled MUSB in host and OTG mode, as well as USB suspend, but this may not be necessary.
  • Install the new kernel on the board.
  • Clone the helper scripts git tree, and copy the content of the arm directory to the BeagleBoard (you need to modify load/setup scripts if you do not have have a copy of musb_hdrc.ko and g_proxy.ko in the same directory).
  • Run ./setup on the BeagleBoard, this will unload the g_ether gadget driver.
  • Plug your USB hub + a HID mouse/keyboard to the BeagleBoard (this can be done earlier).
  • Plug your PC to the BeagleBoard USB slave port (this can be done earlier as well).
  • Run ./unbind: This will unbind the device from the normal Linux driver.
  • Run ./load: this will (re)load the g_proxy driver.
  • Use the mouse/keyboard, it should work.
The code is still full of TODO/FIXME, and is rather likely to cause kernel panics.