1 // FGMacOSXEventInput.hxx -- handle event driven input devices for Mac OS X
3 // Written by Tatsuhiro Nishioka, started Aug. 2009.
5 // Copyright (C) 2009 Tasuhiro Nishioka, tat <dot> fgmacosx <at> gmail <dot> com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #ifndef __FGMACOSXEVENTINPUT_HXX_
24 #define __FGMACOSXEVENTINPUT_HXX_
31 #include <mach/mach.h>
32 #include <mach/mach_error.h>
33 #include <IOKit/IOKitLib.h>
34 #include <IOKit/hid/IOHIDLib.h>
35 #include <IOKit/hid/IOHIDKeys.h>
36 #include <IOKit/IOCFPlugIn.h>
37 #include <CoreFoundation/CoreFoundation.h>
38 #include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
41 #include "FGEventInput.hxx"
45 kHIDUsageNotSupported = -1, // Debug use
46 kHIDElementType = 0, // Debug use
47 kHIDElementPage, // Debug use
48 kHIDUsageSel, // Selector; Contained in a Named Array - not supported yet
49 kHIDUsageSV, // Static Value; Axis?(Constant, Variable, Absolute) - not supported yet
50 kHIDUsageSF, // Static Flag; Axis?(Constant, Variable, Absolute) - not supported yet
51 kHIDUsageDV, // Dynamic Value; Axis(Data, Variable, Absolute)
52 kHIDUsageDF, // Dynamic Flag; Axis?(Data, Variable, Absolute) - not supported yet
53 kHIDUsageOOC, // On/Off Control; Button?
54 kHIDUsageMC, // Momentary Control; Button
55 kHIDUsageOSC, // One Shot Control; Button
56 kHIDUsageRTC, // Re-trigger Control; Button?
58 kHIDUsageHat, // HatSwitch ; a special usage of DV that generates two FGInputEvent instances
59 kHIDUsageAxis, // Axis; a special usage of DV that has either abs- or rel- prefix
64 struct FGMacOSXEventData : public FGEventData {
65 FGMacOSXEventData(std::string name, double value, double dt, int modifiers) :
66 FGEventData(value, dt, modifiers), name(name) {}
74 const char *eventName;
77 class FGMacOSXInputDevice;
80 // Generic HIDElement that might work for DV, DF types
84 HIDElement(CFDictionaryRef element, long page, long usage);
85 virtual ~HIDElement() {}
86 virtual float readStatus(IOHIDDeviceInterface **interface);
88 virtual void generateEvent(FGMacOSXInputDevice *device, double dt, int modifiers);
89 std::string getName() { return name; }
90 virtual void write(IOHIDDeviceInterface **interface, double value) {
91 std::cout << "writing is not implemented on this device: " << name << std::endl;
94 IOHIDElementCookie cookie;
104 class AxisElement : public HIDElement {
106 AxisElement(CFDictionaryRef element, long page, long usage);
107 virtual ~AxisElement() {}
108 virtual float readStatus(IOHIDDeviceInterface **interface);
120 class ButtonElement : public HIDElement {
122 ButtonElement(CFDictionaryRef element, long page, long usage);
123 virtual ~ButtonElement() {}
126 class HatElement : public HIDElement {
128 HatElement(CFDictionaryRef element, long page, long usage, int id);
129 virtual ~HatElement() {}
130 virtual void generateEvent(FGMacOSXInputDevice *device, double dt, int modifiers);
137 class LEDElement : public HIDElement {
139 LEDElement(CFDictionaryRef element, long page, long usage);
140 virtual ~LEDElement() {}
141 virtual void write(IOHIDDeviceInterface **interface, double value);
144 class FeatureElement : public HIDElement {
146 FeatureElement(CFDictionaryRef element, long page, long usage, int count);
147 virtual ~FeatureElement() {}
148 virtual float readStatus(IOHIDDeviceInterface **inerface);
152 // FGMacOSXInputDevice
154 class FGMacOSXInputDevice : public FGInputDevice {
156 FGMacOSXInputDevice(io_object_t device);
157 virtual ~FGMacOSXInputDevice() { Close(); }
161 virtual void update(double dt);
162 virtual const char *TranslateEventName(FGEventData &eventData);
164 CFDictionaryRef getProperties() {
165 return FGMacOSXInputDevice::getProperties(device);
167 static CFDictionaryRef getProperties(io_object_t device);
168 void addElement(HIDElement *element);
169 void Send( const char *eventName, double value);
173 IOHIDDeviceInterface **devInterface;
174 std::map<std::string, HIDElement *> elements;
178 // HID element parser
180 class HIDElementFactory {
182 static void create(CFTypeRef element, FGMacOSXInputDevice *inputDevice);
183 static void elementEnumerator( const void *element, void *inputDevice);
184 static void parseElement(CFDictionaryRef element, FGMacOSXInputDevice *device);
190 class FGMacOSXEventInput : public FGEventInput {
192 FGMacOSXEventInput() : FGEventInput() { FGMacOSXEventInput::_instance = this; SG_LOG(SG_INPUT, SG_ALERT, "FGMacOSXEventInput created"); }
193 virtual ~FGMacOSXEventInput();
194 static void deviceAttached(void *ref, io_iterator_t iterator) {
195 FGMacOSXEventInput::instance().attachDevice(iterator);
197 static void deviceDetached(void *ref, io_iterator_t iterator) {
198 FGMacOSXEventInput::instance().detachDevice(iterator);
200 static FGMacOSXEventInput &instance();
202 void attachDevice(io_iterator_t iterator);
203 void detachDevice(io_iterator_t iterator);
204 virtual void update(double dt);
208 static FGMacOSXEventInput *_instance;
210 IONotificationPortRef notifyPort;
211 CFRunLoopSourceRef runLoopSource;
212 io_iterator_t addedIterator;
213 io_iterator_t removedIterator;
215 std::map<io_object_t, unsigned> deviceIndices;
220 // For debug and warnings
222 class HIDTypeByID : public std::map<long, std::pair<HIDUsageType, const char *>*> {
224 HIDTypeByID(struct HIDTypes *table) {
225 for( int i = 0; table[i].key!= -1; i++ )
226 (*this)[table[i].key] = new std::pair<HIDUsageType, const char *>(table[i].type, table[i].eventName);
230 std::map<long, std::pair<HIDUsageType, const char *>*>::iterator it;
231 for (it = this->begin(); it != this->end(); it++) {
237 const char *getName(long key) {
238 std::pair<HIDUsageType, const char *> *usageType = (*this)[key];
239 if (usageType == NULL) {
242 return usageType->second;
246 const HIDUsageType getType(long key) {
247 std::pair<HIDUsageType, const char *> *usageType = (*this)[key];
248 if (usageType == NULL) {
249 return kHIDUsageNotSupported;
251 return usageType->first;