[1/1] winejoystick.drv/joystick_osx.c: fixed axes mapping, add feature support

David Lawrie david.dljunk at gmail.com
Fri Jun 10 01:11:40 CDT 2016


This patch fixes Slider and Ry/Rx axes mapping and adds support for
general multi-axis controllers (up to 6-axis controllers), steering
wheels w/ accelerators/brakes, multiple sliders/dials/wheels (up to 3),
rudder pedals, and throttles.

Tested on OS X 10.10.5

Signed-off-by: David Lawrie david.dljunk at gmail.com
---
 dlls/winejoystick.drv/joystick_osx.c | 171 ++++++++++++++++++++++++-----------
 1 file changed, 119 insertions(+), 52 deletions(-)

diff --git a/dlls/winejoystick.drv/joystick_osx.c b/dlls/winejoystick.drv/joystick_osx.c
index 48c05a0..973fd62 100644
--- a/dlls/winejoystick.drv/joystick_osx.c
+++ b/dlls/winejoystick.drv/joystick_osx.c
@@ -9,6 +9,7 @@
  * Copyright 2002 David Hagood
  * Copyright 2009 CodeWeavers, Aric Stewart
  * Copyright 2015 Ken Thomases for CodeWeavers Inc.
+ * Copyright 2016 David Lawrie
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -97,8 +98,8 @@ enum {
     AXIS_X,
     AXIS_Y,
     AXIS_Z,
-    AXIS_RX,
     AXIS_RY,
+    AXIS_RX,
     AXIS_RZ,
     NUM_AXES
 };
@@ -165,7 +166,7 @@ static const char* debugstr_element(IOHIDElementRef element)
 }
 
 
