mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-02-25 15:46:51 +00:00
[Mac] Use cookies to match HID joystick elements
This commit is contained in:
parent
d4c6b2e699
commit
4231cf2cdd
|
@ -45,6 +45,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
using CFTypeRef = System.IntPtr;
|
using CFTypeRef = System.IntPtr;
|
||||||
using IOHIDDeviceRef = System.IntPtr;
|
using IOHIDDeviceRef = System.IntPtr;
|
||||||
using IOHIDElementRef = System.IntPtr;
|
using IOHIDElementRef = System.IntPtr;
|
||||||
|
using IOHIDElementCookie = System.IntPtr;
|
||||||
using IOHIDManagerRef = System.IntPtr;
|
using IOHIDManagerRef = System.IntPtr;
|
||||||
using IOHIDValueRef = System.IntPtr;
|
using IOHIDValueRef = System.IntPtr;
|
||||||
using IOOptionBits = System.IntPtr;
|
using IOOptionBits = System.IntPtr;
|
||||||
|
@ -72,10 +73,59 @@ namespace OpenTK.Platform.MacOS
|
||||||
public Guid Guid;
|
public Guid Guid;
|
||||||
public JoystickState State;
|
public JoystickState State;
|
||||||
public JoystickCapabilities Capabilities;
|
public JoystickCapabilities Capabilities;
|
||||||
readonly public Dictionary<int, JoystickButton> ElementUsageToButton =
|
|
||||||
new Dictionary<int, JoystickButton>();
|
readonly public Dictionary<IOHIDElementCookie, JoystickElement> Elements =
|
||||||
readonly public Dictionary<IOHIDElementRef, JoystickHat> ElementToHat =
|
new Dictionary<IOHIDElementCookie, JoystickElement>();
|
||||||
new Dictionary<IOHIDElementRef, JoystickHat>(new IntPtrEqualityComparer());
|
|
||||||
|
public void AddElement(
|
||||||
|
IntPtr element, IntPtr cookie, int order,
|
||||||
|
HIDPage page, int usage,
|
||||||
|
int min, int max)
|
||||||
|
{
|
||||||
|
if (!Elements.ContainsKey(cookie))
|
||||||
|
{
|
||||||
|
Elements.Add(cookie, new JoystickElement(element, cookie, order, page, usage, min, max));
|
||||||
|
Debug.Print("[{0}] Discovered joystick element {1:x} ({2}/{3})",
|
||||||
|
typeof(HIDInput).Name, cookie, page, usage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Print("[{0}] Attempted to add joystick element {1:x} ({2}/{3}) twice, ignoring.",
|
||||||
|
typeof(HIDInput).Name, cookie, page, usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JoystickElement
|
||||||
|
{
|
||||||
|
public IntPtr Element;
|
||||||
|
public IntPtr Cookie;
|
||||||
|
// Order in which this element was reported
|
||||||
|
public int Order;
|
||||||
|
public HIDPage Page;
|
||||||
|
public int Usage;
|
||||||
|
// Hardware axis range
|
||||||
|
public int Min;
|
||||||
|
public int Max;
|
||||||
|
// Reported axis range (can sometimes be larger than hardware range)
|
||||||
|
public int MinReported;
|
||||||
|
public int MaxReported;
|
||||||
|
|
||||||
|
public JoystickElement(
|
||||||
|
IntPtr element, IntPtr cookie, int order,
|
||||||
|
HIDPage page, int usage,
|
||||||
|
int min, int max)
|
||||||
|
{
|
||||||
|
Element = element;
|
||||||
|
Cookie = cookie;
|
||||||
|
Order = order;
|
||||||
|
Page = page;
|
||||||
|
Usage = usage;
|
||||||
|
Min = min;
|
||||||
|
Max = max;
|
||||||
|
MinReported = min;
|
||||||
|
MaxReported = max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IOHIDManagerRef hidmanager;
|
IOHIDManagerRef hidmanager;
|
||||||
|
@ -584,18 +634,18 @@ namespace OpenTK.Platform.MacOS
|
||||||
int axes = 0;
|
int axes = 0;
|
||||||
int buttons = 0;
|
int buttons = 0;
|
||||||
int hats = 0;
|
int hats = 0;
|
||||||
|
int vendor = 0;
|
||||||
|
|
||||||
CFStringRef name_ref = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDProductKey);
|
CFStringRef name_ref = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDProductKey);
|
||||||
string name = CF.CFStringGetCString(name_ref);
|
string name = CF.CFStringGetCString(name_ref);
|
||||||
|
|
||||||
Guid guid = CreateJoystickGuid(device, name);
|
Guid guid = CreateJoystickGuid(device, name);
|
||||||
|
|
||||||
List<int> button_elements = new List<int>();
|
|
||||||
List<IOHIDElementRef> hat_elements = new List<CFAllocatorRef>();
|
|
||||||
CFArray element_array = new CFArray(element_array_ref);
|
CFArray element_array = new CFArray(element_array_ref);
|
||||||
for (int i = 0; i < element_array.Count; i++)
|
for (int i = 0; i < element_array.Count; i++)
|
||||||
{
|
{
|
||||||
IOHIDElementRef element_ref = element_array[i];
|
IOHIDElementRef element_ref = element_array[i];
|
||||||
|
IOHIDElementCookie cookie = NativeMethods.IOHIDElementGetCookie(element_ref);
|
||||||
HIDPage page = NativeMethods.IOHIDElementGetUsagePage(element_ref);
|
HIDPage page = NativeMethods.IOHIDElementGetUsagePage(element_ref);
|
||||||
int usage = NativeMethods.IOHIDElementGetUsage(element_ref);
|
int usage = NativeMethods.IOHIDElementGetUsage(element_ref);
|
||||||
|
|
||||||
|
@ -613,12 +663,27 @@ namespace OpenTK.Platform.MacOS
|
||||||
case HIDUsageGD.Slider:
|
case HIDUsageGD.Slider:
|
||||||
case HIDUsageGD.Dial:
|
case HIDUsageGD.Dial:
|
||||||
case HIDUsageGD.Wheel:
|
case HIDUsageGD.Wheel:
|
||||||
axes++;
|
if (axes < JoystickState.MaxAxes)
|
||||||
|
{
|
||||||
|
joy.AddElement(element_ref, cookie, axes++, page, usage, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Print("[{0}] Failed to add axis (limit of {1} has been reached).",
|
||||||
|
GetType().Name, JoystickState.MaxAxes);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HIDUsageGD.Hatswitch:
|
case HIDUsageGD.Hatswitch:
|
||||||
hats++;
|
if (hats < JoystickState.MaxHats)
|
||||||
hat_elements.Add(element_ref);
|
{
|
||||||
|
joy.AddElement(element_ref, cookie, hats++, page, usage, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Print("[{0}] Failed to add hat (limit of {1} has been reached).",
|
||||||
|
GetType().Name, JoystickState.MaxHats);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -628,13 +693,33 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
case HIDUsageSim.Rudder:
|
case HIDUsageSim.Rudder:
|
||||||
case HIDUsageSim.Throttle:
|
case HIDUsageSim.Throttle:
|
||||||
axes++;
|
if (axes < JoystickState.MaxAxes)
|
||||||
|
{
|
||||||
|
joy.AddElement(element_ref, cookie, axes++, page, usage, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Print("[{0}] Failed to add axis (limit of {1} has been reached).",
|
||||||
|
GetType().Name, JoystickState.MaxAxes);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HIDPage.Button:
|
case HIDPage.Button:
|
||||||
button_elements.Add(usage);
|
if (buttons < JoystickState.MaxButtons)
|
||||||
|
{
|
||||||
|
joy.AddElement(element_ref, cookie, buttons++, page, usage, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Print("[{0}] Failed to add button (limit of {1} has been reached).",
|
||||||
|
GetType().Name, JoystickState.MaxButtons);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HIDPage.VendorDefinedStart:
|
||||||
|
joy.AddElement(element_ref, cookie, vendor++, page, usage, 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -662,17 +747,6 @@ namespace OpenTK.Platform.MacOS
|
||||||
joy.Guid = guid;
|
joy.Guid = guid;
|
||||||
joy.State.SetIsConnected(true);
|
joy.State.SetIsConnected(true);
|
||||||
joy.Capabilities = new JoystickCapabilities(axes, buttons, hats, true);
|
joy.Capabilities = new JoystickCapabilities(axes, buttons, hats, true);
|
||||||
|
|
||||||
// Map button elements to JoystickButtons
|
|
||||||
for (int button = 0; button < button_elements.Count; button++)
|
|
||||||
{
|
|
||||||
joy.ElementUsageToButton.Add(button_elements[button], JoystickButton.Button0 + button);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int hat = 0; hat < hat_elements.Count; hat++)
|
|
||||||
{
|
|
||||||
joy.ElementToHat.Add(hat_elements[hat], JoystickHat.Hat0 + hat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CF.CFRelease(element_array_ref);
|
CF.CFRelease(element_array_ref);
|
||||||
|
|
||||||
|
@ -749,9 +823,17 @@ namespace OpenTK.Platform.MacOS
|
||||||
static void UpdateJoystick(JoystickData joy, IOHIDValueRef val)
|
static void UpdateJoystick(JoystickData joy, IOHIDValueRef val)
|
||||||
{
|
{
|
||||||
IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
|
IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
|
||||||
|
IOHIDElementCookie cookie = NativeMethods.IOHIDElementGetCookie(elem);
|
||||||
HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
|
HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
|
||||||
int usage = NativeMethods.IOHIDElementGetUsage(elem);
|
int usage = NativeMethods.IOHIDElementGetUsage(elem);
|
||||||
|
|
||||||
|
if (!joy.Elements.ContainsKey(cookie))
|
||||||
|
{
|
||||||
|
Debug.Print("[{0}] Reported joystick element {1:x} ({2}/{3}) is unknown",
|
||||||
|
typeof(HIDInput).Name, cookie, page, usage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (page)
|
switch (page)
|
||||||
{
|
{
|
||||||
case HIDPage.GenericDesktop:
|
case HIDPage.GenericDesktop:
|
||||||
|
@ -767,7 +849,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
case HIDUsageGD.Dial:
|
case HIDUsageGD.Dial:
|
||||||
case HIDUsageGD.Wheel:
|
case HIDUsageGD.Wheel:
|
||||||
short offset = GetJoystickAxis(val, elem);
|
short offset = GetJoystickAxis(val, elem);
|
||||||
JoystickAxis axis = HidHelper.TranslateJoystickAxis(page, usage);
|
JoystickAxis axis = JoystickAxis.Axis0 + joy.Elements[cookie].Order;
|
||||||
if (axis >= JoystickAxis.Axis0 && axis <= JoystickAxis.Last)
|
if (axis >= JoystickAxis.Axis0 && axis <= JoystickAxis.Last)
|
||||||
{
|
{
|
||||||
joy.State.SetAxis(axis, offset);
|
joy.State.SetAxis(axis, offset);
|
||||||
|
@ -776,7 +858,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
|
|
||||||
case HIDUsageGD.Hatswitch:
|
case HIDUsageGD.Hatswitch:
|
||||||
HatPosition position = GetJoystickHat(val, elem);
|
HatPosition position = GetJoystickHat(val, elem);
|
||||||
JoystickHat hat = TranslateJoystickHat(joy, elem);
|
JoystickHat hat = JoystickHat.Hat0 + joy.Elements[cookie].Order;
|
||||||
if (hat >= JoystickHat.Hat0 && hat <= JoystickHat.Last)
|
if (hat >= JoystickHat.Hat0 && hat <= JoystickHat.Last)
|
||||||
{
|
{
|
||||||
joy.State.SetHat(hat, new JoystickHatState(position));
|
joy.State.SetHat(hat, new JoystickHatState(position));
|
||||||
|
@ -791,7 +873,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
case HIDUsageSim.Rudder:
|
case HIDUsageSim.Rudder:
|
||||||
case HIDUsageSim.Throttle:
|
case HIDUsageSim.Throttle:
|
||||||
short offset = GetJoystickAxis(val, elem);
|
short offset = GetJoystickAxis(val, elem);
|
||||||
JoystickAxis axis = HidHelper.TranslateJoystickAxis(page, usage);
|
JoystickAxis axis = JoystickAxis.Axis0 + joy.Elements[cookie].Order;
|
||||||
if (axis >= JoystickAxis.Axis0 && axis <= JoystickAxis.Last)
|
if (axis >= JoystickAxis.Axis0 && axis <= JoystickAxis.Last)
|
||||||
{
|
{
|
||||||
joy.State.SetAxis(axis, offset);
|
joy.State.SetAxis(axis, offset);
|
||||||
|
@ -803,7 +885,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
case HIDPage.Button:
|
case HIDPage.Button:
|
||||||
{
|
{
|
||||||
bool pressed = GetJoystickButton(val, elem);
|
bool pressed = GetJoystickButton(val, elem);
|
||||||
JoystickButton button = TranslateJoystickButton(joy, usage);
|
JoystickButton button = JoystickButton.Button0 + joy.Elements[cookie].Order;
|
||||||
if (button >= JoystickButton.Button0 && button <= JoystickButton.Last)
|
if (button >= JoystickButton.Button0 && button <= JoystickButton.Last)
|
||||||
{
|
{
|
||||||
joy.State.SetButton(button, pressed);
|
joy.State.SetButton(button, pressed);
|
||||||
|
@ -828,16 +910,6 @@ namespace OpenTK.Platform.MacOS
|
||||||
return value >= 1;
|
return value >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JoystickButton TranslateJoystickButton(JoystickData joy, int usage)
|
|
||||||
{
|
|
||||||
JoystickButton button;
|
|
||||||
if (joy.ElementUsageToButton.TryGetValue(usage, out button))
|
|
||||||
{
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
return JoystickButton.Last + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HatPosition GetJoystickHat(IOHIDValueRef val, IOHIDElementRef element)
|
static HatPosition GetJoystickHat(IOHIDValueRef val, IOHIDElementRef element)
|
||||||
{
|
{
|
||||||
HatPosition position = HatPosition.Centered;
|
HatPosition position = HatPosition.Centered;
|
||||||
|
@ -872,16 +944,6 @@ namespace OpenTK.Platform.MacOS
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JoystickHat TranslateJoystickHat(JoystickData joy, IOHIDElementRef elem)
|
|
||||||
{
|
|
||||||
JoystickHat hat;
|
|
||||||
if (joy.ElementToHat.TryGetValue(elem, out hat))
|
|
||||||
{
|
|
||||||
return hat;
|
|
||||||
}
|
|
||||||
return JoystickHat.Last + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -1132,6 +1194,9 @@ namespace OpenTK.Platform.MacOS
|
||||||
[DllImport(hid)]
|
[DllImport(hid)]
|
||||||
public static extern IOHIDElementRef IOHIDValueGetElement(IOHIDValueRef @value);
|
public static extern IOHIDElementRef IOHIDValueGetElement(IOHIDValueRef @value);
|
||||||
|
|
||||||
|
[DllImport(hid)]
|
||||||
|
public static extern IOHIDElementCookie IOHIDElementGetCookie(IOHIDElementRef element);
|
||||||
|
|
||||||
[DllImport(hid)]
|
[DllImport(hid)]
|
||||||
public static extern CFIndex IOHIDValueGetIntegerValue(IOHIDValueRef @value);
|
public static extern CFIndex IOHIDValueGetIntegerValue(IOHIDValueRef @value);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue