[Win] Correct joystick GUID generation

Joystick GUIDs now match SDL2/DirectInput for USB devices. (Bluetooth
devices still need to be tested.)
This commit is contained in:
thefiddler 2014-09-02 22:12:13 +02:00
parent ec37a9a16d
commit 388acee32a

View file

@ -243,8 +243,8 @@ namespace OpenTK.Platform.Windows
// because it is costly to query (and we need to query // because it is costly to query (and we need to query
// that every time we process a device event.) // that every time we process a device event.)
IntPtr handle = dev.Device; IntPtr handle = dev.Device;
bool is_xinput; bool is_xinput = IsXInput(handle);
Guid guid = GetDeviceGuid(handle, out is_xinput); Guid guid = GetDeviceGuid(handle);
long hardware_id = handle.ToInt64(); long hardware_id = handle.ToInt64();
Device device = Devices.FromHardwareId(hardware_id); Device device = Devices.FromHardwareId(hardware_id);
@ -499,7 +499,8 @@ namespace OpenTK.Platform.Windows
switch (page) switch (page)
{ {
case HIDPage.GenericDesktop: case HIDPage.GenericDesktop:
switch ((HIDUsageGD)stick.AxisCaps[i].NotRange.Usage) HIDUsageGD gd_usage = (HIDUsageGD)stick.AxisCaps[i].NotRange.Usage;
switch (gd_usage)
{ {
case HIDUsageGD.X: case HIDUsageGD.X:
case HIDUsageGD.Y: case HIDUsageGD.Y:
@ -522,6 +523,11 @@ namespace OpenTK.Platform.Windows
page, (HIDUsageGD)stick.AxisCaps[i].NotRange.Usage); page, (HIDUsageGD)stick.AxisCaps[i].NotRange.Usage);
stick.SetHat(collection, page, stick.AxisCaps[i].NotRange.Usage, HatPosition.Centered); stick.SetHat(collection, page, stick.AxisCaps[i].NotRange.Usage, HatPosition.Centered);
break; break;
default:
Debug.Print("Unknown usage {0} for page {1}",
gd_usage, page);
break;
} }
break; break;
@ -537,6 +543,10 @@ namespace OpenTK.Platform.Windows
break; break;
} }
break; break;
default:
Debug.Print("Unknown page {0}", page);
break;
} }
} }
@ -642,12 +652,41 @@ namespace OpenTK.Platform.Windows
return true; return true;
} }
// Retrieves the GUID of a device, which is stored // Get a DirectInput-compatible Guid
// in the last part of the DEVICENAME string // (equivalent to DIDEVICEINSTANCE guidProduct field)
Guid GetDeviceGuid(IntPtr handle, out bool is_xinput) Guid GetDeviceGuid(IntPtr handle)
{ {
is_xinput = false; // Retrieve a RID_DEVICE_INFO struct which contains the VID and PID
Guid guid = new Guid(); RawInputDeviceInfo info = new RawInputDeviceInfo();
int size = info.Size;
if (Functions.GetRawInputDeviceInfo(handle, RawInputDeviceInfoEnum.DEVICEINFO, info, ref size) < 0)
{
Debug.Print("[WinRawJoystick] Functions.GetRawInputDeviceInfo(DEVICEINFO) failed with error {0}",
Marshal.GetLastWin32Error());
return Guid.Empty;
}
// Todo: this Guid format is only valid for USB joysticks.
// Bluetooth devices, such as OUYA controllers, have a totally
// different PID/VID format in DirectInput.
// Do we need to use the same guid or could we simply use PID/VID
// there too? (Test with an OUYA controller.)
int vid = info.Device.HID.VendorId;
int pid = info.Device.HID.ProductId;
return new Guid(
(pid << 16) | vid,
0, 0,
0, 0,
(byte)'P', (byte)'I', (byte)'D',
(byte)'V', (byte)'I', (byte)'D');
}
// Checks whether this is an XInput device.
// XInput devices should be handled through
// the XInput API.
bool IsXInput(IntPtr handle)
{
bool is_xinput = false;
unsafe unsafe
{ {
@ -658,7 +697,7 @@ namespace OpenTK.Platform.Windows
{ {
Debug.Print("[WinRawJoystick] Functions.GetRawInputDeviceInfo(DEVICENAME) failed with error {0}", Debug.Print("[WinRawJoystick] Functions.GetRawInputDeviceInfo(DEVICENAME) failed with error {0}",
Marshal.GetLastWin32Error()); Marshal.GetLastWin32Error());
return guid; return is_xinput;
} }
// Allocate memory and retrieve the DEVICENAME string // Allocate memory and retrieve the DEVICENAME string
@ -667,7 +706,7 @@ namespace OpenTK.Platform.Windows
{ {
Debug.Print("[WinRawJoystick] Functions.GetRawInputDeviceInfo(DEVICENAME) failed with error {0}", Debug.Print("[WinRawJoystick] Functions.GetRawInputDeviceInfo(DEVICENAME) failed with error {0}",
Marshal.GetLastWin32Error()); Marshal.GetLastWin32Error());
return guid; return is_xinput;
} }
// Convert the buffer to a .Net string, and split it into parts // Convert the buffer to a .Net string, and split it into parts
@ -675,20 +714,13 @@ namespace OpenTK.Platform.Windows
if (String.IsNullOrEmpty(name)) if (String.IsNullOrEmpty(name))
{ {
Debug.Print("[WinRawJoystick] Failed to construct device name"); Debug.Print("[WinRawJoystick] Failed to construct device name");
return guid; return is_xinput;
}
// The GUID is stored in the last part of the string
string[] parts = name.Split('#');
if (parts.Length > 3)
{
guid = new Guid(parts[3]);
} }
is_xinput = name.Contains("IG_"); is_xinput = name.Contains("IG_");
} }
return guid; return is_xinput;
} }
Device GetDevice(IntPtr handle) Device GetDevice(IntPtr handle)