Posted on May 14, 2014

Accessing joysticks and other USB input devices is very difficult to do from a browser. Over the last few years there have been efforts to improve the situation my means of the Gamepad API. However, it has been under development for a long time and makes very little progress. Besides Gamepad API is painfully narrow of scope as the name suggests. This is very strange because there already is a fantastic standard called "Human Interface Device" or HID for short. It is suprising that there is no API proposal that seeks to implement access at HID level.

With the HID server I hope to change that. The HID server is a http server running on windows which acts as the link between a browser and the HID devices connected to your computer. It uses JSON-P to get across domains. At this stage it is only capable to send raw HID input data but at a later stage it will also be able to apply meaning to the data using the HID device descriptors

The solution is based around Delphi code written by Robert Marquardt at Softgems

The screenshot above shows the HID server running. It dynamically maintains a list of HID devices detected on your PC. In the browser I am able to request the device list. Select a device and start receiving the input data for that device. In the picture a cheap Genius joystick device is selected and you can see the raw input data for that device displayed in the left column. The server is simply run on a windows PC and requires no installation or configuration as it is addressed as localhost. It is however perfectly possible to have multiple browsers query the same input device

How it looks on the browser

On the browser things could not be easier. I write a hidServer class in Javascript that will handle all the communication with the HID Server and all the programmer needs to do is make calls to this javascript object. For example, to get a device list:

var hidserver = new hidServer('http://localhost:7777');

hidserver.getDeviceList(function(data){
	alert(data.devices);
});

Devices are selected by name. So in order to select your preferred joystick. Code to select the first device in the list would look like this:

var hidserver = new hidServer('http://localhost:7777');

hidserver.getDeviceList(function(data){
	hidserver.selectDevice(data.devices[0]);
});

Or if you know the device name already. Simply:

hidserver.selectDevice('SideWinder Force Feedback 2 Joystick');

You can verify this because in the HID server you will see the selected item in the device list change.

In order to read data from the HID device every 60 milli seconds, you do this:

hidserver.pollServer(60, function(data){
	console.log(data)
});

This will return the raw HID input data in JSON format

{"bytes":[143,1,175,0,0,0,8,0,170,1,172,1]}

The data is raw at this stage. This means that you as a developer need to make sense of the bytes returned by the device. A cheap joystick is likely to send one axis as a single byte but there are other joysticks that return data in chunks of 10 bit which can get fiddly to figure out. Therefore the current solution is only good for a specific device and needs further improvement.

Demo. Try it out!

You will only see an empty dropdown list and white text that says "Data" but download and run the HID server and you should see the device input data change in real-time underneath.Select the device and you will see the data immediately. Make your own implementations and grab this javascript to talk to the HID Server

Devices
Select Result:

Data

What's next

At this point it is cool to see raw number change but a lot more work needs to be done in order to apply meaning to these changing bytes. HID devices carry what is called a HID descriptor. This data is baked into the hardware and can be read out. You can use the HID descriptor to figure out what the fourth bit in the third byte is really used for. This is essential if you want to make your application read out the X and Y coordinate for every joystick out there.

HID descriptors are hard to parse. So although I think the HID server should pass a HID descriptor, it should probably apply these and produce a more consistent and easier to use data stream. I am a bit stuck because I have not managed to understand how HID descriptors work. Any help would be more then welcome

HID devices are bi-directional. This means that it is also possible to define output data and send this to the device. Turn on an LED on your Space Navigator or provide force feedback on your steering wheel. None of this is implemented yet and totally possible.

What about OSX and Linux?

Sort answer, I don't care, I don't use either. But this can be turned into open source if there is interest for it. But ultimately, there should be a HID API specification for browsers that will supercede narrow scoped part solutions such as Gamepad API and Pointer Lock for mice.

Titles

©2009 All Rights Reserved  •  by PlanetInAction.com