[v3 4/4] winejoystick.drv/joystick_osx.c: adds sim page element controls

David Lawrie david.dljunk at gmail.com
Sun Jun 12 22:44:58 CDT 2016


Adds support for input features defined by HID Simulation page: Rudder
(Rz), Throttle (Z), Steering (X), Accelerator (Y), Brake (Rz).

Sources:
https://msdn.microsoft.com/en-us/library/windows/hardware/ff538340(v=vs.
85).aspx
http://opensource.apple.com//source/IOHIDFamily/IOHIDFamily-315.7.16/
IOHIDFamily/IOHIDUsageTables.h

Tested on OS X 10.10.5.

v2: whitespace fixes
v3: split patch up

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

diff --git a/dlls/winejoystick.drv/joystick_osx.c b/dlls/winejoystick.drv/joystick_osx.c
index b400ca6..26b1567 100644
--- a/dlls/winejoystick.drv/joystick_osx.c
+++ b/dlls/winejoystick.drv/joystick_osx.c
@@ -166,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)
     {
@@ -181,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
@@ -383,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:
@@ -394,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 */
@@ -404,66 +418,100 @@ 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)
+                switch (usage_page)
                 {
-                    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:
+                    case kHIDPage_GenericDesktop:
                     {
-                        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
+                        switch(usage)
                         {
-                            joystick->axes[axis].element = (IOHIDElementRef)CFRetain(child);
-                            joystick->axes[axis].min_value = IOHIDElementGetLogicalMin(child);
-                            joystick->axes[axis].max_value = IOHIDElementGetLogicalMax(child);
+                            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 kHIDUsage_GD_Slider:
-                    case kHIDUsage_GD_Dial:
-                    case kHIDUsage_GD_Wheel:
+                    case kHIDPage_Simulation:
                     {
-                        //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
+                        switch(usage)
                         {
-                            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);
+                            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_Misc / Unhandled usage %d\n", usage);
+                        FIXME("kIOHIDElementTypeInput_Axis/Misc / Unhandled Usage Page %d\n", usage_page);
                         break;
                 }
                 break;
@@ -614,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;
-- 
2.5.4 (Apple Git-61)




More information about the wine-patches mailing list