1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: DARWIN HID layer for WX Implementation
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
21 #pragma implementation "hid.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
39 #include "wx/mac/carbon/private/hid.h"
40 #include "wx/string.h"
44 // ---------------------------------------------------------------------------
46 // ---------------------------------------------------------------------------
48 #define wxFORCECHECK_MSG(arg, msg) \
52 wxLogSysError(wxString::Format(wxT("Message:%s\nHID: %s failed!"), wxT(msg), wxT(#arg)));\
56 #define wxIOCHECK(arg, msg) wxFORCECHECK_MSG(arg != kIOReturnSuccess, msg)
57 #define wxKERNCHECK(arg, msg) wxFORCECHECK_MSG(arg != KERN_SUCCESS, msg)
58 #define wxSCHECK(arg, msg) wxFORCECHECK_MSG(arg != S_OK, msg)
61 # define wxVERIFY(arg) wxASSERT(arg)
63 # define wxVERIFY(arg) arg
67 void CFShowTypeIDDescription(CFTypeRef pData)
76 CFStringGetCStringPtr(
77 CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding()
83 // ============================================================================
85 // ============================================================================
87 // ---------------------------------------------------------------------------
89 // ---------------------------------------------------------------------------
91 bool wxHIDDevice::Create (const int& nClass
, const int& nType
)
93 //Create the mach port
94 wxIOCHECK(IOMasterPort(bootstrap_port
, &m_pPort
), "Could not create mach port");
96 //Dictionary that will hold first
97 //the matching dictionary for determining which kind of devices we want,
98 //then later some registry properties from an iterator (see below)
99 CFMutableDictionaryRef pDictionary
;
101 //Create a dictionary
102 //The call to IOServiceMatching filters down the
103 //the services we want to hid services (and also eats the
104 //dictionary up for us (consumes one reference))
105 wxVERIFY((pDictionary
= IOServiceMatching(kIOHIDDeviceKey
)) != NULL
);
107 //Here we'll filter down the services to what we want
110 CFNumberRef pType
= CFNumberCreate(kCFAllocatorDefault
,
111 kCFNumberIntType
, &nType
);
112 CFDictionarySetValue(pDictionary
, CFSTR(kIOHIDPrimaryUsageKey
), pType
);
117 CFNumberRef pClass
= CFNumberCreate(kCFAllocatorDefault
,
118 kCFNumberIntType
, &nClass
);
119 CFDictionarySetValue(pDictionary
, CFSTR(kIOHIDPrimaryUsagePageKey
), pClass
);
123 //Now get the maching services
124 io_iterator_t pIterator
;
125 wxIOCHECK(IOServiceGetMatchingServices(m_pPort
, pDictionary
, &pIterator
), "No Matching HID Services");
126 wxASSERT(pIterator
!= NULL
);
128 //Now we iterate through them
130 while ( (pObject
= IOIteratorNext(pIterator
)) != NULL
)
132 wxVERIFY(IORegistryEntryCreateCFProperties(pObject
, &pDictionary
,
133 kCFAllocatorDefault
, kNilOptions
) == KERN_SUCCESS
);
136 wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary
, CFSTR(kIOHIDProductKey
))) == CFStringGetTypeID());
139 m_szName
= CFStringGetCStringPtr (
140 (CFStringRef
) CFDictionaryGetValue(pDictionary
, CFSTR(kIOHIDProductKey
)),
141 CFStringGetSystemEncoding()
145 //Now the hard part - in order to scan things we need "cookies" -
147 wxCFArray CookieArray
= CFDictionaryGetValue(pDictionary
, CFSTR(kIOHIDElementKey
));
148 BuildCookies(CookieArray
);
149 if (m_ppQueue
!= NULL
)
150 wxVERIFY((*m_ppQueue
)->start(m_ppQueue
) == S_OK
);
152 //Create the interface (good grief - long function names!)
154 IOCFPlugInInterface
** ppPlugin
;
155 wxIOCHECK(IOCreatePlugInInterfaceForService(pObject
, kIOHIDDeviceUserClientTypeID
,
156 kIOCFPlugInInterfaceID
, &ppPlugin
, &nScore
), "");
158 //Now, the final thing we can check before we fall back to asserts
159 //(because the dtor only checks if the device is ok, so if anything
160 //fails from now on the dtor will delete the device anyway, so we can't break from this).
162 //Get the HID interface from the plugin to the mach port
163 wxSCHECK((*ppPlugin
)->QueryInterface(ppPlugin
,
164 CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID
), (void**) &m_ppDevice
), "");
167 (*ppPlugin
)->Release(ppPlugin
);
169 //open the HID interface...
170 wxVERIFY((*m_ppDevice
)->open(m_ppDevice
, 0) == S_OK
);
173 CFRelease(pDictionary
);
174 IOObjectRelease(pObject
);
178 IOObjectRelease(pIterator
);
183 void wxHIDDevice::AddCookie(CFTypeRef Data
, const int& i
)
186 (CFNumberRef
) CFDictionaryGetValue ( (CFDictionaryRef
) Data
187 , CFSTR(kIOHIDElementCookieKey
)
194 void wxHIDDevice::AddCookieInQueue(CFTypeRef Data
, const int& i
)
197 wxVERIFY((*m_ppQueue
)->addElement(m_ppQueue
, m_pCookies
[i
], 0) == S_OK
);//3rd Param flags (none yet)
200 void wxHIDDevice::InitCookies(const size_t& dwSize
, bool bQueue
)
202 m_pCookies
= new IOHIDElementCookie
[dwSize
];
205 wxASSERT( m_ppQueue
!= NULL
);
206 wxVERIFY( (m_ppQueue
= (*m_ppDevice
)->allocQueue(m_ppDevice
)) != NULL
);
207 wxVERIFY( (*m_ppQueue
)->create(m_ppQueue
, 0, 512) == S_OK
); //Param 2, flags, none yet
211 bool wxHIDDevice::IsActive(const int& nIndex
)
213 wxASSERT(m_pCookies
[nIndex
] != NULL
);
214 IOHIDEventStruct Event
;
215 (*m_ppDevice
)->getElementValue(m_ppDevice
, m_pCookies
[nIndex
], &Event
);
216 return !!Event
.value
;
220 wxHIDDevice::~wxHIDDevice()
222 if (m_ppDevice
!= NULL
)
224 (*m_ppDevice
)->close(m_ppDevice
);
225 (*m_ppDevice
)->Release(m_ppDevice
);
226 mach_port_deallocate(mach_task_self(), m_pPort
);
229 if (m_pCookies
!= NULL
)
231 delete [] m_pCookies
;
232 if (m_ppQueue
!= NULL
)
234 (*m_ppQueue
)->stop(m_ppQueue
);
235 (*m_ppQueue
)->dispose(m_ppQueue
);
236 (*m_ppQueue
)->Release(m_ppQueue
);
241 // ---------------------------------------------------------------------------
243 // ---------------------------------------------------------------------------
254 bool wxHIDKeyboard::Create()
256 return wxHIDDevice::Create(kHIDPage_GenericDesktop
, kHIDUsage_GD_Keyboard
);
259 void wxHIDKeyboard::BuildCookies(wxCFArray
& Array
)
261 Array
= CFDictionaryGetValue((CFDictionaryRef
)Array
[0], CFSTR(kIOHIDElementKey
));
265 for (i
= 0; i
< Array
.Count(); ++i
)
268 (CFNumberRef
) CFDictionaryGetValue((CFDictionaryRef
) Array
[i
], CFSTR(kIOHIDElementUsageKey
)),
269 kCFNumberLongType
, &nUsage
);
271 if (nUsage
>= kHIDUsage_KeyboardA
&& nUsage
<= kHIDUsage_KeyboardZ
)
272 AddCookie(Array
[i
], 'A' + (nUsage
- kHIDUsage_KeyboardA
) );
273 else if (nUsage
>= kHIDUsage_Keyboard1
&& nUsage
<= kHIDUsage_Keyboard9
)
274 AddCookie(Array
[i
], '1' + (nUsage
- kHIDUsage_Keyboard1
) );
275 else if (nUsage
>= kHIDUsage_KeyboardF1
&& nUsage
<= kHIDUsage_KeyboardF12
)
276 AddCookie(Array
[i
], WXK_F1
+ (nUsage
- kHIDUsage_KeyboardF1
) );
277 else if (nUsage
>= kHIDUsage_KeyboardF13
&& nUsage
<= kHIDUsage_KeyboardF24
)
278 AddCookie(Array
[i
], WXK_F13
+ (nUsage
- kHIDUsage_KeyboardF13
) );
279 else if (nUsage
>= kHIDUsage_Keypad1
&& nUsage
<= kHIDUsage_Keypad9
)
280 AddCookie(Array
[i
], WXK_NUMPAD1
+ (nUsage
- kHIDUsage_Keypad1
) );
283 //0's (wx & ascii go 0-9, but HID goes 1-0)
284 case kHIDUsage_Keyboard0
:
285 AddCookie(Array
[i
],'0');
287 case kHIDUsage_Keypad0
:
288 AddCookie(Array
[i
],WXK_NUMPAD0
);
292 case kHIDUsage_KeyboardReturnOrEnter
:
293 AddCookie(Array
[i
], WXK_RETURN
);
295 case kHIDUsage_KeyboardEscape
:
296 AddCookie(Array
[i
], WXK_ESCAPE
);
298 case kHIDUsage_KeyboardDeleteOrBackspace
:
299 AddCookie(Array
[i
], WXK_BACK
);
301 case kHIDUsage_KeyboardTab
:
302 AddCookie(Array
[i
], WXK_TAB
);
304 case kHIDUsage_KeyboardSpacebar
:
305 AddCookie(Array
[i
], WXK_SPACE
);
307 case kHIDUsage_KeyboardPageUp
:
308 AddCookie(Array
[i
], WXK_PRIOR
);
310 case kHIDUsage_KeyboardEnd
:
311 AddCookie(Array
[i
], WXK_END
);
313 case kHIDUsage_KeyboardPageDown
:
314 AddCookie(Array
[i
], WXK_NEXT
);
316 case kHIDUsage_KeyboardRightArrow
:
317 AddCookie(Array
[i
], WXK_RIGHT
);
319 case kHIDUsage_KeyboardLeftArrow
:
320 AddCookie(Array
[i
], WXK_LEFT
);
322 case kHIDUsage_KeyboardDownArrow
:
323 AddCookie(Array
[i
], WXK_DOWN
);
325 case kHIDUsage_KeyboardUpArrow
:
326 AddCookie(Array
[i
], WXK_UP
);
330 case kHIDUsage_KeyboardCapsLock
:
331 AddCookie(Array
[i
],WXK_CAPITAL
);
333 case kHIDUsage_KeypadNumLock
:
334 AddCookie(Array
[i
],WXK_NUMLOCK
);
336 case kHIDUsage_KeyboardScrollLock
:
337 AddCookie(Array
[i
],WXK_SCROLL
);
340 //Menu keys, Shift, other specials
341 case kHIDUsage_KeyboardLeftControl
:
342 AddCookie(Array
[i
],WXK_CONTROL
);
344 case kHIDUsage_KeyboardLeftShift
:
345 AddCookie(Array
[i
],WXK_SHIFT
);
347 case kHIDUsage_KeyboardLeftAlt
:
348 AddCookie(Array
[i
],WXK_ALT
);
350 case kHIDUsage_KeyboardLeftGUI
:
351 AddCookie(Array
[i
],WXK_MENU
);
353 case kHIDUsage_KeyboardRightControl
:
354 AddCookie(Array
[i
],WXK_RCONTROL
);
356 case kHIDUsage_KeyboardRightShift
:
357 AddCookie(Array
[i
],WXK_RSHIFT
);
359 case kHIDUsage_KeyboardRightAlt
:
360 AddCookie(Array
[i
],WXK_RALT
);
362 case kHIDUsage_KeyboardRightGUI
:
363 AddCookie(Array
[i
],WXK_RMENU
);
368 //not in wx keycodes - do nothing....