[Mac] Implemented joystick device detection
authorthefiddler <stapostol@gmail.com>
Sun, 5 Jan 2014 02:03:46 +0000 (03:03 +0100)
committerthefiddler <stapostol@gmail.com>
Sun, 5 Jan 2014 02:03:46 +0000 (03:03 +0100)
Source/OpenTK/Platform/MacOS/HIDInput.cs

index 2a8fb48..d333446 100755 (executable)
@@ -376,25 +376,90 @@ namespace OpenTK.Platform.MacOS
             MacJoystick joy = null;
 
             // Retrieve all elements of this device
-            CFArrayRef element_array = NativeMethods.IOHIDDeviceCopyMatchingElements(device, IntPtr.Zero, IntPtr.Zero);
-            if (element_array != IntPtr.Zero)
+            CFArrayRef element_array_ref = NativeMethods.IOHIDDeviceCopyMatchingElements(device, IntPtr.Zero, IntPtr.Zero);
+            if (element_array_ref != IntPtr.Zero)
             {
+                int axes = 0;
+                int buttons = 0;
+                int dpads = 0;
+
                 CFStringRef name_ref = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDProductKey);
                 string name = CF.CFStringGetCString(name_ref);
                 CF.CFRelease(name_ref);
 
-                joy = new MacJoystick(-1, 0, 0);
+                CFArray element_array = new CFArray(element_array_ref);
+                for (int i = 0; i < element_array.Count; i++)
+                {
+                    IOHIDElementRef element_ref = element_array[i];
+                    IOHIDElementType type = NativeMethods.IOHIDElementGetType(element_ref);
+                    HIDPage page = NativeMethods.IOHIDElementGetUsagePage(element_ref);
+                    int usage = NativeMethods.IOHIDElementGetUsage(element_ref);
+
+                    switch (page)
+                    {
+                        case HIDPage.GenericDesktop:
+                            switch ((HIDUsageGD)usage)
+                            {
+                                case HIDUsageGD.X:
+                                case HIDUsageGD.Y:
+                                case HIDUsageGD.Z:
+                                case HIDUsageGD.Rx:
+                                case HIDUsageGD.Ry:
+                                case HIDUsageGD.Rz:
+                                case HIDUsageGD.Slider:
+                                case HIDUsageGD.Dial:
+                                case HIDUsageGD.Wheel:
+                                    axes++;
+                                    break;
+
+                                case HIDUsageGD.Hatswitch:
+                                    dpads++;
+                                    break;
+                            }
+                            break;
+
+                        case HIDPage.Simulation:
+                            switch ((HIDUsageSim)usage)
+                            {
+                                case HIDUsageSim.Rudder:
+                                case HIDUsageSim.Throttle:
+                                    axes++;
+                                    break;
+                            }
+                            break;
+
+                        case HIDPage.Button:
+                            buttons++;
+                            break;
+                    }
+                }
+
+                joy = new MacJoystick(-1, axes, buttons);
                 joy.Details.Name = name;
                 joy.Details.State.SetIsConnected(true);
-                joy.Details.Capabilities = new JoystickCapabilities(0, 0, true);
+                joy.Details.Capabilities = new JoystickCapabilities(axes, buttons, true);
 
                 //NativeMethods.IOHIDDeviceGetProperty(device, nativem
             }
-            CF.CFRelease(element_array);
+            CF.CFRelease(element_array_ref);
 
             return joy;
         }
 
+        MacJoystick GetJoystick(int index)
+        {
+            IntPtr device;
+            if (JoystickIndexToDevice.TryGetValue(index, out device))
+            {
+                MacJoystick joystick;
+                if (JoystickDevices.TryGetValue(device, out joystick))
+                {
+                    return joystick;
+                }
+            }
+            return null;
+        }
+
         void AddJoystick(CFAllocatorRef sender, CFAllocatorRef device)
         {
             if (!JoystickDevices.ContainsKey(device))
@@ -527,16 +592,31 @@ namespace OpenTK.Platform.MacOS
 
         JoystickState IJoystickDriver2.GetState(int index)
         {
+            MacJoystick joystick = GetJoystick(index);
+            if (joystick != null)
+            {
+                return joystick.Details.State;
+            }
             return new JoystickState();
         }
 
         JoystickCapabilities IJoystickDriver2.GetCapabilities(int index)
         {
+            MacJoystick joystick = GetJoystick(index);
+            if (joystick != null)
+            {
+                return joystick.Details.Capabilities;
+            }
             return new JoystickCapabilities();
         }
 
         Guid IJoystickDriver2.GetGuid(int index)
         {
+            MacJoystick joystick = GetJoystick(index);
+            if (joystick != null)
+            {
+                //return joystick.Details.Capabilities;
+            }
             return new Guid();
         }
 
@@ -663,6 +743,10 @@ namespace OpenTK.Platform.MacOS
                 IOHIDValueScaleType type) ;
 
             [DllImport(hid)]
+            public static extern IOHIDElementType IOHIDElementGetType(
+                IOHIDElementRef element);
+
+            [DllImport(hid)]
             public static extern int IOHIDElementGetUsage(IOHIDElementRef elem);
 
             [DllImport(hid)]
@@ -672,6 +756,17 @@ namespace OpenTK.Platform.MacOS
             public delegate void IOHIDValueCallback(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDValueRef val);
         }
 
+        enum IOHIDElementType
+        {
+            Input_Misc = 1,
+            Input_Button = 2,
+            Input_Axis = 3,
+            Input_ScanCodes = 4,
+            Output = 129,
+            Feature = 257,
+            Collection = 513
+        }
+
         enum IOHIDValueScaleType
         {
             Physical, // [device min, device max]
@@ -776,6 +871,65 @@ namespace OpenTK.Platform.MacOS
             Reserved = 0xFFFF
         }
 
+        enum HIDUsageSim
+        {
+            FlightSimulationDevice    = 0x01, /* Application Collection */
+            AutomobileSimulationDevice    = 0x02, /*             Application Collection */
+            TankSimulationDevice  = 0x03, /*             Application Collection */
+            SpaceshipSimulationDevice = 0x04, /*             Application Collection */
+            SubmarineSimulationDevice = 0x05, /*             Application Collection */
+            SailingSimulationDevice   = 0x06, /*             Application Collection */
+            MotorcycleSimulationDevice    = 0x07, /*             Application Collection */
+            SportsSimulationDevice    = 0x08, /*             Application Collection */
+            AirplaneSimulationDevice  = 0x09, /*             Application Collection */
+            HelicopterSimulationDevice    = 0x0A, /*             Application Collection */
+            MagicCarpetSimulationDevice   = 0x0B, /*             Application Collection */
+            BicycleSimulationDevice   = 0x0C, /*             Application Collection */
+            /* 0x0D - 0x1F Reserved */
+            FlightControlStick    = 0x20, /*             Application Collection */
+            FlightStick   = 0x21, /*             Application Collection */
+            CyclicControl = 0x22, /*             Physical Collection */
+            CyclicTrim    = 0x23, /*             Physical Collection */
+            FlightYoke    = 0x24, /*             Application Collection */
+            TrackControl  = 0x25, /*             Physical Collection */
+            /* 0x26 - 0xAF Reserved */
+            Aileron   = 0xB0, /*             Dynamic Value */
+            AileronTrim   = 0xB1, /*             Dynamic Value */
+            AntiTorqueControl = 0xB2, /*             Dynamic Value */
+            AutopilotEnable   = 0xB3, /*             On/Off Control */
+            ChaffRelease  = 0xB4, /*             One-Shot Control */
+            CollectiveControl = 0xB5, /*             Dynamic Value */
+            DiveBrake = 0xB6, /*             Dynamic Value */
+            ElectronicCountermeasures = 0xB7, /*             On/Off Control */
+            Elevator  = 0xB8, /*             Dynamic Value */
+            ElevatorTrim  = 0xB9, /*             Dynamic Value */
+            Rudder    = 0xBA, /*             Dynamic Value */
+            Throttle  = 0xBB, /*             Dynamic Value */
+            FlightCommunications  = 0xBC, /*             On/Off Control */
+            FlareRelease  = 0xBD, /*             One-Shot Control */
+            LandingGear   = 0xBE, /*             On/Off Control */
+            ToeBrake  = 0xBF, /*             Dynamic Value */
+            Trigger   = 0xC0, /*             Momentary Control */
+            WeaponsArm    = 0xC1, /*             On/Off Control */
+            Weapons   = 0xC2, /*             Selector */
+            WingFlaps = 0xC3, /*             Dynamic Value */
+            Accelerator   = 0xC4, /*             Dynamic Value */
+            Brake = 0xC5, /*             Dynamic Value */
+            Clutch    = 0xC6, /*             Dynamic Value */
+            Shifter   = 0xC7, /*             Dynamic Value */
+            Steering  = 0xC8, /*             Dynamic Value */
+            TurretDirection   = 0xC9, /*             Dynamic Value */
+            BarrelElevation   = 0xCA, /*             Dynamic Value */
+            DivePlane = 0xCB, /*             Dynamic Value */
+            Ballast   = 0xCC, /*             Dynamic Value */
+            BicycleCrank  = 0xCD, /*             Dynamic Value */
+            HandleBars    = 0xCE, /*             Dynamic Value */
+            FrontBrake    = 0xCF, /*             Dynamic Value */
+            RearBrake = 0xD0, /*             Dynamic Value */
+            /* 0xD1 - 0xFFFF Reserved */
+            Reserved = 0xFFFF
+        }
+
         enum HIDButton
         {
             Button_1  = 0x01, /* (primary/trigger) */