XInput and DirectInput

Hello everyone,

I know this is a question from almost the beggining of the series, but since I haven't seen the topic I need to do it.

I want to know why are we using XInput that is only compatible with XBox controllers, instead of DirectInput that can work with other type of controllers?

It's because it's easier, or there is another hidden or more powerful reason for this, like other brands following the XBox standard in the new controllers?

I'm beggining the series so I don't know if that is covered ahead in the future. But from the titles I don't see it.
Because it´s easier for PC development for any machine with Windows.

Casys will adress support for other APIs later.

Edited by ThadeuMelo on
As far as I know the biggest difference is that with DirectInput on Xbox controller left and right triggers return value as single axis (as difference between triggers). For XInput those are two separate values.

Some other DirectInput disadvantages for Xbox controllers (not that these are relevant for Handmade Hero):
* not possible to query what audio device id should be used for specific controller
* no vibration effects

Edited by Mārtiņš Možeiko on
Yes, if you want to support XBox controllers you pretty much have to use XInput - DirectInput does not support all the features you want. So, if you want to support most joysticks properly, you end up implementing both. For now, we only need one for testing, so I did the most straightforward one (XInput). But when it comes time to ship we will probably implement DirectInput, assuming people are still commonly using joysticks that require it.

- Casey
Another option would be to use Raw Input API to read Joystick info and not use DirectInput and XInput at all. Afaik DirectInput and XInput both use Raw Input internally. But using Raw Input would require more code, because you would need to parse out Joystick data yourself. Here's example if somebody is interested.
The reason I don't think raw input is an option is because I don't know of any way to send vibration control out to the joysticks if you do it that way :(

Ideally, all of this would go away and you could just use the HID page stuff directly. That would be the best thing. But unfortunately I don't know if you can ever actually do that because I think the USB drivers for the controllers usurp that and there's nothing you can do about that directly :(

- Casey
You can control vibration by sending HID page stuff back to joystick.
I have PS4 controller, and I just now tried running example code from here http://stackoverflow.com/a/27437973 (yes SO) and it works fine. I can control vibration intensity just fine. It gets HID device ID from Raw Input API and then simply writes raw byte buffer with WriteFile to this device. I can even control light color :)

Of course, this means that to support vibration for specific joystick you'll need to correctly prepare HID buffer to send.
Not sure how documented that is. It's possible to find some information on Internet about it, but that is not very official. Most useful one is from Linux drivers people have written:
PS4: https://github.com/chrippa/ds4drv/blob/master/ds4drv/device.py#L117
PS3: https://github.com/ros-drivers/jo...s3joy/scripts/ps3joy_node.py#L274
Xbox controllers:
https://github.com/Grumbel/xboxdr...roller/xbox360_controller.cpp#L93
https://github.com/Grumbel/xboxdr...ox360_wireless_controller.cpp#L57
https://github.com/Grumbel/xboxdr...ontroller/xbox_controller.cpp#L50

It could be that you can get some information about output features device supports automatically using HID API (HidP_GetCaps & friends) - this is what that Raw Input API sample from CodeProject in my previous post uses. And then you won't need to hardcode HID buffers. I guess HidP_SetUsageValue function is meant for that. But I'm not an expert on HID, I'm not sure how to use it.
Wow, I'm amazed for the speed and quality of the answers. Thank you all.
Wait, does that actually work? Because I tried opening the XBox controllers as HID devices before on my own, and it would not allow me to do it, I assumed because the devices were already opened in some exclusive mode by the XBox Controller Thingee(TM) or whatever it is that drives XInput and those annoying pop-ups that it does. So has someone actually conclusively demonstrated that you can reliably open them as HID devices on everyone's system? Because that would be awesome...

- Casey
Ah, there may be difference between Xbox and PS controller. I've tried it only with PS4 controller - connected with bluetooth or with usb. And that works fine.

I'll try to get Xbox controller and check if this is also possible with Xbox controllers.
So I tried this with Xbox360 controller. I can read all input correctly, but it doesn't respond to any output (setting vibration). Its not that it gives error or permission denied or something. I can successfully communicate with controller using ReadFile/WriteFile functions or RawInput api (although format it reports buttons and stick values is very strange, completely different what's in Linux source). But it simply doesn't respond to any output request. Very strange. My guess is that Windows xbox controller drivers are doing something fishy here. Because by sending same bytes on Linux I can get vibration working without any issues.

So currently it seems that XInput is best option for Xbox controllers on Windows.
That was my experience as well, although I seem to recall _not_ being able to open it for write access _at all_, but maybe that was something I was not setting correctly.

- Casey