XInput and HID - architecture

Juan Jose Gonzalez juanj.gh at gmail.com
Thu Mar 3 09:10:12 CST 2016


On 03/03/2016 03:15 PM, Aric Stewart wrote:
> On 3/3/16 7:52 AM, Juan Jose Gonzalez wrote:
>> Thanks for your input.
>>
>> On 03/03/2016 02:14 PM, Aric Stewart wrote:
>>> The registry?
>>>
>>> Would you be able to load mappings from the registry?
>> Sorry, I should have mentioned that. I was planning on storing the
>> mappings in the registry in all three proposed solutions. My question
>> was where to put the code that does the serialization and deserialization.
> Why store the mapping serialized?  I think it would be far better to have the mapping be very clear and user editable in the registry. 
>
> Something like, this is just off the top of my head...
>
> HKCU/Software/wine/Xinput/mapping/<VIDPID>/BTN_A
> Page=0x9
> Usage=0x1
> Released=0x0
> Pressed=0x7fff
> Logic="VAL_TO_BTN_GT_ZERO"
>
> HKCU/Software/wine/Xinput/mapping/<VIDPID>/BTN_B
> Page=0x9
> Usage=0x2
> Released=0x0
> Pressed=0x7fff
> Logic="VAL_TO_BTN_GT_ZERO"
>
> HKCU/Software/wine/Xinput/mapping/<VIDPID>/LTHUMB_X
> Page=0x1
> Usage=0x30
> Inverted=0
>
> HKCU/Software/wine/Xinput/mapping/<VIDPID>/LTHUMB_Y
> Page=0x1
> Usage=0x31
> Inverted=1
The axis/button mappings themselves are pretty easy to do with simple
registry keys. The matching mechanism, however, is more complex. VID/PID
isn't enough here, since the same VID and PID might need completely
different mappings depending on which system you are on and even which
driver you are using to emulate a HID device from an xbox controller.
I've implemented a hierarchical structure which allows composite matches
like the following:
AND(VID = 0x45e, OR(PID = 0x28e, PID = ...), OR(Version = 0x110, ...),
OR(NAME="Microsoft X-Box 360 pad", NAME="Microsoft X-Box 360 wireless
pad"), HASUSAGE(0x01, 0x09, 0x30), ...)).
Storing that in the registry in clear text is doable, but it seems like
a bit of overhead to fill the registry with that. On the other hand, I
have to admit it also feels weird to store configs as binary blobs in
the registry.

I'll implement the clear text serializer/deserializer and see how a
mapping looks for a real controller. I may be picturing it worse than it is.
>
> Then a complete mapping would be required to have all the elements defined. And it would just be the process of loading the values from the registry to build your mapping. 
>
> I think that would be much cleaner than trying to store serialized mappings into the registry. 
>
> It also may be my imagination but I could have sworn that a linux user once told me that there is a big database of gamepad mapping for xbox controllers somewhere out there. If that does actually exist it would be convenient to be able to access that.
For linux, there aren't many driver choices (I'm aware of), so we can
simply take a look at the xpad module's and xboxdrv's source code. I
don't know where to look for default mappings for the available OSX drivers.
>
> We do some mapping like this for dinput on linux already where in HKCU\Software\Wine\DirectInput you can setup <joystick name> = <axes mapping>
>
> (https://wiki.winehq.org/Useful_Registry_Keys)
>
> I think that would be insufficient for what you need, but has the spirit of what I feel like we should do.
>
> -aric
There's still the problem with where to put the
serialization/deserialization code. While xinput itself only needs to
read the mappings, the config tool needs to be able to read, alter and
write them, so we need to at least make the deserialization logic
accessible to both modules. Especially for a text serializer, that is
definitely not something we would want to duplicate.

>
>>> Then you could have a .cpl that allows a user to produce mappings for their controller, likely tagged by VendorId and ProductId, and then Xinput can load those mappings from the registry.
>>>
>>> I think that is the cleanest and easiest way to store those. I would say something in HKCU/Software/wine/Xinput.
>>> I would venture so far as to say that even the default mapping for the Xbox controller could be maintained there, so that the default mapping can be overridden, because it is likely that the xbox controller on the Mac and the xbox controller on Linux may have different controller mappings, and on mac it may even vary based on what xbox controller driver the user has installed, though there is a single prominent one that most people have.
>> I planned to do binary serialization/deserialization, so manually
>> creating registry entries would be a bit difficult. The idea was to ship
>> some default mappings defined in the code and compiled into xinput, and
>> allow new mappings and overrides from the registry. Those would have to
>> be created with a tool (xinput.cpl). Of course, that tool can also be
>> used to define the default mappings, we'd just have to get the generated
>> binary blob into wine.
>>> So this would be your option 2, using the windows registry as the separate logic.
>> The problem is that I need somewhere to put the code that does the
>> serialization/deserialization. It's quite simple as long as the
>> configuration can be stored as a binary blob, but it's still not
>> trivial. If possible, I would like to avoid duplicating the code, hence
>> the need for a common module.
>>> -aric
>>>
>>> On 3/3/16 2:39 AM, Juan Jose Gonzalez 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
>>>>
>> - Juan
>>




More information about the wine-devel mailing list