Merge pull request #7918 from spycrab/iokit_refactor
InputCommon/OSX: Refactor IOKit controller interface
This commit is contained in:
commit
672b582bec
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue