Skip to content
Permalink
Browse files

InputCommon/OSX: Refactor IOKit controller interface

  • Loading branch information...
spycrab committed Mar 21, 2019
1 parent 8713a75 commit 80fd01c3c36e7925fea1016c7f166b02cabdac74
@@ -4,6 +4,8 @@

#pragma once

#include <set>

#include <IOKit/hid/IOHIDLib.h>

#include "InputCommon/ControllerInterface/Device.h"
@@ -84,6 +86,8 @@ class Joystick : public ForceFeedback::ForceFeedbackDevice
const IOHIDDeviceRef m_device;
const std::string m_device_name;

void AddElements(CFArrayRef elements, std::set<IOHIDElementCookie>& cookies);

ForceFeedback::FFDeviceAdapterReference m_ff_device;
};
}
@@ -2,75 +2,68 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "InputCommon/ControllerInterface/OSX/OSXJoystick.h"

#include <algorithm>
#include <sstream>

#include <Foundation/Foundation.h>
#include <IOKit/hid/IOHIDLib.h>

#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<IOHIDElementCookie>& cookies)
{
// Buttons
NSDictionary* buttonDict = @{
@kIOHIDElementTypeKey : @(kIOHIDElementTypeInput_Button),
@kIOHIDElementUsagePageKey : @(kHIDPage_Button)
};
for (int i = 0; i < CFArrayGetCount(elements); i++)
{
IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);

CFArrayRef buttons =
IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)buttonDict, kIOHIDOptionsTypeNone);
const uint32_t type = IOHIDElementGetType(e);

if (buttons)
{
for (int i = 0; i < CFArrayGetCount(buttons); i++)
switch (type)
{
IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(buttons, i);
// DeviceElementDebugPrint(e, nullptr);

AddInput(new Button(e, m_device));
case kIOHIDElementTypeCollection:
AddElements(IOHIDElementGetChildren(e), cookies);
continue;
case kIOHIDElementTypeOutput:
continue;
}
CFRelease(buttons);
}

// Axes
NSDictionary* axisDict = @{
@kIOHIDElementTypeKey : @(kIOHIDElementTypeInput_Misc),
@kIOHIDElementUsagePageKey : @(kHIDPage_GenericDesktop)
};
IOHIDElementCookie cookie = IOHIDElementGetCookie(e);

CFArrayRef axes =
IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)axisDict, kIOHIDOptionsTypeNone);
// Check for any existing elements with the same cookie
if (cookies.count(cookie) > 0)
continue;

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);
});
cookies.insert(cookie);

if (it == elems.end())
elems.push_back(e);
else
*it = e;
}
const uint32_t usage = IOHIDElementGetUsage(e);

for (auto e : elems)
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 @@
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<IOHIDElementCookie> known_cookies;
AddElements(elements, known_cookies);

// Force Feedback
FFCAPABILITIES ff_caps;

0 comments on commit 80fd01c

Please sign in to comment.
You can’t perform that action at this time.