SlimDX: Joystick.Poll() succeeds on disconnected gamepad
Asked Answered
E

2

1

I've got a curious problem with SlimDX: we've seen this on Windows 7, and haven't yet tested other versions: I'm using a bundle of cheap USB gamepads (no serial number), and sometimes one physical gamepad ends up providing the input to more than one Joystick object.

The scenario is:

  1. Plug in gamepad 1 to hub slot 1. Pad appears in DirectInput.GetDevices as GUID f17b2d30. Create Joystick object for pad.
  2. Plug in gamepad 2 to hub slot 2. Pad appears in DirectInput.GetDevices as GUID 5187d2d0. Create Joystick object for pad.
  3. Press a button on gamepad 2. No change to state.
  4. Press a button on gamepad 1. Button appears set in GetCurrentState() after Poll() on both objects.
  5. Unplug gamepad 2. Poll() method on its object continues to return without error, but it no longer appears in DirectInput.GetDevices.
  6. Press a button on gamepad 1. Button appears set in GetCurrentState() after Poll() on both objects.

I've examined the objects in the debugger. Each Joystick references the correct GUID by Information.InstanceGUID, but each has the same USB path in Properties.InterfacePath.

The gamepad hardware seems to be working correctly - If I perform the same sequence with the control panel joystick tester the gamepads remain distinct.

The DirectInput GUIDs seem to be allocated based on the USB PID and VID, then the order the identical gamepads are plugged in, rather than the physical path to USB port they're plugged in to. If I mix different models of gamepad, the problem goes away.

It feels like a SlimDX or even a DirectInput bug - is there a workaround for this?

Elise answered 27/9, 2012 at 10:33 Comment(1)
directinput definitely has a bug. Sometimes my controller shows up as controller 2 even though I only have one, and it's an official xbox 360 controller.Simulator
E
5

My final answer here was to drop DirectInput altogether, and move to RawInput. I implemented a small C DLL to interface between my C# code and RawInput.

I've had two limitations: trouble finding device names, and a crash reading device information under XP. Neither of these are a critical problem for my application.

Sample C++ source code is a bit long to fit in an answer, so is here.

Calling from C# uses these signatures:

    [DllImport("Adapters.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern int InitialiseGamepads(IntPtr hwnd);
    [DllImport("Adapters.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern IntPtr GetDevicePath(int index);
    [DllImport("Adapters.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern int PollDeviceChange();
    [DllImport("Adapters.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern int ProcessInput(IntPtr wParam, IntPtr lParam,
        out byte buttons, out int x, out int y);
Elise answered 20/10, 2012 at 13:33 Comment(6)
Thanks ! Could you share Adapters.dll ?Helio
@Jean-PhilippeEncausse The source is in the pastebin link in the answer - I can't distribute the binary at the moment, and I recommend compiling it into a C++ DLL project.Elise
@Adrian Cox, Last night I compiled successfully your Adapters.dll C++ project with Visual Studio 2013. Today, I tested your method ProcessInput() and I found it returns x = 0 by referece no matter how vigorously I exercise the CH Products VM Desktop joystick, Could you tell me the reason for that observed behavior? Thank you.Garvy
@Garvy I haven't got that joystick, but it's possible that it's returning your x coordinate as a different usage value. For debugging I recommend you start with the returns from HidP_GetUsageValue and look for any that vary as you move the joystick. I was only dealing with simple two-axis digital gamepads, and more complex sticks may behave differently.Elise
@Adrian Cox, How were you able to compile and link Adapters.dll using Microsoft Visual Studio 2013 C++ compiler? Specifically, what include files , include file paths and linker library names and paths did you use. Also, I found and corrected at least 4 compile and runtime errors in the source code in your pastebin link. Would you be interested in reading my changes?Garvy
@Garvy I actually used the VS2010 compilers - I'm interested in seeing the changes, but I'm no longer working on the application this was developed for.Elise
R
-5

I think, you should use:

Joystick joy;
string UniquePathForEachJoystick = joy.Properties.InterfacePath.ToString();
Raising answered 10/3, 2015 at 3:24 Comment(1)
Care to explain why that would help the original problem?Repetend

© 2022 - 2024 — McMap. All rights reserved.