From: Ryan Norton Date: Fri, 23 Jan 2004 09:44:05 +0000 (+0000) Subject: HID support (preliminary - not added to bakefiles yet) X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/7f71c4c8d3211df1bad57c5a275d65350e22c10e?hp=2fd4848088e36e84fbf7ed643ef919485583a8f2 HID support (preliminary - not added to bakefiles yet) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@25335 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/mac/private/hid.h b/include/wx/mac/private/hid.h new file mode 100644 index 0000000000..2947ee3575 --- /dev/null +++ b/include/wx/mac/private/hid.h @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include + +#include + +//Utility wrapper around CFArray +class wxCFArray +{ +public: + wxCFArray(CFTypeRef pData) : pArray((CFArrayRef) pData) {} + CFTypeRef operator [] (const int& nIndex) {return CFArrayGetValueAtIndex(pArray, nIndex); } + int Count() {return CFArrayGetCount(pArray);} +private: + CFArrayRef pArray; +}; + +// +// A wrapper around OS X HID Manager procedures. +// The tutorial "Working With HID Class Device Interfaces" Is +// Quite good, as is the sample program associated with it +// (Depite the author's protests!). +class wxHIDDevice +{ +public: + wxHIDDevice() : m_ppDevice(NULL), m_ppQueue(NULL), m_pCookies(NULL) {} + //kHIDPage_GenericDesktop + //kHIDUsage_GD_Joystick,kHIDUsage_GD_Mouse,kHIDUsage_GD_Keyboard + bool Create (const int& nClass = -1, const int& nType = -1); + + inline void AddCookie(CFTypeRef Data, const int& i); + inline void AddCookieInQueue(CFTypeRef Data, const int& i); + inline void InitCookies(const size_t& dwSize, bool bQueue = false); + + //Must be implemented by derived classes + //builds the cookie array - + //first call InitCookies to initialize the cookie + //array, then AddCookie to add a cookie at a certain point in an array + virtual void BuildCookies(wxCFArray& Array) = 0; + + //checks to see whether the cookie at index nIndex is active (element value != 0) + bool IsActive(const int& nIndex); + + //closes the device and cleans the queue and cookies + virtual ~wxHIDDevice(); +private: + IOHIDDeviceInterface** m_ppDevice; //this, essentially + IOHIDQueueInterface** m_ppQueue; //queue (if we want one) + IOHIDElementCookie* m_pCookies; //cookies + + const char* m_szName; //(product) name + mach_port_t m_pPort; +}; + +class wxHIDKeyboard : public wxHIDDevice +{ +public: + bool Create(); + virtual void BuildCookies(wxCFArray& Array); +}; \ No newline at end of file diff --git a/src/mac/app.cpp b/src/mac/app.cpp index f7e96bddfb..a5f703819b 100644 --- a/src/mac/app.cpp +++ b/src/mac/app.cpp @@ -1817,6 +1817,10 @@ int wxKeyCodeToMacModifier(wxKeyCode key) bool wxGetKeyState(wxKeyCode key) //virtual key code if < 10.2.x, else see below { +//#ifdef __DARWIN__ +// wxHIDKeyboard keyboard; +// return keyboard.IsActive(key); +//#else // TODO: Have it use HID Manager on OSX... //if OS X > 10.2 (i.e. 10.2.x) //a known apple bug prevents the system from determining led @@ -1826,6 +1830,7 @@ bool wxGetKeyState(wxKeyCode key) //virtual key code if < 10.2.x, else see below // KeyMapByteArray keymap; // GetKeys((BigEndianLong*)keymap); // return !!(BitTst(keymap, (sizeof(KeyMapByteArray)*8) - iKey)); +//#endif } #if !TARGET_CARBON diff --git a/src/mac/carbon/app.cpp b/src/mac/carbon/app.cpp index f7e96bddfb..a5f703819b 100644 --- a/src/mac/carbon/app.cpp +++ b/src/mac/carbon/app.cpp @@ -1817,6 +1817,10 @@ int wxKeyCodeToMacModifier(wxKeyCode key) bool wxGetKeyState(wxKeyCode key) //virtual key code if < 10.2.x, else see below { +//#ifdef __DARWIN__ +// wxHIDKeyboard keyboard; +// return keyboard.IsActive(key); +//#else // TODO: Have it use HID Manager on OSX... //if OS X > 10.2 (i.e. 10.2.x) //a known apple bug prevents the system from determining led @@ -1826,6 +1830,7 @@ bool wxGetKeyState(wxKeyCode key) //virtual key code if < 10.2.x, else see below // KeyMapByteArray keymap; // GetKeys((BigEndianLong*)keymap); // return !!(BitTst(keymap, (sizeof(KeyMapByteArray)*8) - iKey)); +//#endif } #if !TARGET_CARBON diff --git a/src/mac/carbon/hid.cpp b/src/mac/carbon/hid.cpp new file mode 100644 index 0000000000..f4ce8a1874 --- /dev/null +++ b/src/mac/carbon/hid.cpp @@ -0,0 +1,417 @@ +#include "hid.h" + +#define wxFORCECHECK_MSG(arg, msg) \ +{\ + if (arg) \ + {\ + wxLogSysError(wxString::Format(wxT("Message:%s\nHID: %s failed!"), wxT(msg), wxT(#arg)));\ + return false;\ + }\ +} +#define wxIOCHECK(arg, msg) wxFORCECHECK_MSG(arg != kIOReturnSuccess, msg) +#define wxKERNCHECK(arg, msg) wxFORCECHECK_MSG(arg != KERN_SUCCESS, msg) +#define wxSCHECK(arg, msg) wxFORCECHECK_MSG(arg != S_OK, msg) + +void CFShowTypeIDDescription(CFTypeRef pData) +{ + if(!pData) + { + wxMessageBox("AHHH!"); + return; + } + + wxMessageBox( + CFStringGetCStringPtr( + CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding() + ) + ); +} + +// ============================================================================ +// implementation +// ============================================================================ + + +bool wxHIDDevice::Create (const int& nClass, const int& nType) +{ + //Create the mach port + wxIOCHECK(IOMasterPort(bootstrap_port, &m_pPort), "Could not create mach port"); + + //Dictionary that will hold first + //the matching dictionary for determining which kind of devices we want, + //then later some registry properties from an iterator (see below) + CFMutableDictionaryRef pDictionary; + + //Create a dictionary + //The call to IOServiceMatching filters down the + //the services we want to hid services (and also eats the + //dictionary up for us (consumes one reference)) + wxASSERT((pDictionary = IOServiceMatching(kIOHIDDeviceKey)) != NULL ); + + //Here we'll filter down the services to what we want + if (nType != -1) + { + CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault, + kCFNumberIntType, &nType); + CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType); + CFRelease(pType); + } + if (nClass != -1) + { + CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault, + kCFNumberIntType, &nClass); + CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass); + CFRelease(pClass); + } + + //Now get the maching services + io_iterator_t pIterator; + wxIOCHECK(IOServiceGetMatchingServices(m_pPort, pDictionary, &pIterator), "No Matching HID Services"); + wxASSERT(pIterator != NULL); + + //Now we iterate through them + io_object_t pObject; + while ( (pObject = IOIteratorNext(pIterator)) != NULL) + { + wxASSERT(IORegistryEntryCreateCFProperties(pObject, &pDictionary, + kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS); + + //Just for sanity :) + wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID()); + + //Get [product] name + m_szName = CFStringGetCStringPtr ( + (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)), + CFStringGetSystemEncoding() + ); + + // + //Now the hard part - in order to scan things we need "cookies" - + // + wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey)); + BuildCookies(CookieArray); + if (m_ppQueue != NULL) + wxASSERT((*m_ppQueue)->start(m_ppQueue) == S_OK); + + //Create the interface (good grief - long function names!) + SInt32 nScore; + IOCFPlugInInterface** ppPlugin; + wxIOCHECK(IOCreatePlugInInterfaceForService(pObject, kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &ppPlugin, &nScore), ""); + + //Now, the final thing we can check before we fall back to asserts + //(because the dtor only checks if the device is ok, so if anything + //fails from now on the dtor will delete the device anyway, so we can't break from this). + + //Get the HID interface from the plugin to the mach port + wxSCHECK((*ppPlugin)->QueryInterface(ppPlugin, + CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void**) &m_ppDevice), ""); + + //release the plugin + (*ppPlugin)->Release(ppPlugin); + + //open the HID interface... + wxASSERT((*m_ppDevice)->open(m_ppDevice, 0) == S_OK); + + //cleanup + CFRelease(pDictionary); + IOObjectRelease(pObject); + break; + } + //iterator cleanup + IOObjectRelease(pIterator); + + return true; +}//end Create() + +void wxHIDDevice::AddCookie(CFTypeRef Data, const int& i) +{ + CFNumberGetValue( + (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data + , CFSTR(kIOHIDElementCookieKey) + ), + kCFNumberIntType, + &m_pCookies[i] + ); +} + +void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, const int& i) +{ + AddCookie(Data, i); + wxASSERT((*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) == S_OK);//3rd Param flags (none yet) +} + +void wxHIDDevice::InitCookies(const size_t& dwSize, bool bQueue) +{ + m_pCookies = new IOHIDElementCookie[dwSize]; + if (bQueue) + { + wxASSERT( m_ppQueue != NULL); + wxASSERT( (m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice)) != NULL); + wxASSERT( (*m_ppQueue)->create(m_ppQueue, 0, 512) == S_OK); //Param 2, flags, none yet + } +} + +bool wxHIDDevice::IsActive(const int& nIndex) +{ + wxASSERT(m_pCookies[nIndex] != NULL); + IOHIDEventStruct Event; + (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event); + return !!Event.value; +} + + +wxHIDDevice::~wxHIDDevice() +{ + if (m_ppDevice != NULL) + { + (*m_ppDevice)->close(m_ppDevice); + (*m_ppDevice)->Release(m_ppDevice); + mach_port_deallocate(mach_task_self(), m_pPort); + } + + if (m_pCookies != NULL) + { + delete [] m_pCookies; + if (m_ppQueue != NULL) + { + (*m_ppQueue)->stop(m_ppQueue); + (*m_ppQueue)->dispose(m_ppQueue); + (*m_ppQueue)->Release(m_ppQueue); + } + } +} +/* +enum +{ + kHIDUsage_KeyboardHyphen = 0x2D, + kHIDUsage_KeyboardEqualSign = 0x2E, + kHIDUsage_KeyboardOpenBracket = 0x2F, + kHIDUsage_KeyboardCloseBracket = 0x30, + kHIDUsage_KeyboardBackslash = 0x31, //* \ or | * + kHIDUsage_KeyboardNonUSPound = 0x32, /* Non-US # or _ * + kHIDUsage_KeyboardSemicolon = 0x33, /* ; or : * + kHIDUsage_KeyboardQuote = 0x34, /* ' or " * + kHIDUsage_KeyboardGraveAccentAndTilde = 0x35, /* Grave Accent and Tilde * + kHIDUsage_KeyboardComma = 0x36, /* , or < * + kHIDUsage_KeyboardPeriod = 0x37, /* . or > * + kHIDUsage_KeyboardSlash = 0x38, /* / or ? * + kHIDUsage_KeyboardCapsLock = 0x39, /* Caps Lock * + + kHIDUsage_KeyboardPrintScreen = 0x46, /* Print Screen * + kHIDUsage_KeyboardScrollLock = 0x47, /* Scroll Lock * + kHIDUsage_KeyboardPause = 0x48, /* Pause * + kHIDUsage_KeyboardInsert = 0x49, /* Insert * + kHIDUsage_KeyboardHome = 0x4A, /* Home * + kHIDUsage_KeyboardDeleteForward = 0x4C, /* Delete Forward * + + kHIDUsage_KeyboardUpArrow + kHIDUsage_KeypadNumLock + kHIDUsage_KeypadSlash + kHIDUsage_KeypadAsterisk + kHIDUsage_KeypadHyphen + kHIDUsage_KeypadPlus + kHIDUsage_KeypadEnter + kHIDUsage_KeypadPeriod + kHIDUsage_KeyboardNonUSBackslash + kHIDUsage_KeyboardApplication + kHIDUsage_KeyboardPower + kHIDUsage_KeypadEqualSign +}; +/* + enum wxKeyCode + { + + WXK_START = 300, + WXK_LBUTTON, + WXK_RBUTTON, + WXK_CANCEL, + WXK_MBUTTON, + WXK_CLEAR, + WXK_SHIFT, + WXK_ALT, + WXK_CONTROL, + WXK_MENU, + WXK_PAUSE, + WXK_PRIOR, * Page up * + WXK_NEXT, * Page down * + WXK_END, + WXK_HOME, + WXK_LEFT, + WXK_UP, + WXK_RIGHT, + WXK_DOWN, + WXK_SELECT, + WXK_PRINT, + WXK_EXECUTE, + WXK_SNAPSHOT, + WXK_INSERT, + WXK_HELP, + WXK_MULTIPLY, + WXK_ADD, + WXK_SEPARATOR, + WXK_SUBTRACT, + WXK_DECIMAL, + WXK_DIVIDE, + WXK_PAGEUP, + WXK_PAGEDOWN, + + WXK_NUMPAD_SPACE, + WXK_NUMPAD_TAB, + WXK_NUMPAD_ENTER, + WXK_NUMPAD_HOME, + WXK_NUMPAD_LEFT, + WXK_NUMPAD_UP, + WXK_NUMPAD_RIGHT, + WXK_NUMPAD_DOWN, + WXK_NUMPAD_PRIOR, + WXK_NUMPAD_PAGEUP, + WXK_NUMPAD_NEXT, + WXK_NUMPAD_PAGEDOWN, + WXK_NUMPAD_END, + WXK_NUMPAD_BEGIN, + WXK_NUMPAD_INSERT, + WXK_NUMPAD_DELETE, + WXK_NUMPAD_EQUAL, + WXK_NUMPAD_MULTIPLY, + WXK_NUMPAD_ADD, + WXK_NUMPAD_SEPARATOR, + WXK_NUMPAD_SUBTRACT, + WXK_NUMPAD_DECIMAL, + WXK_NUMPAD_DIVIDE, + + WXK_WINDOWS_LEFT, + WXK_WINDOWS_RIGHT, + WXK_WINDOWS_MENU , + WXK_COMMAND + }; + + */ +enum +{ + WXK_RSHIFT = 400, + WXK_RALT, + WXK_RCONTROL, + WXK_RMENU + +}; + +bool wxHIDKeyboard::Create() +{ + return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); +} + +void wxHIDKeyboard::BuildCookies(wxCFArray& Array) +{ + Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey)); + InitCookies(500); + int i, + nUsage; + for (i = 0; i < Array.Count(); ++i) + { + CFNumberGetValue( + (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)), + kCFNumberLongType, &nUsage); + + if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ) + AddCookie(Array[i], 'A' + (nUsage - kHIDUsage_KeyboardA) ); + else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9) + AddCookie(Array[i], '1' + (nUsage - kHIDUsage_Keyboard1) ); + else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12) + AddCookie(Array[i], WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) ); + else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24) + AddCookie(Array[i], WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) ); + else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9) + AddCookie(Array[i], WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) ); + else switch (nUsage) + { + //0's (wx & ascii go 0-9, but HID goes 1-0) + case kHIDUsage_Keyboard0: + AddCookie(Array[i],'0'); + break; + case kHIDUsage_Keypad0: + AddCookie(Array[i],WXK_NUMPAD0); + break; + + //Basic + case kHIDUsage_KeyboardReturnOrEnter: + AddCookie(Array[i], WXK_RETURN); + break; + case kHIDUsage_KeyboardEscape: + AddCookie(Array[i], WXK_ESCAPE); + break; + case kHIDUsage_KeyboardDeleteOrBackspace: + AddCookie(Array[i], WXK_BACK); + break; + case kHIDUsage_KeyboardTab: + AddCookie(Array[i], WXK_TAB); + break; + case kHIDUsage_KeyboardSpacebar: + AddCookie(Array[i], WXK_SPACE); + break; + case kHIDUsage_KeyboardPageUp: + AddCookie(Array[i], WXK_PRIOR); + break; + case kHIDUsage_KeyboardEnd: + AddCookie(Array[i], WXK_END); + break; + case kHIDUsage_KeyboardPageDown: + AddCookie(Array[i], WXK_NEXT); + break; + case kHIDUsage_KeyboardRightArrow: + AddCookie(Array[i], WXK_RIGHT); + break; + case kHIDUsage_KeyboardLeftArrow: + AddCookie(Array[i], WXK_LEFT); + break; + case kHIDUsage_KeyboardDownArrow: + AddCookie(Array[i], WXK_DOWN); + break; + case kHIDUsage_KeyboardUpArrow: + AddCookie(Array[i], WXK_UP); + break; + + //LEDS + case kHIDUsage_KeyboardCapsLock: + AddCookie(Array[i],WXK_CAPITAL); + break; + case kHIDUsage_KeypadNumLock: + AddCookie(Array[i],WXK_NUMLOCK); + break; + case kHIDUsage_KeyboardScrollLock: + AddCookie(Array[i],WXK_SCROLL); + break; + + //Menu keys, Shift, other specials + case kHIDUsage_KeyboardLeftControl: + AddCookie(Array[i],WXK_CONTROL); + break; + case kHIDUsage_KeyboardLeftShift: + AddCookie(Array[i],WXK_SHIFT); + break; + case kHIDUsage_KeyboardLeftAlt: + AddCookie(Array[i],WXK_ALT); + break; + case kHIDUsage_KeyboardLeftGUI: + AddCookie(Array[i],WXK_MENU); + break; + case kHIDUsage_KeyboardRightControl: + AddCookie(Array[i],WXK_RCONTROL); + break; + case kHIDUsage_KeyboardRightShift: + AddCookie(Array[i],WXK_RSHIFT); + break; + case kHIDUsage_KeyboardRightAlt: + AddCookie(Array[i],WXK_RALT); + break; + case kHIDUsage_KeyboardRightGUI: + AddCookie(Array[i],WXK_RMENU); + break; + + //Default + default: + //not in wx keycodes - do nothing.... + break; + } + } +}//end buildcookies diff --git a/src/mac/hid.cpp b/src/mac/hid.cpp new file mode 100644 index 0000000000..f4ce8a1874 --- /dev/null +++ b/src/mac/hid.cpp @@ -0,0 +1,417 @@ +#include "hid.h" + +#define wxFORCECHECK_MSG(arg, msg) \ +{\ + if (arg) \ + {\ + wxLogSysError(wxString::Format(wxT("Message:%s\nHID: %s failed!"), wxT(msg), wxT(#arg)));\ + return false;\ + }\ +} +#define wxIOCHECK(arg, msg) wxFORCECHECK_MSG(arg != kIOReturnSuccess, msg) +#define wxKERNCHECK(arg, msg) wxFORCECHECK_MSG(arg != KERN_SUCCESS, msg) +#define wxSCHECK(arg, msg) wxFORCECHECK_MSG(arg != S_OK, msg) + +void CFShowTypeIDDescription(CFTypeRef pData) +{ + if(!pData) + { + wxMessageBox("AHHH!"); + return; + } + + wxMessageBox( + CFStringGetCStringPtr( + CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding() + ) + ); +} + +// ============================================================================ +// implementation +// ============================================================================ + + +bool wxHIDDevice::Create (const int& nClass, const int& nType) +{ + //Create the mach port + wxIOCHECK(IOMasterPort(bootstrap_port, &m_pPort), "Could not create mach port"); + + //Dictionary that will hold first + //the matching dictionary for determining which kind of devices we want, + //then later some registry properties from an iterator (see below) + CFMutableDictionaryRef pDictionary; + + //Create a dictionary + //The call to IOServiceMatching filters down the + //the services we want to hid services (and also eats the + //dictionary up for us (consumes one reference)) + wxASSERT((pDictionary = IOServiceMatching(kIOHIDDeviceKey)) != NULL ); + + //Here we'll filter down the services to what we want + if (nType != -1) + { + CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault, + kCFNumberIntType, &nType); + CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType); + CFRelease(pType); + } + if (nClass != -1) + { + CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault, + kCFNumberIntType, &nClass); + CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass); + CFRelease(pClass); + } + + //Now get the maching services + io_iterator_t pIterator; + wxIOCHECK(IOServiceGetMatchingServices(m_pPort, pDictionary, &pIterator), "No Matching HID Services"); + wxASSERT(pIterator != NULL); + + //Now we iterate through them + io_object_t pObject; + while ( (pObject = IOIteratorNext(pIterator)) != NULL) + { + wxASSERT(IORegistryEntryCreateCFProperties(pObject, &pDictionary, + kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS); + + //Just for sanity :) + wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID()); + + //Get [product] name + m_szName = CFStringGetCStringPtr ( + (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)), + CFStringGetSystemEncoding() + ); + + // + //Now the hard part - in order to scan things we need "cookies" - + // + wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey)); + BuildCookies(CookieArray); + if (m_ppQueue != NULL) + wxASSERT((*m_ppQueue)->start(m_ppQueue) == S_OK); + + //Create the interface (good grief - long function names!) + SInt32 nScore; + IOCFPlugInInterface** ppPlugin; + wxIOCHECK(IOCreatePlugInInterfaceForService(pObject, kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &ppPlugin, &nScore), ""); + + //Now, the final thing we can check before we fall back to asserts + //(because the dtor only checks if the device is ok, so if anything + //fails from now on the dtor will delete the device anyway, so we can't break from this). + + //Get the HID interface from the plugin to the mach port + wxSCHECK((*ppPlugin)->QueryInterface(ppPlugin, + CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void**) &m_ppDevice), ""); + + //release the plugin + (*ppPlugin)->Release(ppPlugin); + + //open the HID interface... + wxASSERT((*m_ppDevice)->open(m_ppDevice, 0) == S_OK); + + //cleanup + CFRelease(pDictionary); + IOObjectRelease(pObject); + break; + } + //iterator cleanup + IOObjectRelease(pIterator); + + return true; +}//end Create() + +void wxHIDDevice::AddCookie(CFTypeRef Data, const int& i) +{ + CFNumberGetValue( + (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data + , CFSTR(kIOHIDElementCookieKey) + ), + kCFNumberIntType, + &m_pCookies[i] + ); +} + +void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, const int& i) +{ + AddCookie(Data, i); + wxASSERT((*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) == S_OK);//3rd Param flags (none yet) +} + +void wxHIDDevice::InitCookies(const size_t& dwSize, bool bQueue) +{ + m_pCookies = new IOHIDElementCookie[dwSize]; + if (bQueue) + { + wxASSERT( m_ppQueue != NULL); + wxASSERT( (m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice)) != NULL); + wxASSERT( (*m_ppQueue)->create(m_ppQueue, 0, 512) == S_OK); //Param 2, flags, none yet + } +} + +bool wxHIDDevice::IsActive(const int& nIndex) +{ + wxASSERT(m_pCookies[nIndex] != NULL); + IOHIDEventStruct Event; + (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event); + return !!Event.value; +} + + +wxHIDDevice::~wxHIDDevice() +{ + if (m_ppDevice != NULL) + { + (*m_ppDevice)->close(m_ppDevice); + (*m_ppDevice)->Release(m_ppDevice); + mach_port_deallocate(mach_task_self(), m_pPort); + } + + if (m_pCookies != NULL) + { + delete [] m_pCookies; + if (m_ppQueue != NULL) + { + (*m_ppQueue)->stop(m_ppQueue); + (*m_ppQueue)->dispose(m_ppQueue); + (*m_ppQueue)->Release(m_ppQueue); + } + } +} +/* +enum +{ + kHIDUsage_KeyboardHyphen = 0x2D, + kHIDUsage_KeyboardEqualSign = 0x2E, + kHIDUsage_KeyboardOpenBracket = 0x2F, + kHIDUsage_KeyboardCloseBracket = 0x30, + kHIDUsage_KeyboardBackslash = 0x31, //* \ or | * + kHIDUsage_KeyboardNonUSPound = 0x32, /* Non-US # or _ * + kHIDUsage_KeyboardSemicolon = 0x33, /* ; or : * + kHIDUsage_KeyboardQuote = 0x34, /* ' or " * + kHIDUsage_KeyboardGraveAccentAndTilde = 0x35, /* Grave Accent and Tilde * + kHIDUsage_KeyboardComma = 0x36, /* , or < * + kHIDUsage_KeyboardPeriod = 0x37, /* . or > * + kHIDUsage_KeyboardSlash = 0x38, /* / or ? * + kHIDUsage_KeyboardCapsLock = 0x39, /* Caps Lock * + + kHIDUsage_KeyboardPrintScreen = 0x46, /* Print Screen * + kHIDUsage_KeyboardScrollLock = 0x47, /* Scroll Lock * + kHIDUsage_KeyboardPause = 0x48, /* Pause * + kHIDUsage_KeyboardInsert = 0x49, /* Insert * + kHIDUsage_KeyboardHome = 0x4A, /* Home * + kHIDUsage_KeyboardDeleteForward = 0x4C, /* Delete Forward * + + kHIDUsage_KeyboardUpArrow + kHIDUsage_KeypadNumLock + kHIDUsage_KeypadSlash + kHIDUsage_KeypadAsterisk + kHIDUsage_KeypadHyphen + kHIDUsage_KeypadPlus + kHIDUsage_KeypadEnter + kHIDUsage_KeypadPeriod + kHIDUsage_KeyboardNonUSBackslash + kHIDUsage_KeyboardApplication + kHIDUsage_KeyboardPower + kHIDUsage_KeypadEqualSign +}; +/* + enum wxKeyCode + { + + WXK_START = 300, + WXK_LBUTTON, + WXK_RBUTTON, + WXK_CANCEL, + WXK_MBUTTON, + WXK_CLEAR, + WXK_SHIFT, + WXK_ALT, + WXK_CONTROL, + WXK_MENU, + WXK_PAUSE, + WXK_PRIOR, * Page up * + WXK_NEXT, * Page down * + WXK_END, + WXK_HOME, + WXK_LEFT, + WXK_UP, + WXK_RIGHT, + WXK_DOWN, + WXK_SELECT, + WXK_PRINT, + WXK_EXECUTE, + WXK_SNAPSHOT, + WXK_INSERT, + WXK_HELP, + WXK_MULTIPLY, + WXK_ADD, + WXK_SEPARATOR, + WXK_SUBTRACT, + WXK_DECIMAL, + WXK_DIVIDE, + WXK_PAGEUP, + WXK_PAGEDOWN, + + WXK_NUMPAD_SPACE, + WXK_NUMPAD_TAB, + WXK_NUMPAD_ENTER, + WXK_NUMPAD_HOME, + WXK_NUMPAD_LEFT, + WXK_NUMPAD_UP, + WXK_NUMPAD_RIGHT, + WXK_NUMPAD_DOWN, + WXK_NUMPAD_PRIOR, + WXK_NUMPAD_PAGEUP, + WXK_NUMPAD_NEXT, + WXK_NUMPAD_PAGEDOWN, + WXK_NUMPAD_END, + WXK_NUMPAD_BEGIN, + WXK_NUMPAD_INSERT, + WXK_NUMPAD_DELETE, + WXK_NUMPAD_EQUAL, + WXK_NUMPAD_MULTIPLY, + WXK_NUMPAD_ADD, + WXK_NUMPAD_SEPARATOR, + WXK_NUMPAD_SUBTRACT, + WXK_NUMPAD_DECIMAL, + WXK_NUMPAD_DIVIDE, + + WXK_WINDOWS_LEFT, + WXK_WINDOWS_RIGHT, + WXK_WINDOWS_MENU , + WXK_COMMAND + }; + + */ +enum +{ + WXK_RSHIFT = 400, + WXK_RALT, + WXK_RCONTROL, + WXK_RMENU + +}; + +bool wxHIDKeyboard::Create() +{ + return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); +} + +void wxHIDKeyboard::BuildCookies(wxCFArray& Array) +{ + Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey)); + InitCookies(500); + int i, + nUsage; + for (i = 0; i < Array.Count(); ++i) + { + CFNumberGetValue( + (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)), + kCFNumberLongType, &nUsage); + + if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ) + AddCookie(Array[i], 'A' + (nUsage - kHIDUsage_KeyboardA) ); + else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9) + AddCookie(Array[i], '1' + (nUsage - kHIDUsage_Keyboard1) ); + else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12) + AddCookie(Array[i], WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) ); + else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24) + AddCookie(Array[i], WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) ); + else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9) + AddCookie(Array[i], WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) ); + else switch (nUsage) + { + //0's (wx & ascii go 0-9, but HID goes 1-0) + case kHIDUsage_Keyboard0: + AddCookie(Array[i],'0'); + break; + case kHIDUsage_Keypad0: + AddCookie(Array[i],WXK_NUMPAD0); + break; + + //Basic + case kHIDUsage_KeyboardReturnOrEnter: + AddCookie(Array[i], WXK_RETURN); + break; + case kHIDUsage_KeyboardEscape: + AddCookie(Array[i], WXK_ESCAPE); + break; + case kHIDUsage_KeyboardDeleteOrBackspace: + AddCookie(Array[i], WXK_BACK); + break; + case kHIDUsage_KeyboardTab: + AddCookie(Array[i], WXK_TAB); + break; + case kHIDUsage_KeyboardSpacebar: + AddCookie(Array[i], WXK_SPACE); + break; + case kHIDUsage_KeyboardPageUp: + AddCookie(Array[i], WXK_PRIOR); + break; + case kHIDUsage_KeyboardEnd: + AddCookie(Array[i], WXK_END); + break; + case kHIDUsage_KeyboardPageDown: + AddCookie(Array[i], WXK_NEXT); + break; + case kHIDUsage_KeyboardRightArrow: + AddCookie(Array[i], WXK_RIGHT); + break; + case kHIDUsage_KeyboardLeftArrow: + AddCookie(Array[i], WXK_LEFT); + break; + case kHIDUsage_KeyboardDownArrow: + AddCookie(Array[i], WXK_DOWN); + break; + case kHIDUsage_KeyboardUpArrow: + AddCookie(Array[i], WXK_UP); + break; + + //LEDS + case kHIDUsage_KeyboardCapsLock: + AddCookie(Array[i],WXK_CAPITAL); + break; + case kHIDUsage_KeypadNumLock: + AddCookie(Array[i],WXK_NUMLOCK); + break; + case kHIDUsage_KeyboardScrollLock: + AddCookie(Array[i],WXK_SCROLL); + break; + + //Menu keys, Shift, other specials + case kHIDUsage_KeyboardLeftControl: + AddCookie(Array[i],WXK_CONTROL); + break; + case kHIDUsage_KeyboardLeftShift: + AddCookie(Array[i],WXK_SHIFT); + break; + case kHIDUsage_KeyboardLeftAlt: + AddCookie(Array[i],WXK_ALT); + break; + case kHIDUsage_KeyboardLeftGUI: + AddCookie(Array[i],WXK_MENU); + break; + case kHIDUsage_KeyboardRightControl: + AddCookie(Array[i],WXK_RCONTROL); + break; + case kHIDUsage_KeyboardRightShift: + AddCookie(Array[i],WXK_RSHIFT); + break; + case kHIDUsage_KeyboardRightAlt: + AddCookie(Array[i],WXK_RALT); + break; + case kHIDUsage_KeyboardRightGUI: + AddCookie(Array[i],WXK_RMENU); + break; + + //Default + default: + //not in wx keycodes - do nothing.... + break; + } + } +}//end buildcookies