Hi all,
I'm working on accessing generic HID devices on Win32 via DirectInput. It's generally going well, but I've hit a snag.
The devices I want to send and receive data to are non-standard devices - that is, they are not keyboards, mice or joysticks. So, I think I need to use SetDataFormat with a custom DIDATAFORMAT structure to define a custom structure for these non-standard devices. I'd expect to iterate through all available objects for the device, get data about each object, and then create a matching data format.
I'm doing just this, but I'm not 100% sure how I should safely create the DIOBJECTDATAFORMAT structures for any potential device object. This is a problem because of the data offsets I am receiving and using.
When iterating through a device's objects with EnumObjects using a dwFlags value of DIDFT_ALL, at least one device I have tested with returns some objects with an offset of 0. Now, I would expect the first object to have an offset of 0, but in this case the 16th and 17th objects did too.
Also, I'm not sure how I'm supposed to tell (for a given object) what the data size of that object is, to use with the dwOfs member of the DIOBJECTDATAFORMAT struct. I though the approach would be to create a DIOBJECTDATAFORMAT struct for every object reported by EnumObjects, but these objects with zero offset have thrown me, as I can't calculate their size by comparing their offset to the offset of the previous object in the enumeration.
So, my question is: what is the recommended way to convert all objects on a HID device into a DIDATAFORMAT for use with SetDataFormat
A couple of extra follow-on questions...
Is the maximum data size I'll ever get back from a call to GetDeviceData a DWORD
Is there a way for me to tell which object has data available for it when I call GetDeviceData I'd assumed that the dwOfs member of the returned DIDEVICEOBJECTDATA would enable me to identify the object in question via its offset in the data format, but the problem mentioned above (multiple objects with an offset of zero) makes me think not.
Any help much appreciated!

Creating custom data structures for HID devices via DirectInput
revati27
But is it wrong to use the native dataformat, i.e. just copiing the information retrieved with the EnumObjects-Callback function
I'm quite confused about this method. Actually it works sometimes and sometimes it does not for no apparent reason.
Hrvoje Zlatar
I think you just need to copy the dwType value, that should uniquely identify the object. Make sure that you're not trying to use objects that have the DIDFT_NODATA bit set. If you do copy the guidType and dwFlags make sure you're copying the guidType value, and that you're not just copying the address of the guidType member. You may need to mask out the non-aspect bits from dwFlags.
Make sure that the values in your custom data format are of the correct size and are properly aligned. All buttons (DIDFT_TGLBUTTON or DIDFT_PSHBUTTON) use BYTE values, and these can be placed at any offset in the structure. Everything else uses DWORD values and these need to be at offset that's a multiple of 4. Each offset in your structure can be used for at most one object, and each object can have at most one offset in your structure.
If you still can't figure out what's wrong, try using the DirectInput debug runtime. It should hopefully print the reason why it's failing in your debugger.
ExcelinLondon
I also copy the GUIDs, dwType and dwFlags from the DIDEVICEOBJECTINSTANCE structure i get from EnumObjects. Somehow this works on my system here but not on another. What else can be done wrong then I mean, the Objectdataformat structure isn't very complex - there are only 4 fields, so there's not very much choice to change something....
BrantCarter
In general, it's impossible to duplicate the native data format that the device sends over the USB wire. You can create a DirectInput data format that contains values for all all the objects you can enumerate, but the data format will be different than the native one. For example, a USB mouse might have a native data format something like this:
Notice how all three buttons are packed into a single byte, and that the relative position data are signed 8-bit values. With DirectInput you can't pack multiple buttons into a single BYTE, each button requires it's own BYTE value, while all other non-boolean values have to be stored in DWORDs. So, a corresponding custom DirectInput data format could be:
Note, the standard DirectInput data format for mouse input is different the from the example I gave above.
Bill Schulz
Hi,
Can anyone help me out with this I've just got my WDDK in the post, and it looks like I need to somehow use HidP_GetData and HidP_SetData to access the Device Object data in more detail by using the lower-level HID API. But I have no idea how.
This page talks about how the DirectInput wDesignatorIndex can be passed to functions in Hidpi.h:
http://msdn.microsoft.com/library/default.asp url=/library/en-us/directx9_c/DIDEVICEOBJECTINSTANCE.asp
...and this page (from the HID docs) talks about the fact that this can happen:
http://msdn.microsoft.com/library/default.asp url=/library/en-us/Hid_d/hh/HID_d/hidclass_fa9f249b-4866-481c-9f7f-c96b19442606.xml.asp
...but I have no idea how the two might link up. Can anyone help
Dave.
Prashant N M
The DIOBJECTDATAFORMAT structures define your own custom data format. It's not supposed to be in the same format as the hardware uses natively. Just create a custom data format that has the objects that both the device supports and your application actually uses. For example, you might use code something like this:
You should also look at the CustomData sample in the DirectX SDK which uses the undocumented DIDFT_OPTIONAL flag to handle optional controls.