-static int axis_for_usage(int usage)
+static int axis_for_usage_GD(int usage)
 {
     switch (usage)
     {
@@ -180,6 +181,19 @@ static int axis_for_usage(int usage)
     return -1;
 }
 
+static int axis_for_usage_Sim(int usage)
+{
+    switch (usage)
+    {
+        case kHIDUsage_Sim_Rudder: return AXIS_RZ;
+        case kHIDUsage_Sim_Throttle: return AXIS_Z;
+        case kHIDUsage_Sim_Steering: return AXIS_X;
+        case kHIDUsage_Sim_Accelerator: return AXIS_Y;
+        case kHIDUsage_Sim_Brake: return AXIS_RZ;
+    }
+
+    return -1;
+}
 
 /**************************************************************************
  *                              joystick_from_id
@@ -263,7 +277,7 @@ static CFIndex find_top_level(IOHIDDeviceRef hid_device, CFMutableArrayRef main_
                 int usage = IOHIDElementGetUsage(element);
 
                 if (usage_page == kHIDPage_GenericDesktop &&
-                    (usage == kHIDUsage_GD_Joystick || usage == kHIDUsage_GD_GamePad))
+                    (usage == kHIDUsage_GD_Joystick || usage == kHIDUsage_GD_GamePad || usage == kHIDUsage_GD_MultiAxisController))
                 {
                     CFArrayAppendValue(main_elements, element);
                     total++;
@@ -283,7 +297,7 @@ static CFIndex find_top_level(IOHIDDeviceRef hid_device, CFMutableArrayRef main_
 static int find_osx_devices(void)
 {
     IOHIDManagerRef hid_manager;
-    int usages[] = { kHIDUsage_GD_Joystick, kHIDUsage_GD_GamePad };
+    int usages[] = { kHIDUsage_GD_Joystick, kHIDUsage_GD_GamePad, kHIDUsage_GD_MultiAxisController };
     int i;
     CFDictionaryRef matching_dicts[sizeof(usages) / sizeof(usages[0])];
     CFArrayRef matching;
@@ -382,10 +396,13 @@ static void collect_joystick_elements(joystick_t* joystick, IOHIDElementRef coll
     {
         IOHIDElementRef child;
         int type;
+		uint32_t usage_page;
 
         child = (IOHIDElementRef)CFArrayGetValueAtIndex(children, i);
         TRACE("child %s\n", debugstr_element(child));
         type = IOHIDElementGetType(child);
+        usage_page = IOHIDElementGetUsagePage(child);
+
         switch (type)
         {
             case kIOHIDElementTypeCollection:
@@ -393,8 +410,6 @@ static void collect_joystick_elements(joystick_t* joystick, IOHIDElementRef coll
                 break;
             case kIOHIDElementTypeInput_Button:
             {
-                int usage_page = IOHIDElementGetUsagePage(child);
-
                 TRACE("kIOHIDElementTypeInput_Button usage_page %d\n", usage_page);
 
                 /* avoid strange elements found on the 360 controller */
@@ -403,52 +418,104 @@ static void collect_joystick_elements(joystick_t* joystick, IOHIDElementRef coll
                 break;
             }
             case kIOHIDElementTypeInput_Axis:
-            {
-                TRACE("kIOHIDElementTypeInput_Axis; ignoring\n");
-                break;
-            }
             case kIOHIDElementTypeInput_Misc:
             {
-                uint32_t usage = IOHIDElementGetUsage( child );
-                switch(usage)
-                {
-                    case kHIDUsage_GD_Hatswitch:
-                    {
-                        TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n");
-                        if (joystick->hatswitch)
-                            TRACE("    ignoring additional hatswitch\n");
-                        else
-                            joystick->hatswitch = (IOHIDElementRef)CFRetain(child);
-                        break;
-                    }
-                    case kHIDUsage_GD_X:
-                    case kHIDUsage_GD_Y:
-                    case kHIDUsage_GD_Z:
-                    case kHIDUsage_GD_Rx:
-                    case kHIDUsage_GD_Ry:
-                    case kHIDUsage_GD_Rz:
-                    {
-                        int axis = axis_for_usage(usage);
-                        TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_<axis> (%d) axis %d\n", usage, axis);
-                        if (axis < 0 || joystick->axes[axis].element)
-                            TRACE("    ignoring\n");
-                        else
-                        {
-                            joystick->axes[axis].element = (IOHIDElementRef)CFRetain(child);
-                            joystick->axes[axis].min_value = IOHIDElementGetLogicalMin(child);
-                            joystick->axes[axis].max_value = IOHIDElementGetLogicalMax(child);
-                        }
-                        break;
-                    }
-                    case kHIDUsage_GD_Slider:
-                        TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Slider; ignoring\n");
-                        break;
-                    default:
-                        FIXME("kIOHIDElementTypeInput_Misc / Unhandled usage %d\n", usage);
-                        break;
-                }
+				uint32_t usage = IOHIDElementGetUsage( child );
+				switch (usage_page)
+				{
+					case kHIDPage_GenericDesktop:
+					{
+						switch(usage)
+						{
+							case kHIDUsage_GD_Hatswitch:
+							{
+								TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n");
+								if (joystick->hatswitch)
+									TRACE("    ignoring additional hatswitch\n");
+								else
+									joystick->hatswitch = (IOHIDElementRef)CFRetain(child);
+								break;
+							}
+							case kHIDUsage_GD_X:
+							case kHIDUsage_GD_Y:
+							case kHIDUsage_GD_Z:
+							case kHIDUsage_GD_Rx:
+							case kHIDUsage_GD_Ry:
+							case kHIDUsage_GD_Rz:
+							{
+								int axis = axis_for_usage_GD(usage);
+								TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_<axis> (%d) axis %d\n", usage, axis);
+								if (axis < 0 || joystick->axes[axis].element)
+									TRACE("    ignoring\n");
+								else
+								{
+									joystick->axes[axis].element = (IOHIDElementRef)CFRetain(child);
+									joystick->axes[axis].min_value = IOHIDElementGetLogicalMin(child);
+									joystick->axes[axis].max_value = IOHIDElementGetLogicalMax(child);
+								}
+								break;
+							}
+							case kHIDUsage_GD_Slider:
+							case kHIDUsage_GD_Dial:
+							case kHIDUsage_GD_Wheel:
+							{
+								//if one axis is taken, fall to the next until axes are filled
+								int possible_axes[3] = {AXIS_Z,AXIS_RY,AXIS_RX};
+								int axis = 0;
+								TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_<axis> (%d)", usage);
+								while(axis < 3 && joystick->axes[possible_axes[axis]].element)
+									axis++;
+								if (axis == 3)
+									TRACE("    ignoring\n");
+								else
+								{
+									TRACE(" axis %d\n", possible_axes[axis]);
+									joystick->axes[possible_axes[axis]].element = (IOHIDElementRef)CFRetain(child);
+									joystick->axes[possible_axes[axis]].min_value = IOHIDElementGetLogicalMin(child);
+									joystick->axes[possible_axes[axis]].max_value = IOHIDElementGetLogicalMax(child);
+								}
+								break;
+							}
+							default:
+								FIXME("kIOHIDElementTypeInput_Axis/Misc / Unhandled GD Page usage %d\n", usage);
+								break;
+						}
+						break;
+					}
+					case kHIDPage_Simulation:
+					{
+						switch(usage)
+						{
+							case kHIDUsage_Sim_Rudder:
+							case kHIDUsage_Sim_Throttle:
+							case kHIDUsage_Sim_Steering:
+							case kHIDUsage_Sim_Accelerator:
+							case kHIDUsage_Sim_Brake:
+							{
+								int axis = axis_for_usage_Sim(usage);
+								TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_Sim_<axis> (%d) axis %d\n", usage, axis);
+								if (axis < 0 || joystick->axes[axis].element)
+									TRACE("    ignoring\n");
+								else
+								{
+									joystick->axes[axis].element = (IOHIDElementRef)CFRetain(child);
+									joystick->axes[axis].min_value = IOHIDElementGetLogicalMin(child);
+									joystick->axes[axis].max_value = IOHIDElementGetLogicalMax(child);
+								}
+								break;
+							}
+							default:
+								FIXME("kIOHIDElementTypeInput_Axis/Misc / Unhandled Sim Page usage %d\n", usage);
+								break;
+						}
+						break;
+					}
+					default:
+						FIXME("kIOHIDElementTypeInput_Axis/Misc / Unhandled Usage Page %d\n", usage_page);
+						break;
+				}
                 break;
-            }
+		}
             default:
                 FIXME("Unhandled type %i\n",type);
                 break;
@@ -595,7 +662,7 @@ LRESULT driver_joyGetDevCaps(DWORD_PTR device_id, JOYCAPSW* caps, DWORD size)
     {
         int i;
 
-        /* complete 95 structure */
+        /* complete Win95 structure */
         caps->wRmin = 0;
         caps->wRmax = 0xFFFF;
         caps->wUmin = 0;
@@ -617,8 +684,8 @@ LRESULT driver_joyGetDevCaps(DWORD_PTR device_id, JOYCAPSW* caps, DWORD size)
                 switch (i)
                 {
                     case AXIS_Z:  caps->wCaps |= JOYCAPS_HASZ; break;
-                    case AXIS_RX: caps->wCaps |= JOYCAPS_HASU; break;
-                    case AXIS_RY: caps->wCaps |= JOYCAPS_HASV; break;
+                    case AXIS_RY: caps->wCaps |= JOYCAPS_HASU; break;
+                    case AXIS_RX: caps->wCaps |= JOYCAPS_HASV; break;
                     case AXIS_RZ: caps->wCaps |= JOYCAPS_HASR; break;
                 }
             }
-- 
1.7.12.4 (Apple Git-37)




More information about the wine-patches mailing list