1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: DARWIN HID layer for WX Implementation
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "hid.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
34 #include "wx/mac/carbon/private/hid.h"
35 #include "wx/string.h"
39 // ---------------------------------------------------------------------------
41 // ---------------------------------------------------------------------------
43 #define wxFORCECHECK_MSG(arg, msg) \
47 wxLogSysError(wxString::Format(wxT("Message:%s\nHID: %s failed!"), wxT(msg), wxT(#arg)));\
51 #define wxIOCHECK(arg, msg) wxFORCECHECK_MSG(arg != kIOReturnSuccess, msg)
52 #define wxKERNCHECK(arg, msg) wxFORCECHECK_MSG(arg != KERN_SUCCESS, msg)
53 #define wxSCHECK(arg, msg) wxFORCECHECK_MSG(arg != S_OK, msg)
56 # define wxVERIFY(arg) wxASSERT(arg)
58 # define wxVERIFY(arg) arg
62 void CFShowTypeIDDescription(CFTypeRef pData)
71 CFStringGetCStringPtr(
72 CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding()
78 // ============================================================================
80 // ============================================================================
82 // ---------------------------------------------------------------------------
84 // ---------------------------------------------------------------------------
86 bool wxHIDDevice::Create (const int& nClass
, const int& nType
)
88 //Create the mach port
89 wxIOCHECK(IOMasterPort(bootstrap_port
, &m_pPort
), "Could not create mach port");
91 //Dictionary that will hold first
92 //the matching dictionary for determining which kind of devices we want,
93 //then later some registry properties from an iterator (see below)
94 CFMutableDictionaryRef pDictionary
;
97 //The call to IOServiceMatching filters down the
98 //the services we want to hid services (and also eats the
99 //dictionary up for us (consumes one reference))
100 wxVERIFY((pDictionary
= IOServiceMatching(kIOHIDDeviceKey
)) != NULL
);
102 //Here we'll filter down the services to what we want
105 CFNumberRef pType
= CFNumberCreate(kCFAllocatorDefault
,
106 kCFNumberIntType
, &nType
);
107 CFDictionarySetValue(pDictionary
, CFSTR(kIOHIDPrimaryUsageKey
), pType
);
112 CFNumberRef pClass
= CFNumberCreate(kCFAllocatorDefault
,
113 kCFNumberIntType
, &nClass
);
114 CFDictionarySetValue(pDictionary
, CFSTR(kIOHIDPrimaryUsagePageKey
), pClass
);
118 //Now get the maching services
119 io_iterator_t pIterator
;
120 wxIOCHECK(IOServiceGetMatchingServices(m_pPort
, pDictionary
, &pIterator
), "No Matching HID Services");
121 wxASSERT(pIterator
!= 0);
123 //Now we iterate through them
125 while ( (pObject
= IOIteratorNext(pIterator
)) != 0)
127 wxVERIFY(IORegistryEntryCreateCFProperties(pObject
, &pDictionary
,
128 kCFAllocatorDefault
, kNilOptions
) == KERN_SUCCESS
);
131 wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary
, CFSTR(kIOHIDProductKey
))) == CFStringGetTypeID());
134 m_szName
= CFStringGetCStringPtr (
135 (CFStringRef
) CFDictionaryGetValue(pDictionary
, CFSTR(kIOHIDProductKey
)),
136 CFStringGetSystemEncoding()
140 //Now the hard part - in order to scan things we need "cookies" -
142 wxCFArray CookieArray
= CFDictionaryGetValue(pDictionary
, CFSTR(kIOHIDElementKey
));
143 BuildCookies(CookieArray
);
144 if (m_ppQueue
!= NULL
)
145 wxVERIFY((*m_ppQueue
)->start(m_ppQueue
) == S_OK
);
147 //Create the interface (good grief - long function names!)
149 IOCFPlugInInterface
** ppPlugin
;
150 wxIOCHECK(IOCreatePlugInInterfaceForService(pObject
, kIOHIDDeviceUserClientTypeID
,
151 kIOCFPlugInInterfaceID
, &ppPlugin
, &nScore
), "");
153 //Now, the final thing we can check before we fall back to asserts
154 //(because the dtor only checks if the device is ok, so if anything
155 //fails from now on the dtor will delete the device anyway, so we can't break from this).
157 //Get the HID interface from the plugin to the mach port
158 wxSCHECK((*ppPlugin
)->QueryInterface(ppPlugin
,
159 CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID
), (void**) &m_ppDevice
), "");
162 (*ppPlugin
)->Release(ppPlugin
);
164 //open the HID interface...
165 wxVERIFY((*m_ppDevice
)->open(m_ppDevice
, 0) == S_OK
);
168 CFRelease(pDictionary
);
169 IOObjectRelease(pObject
);
173 IOObjectRelease(pIterator
);
178 void wxHIDDevice::AddCookie(CFTypeRef Data
, const int& i
)
181 (CFNumberRef
) CFDictionaryGetValue ( (CFDictionaryRef
) Data
182 , CFSTR(kIOHIDElementCookieKey
)
189 void wxHIDDevice::AddCookieInQueue(CFTypeRef Data
, const int& i
)
192 wxVERIFY((*m_ppQueue
)->addElement(m_ppQueue
, m_pCookies
[i
], 0) == S_OK
);//3rd Param flags (none yet)
195 void wxHIDDevice::InitCookies(const size_t& dwSize
, bool bQueue
)
197 m_pCookies
= new IOHIDElementCookie
[dwSize
];
200 wxASSERT( m_ppQueue
!= NULL
);
201 wxVERIFY( (m_ppQueue
= (*m_ppDevice
)->allocQueue(m_ppDevice
)) != NULL
);
202 wxVERIFY( (*m_ppQueue
)->create(m_ppQueue
, 0, 512) == S_OK
); //Param 2, flags, none yet
206 bool wxHIDDevice::IsActive(const int& nIndex
)
208 wxASSERT(m_pCookies
[nIndex
] != NULL
);
209 IOHIDEventStruct Event
;
210 (*m_ppDevice
)->getElementValue(m_ppDevice
, m_pCookies
[nIndex
], &Event
);
211 return !!Event
.value
;
215 wxHIDDevice::~wxHIDDevice()
217 if (m_ppDevice
!= NULL
)
219 (*m_ppDevice
)->close(m_ppDevice
);
220 (*m_ppDevice
)->Release(m_ppDevice
);
221 mach_port_deallocate(mach_task_self(), m_pPort
);
224 if (m_pCookies
!= NULL
)
226 delete [] m_pCookies
;
227 if (m_ppQueue
!= NULL
)
229 (*m_ppQueue
)->stop(m_ppQueue
);
230 (*m_ppQueue
)->dispose(m_ppQueue
);
231 (*m_ppQueue
)->Release(m_ppQueue
);
236 // ---------------------------------------------------------------------------
238 // ---------------------------------------------------------------------------
249 bool wxHIDKeyboard::Create()
251 return wxHIDDevice::Create(kHIDPage_GenericDesktop
, kHIDUsage_GD_Keyboard
);
254 void wxHIDKeyboard::BuildCookies(wxCFArray
& Array
)
256 Array
= CFDictionaryGetValue((CFDictionaryRef
)Array
[0], CFSTR(kIOHIDElementKey
));
260 for (i
= 0; i
< Array
.Count(); ++i
)
263 (CFNumberRef
) CFDictionaryGetValue((CFDictionaryRef
) Array
[i
], CFSTR(kIOHIDElementUsageKey
)),
264 kCFNumberLongType
, &nUsage
);
266 if (nUsage
>= kHIDUsage_KeyboardA
&& nUsage
<= kHIDUsage_KeyboardZ
)
267 AddCookie(Array
[i
], 'A' + (nUsage
- kHIDUsage_KeyboardA
) );
268 else if (nUsage
>= kHIDUsage_Keyboard1
&& nUsage
<= kHIDUsage_Keyboard9
)
269 AddCookie(Array
[i
], '1' + (nUsage
- kHIDUsage_Keyboard1
) );
270 else if (nUsage
>= kHIDUsage_KeyboardF1
&& nUsage
<= kHIDUsage_KeyboardF12
)
271 AddCookie(Array
[i
], WXK_F1
+ (nUsage
- kHIDUsage_KeyboardF1
) );
272 else if (nUsage
>= kHIDUsage_KeyboardF13
&& nUsage
<= kHIDUsage_KeyboardF24
)
273 AddCookie(Array
[i
], WXK_F13
+ (nUsage
- kHIDUsage_KeyboardF13
) );
274 else if (nUsage
>= kHIDUsage_Keypad1
&& nUsage
<= kHIDUsage_Keypad9
)
275 AddCookie(Array
[i
], WXK_NUMPAD1
+ (nUsage
- kHIDUsage_Keypad1
) );
278 //0's (wx & ascii go 0-9, but HID goes 1-0)
279 case kHIDUsage_Keyboard0
:
280 AddCookie(Array
[i
],'0');
282 case kHIDUsage_Keypad0
:
283 AddCookie(Array
[i
],WXK_NUMPAD0
);
287 case kHIDUsage_KeyboardReturnOrEnter
:
288 AddCookie(Array
[i
], WXK_RETURN
);
290 case kHIDUsage_KeyboardEscape
:
291 AddCookie(Array
[i
], WXK_ESCAPE
);
293 case kHIDUsage_KeyboardDeleteOrBackspace
:
294 AddCookie(Array
[i
], WXK_BACK
);
296 case kHIDUsage_KeyboardTab
:
297 AddCookie(Array
[i
], WXK_TAB
);
299 case kHIDUsage_KeyboardSpacebar
:
300 AddCookie(Array
[i
], WXK_SPACE
);
302 case kHIDUsage_KeyboardPageUp
:
303 AddCookie(Array
[i
], WXK_PRIOR
);
305 case kHIDUsage_KeyboardEnd
:
306 AddCookie(Array
[i
], WXK_END
);
308 case kHIDUsage_KeyboardPageDown
:
309 AddCookie(Array
[i
], WXK_NEXT
);
311 case kHIDUsage_KeyboardRightArrow
:
312 AddCookie(Array
[i
], WXK_RIGHT
);
314 case kHIDUsage_KeyboardLeftArrow
:
315 AddCookie(Array
[i
], WXK_LEFT
);
317 case kHIDUsage_KeyboardDownArrow
:
318 AddCookie(Array
[i
], WXK_DOWN
);
320 case kHIDUsage_KeyboardUpArrow
:
321 AddCookie(Array
[i
], WXK_UP
);
325 case kHIDUsage_KeyboardCapsLock
:
326 AddCookie(Array
[i
],WXK_CAPITAL
);
328 case kHIDUsage_KeypadNumLock
:
329 AddCookie(Array
[i
],WXK_NUMLOCK
);
331 case kHIDUsage_KeyboardScrollLock
:
332 AddCookie(Array
[i
],WXK_SCROLL
);
335 //Menu keys, Shift, other specials
336 case kHIDUsage_KeyboardLeftControl
:
337 AddCookie(Array
[i
],WXK_CONTROL
);
339 case kHIDUsage_KeyboardLeftShift
:
340 AddCookie(Array
[i
],WXK_SHIFT
);
342 case kHIDUsage_KeyboardLeftAlt
:
343 AddCookie(Array
[i
],WXK_ALT
);
345 case kHIDUsage_KeyboardLeftGUI
:
346 AddCookie(Array
[i
],WXK_MENU
);
348 case kHIDUsage_KeyboardRightControl
:
349 AddCookie(Array
[i
],WXK_RCONTROL
);
351 case kHIDUsage_KeyboardRightShift
:
352 AddCookie(Array
[i
],WXK_RSHIFT
);
354 case kHIDUsage_KeyboardRightAlt
:
355 AddCookie(Array
[i
],WXK_RALT
);
357 case kHIDUsage_KeyboardRightGUI
:
358 AddCookie(Array
[i
],WXK_RMENU
);
363 //not in wx keycodes - do nothing....