XInput and HID - architecture

Roderick Colenbrander thunderbird2k at gmail.com
Mon Mar 21 19:27:39 CDT 2016


On Sat, Mar 19, 2016 at 10:59 AM, Juan Jose Gonzalez <juanj.gh at gmail.com> wrote:
> Hi,
>
> On 03/16/2016 02:45 AM, Roderick Colenbrander wrote:
>> Hi Juan,
>>
>> Let me reply to the start of the thread before diving into the
>> specifics on calibration.
>>
>> In my opinion, I'm not sure what the best way would be to handle
>> passing of HID data to xinput. The main thing to consider as part of
>> this is handling of non-native xinput devices (e.g. DS4 or
>> SteamController) provided we want to support this. Aside from passing
>> up the HID data the other challenge for xinput devices is the
>> enumeration part, which many (older) games do through a mixture of
>> WMI, dinput and xinput. For this to work we need to report an actual
>> xinput gamepad.
> Wine is supposed to mimic Windows' behavior as well as possible. Thus,
> the proper way to implement xinput would be to access the USB devices
> directly. The hid->xinput mapping is already non-compliant with the
> windows behavior, but currently necessary. However, in my opinion, we
> should only try to parse those HID descriptors that correspond to XInput
> devices, as provided by common XInput->HID drivers on different host
> OSs. Nevertheless, once wine's HID->Xinput backend is finished, the
> end-users can (locally) add their own mappings for any HID controller
> they want to use. I just wouldn't add those mappings to the wine repo.
> I would like to get some input on that, however. Do you think we should
> add mappings for non-xinput devices?
>
> Thank you for pointing out the enumeration process. The reason I
> implemented Xinput was to play a game that didn't support any other
> input method, so until now, I hadn't given it much thought. According to
> https://msdn.microsoft.com/en-us/library/windows/desktop/ee417014%28v=vs.85%29.aspx
> , an XInput device shows up in DInput with an ID containing "IG_", which
> is what developers should use to filter them out. This might make things
> a bit difficult, since in Wine, both DInput and XInput devices are
> supposed to be created from a common HID base, so Wine's DInput cannot
> know anything about whether a device is an XInput device or not.
>>
>> My feeling would be for xinput to be quite stupid like it is on
>> Windows and feed it xbox controller compatible HID reports with the
>> same axes ranges, rumble ranges as the xbox controller. For more
>> custom devices you may want to support special handling e.g. button
>> emulation using touchpad on DS4 or maybe even on SteamController.
> The problem is that there is not a unique HID descriptor set for XInput.
> Each driver on each OS maps the xinput controls to a different layout,
> so we need some logic on the Wine XInput driver to tell those apart and
> map them back to XInput controls.

Nonetheless a mapping is needed from evdev, optionally Linux hidraw
and whatever backend other OSes use. HID is nice in theory, but in
practice it is quite messy (many buggy devices, spec abuses, custom
HID requests to enable a device..). My feeling is to handle the
mapping to x360 at a level below xinput to avoid the mapping issues in
xinput. Depending on what other non-native xinput devices we may want
to handle (ds3, ds4, wii u controller, steam controller are all easy)
you may want more control at a lower level to handle custom
functionality, which could optionally need handling through many
different fields in the HID descriptor (e.g. touch).

>>
>> As you have seen the xbox controller lacks proper HID descriptors and
>> on Windows the drivers fake descriptors to allow DirectInput to work
>> as well. We would be doing something not to different. For the
>> DirectInput I would report the real device name and the real ranges,
>> similar if games use raw input (not sure if there are games which do
>> this).
> On Wine, this would work the other way around. We would have raw (HID)
> devices as a base, and create DInput and XInput devices from those.

I understand that part. What I meant is that Windows reports 2
different devices one with HID and one without. I was suggesting this
as a way to potentially handle non-native xinput devices, e.g. the
non-native device is made to appear like the xbox one on windows with
the missing descriptors etcetera. Though this still wouldn't handle
the enumeration situation for apps using wmi.

>
> - Juan
>> Thanks,
>> Roderick
>>
>>
>>
>>
>> On Thu, Mar 3, 2016 at 12:39 AM, Juan Jose Gonzalez <juanj.gh at gmail.com> wrote:
>>> Hi,
>>>
>>> I got a bit stuck and would like to hear your opinion on the XInput HID
>>> backend, specifically on the mappings, i.e. the code that "accepts" a
>>> certain device based on its properties and then maps its buttons and axes to
>>> XInput buttons and axes.
>>>
>>> As long as the mappings are fixed, i.e. are not supposed to be extended or
>>> edited by the user, everything can be compiled into xinput1_3.dll. However,
>>> I would like to provide a "xinput.cpl" control panel node for xinput similar
>>> to "joy.cpl", where the user can not only test the XInput gamepads, but also
>>> manage the XInput-HID backend mappings. The first part can be accomplished
>>> by using xinput1_3.dll. However, in order to load and persist different
>>> mappings, the second part requires access to the functions that serialize
>>> and deserialize the mappings. It also needs some way of getting raw
>>> capabilities and changes in HID devices in order to be able to create new
>>> mappings.
>>>
>>> Here are some possible ways of solving it:
>>>
>>> Extend xinput1_3.dll with the required management functions and add a
>>> "wine/xinput_hid_mgmt.h" or similar header that declares those methods.
>>> xinput.cpl could then simply use xinput1_3.dll to perform all management
>>> functions. I'm not sure if this would break anything due to the additional
>>> exports in the dll.
>>> Extract the mapping load and store logic into a separate "xinputhid.dll" or
>>> similar. I this case both xinput1_3.dll and xinput.cpl would access this
>>> library to load and store mappings.
>>> Move the xinput core and backends into a driver and let xinput1_3.dll access
>>> it via IOCTLs. I believe this is the way it works on windows, although there
>>> doesn't seem to be any freely available documentation regarding the internal
>>> architecture. The XInput-HID backend could then create its own kernel object
>>> as a management interface, which could be accessed by xinput.cpl. This would
>>> have the added effect of having a single instance managing the xinput
>>> devices if several programs are running at the same time, which mimics the
>>> behavior of windows.
>>>
>>> What do you think would be the best option? Is there another way I haven't
>>> mentioned?
>>>
>>> - Juan
>>>
>>>
>>>
>>>
>



More information about the wine-devel mailing list