]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/hid.cpp
made GetTempBuffer() static to avoid duplicate function errors during linking
[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 wxVERIFY(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 /*
248 enum wxKeyCode
249 {
250
251 WXK_START = 300,
252 WXK_LBUTTON,
253 WXK_RBUTTON,
254 WXK_CANCEL,
255 WXK_MBUTTON,
256 WXK_CLEAR,
257 WXK_SHIFT,
258 WXK_ALT,
259 WXK_CONTROL,
260 WXK_MENU,
261 WXK_PAUSE,
262 WXK_PRIOR, * Page up *
263 WXK_NEXT, * Page down *
264 WXK_END,
265 WXK_HOME,
266 WXK_LEFT,
267 WXK_UP,
268 WXK_RIGHT,
269 WXK_DOWN,
270 WXK_SELECT,
271 WXK_PRINT,
272 WXK_EXECUTE,
273 WXK_SNAPSHOT,
274 WXK_INSERT,
275 WXK_HELP,
276 WXK_MULTIPLY,
277 WXK_ADD,
278 WXK_SEPARATOR,
279 WXK_SUBTRACT,
280 WXK_DECIMAL,
281 WXK_DIVIDE,
282 WXK_PAGEUP,
283 WXK_PAGEDOWN,
284
285 WXK_NUMPAD_SPACE,
286 WXK_NUMPAD_TAB,
287 WXK_NUMPAD_ENTER,
288 WXK_NUMPAD_HOME,
289 WXK_NUMPAD_LEFT,
290 WXK_NUMPAD_UP,
291 WXK_NUMPAD_RIGHT,
292 WXK_NUMPAD_DOWN,
293 WXK_NUMPAD_PRIOR,
294 WXK_NUMPAD_PAGEUP,
295 WXK_NUMPAD_NEXT,
296 WXK_NUMPAD_PAGEDOWN,
297 WXK_NUMPAD_END,
298 WXK_NUMPAD_BEGIN,
299 WXK_NUMPAD_INSERT,
300 WXK_NUMPAD_DELETE,
301 WXK_NUMPAD_EQUAL,
302 WXK_NUMPAD_MULTIPLY,
303 WXK_NUMPAD_ADD,
304 WXK_NUMPAD_SEPARATOR,
305 WXK_NUMPAD_SUBTRACT,
306 WXK_NUMPAD_DECIMAL,
307 WXK_NUMPAD_DIVIDE,
308
309 WXK_WINDOWS_LEFT,
310 WXK_WINDOWS_RIGHT,
311 WXK_WINDOWS_MENU ,
312 WXK_COMMAND
313 };
314
315 */
316 enum
317 {
318 WXK_RSHIFT = 400,
319 WXK_RALT,
320 WXK_RCONTROL,
321 WXK_RMENU
322
323 };
324
325 bool wxHIDKeyboard::Create()
326 {
327 return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
328 }
329
330 void wxHIDKeyboard::BuildCookies(wxCFArray& Array)
331 {
332 Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey));
333 InitCookies(500);
334 int i,
335 nUsage;
336 for (i = 0; i < Array.Count(); ++i)
337 {
338 CFNumberGetValue(
339 (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)),
340 kCFNumberLongType, &nUsage);
341
342 if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ)
343 AddCookie(Array[i], 'A' + (nUsage - kHIDUsage_KeyboardA) );
344 else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9)
345 AddCookie(Array[i], '1' + (nUsage - kHIDUsage_Keyboard1) );
346 else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12)
347 AddCookie(Array[i], WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) );
348 else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24)
349 AddCookie(Array[i], WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) );
350 else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9)
351 AddCookie(Array[i], WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) );
352 else switch (nUsage)
353 {
354 //0's (wx & ascii go 0-9, but HID goes 1-0)
355 case kHIDUsage_Keyboard0:
356 AddCookie(Array[i],'0');
357 break;
358 case kHIDUsage_Keypad0:
359 AddCookie(Array[i],WXK_NUMPAD0);
360 break;
361
362 //Basic
363 case kHIDUsage_KeyboardReturnOrEnter:
364 AddCookie(Array[i], WXK_RETURN);
365 break;
366 case kHIDUsage_KeyboardEscape:
367 AddCookie(Array[i], WXK_ESCAPE);
368 break;
369 case kHIDUsage_KeyboardDeleteOrBackspace:
370 AddCookie(Array[i], WXK_BACK);
371 break;
372 case kHIDUsage_KeyboardTab:
373 AddCookie(Array[i], WXK_TAB);
374 break;
375 case kHIDUsage_KeyboardSpacebar:
376 AddCookie(Array[i], WXK_SPACE);
377 break;
378 case kHIDUsage_KeyboardPageUp:
379 AddCookie(Array[i], WXK_PRIOR);
380 break;
381 case kHIDUsage_KeyboardEnd:
382 AddCookie(Array[i], WXK_END);
383 break;
384 case kHIDUsage_KeyboardPageDown:
385 AddCookie(Array[i], WXK_NEXT);
386 break;
387 case kHIDUsage_KeyboardRightArrow:
388 AddCookie(Array[i], WXK_RIGHT);
389 break;
390 case kHIDUsage_KeyboardLeftArrow:
391 AddCookie(Array[i], WXK_LEFT);
392 break;
393 case kHIDUsage_KeyboardDownArrow:
394 AddCookie(Array[i], WXK_DOWN);
395 break;
396 case kHIDUsage_KeyboardUpArrow:
397 AddCookie(Array[i], WXK_UP);
398 break;
399
400 //LEDS
401 case kHIDUsage_KeyboardCapsLock:
402 AddCookie(Array[i],WXK_CAPITAL);
403 break;
404 case kHIDUsage_KeypadNumLock:
405 AddCookie(Array[i],WXK_NUMLOCK);
406 break;
407 case kHIDUsage_KeyboardScrollLock:
408 AddCookie(Array[i],WXK_SCROLL);
409 break;
410
411 //Menu keys, Shift, other specials
412 case kHIDUsage_KeyboardLeftControl:
413 AddCookie(Array[i],WXK_CONTROL);
414 break;
415 case kHIDUsage_KeyboardLeftShift:
416 AddCookie(Array[i],WXK_SHIFT);
417 break;
418 case kHIDUsage_KeyboardLeftAlt:
419 AddCookie(Array[i],WXK_ALT);
420 break;
421 case kHIDUsage_KeyboardLeftGUI:
422 AddCookie(Array[i],WXK_MENU);
423 break;
424 case kHIDUsage_KeyboardRightControl:
425 AddCookie(Array[i],WXK_RCONTROL);
426 break;
427 case kHIDUsage_KeyboardRightShift:
428 AddCookie(Array[i],WXK_RSHIFT);
429 break;
430 case kHIDUsage_KeyboardRightAlt:
431 AddCookie(Array[i],WXK_RALT);
432 break;
433 case kHIDUsage_KeyboardRightGUI:
434 AddCookie(Array[i],WXK_RMENU);
435 break;
436
437 //Default
438 default:
439 //not in wx keycodes - do nothing....
440 break;
441 }
442 }
443 }//end buildcookies
444
445 #endif //__DARWIN__