]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/hid.cpp
Enable UpdateUI events in wxTaskBarIcon.
[wxWidgets.git] / src / mac / carbon / hid.cpp
CommitLineData
ec8bd392
RN
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
1553abf4
RN
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20#ifdef __GNUG__
21#pragma implementation "hid.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/defs.h"
33#endif
34
ec8bd392
RN
35
36//DARWIN _ONLY_
37#ifdef __DARWIN__
38
39#include "wx/mac/carbon/private/hid.h"
40#include "wx/string.h"
41#include "wx/log.h"
7f71c4c8 42
1553abf4
RN
43
44// ---------------------------------------------------------------------------
45// assertion macros
46// ---------------------------------------------------------------------------
47
7f71c4c8
RN
48#define wxFORCECHECK_MSG(arg, msg) \
49{\
50 if (arg) \
51 {\
52 wxLogSysError(wxString::Format(wxT("Message:%s\nHID: %s failed!"), wxT(msg), wxT(#arg)));\
53 return false;\
54 }\
55}
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)
59
ec8bd392
RN
60#ifdef __WXDEBUG___
61# define wxVERIFY(arg) wxASSERT(arg)
62#else
63# define wxVERIFY(arg) arg
64#endif
65
66/*
7f71c4c8
RN
67void CFShowTypeIDDescription(CFTypeRef pData)
68{
69 if(!pData)
70 {
ec8bd392 71 wxASSERT(false);
7f71c4c8
RN
72 return;
73 }
74
75 wxMessageBox(
76 CFStringGetCStringPtr(
77 CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding()
78 )
79 );
80}
ec8bd392 81*/
7f71c4c8
RN
82
83// ============================================================================
84// implementation
85// ============================================================================
86
1553abf4
RN
87// ---------------------------------------------------------------------------
88// wxHIDDevice
89// ---------------------------------------------------------------------------
7f71c4c8
RN
90
91bool wxHIDDevice::Create (const int& nClass, const int& nType)
92{
93 //Create the mach port
94 wxIOCHECK(IOMasterPort(bootstrap_port, &m_pPort), "Could not create mach port");
95
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;
100
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))
ec8bd392 105 wxVERIFY((pDictionary = IOServiceMatching(kIOHIDDeviceKey)) != NULL );
7f71c4c8
RN
106
107 //Here we'll filter down the services to what we want
108 if (nType != -1)
109 {
110 CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
111 kCFNumberIntType, &nType);
112 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
113 CFRelease(pType);
114 }
115 if (nClass != -1)
116 {
117 CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
118 kCFNumberIntType, &nClass);
119 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
120 CFRelease(pClass);
121 }
122
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);
127
128 //Now we iterate through them
129 io_object_t pObject;
130 while ( (pObject = IOIteratorNext(pIterator)) != NULL)
131 {
ec8bd392 132 wxVERIFY(IORegistryEntryCreateCFProperties(pObject, &pDictionary,
7f71c4c8
RN
133 kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS);
134
135 //Just for sanity :)
342689c8 136 wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID());
7f71c4c8
RN
137
138 //Get [product] name
139 m_szName = CFStringGetCStringPtr (
140 (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)),
141 CFStringGetSystemEncoding()
142 );
143
144 //
145 //Now the hard part - in order to scan things we need "cookies" -
146 //
147 wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey));
148 BuildCookies(CookieArray);
149 if (m_ppQueue != NULL)
ec8bd392 150 wxVERIFY((*m_ppQueue)->start(m_ppQueue) == S_OK);
7f71c4c8
RN
151
152 //Create the interface (good grief - long function names!)
153 SInt32 nScore;
154 IOCFPlugInInterface** ppPlugin;
155 wxIOCHECK(IOCreatePlugInInterfaceForService(pObject, kIOHIDDeviceUserClientTypeID,
156 kIOCFPlugInInterfaceID, &ppPlugin, &nScore), "");
157
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).
161
162 //Get the HID interface from the plugin to the mach port
163 wxSCHECK((*ppPlugin)->QueryInterface(ppPlugin,
164 CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void**) &m_ppDevice), "");
165
166 //release the plugin
167 (*ppPlugin)->Release(ppPlugin);
168
169 //open the HID interface...
ec8bd392 170 wxVERIFY((*m_ppDevice)->open(m_ppDevice, 0) == S_OK);
7f71c4c8
RN
171
172 //cleanup
173 CFRelease(pDictionary);
174 IOObjectRelease(pObject);
175 break;
176 }
177 //iterator cleanup
178 IOObjectRelease(pIterator);
179
180 return true;
181}//end Create()
182
183void wxHIDDevice::AddCookie(CFTypeRef Data, const int& i)
184{
185 CFNumberGetValue(
186 (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data
187 , CFSTR(kIOHIDElementCookieKey)
188 ),
189 kCFNumberIntType,
190 &m_pCookies[i]
191 );
192}
193
194void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, const int& i)
195{
196 AddCookie(Data, i);
ec8bd392 197 wxVERIFY((*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) == S_OK);//3rd Param flags (none yet)
7f71c4c8
RN
198}
199
200void wxHIDDevice::InitCookies(const size_t& dwSize, bool bQueue)
201{
202 m_pCookies = new IOHIDElementCookie[dwSize];
203 if (bQueue)
204 {
205 wxASSERT( m_ppQueue != NULL);
ec8bd392
RN
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
7f71c4c8
RN
208 }
209}
210
211bool wxHIDDevice::IsActive(const int& nIndex)
212{
213 wxASSERT(m_pCookies[nIndex] != NULL);
214 IOHIDEventStruct Event;
215 (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event);
216 return !!Event.value;
217}
218
219
220wxHIDDevice::~wxHIDDevice()
221{
222 if (m_ppDevice != NULL)
223 {
224 (*m_ppDevice)->close(m_ppDevice);
225 (*m_ppDevice)->Release(m_ppDevice);
226 mach_port_deallocate(mach_task_self(), m_pPort);
227 }
228
229 if (m_pCookies != NULL)
230 {
231 delete [] m_pCookies;
232 if (m_ppQueue != NULL)
233 {
234 (*m_ppQueue)->stop(m_ppQueue);
235 (*m_ppQueue)->dispose(m_ppQueue);
236 (*m_ppQueue)->Release(m_ppQueue);
237 }
238 }
239}
7f71c4c8 240
1553abf4
RN
241// ---------------------------------------------------------------------------
242// wxHIDKeyboard
243// ---------------------------------------------------------------------------
244
7f71c4c8
RN
245enum
246{
247 WXK_RSHIFT = 400,
248 WXK_RALT,
249 WXK_RCONTROL,
250 WXK_RMENU
251
252};
253
254bool wxHIDKeyboard::Create()
255{
256 return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
257}
258
259void wxHIDKeyboard::BuildCookies(wxCFArray& Array)
260{
261 Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey));
262 InitCookies(500);
263 int i,
264 nUsage;
265 for (i = 0; i < Array.Count(); ++i)
266 {
267 CFNumberGetValue(
268 (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)),
269 kCFNumberLongType, &nUsage);
270
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) );
281 else switch (nUsage)
282 {
283 //0's (wx & ascii go 0-9, but HID goes 1-0)
284 case kHIDUsage_Keyboard0:
285 AddCookie(Array[i],'0');
286 break;
287 case kHIDUsage_Keypad0:
288 AddCookie(Array[i],WXK_NUMPAD0);
289 break;
290
291 //Basic
292 case kHIDUsage_KeyboardReturnOrEnter:
293 AddCookie(Array[i], WXK_RETURN);
294 break;
295 case kHIDUsage_KeyboardEscape:
296 AddCookie(Array[i], WXK_ESCAPE);
297 break;
298 case kHIDUsage_KeyboardDeleteOrBackspace:
299 AddCookie(Array[i], WXK_BACK);
300 break;
301 case kHIDUsage_KeyboardTab:
302 AddCookie(Array[i], WXK_TAB);
303 break;
304 case kHIDUsage_KeyboardSpacebar:
305 AddCookie(Array[i], WXK_SPACE);
306 break;
307 case kHIDUsage_KeyboardPageUp:
308 AddCookie(Array[i], WXK_PRIOR);
309 break;
310 case kHIDUsage_KeyboardEnd:
311 AddCookie(Array[i], WXK_END);
312 break;
313 case kHIDUsage_KeyboardPageDown:
314 AddCookie(Array[i], WXK_NEXT);
315 break;
316 case kHIDUsage_KeyboardRightArrow:
317 AddCookie(Array[i], WXK_RIGHT);
318 break;
319 case kHIDUsage_KeyboardLeftArrow:
320 AddCookie(Array[i], WXK_LEFT);
321 break;
322 case kHIDUsage_KeyboardDownArrow:
323 AddCookie(Array[i], WXK_DOWN);
324 break;
325 case kHIDUsage_KeyboardUpArrow:
326 AddCookie(Array[i], WXK_UP);
327 break;
328
329 //LEDS
330 case kHIDUsage_KeyboardCapsLock:
331 AddCookie(Array[i],WXK_CAPITAL);
332 break;
333 case kHIDUsage_KeypadNumLock:
334 AddCookie(Array[i],WXK_NUMLOCK);
335 break;
336 case kHIDUsage_KeyboardScrollLock:
337 AddCookie(Array[i],WXK_SCROLL);
338 break;
339
340 //Menu keys, Shift, other specials
341 case kHIDUsage_KeyboardLeftControl:
342 AddCookie(Array[i],WXK_CONTROL);
343 break;
344 case kHIDUsage_KeyboardLeftShift:
345 AddCookie(Array[i],WXK_SHIFT);
346 break;
347 case kHIDUsage_KeyboardLeftAlt:
348 AddCookie(Array[i],WXK_ALT);
349 break;
350 case kHIDUsage_KeyboardLeftGUI:
351 AddCookie(Array[i],WXK_MENU);
352 break;
353 case kHIDUsage_KeyboardRightControl:
354 AddCookie(Array[i],WXK_RCONTROL);
355 break;
356 case kHIDUsage_KeyboardRightShift:
357 AddCookie(Array[i],WXK_RSHIFT);
358 break;
359 case kHIDUsage_KeyboardRightAlt:
360 AddCookie(Array[i],WXK_RALT);
361 break;
362 case kHIDUsage_KeyboardRightGUI:
363 AddCookie(Array[i],WXK_RMENU);
364 break;
365
366 //Default
367 default:
368 //not in wx keycodes - do nothing....
369 break;
370 }
371 }
372}//end buildcookies
ec8bd392
RN
373
374#endif //__DARWIN__