]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/hid.cpp
Compile fixes.
[wxWidgets.git] / src / mac / carbon / hid.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: hid.cpp
3 // Purpose: DARWIN HID layer for WX Implementation
4 // Author: Ryan Norton
5 // Modified by:
6 // Created: 11/11/2003
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/defs.h"
13
14 //DARWIN _ONLY_
15 #ifdef __DARWIN__
16
17 #include "wx/mac/carbon/private/hid.h"
18 #include "wx/string.h"
19 #include "wx/log.h"
20
21 #define wxFORCECHECK_MSG(arg, msg) \
22 {\
23 if (arg) \
24 {\
25 wxLogSysError(wxString::Format(wxT("Message:%s\nHID: %s failed!"), wxT(msg), wxT(#arg)));\
26 return false;\
27 }\
28 }
29 #define wxIOCHECK(arg, msg) wxFORCECHECK_MSG(arg != kIOReturnSuccess, msg)
30 #define wxKERNCHECK(arg, msg) wxFORCECHECK_MSG(arg != KERN_SUCCESS, msg)
31 #define wxSCHECK(arg, msg) wxFORCECHECK_MSG(arg != S_OK, msg)
32
33 #ifdef __WXDEBUG___
34 # define wxVERIFY(arg) wxASSERT(arg)
35 #else
36 # define wxVERIFY(arg) arg
37 #endif
38
39 /*
40 void CFShowTypeIDDescription(CFTypeRef pData)
41 {
42 if(!pData)
43 {
44 wxASSERT(false);
45 return;
46 }
47
48 wxMessageBox(
49 CFStringGetCStringPtr(
50 CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding()
51 )
52 );
53 }
54 */
55
56 // ============================================================================
57 // implementation
58 // ============================================================================
59
60
61 bool wxHIDDevice::Create (const int& nClass, const int& nType)
62 {
63 //Create the mach port
64 wxIOCHECK(IOMasterPort(bootstrap_port, &m_pPort), "Could not create mach port");
65
66 //Dictionary that will hold first
67 //the matching dictionary for determining which kind of devices we want,
68 //then later some registry properties from an iterator (see below)
69 CFMutableDictionaryRef pDictionary;
70
71 //Create a dictionary
72 //The call to IOServiceMatching filters down the
73 //the services we want to hid services (and also eats the
74 //dictionary up for us (consumes one reference))
75 wxVERIFY((pDictionary = IOServiceMatching(kIOHIDDeviceKey)) != NULL );
76
77 //Here we'll filter down the services to what we want
78 if (nType != -1)
79 {
80 CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
81 kCFNumberIntType, &nType);
82 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
83 CFRelease(pType);
84 }
85 if (nClass != -1)
86 {
87 CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
88 kCFNumberIntType, &nClass);
89 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
90 CFRelease(pClass);
91 }
92
93 //Now get the maching services
94 io_iterator_t pIterator;
95 wxIOCHECK(IOServiceGetMatchingServices(m_pPort, pDictionary, &pIterator), "No Matching HID Services");
96 wxASSERT(pIterator != NULL);
97
98 //Now we iterate through them
99 io_object_t pObject;
100 while ( (pObject = IOIteratorNext(pIterator)) != NULL)
101 {
102 wxVERIFY(IORegistryEntryCreateCFProperties(pObject, &pDictionary,
103 kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS);
104
105 //Just for sanity :)
106 wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID());
107
108 //Get [product] name
109 m_szName = CFStringGetCStringPtr (
110 (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)),
111 CFStringGetSystemEncoding()
112 );
113
114 //
115 //Now the hard part - in order to scan things we need "cookies" -
116 //
117 wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey));
118 BuildCookies(CookieArray);
119 if (m_ppQueue != NULL)
120 wxVERIFY((*m_ppQueue)->start(m_ppQueue) == S_OK);
121
122 //Create the interface (good grief - long function names!)
123 SInt32 nScore;
124 IOCFPlugInInterface** ppPlugin;
125 wxIOCHECK(IOCreatePlugInInterfaceForService(pObject, kIOHIDDeviceUserClientTypeID,
126 kIOCFPlugInInterfaceID, &ppPlugin, &nScore), "");
127
128 //Now, the final thing we can check before we fall back to asserts
129 //(because the dtor only checks if the device is ok, so if anything
130 //fails from now on the dtor will delete the device anyway, so we can't break from this).
131
132 //Get the HID interface from the plugin to the mach port
133 wxSCHECK((*ppPlugin)->QueryInterface(ppPlugin,
134 CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void**) &m_ppDevice), "");
135
136 //release the plugin
137 (*ppPlugin)->Release(ppPlugin);
138
139 //open the HID interface...
140 wxVERIFY((*m_ppDevice)->open(m_ppDevice, 0) == S_OK);
141
142 //cleanup
143 CFRelease(pDictionary);
144 IOObjectRelease(pObject);
145 break;
146 }
147 //iterator cleanup
148 IOObjectRelease(pIterator);
149
150 return true;
151 }//end Create()
152
153 void wxHIDDevice::AddCookie(CFTypeRef Data, const int& i)
154 {
155 CFNumberGetValue(
156 (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data
157 , CFSTR(kIOHIDElementCookieKey)
158 ),
159 kCFNumberIntType,
160 &m_pCookies[i]
161 );
162 }
163
164 void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, const int& i)
165 {
166 AddCookie(Data, i);
167 wxVERIFY((*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) == S_OK);//3rd Param flags (none yet)
168 }
169
170 void wxHIDDevice::InitCookies(const size_t& dwSize, bool bQueue)
171 {
172 m_pCookies = new IOHIDElementCookie[dwSize];
173 if (bQueue)
174 {
175 wxASSERT( m_ppQueue != NULL);
176 wxVERIFY( (m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice)) != NULL);
177 wxVERIFY( (*m_ppQueue)->create(m_ppQueue, 0, 512) == S_OK); //Param 2, flags, none yet
178 }
179 }
180
181 bool wxHIDDevice::IsActive(const int& nIndex)
182 {
183 wxASSERT(m_pCookies[nIndex] != NULL);
184 IOHIDEventStruct Event;
185 (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event);
186 return !!Event.value;
187 }
188
189
190 wxHIDDevice::~wxHIDDevice()
191 {
192 if (m_ppDevice != NULL)
193 {
194 (*m_ppDevice)->close(m_ppDevice);
195 (*m_ppDevice)->Release(m_ppDevice);
196 mach_port_deallocate(mach_task_self(), m_pPort);
197 }
198
199 if (m_pCookies != NULL)
200 {
201 delete [] m_pCookies;
202 if (m_ppQueue != NULL)
203 {
204 (*m_ppQueue)->stop(m_ppQueue);
205 (*m_ppQueue)->dispose(m_ppQueue);
206 (*m_ppQueue)->Release(m_ppQueue);
207 }
208 }
209 }
210 /*
211 enum
212 {
213 kHIDUsage_KeyboardHyphen = 0x2D,
214 kHIDUsage_KeyboardEqualSign = 0x2E,
215 kHIDUsage_KeyboardOpenBracket = 0x2F,
216 kHIDUsage_KeyboardCloseBracket = 0x30,
217 kHIDUsage_KeyboardBackslash = 0x31, // \ or | *
218 kHIDUsage_KeyboardNonUSPound = 0x32, / Non-US # or _ *
219 kHIDUsage_KeyboardSemicolon = 0x33, / ; or : *
220 kHIDUsage_KeyboardQuote = 0x34, / ' or " *
221 kHIDUsage_KeyboardGraveAccentAndTilde = 0x35, / Grave Accent and Tilde *
222 kHIDUsage_KeyboardComma = 0x36, / , or < *
223 kHIDUsage_KeyboardPeriod = 0x37, / . or > *
224 kHIDUsage_KeyboardSlash = 0x38, / / or ? *
225 kHIDUsage_KeyboardCapsLock = 0x39, / Caps Lock *
226
227 kHIDUsage_KeyboardPrintScreen = 0x46, / Print Screen *
228 kHIDUsage_KeyboardScrollLock = 0x47, / Scroll Lock *
229 kHIDUsage_KeyboardPause = 0x48, / Pause *
230 kHIDUsage_KeyboardInsert = 0x49, / Insert *
231 kHIDUsage_KeyboardHome = 0x4A, / Home *
232 kHIDUsage_KeyboardDeleteForward = 0x4C, / Delete Forward *
233
234 kHIDUsage_KeyboardUpArrow
235 kHIDUsage_KeypadNumLock
236 kHIDUsage_KeypadSlash
237 kHIDUsage_KeypadAsterisk
238 kHIDUsage_KeypadHyphen
239 kHIDUsage_KeypadPlus
240 kHIDUsage_KeypadEnter
241 kHIDUsage_KeypadPeriod
242 kHIDUsage_KeyboardNonUSBackslash
243 kHIDUsage_KeyboardApplication
244 kHIDUsage_KeyboardPower
245 kHIDUsage_KeypadEqualSign
246 };
247 enum wxKeyCode
248 {
249
250 WXK_START = 300,
251 WXK_LBUTTON,
252 WXK_RBUTTON,
253 WXK_CANCEL,
254 WXK_MBUTTON,
255 WXK_CLEAR,
256 WXK_SHIFT,
257 WXK_ALT,
258 WXK_CONTROL,
259 WXK_MENU,
260 WXK_PAUSE,
261 WXK_PRIOR, * Page up *
262 WXK_NEXT, * Page down *
263 WXK_END,
264 WXK_HOME,
265 WXK_LEFT,
266 WXK_UP,
267 WXK_RIGHT,
268 WXK_DOWN,
269 WXK_SELECT,
270 WXK_PRINT,
271 WXK_EXECUTE,
272 WXK_SNAPSHOT,
273 WXK_INSERT,
274 WXK_HELP,
275 WXK_MULTIPLY,
276 WXK_ADD,
277 WXK_SEPARATOR,
278 WXK_SUBTRACT,
279 WXK_DECIMAL,
280 WXK_DIVIDE,
281 WXK_PAGEUP,
282 WXK_PAGEDOWN,
283
284 WXK_NUMPAD_SPACE,
285 WXK_NUMPAD_TAB,
286 WXK_NUMPAD_ENTER,
287 WXK_NUMPAD_HOME,
288 WXK_NUMPAD_LEFT,
289 WXK_NUMPAD_UP,
290 WXK_NUMPAD_RIGHT,
291 WXK_NUMPAD_DOWN,
292 WXK_NUMPAD_PRIOR,
293 WXK_NUMPAD_PAGEUP,
294 WXK_NUMPAD_NEXT,
295 WXK_NUMPAD_PAGEDOWN,
296 WXK_NUMPAD_END,
297 WXK_NUMPAD_BEGIN,
298 WXK_NUMPAD_INSERT,
299 WXK_NUMPAD_DELETE,
300 WXK_NUMPAD_EQUAL,
301 WXK_NUMPAD_MULTIPLY,
302 WXK_NUMPAD_ADD,
303 WXK_NUMPAD_SEPARATOR,
304 WXK_NUMPAD_SUBTRACT,
305 WXK_NUMPAD_DECIMAL,
306 WXK_NUMPAD_DIVIDE,
307
308 WXK_WINDOWS_LEFT,
309 WXK_WINDOWS_RIGHT,
310 WXK_WINDOWS_MENU ,
311 WXK_COMMAND
312 };
313
314 */
315 enum
316 {
317 WXK_RSHIFT = 400,
318 WXK_RALT,
319 WXK_RCONTROL,
320 WXK_RMENU
321
322 };
323
324 bool wxHIDKeyboard::Create()
325 {
326 return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
327 }
328
329 void wxHIDKeyboard::BuildCookies(wxCFArray& Array)
330 {
331 Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey));
332 InitCookies(500);
333 int i,
334 nUsage;
335 for (i = 0; i < Array.Count(); ++i)
336 {
337 CFNumberGetValue(
338 (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)),
339 kCFNumberLongType, &nUsage);
340
341 if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ)
342 AddCookie(Array[i], 'A' + (nUsage - kHIDUsage_KeyboardA) );
343 else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9)
344 AddCookie(Array[i], '1' + (nUsage - kHIDUsage_Keyboard1) );
345 else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12)
346 AddCookie(Array[i], WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) );
347 else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24)
348 AddCookie(Array[i], WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) );
349 else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9)
350 AddCookie(Array[i], WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) );
351 else switch (nUsage)
352 {
353 //0's (wx & ascii go 0-9, but HID goes 1-0)
354 case kHIDUsage_Keyboard0:
355 AddCookie(Array[i],'0');
356 break;
357 case kHIDUsage_Keypad0:
358 AddCookie(Array[i],WXK_NUMPAD0);
359 break;
360
361 //Basic
362 case kHIDUsage_KeyboardReturnOrEnter:
363 AddCookie(Array[i], WXK_RETURN);
364 break;
365 case kHIDUsage_KeyboardEscape:
366 AddCookie(Array[i], WXK_ESCAPE);
367 break;
368 case kHIDUsage_KeyboardDeleteOrBackspace:
369 AddCookie(Array[i], WXK_BACK);
370 break;
371 case kHIDUsage_KeyboardTab:
372 AddCookie(Array[i], WXK_TAB);
373 break;
374 case kHIDUsage_KeyboardSpacebar:
375 AddCookie(Array[i], WXK_SPACE);
376 break;
377 case kHIDUsage_KeyboardPageUp:
378 AddCookie(Array[i], WXK_PRIOR);
379 break;
380 case kHIDUsage_KeyboardEnd:
381 AddCookie(Array[i], WXK_END);
382 break;
383 case kHIDUsage_KeyboardPageDown:
384 AddCookie(Array[i], WXK_NEXT);
385 break;
386 case kHIDUsage_KeyboardRightArrow:
387 AddCookie(Array[i], WXK_RIGHT);
388 break;
389 case kHIDUsage_KeyboardLeftArrow:
390 AddCookie(Array[i], WXK_LEFT);
391 break;
392 case kHIDUsage_KeyboardDownArrow:
393 AddCookie(Array[i], WXK_DOWN);
394 break;
395 case kHIDUsage_KeyboardUpArrow:
396 AddCookie(Array[i], WXK_UP);
397 break;
398
399 //LEDS
400 case kHIDUsage_KeyboardCapsLock:
401 AddCookie(Array[i],WXK_CAPITAL);
402 break;
403 case kHIDUsage_KeypadNumLock:
404 AddCookie(Array[i],WXK_NUMLOCK);
405 break;
406 case kHIDUsage_KeyboardScrollLock:
407 AddCookie(Array[i],WXK_SCROLL);
408 break;
409
410 //Menu keys, Shift, other specials
411 case kHIDUsage_KeyboardLeftControl:
412 AddCookie(Array[i],WXK_CONTROL);
413 break;
414 case kHIDUsage_KeyboardLeftShift:
415 AddCookie(Array[i],WXK_SHIFT);
416 break;
417 case kHIDUsage_KeyboardLeftAlt:
418 AddCookie(Array[i],WXK_ALT);
419 break;
420 case kHIDUsage_KeyboardLeftGUI:
421 AddCookie(Array[i],WXK_MENU);
422 break;
423 case kHIDUsage_KeyboardRightControl:
424 AddCookie(Array[i],WXK_RCONTROL);
425 break;
426 case kHIDUsage_KeyboardRightShift:
427 AddCookie(Array[i],WXK_RSHIFT);
428 break;
429 case kHIDUsage_KeyboardRightAlt:
430 AddCookie(Array[i],WXK_RALT);
431 break;
432 case kHIDUsage_KeyboardRightGUI:
433 AddCookie(Array[i],WXK_RMENU);
434 break;
435
436 //Default
437 default:
438 //not in wx keycodes - do nothing....
439 break;
440 }
441 }
442 }//end buildcookies
443
444 #endif //__DARWIN__