XInput and HID - architecture

Aric Stewart aric at codeweavers.com
Tue Mar 22 07:35:18 CDT 2016


On 3/21/16 7:27 PM, Roderick Colenbrander wrote:
> 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).
> 

The grand hope is that we can move all the platform specific code to HID and not have it reproduces in 3 different locations. We write dinput, winmm and Xinput to all be HID clients.

You give a number of reasons that HID is messy, but I assume you are talking about windows native HID? Since right now we would be going through our own hid and hid minidrivers we are able to avoid a lot of that messiness.

What are the specific areas that HID will be insufficient for xinput? Having specific examples will be helpful in figuring out a course of action.


>>>
>>> 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.

Can we just have the minidrivers for evdev / OSX / hidraw implement this? Do you have specs on what things they would need to report? What are the missing descriptors?

thanks!
-aric

> 
>>
>> - 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