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