]> git.mxchange.org Git - flightgear.git/blob - src/Input/FGMacOSXEventInput.hxx
Allow setting of NED velocities.
[flightgear.git] / src / Input / FGMacOSXEventInput.hxx
1 // FGMacOSXEventInput.hxx -- handle event driven input devices for Mac OS X
2 //
3 // Written by Tatsuhiro Nishioka, started Aug. 2009.
4 //
5 // Copyright (C) 2009 Tasuhiro Nishioka, tat <dot> fgmacosx <at> gmail <dot> com
6 //
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.
11 //
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.
16 //
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.
20 //
21 // $Id$
22
23 #ifndef __FGMACOSXEVENTINPUT_HXX_
24 #define __FGMACOSXEVENTINPUT_HXX_
25
26 #include <iostream>
27 #include <string>
28 #include <vector>
29 #include <map>
30 #include <sstream>
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>
39
40 #ifndef _TEST
41 #include "FGEventInput.hxx"
42 #endif
43
44 typedef enum {
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?
57   // FG specific types
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 
60 } HIDUsageType;
61   
62
63 class HIDElement;
64 struct FGMacOSXEventData : public FGEventData {
65   FGMacOSXEventData(std::string name, double value, double dt, int modifiers) : 
66     FGEventData(value, dt, modifiers), name(name) {}
67   std::string name;
68 };
69
70
71 struct HIDTypes {
72   long key;
73   HIDUsageType type;
74   const char *eventName;
75 };
76
77 class FGMacOSXInputDevice;
78
79 //
80 // Generic HIDElement that might work for DV, DF types
81 // 
82 class HIDElement {
83 public:
84   HIDElement(CFDictionaryRef element, long page, long usage);
85   virtual ~HIDElement() {}
86   virtual float readStatus(IOHIDDeviceInterface **interface);
87   bool isUpdated();
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; 
92   }
93 protected:
94   IOHIDElementCookie cookie;
95   long type;
96   long page;
97   long usage;
98   float value;
99   float lastValue;
100
101   std::string name;
102 };
103
104 class AxisElement : public HIDElement {
105 public:
106   AxisElement(CFDictionaryRef element, long page, long usage);
107   virtual ~AxisElement() {}
108   virtual float readStatus(IOHIDDeviceInterface **interface);
109 private:
110   long min;
111   long max;
112   float dead_band;
113   float saturate;
114   long center;
115   bool isRelative;
116   bool isWrapping;
117   bool isNonLinear;
118 };
119
120 class ButtonElement : public HIDElement {
121 public:
122   ButtonElement(CFDictionaryRef element, long page, long usage);
123   virtual ~ButtonElement() {}
124 };
125
126 class HatElement : public HIDElement {
127 public:
128   HatElement(CFDictionaryRef element, long page, long usage, int id);
129   virtual ~HatElement() {}
130   virtual void generateEvent(FGMacOSXInputDevice *device, double dt, int modifiers);
131 private:
132   int id;
133   long min;
134   long max;
135 };
136
137 class LEDElement : public HIDElement {
138 public:
139   LEDElement(CFDictionaryRef element, long page, long usage);
140   virtual ~LEDElement() {}
141   virtual void write(IOHIDDeviceInterface **interface, double value);
142 };
143
144 class FeatureElement : public HIDElement {
145 public:
146   FeatureElement(CFDictionaryRef element, long page, long usage, int count);
147   virtual ~FeatureElement() {}
148   virtual float readStatus(IOHIDDeviceInterface **inerface);
149 };
150
151 //
152 // FGMacOSXInputDevice
153 //
154 class FGMacOSXInputDevice : public FGInputDevice {
155 public:
156   FGMacOSXInputDevice(io_object_t device);
157   virtual ~FGMacOSXInputDevice() { Close(); }
158   void Open();
159   void Close();
160   void readStatus();
161   virtual void update(double dt);
162   virtual const char *TranslateEventName(FGEventData &eventData);
163
164   CFDictionaryRef getProperties() {
165     return FGMacOSXInputDevice::getProperties(device); 
166   }
167   static CFDictionaryRef getProperties(io_object_t device); 
168   void addElement(HIDElement *element);
169   void Send( const char *eventName, double value);
170
171 private:
172   io_object_t device;
173   IOHIDDeviceInterface **devInterface;
174   std::map<std::string, HIDElement *> elements;
175 };
176
177 //
178 // HID element parser
179 //
180 class HIDElementFactory {
181 public:
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);
185 };
186
187 //
188 //
189 //
190 class FGMacOSXEventInput : public FGEventInput {
191 public:
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); 
196   }
197   static void deviceDetached(void *ref, io_iterator_t iterator) { 
198     FGMacOSXEventInput::instance().detachDevice(iterator); 
199   }
200   static FGMacOSXEventInput &instance();
201
202   void attachDevice(io_iterator_t iterator);
203   void detachDevice(io_iterator_t iterator);
204   virtual void update(double dt);
205
206   virtual void init();
207
208   static FGMacOSXEventInput *_instance;
209 private:
210   IONotificationPortRef notifyPort;
211   CFRunLoopSourceRef runLoopSource;
212   io_iterator_t addedIterator; 
213   io_iterator_t removedIterator;
214
215   std::map<io_object_t, unsigned> deviceIndices;
216 };
217
218
219 //
220 // For debug and warnings
221 // 
222 class HIDTypeByID : public std::map<long, std::pair<HIDUsageType, const char *>*> {
223 public:
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);
227   }
228
229   ~HIDTypeByID() {
230     std::map<long, std::pair<HIDUsageType, const char *>*>::iterator it;
231     for (it = this->begin(); it != this->end(); it++) {
232       delete (*it).second;
233     }
234     clear();
235   }
236
237   const char *getName(long key) {
238     std::pair<HIDUsageType, const char *> *usageType = (*this)[key];
239     if (usageType == NULL) {
240       return "";
241     } else {
242       return usageType->second;
243     }
244   }
245
246   const HIDUsageType getType(long key) {
247     std::pair<HIDUsageType, const char *> *usageType = (*this)[key];
248     if (usageType == NULL) {
249       return kHIDUsageNotSupported;
250     } else {
251       return usageType->first;
252     }
253   }
254 };
255
256 #endif