Another thing that I have recently implemented is a USBGamepad class. It's very similar to other previously described HID devices. Let's take a look at report descriptor:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
reportDesc.usagePage(ReportDescriptor.PAGE_GENERIC_DESKTOP); | |
reportDesc.usage(GenericDesktopPage.GAMEPAD); | |
reportDesc.collection(ReportDescriptor.COLLECTION_APPLICATION); | |
reportDesc.collection(ReportDescriptor.COLLECTION_PHYSICAL); | |
reportDesc.reportId(1); | |
//buttons | |
reportDesc.usagePage(ReportDescriptor.PAGE_BUTTON); | |
reportDesc.usageMinimum(1); | |
reportDesc.usageMaximum(16); | |
reportDesc.logicalMinimum(0); | |
reportDesc.logicalMaximum(1); | |
reportDesc.reportCount(16); | |
reportDesc.reportSize(1); | |
reportDesc.input(ReportDescriptor.DATA | ReportDescriptor.VARIABLE | ReportDescriptor.ABSOLUTE); | |
//axis | |
reportDesc.usagePage(ReportDescriptor.PAGE_GENERIC_DESKTOP); | |
reportDesc.usage(GenericDesktopPage.X); | |
reportDesc.usage(GenericDesktopPage.Y); | |
reportDesc.usage(GenericDesktopPage.Z); | |
reportDesc.usage(GenericDesktopPage.rX); | |
reportDesc.logicalMinimum(-127); | |
reportDesc.logicalMaximum(127); | |
reportDesc.reportSize(8); | |
reportDesc.reportCount(4); | |
reportDesc.input(ReportDescriptor.DATA | ReportDescriptor.VARIABLE | ReportDescriptor.ABSOLUTE); | |
reportDesc.collectionEnd(); | |
reportDesc.collectionEnd(); |
As you can see, my gamepad implementation supports up to 16 buttons and 4 axes. First byte of USB report is always set to 1 (report ID), next two bytes are an array containing data about state of buttons, followed by 4 bytes, one for each axis. Endpoint 1 has polling interval set to 8 ms in order to reduce latency, what is very important in case of a gamepad device. There are following methods offered by this class:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public synchronized void setButton(int button, boolean state); | |
public synchronized void setAxis(int axis, byte value); | |
public synchronized void sendReport(); |
In order to demonstrate USBGamepad class in action I have prepared simple GamepadDemo app. As you can see there are 8 buttons (multi-touch is supported). Data for X and Y axes is gathered from accelerometer, Z and rX axes are not used. Application sends data every 25 ms, but I guess any interval greater than 8 ms (endpoint polling interval) should be ok.
![]() |
GamepadDemo app. |
![]() |
Devices and Printers |
On the screen above you can see that Windows sees InputStick as a USB game controller device. I didn't check this class on any other operating system beside Windows, but if a physical gamepad is supported, then InputStick will also work.
Here's a video of me playing GRID with my phone as a controller (it's a bit difficult to steer when you have camera between yourself and phone) :
No comments:
Post a Comment