1
0
Fork 0

Rewrite Mac Event-Input code

This commit is contained in:
James Turner 2016-09-28 21:11:47 -05:00
parent 347a89c1f2
commit c4f584dadf
3 changed files with 552 additions and 924 deletions

View file

@ -210,6 +210,7 @@ include( ConfigureMsvc3rdParty )
if(EVENT_INPUT) if(EVENT_INPUT)
if(APPLE) if(APPLE)
add_definitions(-DWITH_EVENTINPUT)
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(NOT UDEV_FOUND) if(NOT UDEV_FOUND)
message(WARNING "UDev not found, event input is disabled!") message(WARNING "UDev not found, event input is disabled!")

File diff suppressed because it is too large Load diff

View file

@ -23,247 +23,38 @@
#ifndef __FGMACOSXEVENTINPUT_HXX_ #ifndef __FGMACOSXEVENTINPUT_HXX_
#define __FGMACOSXEVENTINPUT_HXX_ #define __FGMACOSXEVENTINPUT_HXX_
#include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <sstream> #include <memory>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/IOCFPlugIn.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
#ifndef _TEST
#include "FGEventInput.hxx" #include "FGEventInput.hxx"
#endif
// class FGMacOSXEventInputPrivate;
// HID Usage type
// HIDElementFactory will create a proper HIDElement subclass
// depending on the usage type of a detected HID element
// See http://www.usb.org/developers/devclass_docs/Hut1_12.pdf for detail
//
typedef enum {
kHIDUsageNotSupported = -1, // Debug use
kHIDElementType = 0, // Debug use
kHIDElementPage, // Debug use
kHIDUsageSel, // Selector; Contained in a Named Array - not supported yet
kHIDUsageSV, // Static Value; Axis?(Constant, Variable, Absolute) - not supported yet
kHIDUsageSF, // Static Flag; Axis?(Constant, Variable, Absolute) - not supported yet
kHIDUsageDV, // Dynamic Value; Axis(Data, Variable, Absolute)
kHIDUsageDF, // Dynamic Flag; Axis?(Data, Variable, Absolute) - not supported yet
kHIDUsageOOC, // On/Off Control; Button?
kHIDUsageMC, // Momentary Control; Button
kHIDUsageOSC, // One Shot Control; Button
kHIDUsageRTC, // Re-trigger Control; Button?
// FG specific types
kHIDUsageHat, // HatSwitch ; a special usage of DV that generates two FGInputEvent instances
kHIDUsageAxis, // Axis; a special usage of DV that has either abs- or rel- prefix
} HIDUsageType;
class HIDElement;
struct FGMacOSXEventData : public FGEventData { struct FGMacOSXEventData : public FGEventData {
FGMacOSXEventData(std::string name, double value, double dt, int modifiers) : FGMacOSXEventData(std::string name, double value, double dt, int modifiers) :
FGEventData(value, dt, modifiers), name(name) {} FGEventData(value, dt, modifiers), name(name) {}
std::string name; std::string name;
}; };
//
// For mapping HID element page/usage, usage type, and event names
//
struct HIDTypes {
long key;
HIDUsageType type;
const char *eventName;
};
class FGMacOSXInputDevice;
//
// Generic HIDElement for DV, DF types
//
class HIDElement {
public:
HIDElement(CFDictionaryRef element, long page, long usage);
virtual ~HIDElement() {}
bool isUpdated();
std::string getName() { return name; }
virtual void generateEvent(FGMacOSXInputDevice *device, double dt, int modifiers);
virtual long read(IOHIDDeviceInterface **interface);
virtual void write(IOHIDDeviceInterface **interface, double value) {
SG_LOG(SG_INPUT, SG_WARN, "writing is not implemented on this device: " << name);
}
protected:
IOHIDElementCookie cookie;
long type;
long page;
long usage;
float value;
float lastValue;
std::string name;
};
class AxisElement : public HIDElement {
public:
AxisElement(CFDictionaryRef element, long page, long usage);
virtual ~AxisElement() {}
virtual long read(IOHIDDeviceInterface **interface);
virtual void generateEvent(FGMacOSXInputDevice *device, double dt, int modifiers);
private:
long min;
long max;
float dead_band;
long center;
bool isRelative;
bool isWrapping;
bool isNonLinear;
};
class ButtonElement : public HIDElement {
public:
ButtonElement(CFDictionaryRef element, long page, long usage);
virtual ~ButtonElement() {}
private:
};
class HatElement : public HIDElement {
public:
HatElement(CFDictionaryRef element, long page, long usage, int id);
virtual ~HatElement() {}
virtual void generateEvent(FGMacOSXInputDevice *device, double dt, int modifiers);
private:
int id;
long min;
long max;
};
class LEDElement : public HIDElement {
public:
LEDElement(CFDictionaryRef element, long page, long usage);
virtual ~LEDElement() {}
virtual void write(IOHIDDeviceInterface **interface, double value);
};
class FeatureElement : public HIDElement {
public:
FeatureElement(CFDictionaryRef element, long page, long usage, int count);
virtual ~FeatureElement() {}
virtual long read(IOHIDDeviceInterface **inerface);
};
//
// FGMacOSXInputDevice
// Mac OS X specific FGInputDevice
//
class FGMacOSXInputDevice : public FGInputDevice {
public:
FGMacOSXInputDevice(io_object_t device);
virtual ~FGMacOSXInputDevice() { Close(); }
void Open();
void Close();
virtual void update(double dt);
virtual const char *TranslateEventName(FGEventData &eventData);
void Send( const char *eventName, double value);
// Mac OS X specific methods
CFDictionaryRef getProperties() {
return FGMacOSXInputDevice::getProperties(device);
}
static CFDictionaryRef getProperties(io_object_t device);
void addElement(HIDElement *element);
private:
io_object_t device;
IOHIDDeviceInterface **devInterface;
std::map<std::string, HIDElement *> elements; // maps eventName and its relevant element for Send()
};
//
// HID element factory that iteratively parses and creates
// HIDElement instances and add these to FGMacOSXDeviceInput
//
class HIDElementFactory {
public:
static void create(CFTypeRef element, FGMacOSXInputDevice *inputDevice);
static void elementEnumerator( const void *element, void *inputDevice);
static void parseElement(CFDictionaryRef element, FGMacOSXInputDevice *device);
};
// //
// Mac OS X specific FGEventInput // Mac OS X specific FGEventInput
// //
class FGMacOSXEventInput : public FGEventInput { class FGMacOSXEventInput : public FGEventInput {
public: public:
FGMacOSXEventInput() : FGEventInput() { SG_LOG(SG_INPUT, SG_DEBUG, "FGMacOSXEventInput created"); } FGMacOSXEventInput();
virtual ~FGMacOSXEventInput(); virtual ~FGMacOSXEventInput();
virtual void update(double dt); virtual void update(double dt);
virtual void init(); virtual void init();
virtual void postinit();
// Mac OS X specific methods virtual void shutdown();
static void deviceAttached(void *device, io_iterator_t iterator) {
static_cast<FGMacOSXEventInput *>(device)->attachDevice(iterator);
}
static void deviceDetached(void *device, io_iterator_t iterator) {
static_cast<FGMacOSXEventInput *>(device)->detachDevice(iterator);
}
void attachDevice(io_iterator_t iterator);
void detachDevice(io_iterator_t iterator);
private: private:
IONotificationPortRef notifyPort; friend class FGMacOSXEventInputPrivate;
CFRunLoopSourceRef runLoopSource;
io_iterator_t addedIterator;
io_iterator_t removedIterator;
// maps FG device property ID (i.e. /input/events/device[ID]) with io_object for detaching devices std::auto_ptr<FGMacOSXEventInputPrivate> d;
std::map<io_object_t, unsigned> deviceIndices;
};
//
// For obtaining event name and type from both HID element page and usage
//
class HIDTypeByID : public std::map<long, std::pair<HIDUsageType, const char *>*> {
public:
HIDTypeByID(struct HIDTypes *table) {
for( int i = 0; table[i].key!= -1; i++ )
(*this)[table[i].key] = new std::pair<HIDUsageType, const char *>(table[i].type, table[i].eventName);
}
~HIDTypeByID() {
std::map<long, std::pair<HIDUsageType, const char *>*>::iterator it;
for (it = this->begin(); it != this->end(); it++) {
delete (*it).second;
}
clear();
}
// key = (HID_element_page) << 16 | HID_element_usage)
const char *getName(long key) {
std::pair<HIDUsageType, const char *> *usageType = (*this)[key];
if (usageType == NULL) {
return "";
} else {
return usageType->second;
}
}
const HIDUsageType getType(long key) {
std::pair<HIDUsageType, const char *> *usageType = (*this)[key];
if (usageType == NULL) {
return kHIDUsageNotSupported;
} else {
return usageType->first;
}
}
}; };
#endif #endif