From 80fd01c3c36e7925fea1016c7f166b02cabdac74 Mon Sep 17 00:00:00 2001 From: spycrab Date: Thu, 21 Mar 2019 16:57:17 +0100 Subject: [PATCH] InputCommon/OSX: Refactor IOKit controller interface --- .../ControllerInterface/OSX/OSXJoystick.h | 4 + .../ControllerInterface/OSX/OSXJoystick.mm | 142 +++++++++++------- 2 files changed, 94 insertions(+), 52 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h index dbe6a725c1..d3393218c6 100644 --- a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h +++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h @@ -4,6 +4,8 @@ #pragma once +#include + #include #include "InputCommon/ControllerInterface/Device.h" @@ -84,6 +86,8 @@ private: const IOHIDDeviceRef m_device; const std::string m_device_name; + void AddElements(CFArrayRef elements, std::set& cookies); + ForceFeedback::FFDeviceAdapterReference m_ff_device; }; } diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm index bfe2f27505..e2c08707c5 100644 --- a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm +++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.mm @@ -2,75 +2,68 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "InputCommon/ControllerInterface/OSX/OSXJoystick.h" + #include #include #include #include +#include "Common/Logging/Log.h" #include "Common/StringUtil.h" -#include "InputCommon/ControllerInterface/OSX/OSXJoystick.h" namespace ciface { namespace OSX { -Joystick::Joystick(IOHIDDeviceRef device, std::string name) - : m_device(device), m_device_name(name), m_ff_device(nullptr) +void Joystick::AddElements(CFArrayRef elements, std::set& cookies) { - // Buttons - NSDictionary* buttonDict = @{ - @kIOHIDElementTypeKey : @(kIOHIDElementTypeInput_Button), - @kIOHIDElementUsagePageKey : @(kHIDPage_Button) - }; - - CFArrayRef buttons = - IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)buttonDict, kIOHIDOptionsTypeNone); - - if (buttons) + for (int i = 0; i < CFArrayGetCount(elements); i++) { - for (int i = 0; i < CFArrayGetCount(buttons); i++) + IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i); + + const uint32_t type = IOHIDElementGetType(e); + + switch (type) { - IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(buttons, i); - // DeviceElementDebugPrint(e, nullptr); - - AddInput(new Button(e, m_device)); - } - CFRelease(buttons); - } - - // Axes - NSDictionary* axisDict = @{ - @kIOHIDElementTypeKey : @(kIOHIDElementTypeInput_Misc), - @kIOHIDElementUsagePageKey : @(kHIDPage_GenericDesktop) - }; - - CFArrayRef axes = - IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)axisDict, kIOHIDOptionsTypeNone); - - if (axes) - { - std::vector elems; - for (int i = 0; i < CFArrayGetCount(axes); i++) - { - IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(axes, i); - // DeviceElementDebugPrint(e, nullptr); - uint32_t usage = IOHIDElementGetUsage(e); - - // Check for any existing elements with the same usage - auto it = std::find_if(elems.begin(), elems.end(), [usage](const auto& ref) { - return usage == IOHIDElementGetUsage(ref); - }); - - if (it == elems.end()) - elems.push_back(e); - else - *it = e; + case kIOHIDElementTypeCollection: + AddElements(IOHIDElementGetChildren(e), cookies); + continue; + case kIOHIDElementTypeOutput: + continue; } - for (auto e : elems) + IOHIDElementCookie cookie = IOHIDElementGetCookie(e); + + // Check for any existing elements with the same cookie + if (cookies.count(cookie) > 0) + continue; + + cookies.insert(cookie); + + const uint32_t usage = IOHIDElementGetUsage(e); + + switch (usage) { - if (IOHIDElementGetUsage(e) == kHIDUsage_GD_Hatswitch) + // Axis + 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 kHIDUsage_GD_Slider: + case kHIDUsage_GD_Dial: + case kHIDUsage_GD_Wheel: + case kHIDUsage_GD_Hatswitch: + // Simulator + case kHIDUsage_Sim_Accelerator: + case kHIDUsage_Sim_Brake: + case kHIDUsage_Sim_Rudder: + case kHIDUsage_Sim_Throttle: + { + if (usage == kHIDUsage_GD_Hatswitch) { AddInput(new Hat(e, m_device, Hat::up)); AddInput(new Hat(e, m_device, Hat::right)); @@ -82,10 +75,55 @@ Joystick::Joystick(IOHIDDeviceRef device, std::string name) AddAnalogInputs(new Axis(e, m_device, Axis::negative), new Axis(e, m_device, Axis::positive)); } + break; } + // Buttons + case kHIDUsage_GD_DPadUp: + case kHIDUsage_GD_DPadDown: + case kHIDUsage_GD_DPadRight: + case kHIDUsage_GD_DPadLeft: + case kHIDUsage_GD_Start: + case kHIDUsage_GD_Select: + case kHIDUsage_GD_SystemMainMenu: + AddInput(new Button(e, m_device)); + break; - CFRelease(axes); + default: + // Catch any easily identifiable axis and buttons that slipped through + if (type == kIOHIDElementTypeInput_Button) + { + AddInput(new Button(e, m_device)); + break; + } + + const uint32_t usage_page = IOHIDElementGetUsagePage(e); + + if (usage_page == kHIDPage_Button || usage_page == kHIDPage_Consumer) + { + AddInput(new Button(e, m_device)); + break; + } + + if (type == kIOHIDElementTypeInput_Axis) + { + AddAnalogInputs(new Axis(e, m_device, Axis::negative), + new Axis(e, m_device, Axis::positive)); + break; + } + + NOTICE_LOG(SERIALINTERFACE, "Unknown IOHIDElement, ignoring (Usage: %x, Type: %x)\n", usage, + IOHIDElementGetType(e)); + + break; + } } +} +Joystick::Joystick(IOHIDDeviceRef device, std::string name) + : m_device(device), m_device_name(name), m_ff_device(nullptr) +{ + CFArrayRef elements = IOHIDDeviceCopyMatchingElements(m_device, nullptr, kIOHIDOptionsTypeNone); + std::set known_cookies; + AddElements(elements, known_cookies); // Force Feedback FFCAPABILITIES ff_caps;