|
|
<HTML> <HEAD> <TITLE>Designing HID Gaming Devices for DirectInput</TITLE> </HEAD> <BODY BGCOLOR=#FFFFFF TEXT=#000000 LINK=#000000 VLINK=#808080 ALINK=#000000>
<H2>Designing HID Gaming Devices for DirectInput 5.0x and Beyond</H2>
<ADDRESS> Raymond Chen<br> Microsoft Corporation<br> 4 November 1997 </ADDRESS>
<h3>Abstract</h3>
<p> When designing a game controller compliant with the Human Interface Devices (HID) firmware specification, <!-- version 1.0 --> care should be taken to ensure that the device expresses its capabilities in a manner that applications can exploit. This document briefly outlines issues that should be taken into consideration to allow the device to be used by the widest range of applications across a variety of operating system platforms.
<h3>Definitions</h3>
<p> Since input devices can be oriented in several attitudes, this document will attempt to avoid using terms such as "up" and "left". Instead, compass directions will be used ("north", "west", <i>etc</i>.) For a control mounted on a horizontal surface, "north" is typically represented by motion away from the user. For a control mounted on a vertical surface, "north" is typically represented by motion away from the earth. In general, devices should choose a northerly direction that is intuitively obvious to the user.
<h3>Device Usage and Usage Page</h3>
<p> For DirectInput to recognize a HID game controller as a joystick or gamepad, it must declare its top-level collection as belonging to the Generic Desktop Page (0x01), and deploy usage Joystick (0x04) or Game Pad (0x05), respectively.
<p> Although devices declared otherwise will still be accessible to DirectInput applications which request non-joystick-compatible devices, the vast majority of gaming applications restrict themselves to joystick-compatible input devices.
<h3>Logical and Physical Ranges</h3>
<p> Absolute axes on gaming devices should express their physical ranges entirely with non-negative integers. Historically, calibration information has been expressed in unspecified time units, indicating how long it takes the joystick gameport capacitor to charge after a discharge. Consequently, applications have assumed that calibration values are never negative.
<p> Logical ranges, of course, can indeed be negative. It is recommended that the device translate its logical range by the minimum value, thereby making all physical values non-negative. For example, a joystick might report its X-axis with the logical range -512 to +511. A corresponding physical range of 0 to +1023 would retain full resolution while ensuring that the resulting physical values are non-negative.
<p> It is also recommended that the logical range accurately describes the full range of motion of the control and that the center position of the control lie at the midpoint between the minimum and maximum values. When DirectInput first encounters a device, it uses the logical range information as the basis for the default calibration. If a device conforms to this recommendation, the end-user is relieved of the responsibility of calibration, allowing your device to be truly Plug-and-Play.
<h3>Absolute <i>versus</i> Relative</h3>
<p> Applications assume that all axes on a game controller return absolute coordinates rather than relative coordinates. If a device reports its axes as relative, applications which use DirectInput will receive integrated values, but applications which use the old Multimedia functions to access the device will receive non-integrated deltas and will likely not handle the values properly. Furthermore, even applications which use DirectInput typically do not expect to receive unrestricted values (as would result from integration of a relative control).
<h3>HID and DirectInput</h3>
<p> Beginning with Windows 98 and Windows NT 5.0, DirectInput maps HID usages to its own concept of axis semantics, named X, Y, Z, Rx, Ry, Rz (rotations), and Slider. Again, each application is free to apply arbitrary semantics to each of these axis types.
<p> The following table describes how DirectInput maps HID usages to axis types.
<p align=center> <table border> <tr> <th>Usage Page</th> <th>Usage</th> <th>DirectInput</th> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x30 (X)</td> <td align=center>X</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x31 (Y)</td> <td align=center>Y</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x32 (Z)</td> <td align=center>Z</td> </tr>
<tr> <td>0x02 (Simulation)</td> <td>0xBA (Rudder)</td> <td align=center>Z</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x33 (RX)</td> <td align=center>Rx</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x34 (RY)</td> <td align=center>Ry</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x35 (RZ)</td> <td align=center>Rz</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x36 (Slider)</td> <td align=center>Slider</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x37 (Dial)</td> <td align=center>Slider</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x38 (Wheel)</td> <td align=center>Slider</td> </tr>
<tr> <td>0x02 (Simulation)</td> <td>0xBB (Throttle)</td> <td align=center>Slider</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x39 (Hatswitch)</td> <td align=center>POV</td> </tr>
<tr> <td>0x09 (Button)</td> <td>any</td> <td align=center>Buttons</td> </tr>
<tr> <td>any</td> <td>any (see below)</td> <td align=center>Buttons</td> </tr>
</table></p>
<p> DirectInput treats any usage on any usage page with bit size of unity as a button. Furthermore, any usage on the Button page is treated as a button, even if its bit size is greater than unity. Under such conditions, DirectInput treats the button as a "button with intermediate positions". Such a button can report to the application states such as "half-pressed".
<p> DirectInput does not limit the number of usages that can map to each type of axis. Applications designed for DirectInput typically request up to 128 buttons, four POV's, two sliders, and one each of X, Y, Z, Rx, Ry, and Rz.
<p> X and Y axes must report their values as increasing east and south, respectively. This requirement is in agreement with the HID specification.
<p> Hat Switch controls must report a Null value when not pressed. When pressed, the logical minimum value represents north, and increasing logical values represent directions equally spaced clockwise around the compass. For example, the following two tables describe two different types of Hat Switches, one with eight positions and one with four positions.
<p align=center> <table border>
<tr> <th>Value</th> <th>8-direction</th> <th>4-direction</th> </tr>
<tr> <td>Logical Minimum</td> <td align=right>0</td> <td align=right>0</td> </tr>
<tr> <td>Logical Maximum</td> <td align=right>7</td> <td align=right>3</td> </tr>
<tr> <td>Null value</td> <td align=right>-1</td> <td align=right>-1</td> </tr>
<tr> <td>North</td> <td align=right>0</td> <td align=right>0</td> </tr>
<tr> <td>Northeast</td> <td align=right>1</td> <td align=right>N/A</td> </tr>
<tr> <td>East</td> <td align=right>2</td> <td align=right>1</td> </tr>
<tr> <td>Southeast</td> <td align=right>3</td> <td align=right>N/A</td> </tr>
<tr> <td>South</td> <td align=right>4</td> <td align=right>2</td> </tr>
<tr> <td>Southwest</td> <td align=right>5</td> <td align=right>N/A</td> </tr>
<tr> <td>West</td> <td align=right>6</td> <td align=right>3</td> </tr>
<tr> <td>Northwest</td> <td align=right>7</td> <td align=right>N/A</td> </tr>
</table></p>
<p> Devices are strongly recommended not to report logical ranges with higher resolution than physically supported by the device. For example, a device whose Hat Switch supports four compass directions could in principle report itself as if it were an 8-direction Hat Switch. However, devices which do so will mislead applications into believing that the control supports a higher degree of resolution than it actually does. (DirectInput provides a method for applications to query the resolution of a hat switch, and DirectInput relies on the accuracy of the values in the report descriptor to report the resolution accurately.)
<p> DirectInput requires that the Hat Switch reside in its own capability descriptor. Do not combine the Hat Switch capability with capabilities for adjacent usages (Wheel and Counted Buffer).
<p> Although usages not listed in the above table will still be accessible via DirectInput, few game applications will take advantage of their existence.
<h3>HID and Legacy Game Controller API's in Windows 98</h3>
<p> In Windows 98, the HID-to-legacy mapper (JoyHID.VxD) maps HID usages to the "classical" joystick axes, named X, Y, Z, R, U, and V. Each application is free to apply arbitrary semantics to each of these axes, although the X and Y axes are customarily used for two-dimensional motion control, and the R control is customarily as a rudder. The Z control is often used as a throttle.
<p> (The issue of allowing applications to assign semantics to controls in an intelligent manner is the subject of a separate document.)
<p> The following table describes how JOYHID maps HID usages to "classical" joystick axes, buttons, and POV controllers.
<p align=center> <table border> <tr> <th>Usage Page</th> <th>Usage</th> <th>JoyHID.VxD</th> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x30 (X)</td> <td align=center>X</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x31 (Y)</td> <td align=center>Y</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x32 (Z)</td> <td align=center>Z</td> </tr>
<tr> <td>0x02 (Simulation)</td> <td>0xBB (Throttle)</td> <td align=center>Z or U</td> </tr>
<tr> <td>0x02 (Simulation)</td> <td>0xBA (Rudder)</td> <td align=center>R</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x35 (RZ)</td> <td align=center>R</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x36 (Slider)</td> <td align=center>U</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x37 (Dial)</td> <td align=center>U</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x33 (RX)</td> <td align=center>V</td> </tr>
<tr> <td>0x09 (Button)</td> <td>any</td> <td align=center>Buttons</td> </tr>
<tr> <td>0x01 (Generic)</td> <td>0x39 (Hatswitch)</td> <td align=center>POV</td> </tr>
</table></p>
<p> If more than one control can map to an axis or button or POV, then the first one on the list is used and the others are ignored. For example, if a joystick has both a slider and a dial, then the slider will be mapped to classical axis U, and the dial will be ignored.
<p> As a special case, a throttle will be mapped to the Z-axis unless the Z-axis has already been claimed by the Z control, in which case it will be mapped to the U-axis. (In such case, the throttle will displace any slider or dial that would otherwise be mapped to the U-axis.)
<p> For buttons, all usages reported on the Button page (0x09) will be reported, but they must be consecutively numbered starting from zero.
<p> The requirements on X-axis, Y-axis, and Hat Switch controls which apply to DirectInput also apply here.
<p> Any usages that do not appear in the above table are ignored by JoyHID.VxD.
<h3>References</h3>
<p> <cite> <a href=http://www.usb.org/>Universal Serial Bus</a> HID Usage Tables</cite>, Version 1.0, USB Implementers Forum.
<p> <cite> <a href=http://www.microsoft.com/directx/resources/dx5ddk.htm> DirectX 5.0 DDK</a> </cite>, Microsoft Corporation.
<p> <cite> <a href=http://www.microsoft.com/directx/resources/dx5sdk.htm> DirectX 5.0 SDK</a> </cite>, Microsoft Corporation.
</BODY> </HTML>
|