Tuesday, October 11, 2011

OpenSUSE Hackweek VII - Hacking USB Joysticks in YaST

Introduction

This hackweek I spent playing with joysticks in YaST and hwinfo (libhd).
YaST already has a module for configuring joysticks, but I only supported Gameport joysticks which are quite obsoleted these days.

AFAIK all recent mainboards do not have gamport connectors (just a pin header) or the gameport is completely missing. And if you want to buy a joystick you will find only USB models anyway.

There was a note in the YaST module that it only supports Gameport joysticks but some users find it confusing.

So I decided to change the situation and do something interesting during my Hackweek project - to add USB joystick support to YaST.

Hacking

The support in YaST actually has three parts. YaST uses libhd (from hwinfo package) for hardware detection, than there is yast2-hardware-detection package which is a libhd wrapper converting C functions and data to YCP (the main YaST language) and finally there is yast2-sound package which contains the joystick configuration module.

The first step was to add USB joystick support to hwinfo so it could be used for joystick detection. The problem was that hwinfo found the USB joystick device but it didn't know that it's a joystick and reported it as an unclassified generic USB device and also the joystick result was empty:

So the detection code was there, it just needed small improvement. This was rather easy.
Then I checked also hwinfo --joystick output, it was fine.

Then I put an old low-end sound (Sound Blaster 128 PCI) with gameport into my PC and connected an old analog joystick. The old YaST joystick module worked fine I and I configured it.

Then I checked hwinfo --joystick output again and the analog joystick was not found. It turned out that the hwinfo code actually could never detect any joystick. So I also added Gameport support and fixed Gameport joystick detection.

So at this point I had working joystick detection, but I wanted to improve it a little bit. I wanted detect and report some joystick properties, like number of buttons and axes it has. This turned out to be similar to mouse button detection which already worked fine. So again not a big problem.

The detection part was ready, then I just added passing joystick details into the yast2-hardware-detection layer so it could be used from YaST.

The most complicated part was the YaST joystick module itself because it supported only gameport joystick and USB joysticks could not be simply added to the UI and also the internal structure had to be completely rewritten.

The Outcome

So what has been changed?

The hwinfo --joystick output will contain all detected joysticks (both USB and Gameport):

The changes are highlighted: it correctly finds the joystick, reports number of axes and buttons, /dev/input/jsX device name is reported, game port joystick is found and for game port joysticks it reports also the sound card to which it is attached to.

The changes in the YaST module are best described by the following screen shots. Let's start with the old YaST module:

The old YaST module with one configured Gameport joystick

When the computer doesn't have any game port the old module displayed just this message although an USB joystick could be attached.

Old joystick test dialog, notice the wrong number of buttons and axes, also using progress bars is not appropriate for this dialog

Here is the new updated YaST module:

Both USB and Gameport joysticks are displayed with more details

The testing dialog has been improved - button and axes detection is correct, sliders are used instead of progress bars and also the joystick name is displayed (usefull when there are more joysticks attached).

This is quite a nice change, isn't it?

As a bonus I have added hotplug handling into the joystick module - if you plug or unplug any USB joystick the table get refreshed. AFAIK that is unique feature among all YaST modules...

All these changes have been submitted to Factory/12.1 and should be available in 12.1-RC1 when released.