Merge pull request #7918 from spycrab/iokit_refactor

InputCommon/OSX: Refactor IOKit controller interface
This commit is contained in:
spycrab 2019-03-22 21:18:27 +01:00 committed by GitHub
commit 672b582bec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 52 deletions

View File

@ -4,6 +4,8 @@
#pragma once #pragma once
#include <set>
#include <IOKit/hid/IOHIDLib.h> #include <IOKit/hid/IOHIDLib.h>
#include "InputCommon/ControllerInterface/Device.h" #include "InputCommon/ControllerInterface/Device.h"
@ -84,6 +86,8 @@ private:
const IOHIDDeviceRef m_device; const IOHIDDeviceRef m_device;
const std::string m_device_name; const std::string m_device_name;
void AddElements(CFArrayRef elements, std::set<IOHIDElementCookie>& cookies);
ForceFeedback::FFDeviceAdapterReference m_ff_device; ForceFeedback::FFDeviceAdapterReference m_ff_device;
}; };
} }

View File

@ -2,75 +2,68 @@
// Licensed under GPLv2+ // Licensed under GPLv2+
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "InputCommon/ControllerInterface/OSX/OSXJoystick.h"
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
#include <Foundation/Foundation.h> #include <Foundation/Foundation.h>
#include <IOKit/hid/IOHIDLib.h> #include <IOKit/hid/IOHIDLib.h>
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "InputCommon/ControllerInterface/OSX/OSXJoystick.h"
namespace ciface namespace ciface
{ {
namespace OSX namespace OSX
{ {
Joystick::Joystick(IOHIDDeviceRef device, std::string name) void Joystick::AddElements(CFArrayRef elements, std::set<IOHIDElementCookie>& cookies)
: m_device(device), m_device_name(name), m_ff_device(nullptr)
{ {
// Buttons for (int i = 0; i < CFArrayGetCount(elements); i++)
NSDictionary* buttonDict = @{
@kIOHIDElementTypeKey : @(kIOHIDElementTypeInput_Button),
@kIOHIDElementUsagePageKey : @(kHIDPage_Button)
};
CFArrayRef buttons =
IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)buttonDict, kIOHIDOptionsTypeNone);
if (buttons)
{ {
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); case kIOHIDElementTypeCollection:
// DeviceElementDebugPrint(e, nullptr); AddElements(IOHIDElementGetChildren(e), cookies);
continue;
AddInput(new Button(e, m_device)); case kIOHIDElementTypeOutput:
} continue;
CFRelease(buttons);
}
// Axes
NSDictionary* axisDict = @{
@kIOHIDElementTypeKey : @(kIOHIDElementTypeInput_Misc),
@kIOHIDElementUsagePageKey : @(kHIDPage_GenericDesktop)
};
CFArrayRef axes =
IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)axisDict, kIOHIDOptionsTypeNone);
if (axes)
{
std::vector<IOHIDElementRef> 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;
} }
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::up));
AddInput(new Hat(e, m_device, Hat::right)); 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), AddAnalogInputs(new Axis(e, m_device, Axis::negative),
new Axis(e, m_device, Axis::positive)); 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<IOHIDElementCookie> known_cookies;
AddElements(elements, known_cookies);
// Force Feedback // Force Feedback
FFCAPABILITIES ff_caps; FFCAPABILITIES ff_caps;