The ControllerInterface API has the notion of an "id" which is presumably
meant as a ideally persistent device instance number. In a dynamic environment such as when dealing with USB/bluetooth HID's, I am not sure how much sense such an id can make and it would probably be better to identify devices by an opaque blob (and a printable string). In any case, the OS X HID manager does not offer the illusion of a persistent integer instance identifier. A string in the form of the device's own name is not sufficient as on e.g. my Macbook Pro, there are three HID devices all bearing the name "Apple Internal Keyboard / Trackpad". For now, hijack the ControllerInterface id to mean the the HID usage page number. This at least separates keyboards and pointing devices, allowing the keyboard to be selected in the configuration dialog. Also some minor cleanup. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5793 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
ebbfba62a0
commit
a53d0cb6d5
|
@ -172,4 +172,3 @@
|
|||
{ kHIDUsage_KeyboardRightAlt, "Right Alt" },
|
||||
{ kHIDUsage_KeyboardRightGUI, "Right GUI" },
|
||||
/* 0x4E - 0xFFFF Reserved */
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace ciface
|
|||
namespace OSX
|
||||
{
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices );
|
||||
void Init(std::vector<ControllerInterface::Device*>& devices);
|
||||
void DeInit();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
#include <Foundation/Foundation.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_OSX
|
||||
|
||||
#include "OSX.h"
|
||||
#include "OSXKeyboard.h"
|
||||
#include "OSXMouse.h"
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
|
@ -17,69 +15,98 @@ namespace OSX
|
|||
static IOHIDManagerRef HIDManager = NULL;
|
||||
static CFStringRef OurRunLoop = CFSTR("DolphinOSXInput");
|
||||
|
||||
|
||||
void DeviceElementDebugPrint(const void *value, void *context)
|
||||
{
|
||||
IOHIDElementRef e = (IOHIDElementRef)value;
|
||||
bool recurse = false;
|
||||
if (context)
|
||||
recurse = *(bool*)context;
|
||||
|
||||
|
||||
std::string type = "";
|
||||
switch (IOHIDElementGetType(e))
|
||||
{
|
||||
case kIOHIDElementTypeInput_Axis: type = "axis"; break;
|
||||
case kIOHIDElementTypeInput_Button: type = "button"; break;
|
||||
case kIOHIDElementTypeInput_Misc: type = "misc"; break;
|
||||
case kIOHIDElementTypeInput_ScanCodes: type = "scancodes"; break;
|
||||
case kIOHIDElementTypeOutput: type = "output"; break;
|
||||
case kIOHIDElementTypeFeature: type = "feature"; break;
|
||||
case kIOHIDElementTypeCollection: type = "collection"; break;
|
||||
switch (IOHIDElementGetType(e)) {
|
||||
case kIOHIDElementTypeInput_Axis:
|
||||
type = "axis";
|
||||
break;
|
||||
case kIOHIDElementTypeInput_Button:
|
||||
type = "button";
|
||||
break;
|
||||
case kIOHIDElementTypeInput_Misc:
|
||||
type = "misc";
|
||||
break;
|
||||
case kIOHIDElementTypeInput_ScanCodes:
|
||||
type = "scancodes";
|
||||
break;
|
||||
case kIOHIDElementTypeOutput:
|
||||
type = "output";
|
||||
break;
|
||||
case kIOHIDElementTypeFeature:
|
||||
type = "feature";
|
||||
break;
|
||||
case kIOHIDElementTypeCollection:
|
||||
type = "collection";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
std::string c_type = "";
|
||||
if (type == "collection")
|
||||
{
|
||||
switch (IOHIDElementGetCollectionType(e))
|
||||
{
|
||||
case kIOHIDElementCollectionTypePhysical: c_type = "physical"; break;
|
||||
case kIOHIDElementCollectionTypeApplication: c_type = "application"; break;
|
||||
case kIOHIDElementCollectionTypeLogical: c_type = "logical"; break;
|
||||
case kIOHIDElementCollectionTypeReport: c_type = "report"; break;
|
||||
case kIOHIDElementCollectionTypeNamedArray: c_type = "namedArray"; break;
|
||||
case kIOHIDElementCollectionTypeUsageSwitch: c_type = "usageSwitch"; break;
|
||||
case kIOHIDElementCollectionTypeUsageModifier: c_type = "usageModifier"; break;
|
||||
switch (IOHIDElementGetCollectionType(e)) {
|
||||
case kIOHIDElementCollectionTypePhysical:
|
||||
c_type = "physical";
|
||||
break;
|
||||
case kIOHIDElementCollectionTypeApplication:
|
||||
c_type = "application";
|
||||
break;
|
||||
case kIOHIDElementCollectionTypeLogical:
|
||||
c_type = "logical";
|
||||
break;
|
||||
case kIOHIDElementCollectionTypeReport:
|
||||
c_type = "report";
|
||||
break;
|
||||
case kIOHIDElementCollectionTypeNamedArray:
|
||||
c_type = "namedArray";
|
||||
break;
|
||||
case kIOHIDElementCollectionTypeUsageSwitch:
|
||||
c_type = "usageSwitch";
|
||||
break;
|
||||
case kIOHIDElementCollectionTypeUsageModifier:
|
||||
c_type = "usageModifier";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
c_type.append(" ");
|
||||
NSLog(@"%s%s%spage: 0x%x usage: 0x%x name: %s lmin: %i lmax: %i pmin: %i pmax: %i",
|
||||
NSLog(@"%s%s%spage: 0x%x usage: 0x%x name: %s "
|
||||
"lmin: %i lmax: %i pmin: %i pmax: %i",
|
||||
type.c_str(),
|
||||
type == "collection" ? ":" : "",
|
||||
type == "collection" ? c_type.c_str() : " ",
|
||||
IOHIDElementGetUsagePage(e),
|
||||
IOHIDElementGetUsage(e),
|
||||
IOHIDElementGetName(e), // TOO BAD IT"S FUCKING USELESS
|
||||
IOHIDElementGetName(e), // usually just NULL
|
||||
IOHIDElementGetLogicalMin(e),
|
||||
IOHIDElementGetLogicalMax(e),
|
||||
IOHIDElementGetPhysicalMin(e),
|
||||
IOHIDElementGetPhysicalMax(e));
|
||||
|
||||
|
||||
if ((type == "collection") && recurse)
|
||||
{
|
||||
CFArrayRef elements = IOHIDElementGetChildren(e);
|
||||
CFRange range = {0, CFArrayGetCount(elements)};
|
||||
// this leaks...but it's just debug code, right? :D
|
||||
CFArrayApplyFunction(elements, range, DeviceElementDebugPrint, NULL);
|
||||
CFArrayApplyFunction(elements, range,
|
||||
DeviceElementDebugPrint, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceDebugPrint(IOHIDDeviceRef device)
|
||||
{
|
||||
//#define shortlog(x) NSLog(@"%s: %@", x, IOHIDDeviceGetProperty(device, CFSTR(x)));
|
||||
#ifdef shortlog
|
||||
#if 0
|
||||
#define shortlog(x) NSLog(@"%s: %@", \
|
||||
x, IOHIDDeviceGetProperty(device, CFSTR(x)));
|
||||
NSLog(@"-------------------------");
|
||||
NSLog(@"Got Device: %@", IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)));
|
||||
NSLog(@"Got Device: %@",
|
||||
IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)));
|
||||
shortlog(kIOHIDTransportKey)
|
||||
shortlog(kIOHIDVendorIDKey)
|
||||
shortlog(kIOHIDVendorIDSourceKey)
|
||||
|
@ -100,77 +127,98 @@ void DeviceDebugPrint(IOHIDDeviceRef device)
|
|||
shortlog(kIOHIDMaxFeatureReportSizeKey)
|
||||
shortlog(kIOHIDReportIntervalKey)
|
||||
shortlog(kIOHIDReportDescriptorKey)
|
||||
#endif
|
||||
#undef shortlog
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void DeviceMatching_callback(void* inContext,
|
||||
IOReturn inResult,
|
||||
void* inSender,
|
||||
IOHIDDeviceRef inIOHIDDeviceRef)
|
||||
IOReturn inResult,
|
||||
void *inSender,
|
||||
IOHIDDeviceRef inIOHIDDeviceRef)
|
||||
{
|
||||
DeviceDebugPrint(inIOHIDDeviceRef);
|
||||
|
||||
std::vector<ControllerInterface::Device*> *devices = (std::vector<ControllerInterface::Device*> *)inContext;
|
||||
|
||||
|
||||
std::vector<ControllerInterface::Device*> *devices =
|
||||
(std::vector<ControllerInterface::Device*> *)inContext;
|
||||
|
||||
// Add to the devices vector if it's of a type we want
|
||||
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard) ||
|
||||
IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad))
|
||||
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef,
|
||||
kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard) ||
|
||||
IOHIDDeviceConformsTo(inIOHIDDeviceRef,
|
||||
kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad))
|
||||
{
|
||||
devices->push_back(new Keyboard(inIOHIDDeviceRef));
|
||||
}
|
||||
|
||||
// We can probably generalize this class for mouse and gamepad inputs
|
||||
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse) /*||
|
||||
IOHIDDeviceConformsTo(inIOHIDDeviceRef, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad)*/)
|
||||
if (IOHIDDeviceConformsTo(inIOHIDDeviceRef,
|
||||
kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse) /*||
|
||||
IOHIDDeviceConformsTo(inIOHIDDeviceRef,
|
||||
kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad)*/)
|
||||
{
|
||||
devices->push_back(new Mouse(inIOHIDDeviceRef));
|
||||
}
|
||||
}
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices )
|
||||
void Init(std::vector<ControllerInterface::Device*>& devices)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
|
||||
HIDManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||
kIOHIDOptionsTypeNone);
|
||||
if (!HIDManager)
|
||||
NSLog(@"Failed to create HID Manager reference");
|
||||
|
||||
|
||||
// HID Manager will give us the following devices:
|
||||
// Keyboard, Keypad, Mouse, GamePad
|
||||
NSArray *matchingDevices =
|
||||
[NSArray arrayWithObjects:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop], @ kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_Keyboard], @ kIOHIDDeviceUsageKey, nil],
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop],
|
||||
@kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_Keyboard],
|
||||
@kIOHIDDeviceUsageKey, nil],
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop], @ kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_Keypad], @ kIOHIDDeviceUsageKey, nil],
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop],
|
||||
@kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_Keypad],
|
||||
@kIOHIDDeviceUsageKey, nil],
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop], @ kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_Mouse], @ kIOHIDDeviceUsageKey, nil],
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop],
|
||||
@kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_Mouse],
|
||||
@kIOHIDDeviceUsageKey, nil],
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop], @ kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_GamePad], @ kIOHIDDeviceUsageKey, nil],
|
||||
[NSNumber numberWithInteger:kHIDPage_GenericDesktop],
|
||||
@kIOHIDDeviceUsagePageKey,
|
||||
[NSNumber numberWithInteger:kHIDUsage_GD_GamePad],
|
||||
@kIOHIDDeviceUsageKey, nil],
|
||||
nil];
|
||||
// Pass NULL to get all devices
|
||||
IOHIDManagerSetDeviceMatchingMultiple(HIDManager, (CFArrayRef)matchingDevices);
|
||||
|
||||
// Callbacks for acquisition or loss of a matching device
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, DeviceMatching_callback, (void *)&devices);
|
||||
IOHIDManagerSetDeviceMatchingMultiple(HIDManager,
|
||||
(CFArrayRef)matchingDevices);
|
||||
|
||||
// Match devices that are plugged right now.
|
||||
IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetCurrent(), OurRunLoop);
|
||||
if (IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
|
||||
// Callbacks for acquisition or loss of a matching device
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(HIDManager,
|
||||
DeviceMatching_callback, (void *)&devices);
|
||||
|
||||
// Match devices that are plugged in right now
|
||||
IOHIDManagerScheduleWithRunLoop(HIDManager,
|
||||
CFRunLoopGetCurrent(), OurRunLoop);
|
||||
if (IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone) !=
|
||||
kIOReturnSuccess)
|
||||
NSLog(@"Failed to open HID Manager");
|
||||
|
||||
|
||||
// Wait while current devices are initialized
|
||||
while (CFRunLoopRunInMode(OurRunLoop,0,TRUE) == kCFRunLoopRunHandledSource);
|
||||
|
||||
// Things should be configured now. Disable hotplugging and other scheduling
|
||||
while (CFRunLoopRunInMode(OurRunLoop, 0, TRUE) ==
|
||||
kCFRunLoopRunHandledSource);
|
||||
|
||||
// Things should be configured now
|
||||
// Disable hotplugging and other scheduling
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, NULL, NULL);
|
||||
IOHIDManagerUnscheduleFromRunLoop(HIDManager, CFRunLoopGetCurrent(), OurRunLoop);
|
||||
|
||||
IOHIDManagerUnscheduleFromRunLoop(HIDManager,
|
||||
CFRunLoopGetCurrent(), OurRunLoop);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
|
@ -184,5 +232,3 @@ void DeInit()
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
|
@ -12,45 +11,47 @@ class Keyboard : public ControllerInterface::Device
|
|||
{
|
||||
friend class ControllerInterface;
|
||||
friend class ControllerInterface::ControlReference;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
class Input : public ControllerInterface::Device::Input
|
||||
{
|
||||
friend class Keyboard;
|
||||
protected:
|
||||
virtual ControlState GetState(IOHIDDeviceRef device) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class Key : public Input
|
||||
{
|
||||
friend class Keyboard;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Key( IOHIDElementRef element );
|
||||
Key(IOHIDElementRef element);
|
||||
ControlState GetState(IOHIDDeviceRef device) const;
|
||||
private:
|
||||
IOHIDElementRef m_element;
|
||||
IOHIDElementRef m_element;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
ControlState GetInputState( const ControllerInterface::Device::Input* const input ) const;
|
||||
void SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state );
|
||||
|
||||
|
||||
ControlState GetInputState(
|
||||
const ControllerInterface::Device::Input* const input) const;
|
||||
void SetOutputState(
|
||||
const ControllerInterface::Device::Output* const output,
|
||||
const ControlState state);
|
||||
|
||||
public:
|
||||
Keyboard(IOHIDDeviceRef device);
|
||||
|
||||
|
||||
std::string GetName() const;
|
||||
std::string GetSource() const;
|
||||
int GetId() const;
|
||||
|
||||
|
||||
private:
|
||||
IOHIDDeviceRef m_device;
|
||||
std::string m_device_name;
|
||||
std::string m_device_name;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_OSX
|
||||
|
||||
#include "OSXKeyboard.h"
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
#include "OSXKeyboard.h"
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace OSX
|
||||
{
|
||||
|
||||
|
||||
struct PrettyKeys
|
||||
const struct PrettyKeys
|
||||
{
|
||||
const uint32_t code;
|
||||
const char* const name;
|
||||
|
@ -21,50 +19,54 @@ struct PrettyKeys
|
|||
#include "NamedKeys.h"
|
||||
};
|
||||
|
||||
extern void DeviceElementDebugPrint(const void*, void*);
|
||||
|
||||
extern void DeviceElementDebugPrint(const void *, void *);
|
||||
|
||||
Keyboard::Keyboard(IOHIDDeviceRef device)
|
||||
: m_device(device)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
m_device_name = [(NSString *)IOHIDDeviceGetProperty(m_device, CFSTR(kIOHIDProductKey)) UTF8String];
|
||||
|
||||
|
||||
m_device_name = [(NSString *)IOHIDDeviceGetProperty(m_device,
|
||||
CFSTR(kIOHIDProductKey)) UTF8String];
|
||||
|
||||
// This class should only recieve Keyboard or Keypad devices
|
||||
// Now, filter on just the buttons we can handle sanely
|
||||
NSDictionary *matchingElements =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInteger:kIOHIDElementTypeInput_Button], @ kIOHIDElementTypeKey,
|
||||
[NSNumber numberWithInteger:0], @ kIOHIDElementMinKey,
|
||||
[NSNumber numberWithInteger:1], @ kIOHIDElementMaxKey,
|
||||
[NSNumber numberWithInteger:kIOHIDElementTypeInput_Button],
|
||||
@kIOHIDElementTypeKey,
|
||||
[NSNumber numberWithInteger: 0], @kIOHIDElementMinKey,
|
||||
[NSNumber numberWithInteger: 1], @kIOHIDElementMaxKey,
|
||||
nil];
|
||||
|
||||
CFArrayRef elements =
|
||||
IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)matchingElements, kIOHIDOptionsTypeNone);
|
||||
|
||||
|
||||
CFArrayRef elements = IOHIDDeviceCopyMatchingElements(m_device,
|
||||
(CFDictionaryRef)matchingElements, kIOHIDOptionsTypeNone);
|
||||
|
||||
if (elements)
|
||||
{
|
||||
for (int i = 0; i < CFArrayGetCount(elements); i++)
|
||||
{
|
||||
IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
|
||||
IOHIDElementRef e =
|
||||
(IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
|
||||
//DeviceElementDebugPrint(e, NULL);
|
||||
|
||||
try { AddInput(new Key(e)); }
|
||||
catch (std::bad_alloc&) { /*Thrown if the key is reserved*/ }
|
||||
|
||||
AddInput(new Key(e));
|
||||
}
|
||||
CFRelease(elements);
|
||||
}
|
||||
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
ControlState Keyboard::GetInputState( const ControllerInterface::Device::Input* const input ) const
|
||||
ControlState Keyboard::GetInputState(
|
||||
const ControllerInterface::Device::Input* const input) const
|
||||
{
|
||||
return ((Input*)input)->GetState(m_device);
|
||||
}
|
||||
|
||||
void Keyboard::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
|
||||
void Keyboard::SetOutputState(
|
||||
const ControllerInterface::Device::Output * const output,
|
||||
const ControlState state)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -85,20 +87,20 @@ std::string Keyboard::GetName() const
|
|||
|
||||
std::string Keyboard::GetSource() const
|
||||
{
|
||||
return "OSX";
|
||||
return "HID";
|
||||
}
|
||||
|
||||
int Keyboard::GetId() const
|
||||
{
|
||||
return 0;
|
||||
// Overload the "id" to identify devices by HID type when names collide
|
||||
return kHIDUsage_GD_Keyboard;
|
||||
}
|
||||
|
||||
|
||||
Keyboard::Key::Key(IOHIDElementRef element)
|
||||
: m_element(element)
|
||||
, m_name("RESERVED") // for some reason HID Manager gives these to us.
|
||||
{
|
||||
uint32_t keycode = IOHIDElementGetUsage(m_element);
|
||||
|
||||
for (uint32_t i = 0; i < sizeof(named_keys)/sizeof(*named_keys); i++)
|
||||
{
|
||||
if (named_keys[i].code == keycode)
|
||||
|
@ -107,14 +109,18 @@ Keyboard::Key::Key(IOHIDElementRef element)
|
|||
return;
|
||||
}
|
||||
}
|
||||
NSLog(@"Got key 0x%x of type RESERVED", IOHIDElementGetUsage(m_element));
|
||||
|
||||
m_name = "RESERVED"; /* XXX */
|
||||
}
|
||||
|
||||
ControlState Keyboard::Key::GetState(IOHIDDeviceRef device) const
|
||||
{
|
||||
IOHIDValueRef value;
|
||||
if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
|
||||
|
||||
if (IOHIDDeviceGetValue(device, m_element, &value) ==
|
||||
kIOReturnSuccess) {
|
||||
return IOHIDValueGetIntegerValue(value) > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -127,5 +133,3 @@ std::string Keyboard::Key::GetName() const
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
|
@ -12,29 +11,28 @@ class Mouse : public ControllerInterface::Device
|
|||
{
|
||||
friend class ControllerInterface;
|
||||
friend class ControllerInterface::ControlReference;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
class Input : public ControllerInterface::Device::Input
|
||||
{
|
||||
friend class Mouse;
|
||||
protected:
|
||||
virtual ControlState GetState(IOHIDDeviceRef device) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class Button : public Input
|
||||
{
|
||||
friend class Mouse;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Button( IOHIDElementRef element );
|
||||
Button(IOHIDElementRef element);
|
||||
ControlState GetState(IOHIDDeviceRef device) const;
|
||||
private:
|
||||
IOHIDElementRef m_element;
|
||||
IOHIDElementRef m_element;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
|
||||
class Axis : public Input
|
||||
{
|
||||
friend class Mouse;
|
||||
|
@ -45,31 +43,34 @@ protected:
|
|||
};
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Axis( IOHIDElementRef element, direction dir );
|
||||
Axis(IOHIDElementRef element, direction dir);
|
||||
ControlState GetState(IOHIDDeviceRef device) const;
|
||||
private:
|
||||
IOHIDElementRef m_element;
|
||||
IOHIDElementRef m_element;
|
||||
std::string m_name;
|
||||
direction m_direction;
|
||||
float m_range;
|
||||
};
|
||||
|
||||
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
ControlState GetInputState( const ControllerInterface::Device::Input* const input ) const;
|
||||
void SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state );
|
||||
|
||||
|
||||
ControlState GetInputState(
|
||||
const ControllerInterface::Device::Input* const input) const;
|
||||
void SetOutputState(
|
||||
const ControllerInterface::Device::Output* const output,
|
||||
const ControlState state);
|
||||
|
||||
public:
|
||||
Mouse(IOHIDDeviceRef device);
|
||||
|
||||
|
||||
std::string GetName() const;
|
||||
std::string GetSource() const;
|
||||
int GetId() const;
|
||||
|
||||
|
||||
private:
|
||||
IOHIDDeviceRef m_device;
|
||||
std::string m_device_name;
|
||||
std::string m_device_name;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_OSX
|
||||
|
||||
#include "OSXMouse.h"
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
#include "OSXMouse.h"
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace OSX
|
||||
|
@ -13,67 +11,75 @@ namespace OSX
|
|||
|
||||
extern void DeviceElementDebugPrint(const void*, void*);
|
||||
|
||||
|
||||
Mouse::Mouse(IOHIDDeviceRef device)
|
||||
: m_device(device)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
m_device_name = [(NSString *)IOHIDDeviceGetProperty(m_device, CFSTR(kIOHIDProductKey)) UTF8String];
|
||||
|
||||
|
||||
m_device_name = [(NSString *)IOHIDDeviceGetProperty(m_device,
|
||||
CFSTR(kIOHIDProductKey)) UTF8String];
|
||||
|
||||
// Buttons
|
||||
NSDictionary *buttonDict =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInteger:kIOHIDElementTypeInput_Button], @ kIOHIDElementTypeKey,
|
||||
[NSNumber numberWithInteger:kHIDPage_Button], @ kIOHIDElementUsagePageKey,
|
||||
[NSNumber numberWithInteger:kIOHIDElementTypeInput_Button],
|
||||
@kIOHIDElementTypeKey,
|
||||
[NSNumber numberWithInteger:kHIDPage_Button],
|
||||
@kIOHIDElementUsagePageKey,
|
||||
nil];
|
||||
|
||||
CFArrayRef buttons =
|
||||
IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)buttonDict, kIOHIDOptionsTypeNone);
|
||||
|
||||
|
||||
CFArrayRef buttons = IOHIDDeviceCopyMatchingElements(m_device,
|
||||
(CFDictionaryRef)buttonDict, kIOHIDOptionsTypeNone);
|
||||
|
||||
if (buttons)
|
||||
{
|
||||
for (int i = 0; i < CFArrayGetCount(buttons); i++)
|
||||
{
|
||||
IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(buttons, i);
|
||||
IOHIDElementRef e =
|
||||
(IOHIDElementRef)CFArrayGetValueAtIndex(buttons, i);
|
||||
//DeviceElementDebugPrint(e, NULL);
|
||||
|
||||
|
||||
AddInput(new Button(e));
|
||||
}
|
||||
CFRelease(buttons);
|
||||
}
|
||||
|
||||
|
||||
// Axes
|
||||
NSDictionary *axisDict =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInteger:kIOHIDElementTypeInput_Misc], @ kIOHIDElementTypeKey,
|
||||
[NSNumber numberWithInteger:kIOHIDElementTypeInput_Misc],
|
||||
@kIOHIDElementTypeKey,
|
||||
nil];
|
||||
|
||||
CFArrayRef axes =
|
||||
IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)axisDict, kIOHIDOptionsTypeNone);
|
||||
|
||||
|
||||
CFArrayRef axes = IOHIDDeviceCopyMatchingElements(m_device,
|
||||
(CFDictionaryRef)axisDict, kIOHIDOptionsTypeNone);
|
||||
|
||||
if (axes)
|
||||
{
|
||||
for (int i = 0; i < CFArrayGetCount(axes); i++)
|
||||
{
|
||||
IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(axes, i);
|
||||
IOHIDElementRef e =
|
||||
(IOHIDElementRef)CFArrayGetValueAtIndex(axes, i);
|
||||
//DeviceElementDebugPrint(e, NULL);
|
||||
|
||||
|
||||
AddInput(new Axis(e, Axis::negative));
|
||||
AddInput(new Axis(e, Axis::positive));
|
||||
}
|
||||
CFRelease(axes);
|
||||
}
|
||||
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
ControlState Mouse::GetInputState( const ControllerInterface::Device::Input* const input ) const
|
||||
ControlState Mouse::GetInputState(
|
||||
const ControllerInterface::Device::Input* const input) const
|
||||
{
|
||||
return ((Input*)input)->GetState(m_device);
|
||||
}
|
||||
|
||||
void Mouse::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
|
||||
void Mouse::SetOutputState(
|
||||
const ControllerInterface::Device::Output* const output,
|
||||
const ControlState state)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -94,12 +100,13 @@ std::string Mouse::GetName() const
|
|||
|
||||
std::string Mouse::GetSource() const
|
||||
{
|
||||
return "OSX";
|
||||
return "HID";
|
||||
}
|
||||
|
||||
int Mouse::GetId() const
|
||||
{
|
||||
return 0;
|
||||
// Overload the "id" to identify devices by HID type when names collide
|
||||
return kHIDUsage_GD_Mouse;
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,21 +139,29 @@ Mouse::Axis::Axis(IOHIDElementRef element, direction dir)
|
|||
{
|
||||
// Need to parse the element a bit first
|
||||
std::string description("unk");
|
||||
|
||||
switch (IOHIDElementGetUsage(m_element))
|
||||
{
|
||||
default:
|
||||
NSLog(@"Unknown axis type 0x%x, using anyways...", IOHIDElementGetUsage(m_element));
|
||||
break;
|
||||
case kHIDUsage_GD_X: description = "X"; break;
|
||||
case kHIDUsage_GD_Y: description = "Y"; break;
|
||||
case kHIDUsage_GD_Wheel: description = "Wheel"; break;
|
||||
case kHIDUsage_Csmr_ACPan: description = "Pan"; break;
|
||||
|
||||
switch (IOHIDElementGetUsage(m_element)) {
|
||||
default:
|
||||
NSLog(@"Unknown axis type 0x%x, using it anyway...",
|
||||
IOHIDElementGetUsage(m_element));
|
||||
break;
|
||||
case kHIDUsage_GD_X:
|
||||
description = "X";
|
||||
break;
|
||||
case kHIDUsage_GD_Y:
|
||||
description = "Y";
|
||||
break;
|
||||
case kHIDUsage_GD_Wheel:
|
||||
description = "Wheel";
|
||||
break;
|
||||
case kHIDUsage_Csmr_ACPan:
|
||||
description = "Pan";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
m_name = std::string("Axis ") + description;
|
||||
m_name.append((m_direction == positive) ? "+" : "-");
|
||||
|
||||
|
||||
// yeah, that factor is completely random :/
|
||||
m_range = (float)IOHIDElementGetLogicalMax(m_element) / 1000.;
|
||||
}
|
||||
|
@ -154,22 +169,22 @@ Mouse::Axis::Axis(IOHIDElementRef element, direction dir)
|
|||
ControlState Mouse::Axis::GetState(IOHIDDeviceRef device) const
|
||||
{
|
||||
IOHIDValueRef value;
|
||||
if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
|
||||
if (IOHIDDeviceGetValue(device, m_element, &value) == kIOReturnSuccess)
|
||||
{
|
||||
int int_value = IOHIDValueGetIntegerValue(value);
|
||||
|
||||
|
||||
if (((int_value < 0) && (m_direction == positive)) ||
|
||||
((int_value > 0) && (m_direction == negative)) ||
|
||||
!int_value)
|
||||
return false;
|
||||
|
||||
|
||||
float actual_value = abs(int_value) / m_range;
|
||||
|
||||
|
||||
//NSLog(@"%s %i %f", m_name.c_str(), int_value, actual_value);
|
||||
|
||||
|
||||
return actual_value;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -181,5 +196,3 @@ std::string Mouse::Axis::GetName() const
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue