X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5aba0d3610d33bd060639a640343025433dc3640..d2d8b4db08075bbfca05f5f6b7b829ec81230917:/src/mac/corefoundation/hid.cpp?ds=sidebyside diff --git a/src/mac/corefoundation/hid.cpp b/src/mac/corefoundation/hid.cpp index b19859b657..c820d8d941 100644 --- a/src/mac/corefoundation/hid.cpp +++ b/src/mac/corefoundation/hid.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: hid.cpp +// Name: src/mac/corefoundation/hid.cpp // Purpose: DARWIN HID layer for WX Implementation // Author: Ryan Norton // Modified by: @@ -17,10 +17,6 @@ // headers // --------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "hid.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -32,654 +28,715 @@ #ifdef __DARWIN__ #include "wx/mac/corefoundation/hid.h" -#include "wx/string.h" -#include "wx/log.h" -#include "wx/mac/corefoundation/cfstring.h" - - -// --------------------------------------------------------------------------- -// assertion macros -// --------------------------------------------------------------------------- -#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) - -#ifdef __WXDEBUG___ -# define wxVERIFY(arg) wxASSERT(arg) -#else -# define wxVERIFY(arg) arg +#ifndef WX_PRECOMP + #include "wx/dynarray.h" + #include "wx/string.h" + #include "wx/log.h" + #include "wx/utils.h" + #include "wx/module.h" #endif -/* -void CFShowTypeIDDescription(CFTypeRef pData) -{ - if(!pData) - { - wxASSERT(false); - return; - } - - wxMessageBox( - CFStringGetCStringPtr( - CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding() - ) - ); -} -*/ +#include "wx/mac/corefoundation/cfstring.h" // ============================================================================ // implementation // ============================================================================ -// --------------------------------------------------------------------------- +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// // wxHIDDevice -// --------------------------------------------------------------------------- +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ---------------------------------------------------------------------------- +// wxHIDDevice::Create +// +// nClass is the HID Page such as +// kHIDPage_GenericDesktop +// nType is the HID Usage such as +// kHIDUsage_GD_Joystick,kHIDUsage_GD_Mouse,kHIDUsage_GD_Keyboard +// nDev is the device number to use +// +// ---------------------------------------------------------------------------- bool wxHIDDevice::Create (int nClass, int nType, int nDev) { - //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)) - wxVERIFY((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_MSG(pIterator != 0, wxT("No devices found!")); - - //Now we iterate through them - io_object_t pObject; - while ( (pObject = IOIteratorNext(pIterator)) != 0) - { + //Create the mach port + if(IOMasterPort(bootstrap_port, &m_pPort) != kIOReturnSuccess) + { + wxLogSysError(wxT("Could not create mach port")); + return false; + } + + //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) + // + //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)) + CFMutableDictionaryRef pDictionary = IOServiceMatching(kIOHIDDeviceKey); + if(pDictionary == NULL) + { + wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") ); + return false; + } + + //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; + if( IOServiceGetMatchingServices(m_pPort, + pDictionary, &pIterator) != kIOReturnSuccess ) + { + wxLogSysError(_T("No Matching HID Services")); + return false; + } + + //Were there any devices matched? + if(pIterator == 0) + return false; // No devices found + + //Now we iterate through them + io_object_t pObject; + while ( (pObject = IOIteratorNext(pIterator)) != 0) + { if(--nDev != 0) + { + IOObjectRelease(pObject); continue; - - wxVERIFY(IORegistryEntryCreateCFProperties(pObject, &pDictionary, - kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS); - - //Just for sanity :) - wxASSERT(CFGetTypeID(CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey))) == CFStringGetTypeID()); - -/* - kIOHIDTransportKey; - kIOHIDVendorIDKey; - kIOHIDProductIDKey; - kIOHIDVersionNumberKey; - kIOHIDManufacturerKey; - kIOHIDSerialNumberKey; - if !kIOHIDLocationIDKey - kUSBDevicePropertyLocationID - kIOHIDPrimaryUsageKey -kIOHIDPrimaryUsagePageKey -idProduct -idVendor -USB Product Name -*/ - //Get [product] name - m_szProductName = wxMacCFStringHolder( (CFStringRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)), false ).AsString(); - - CFNumberRef nref = (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey)); - - if (nref) - CFNumberGetValue( - nref, - kCFNumberIntType, - &m_nProductId - ); - - nref = (CFNumberRef) CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey)); - if (nref) - CFNumberGetValue( - nref, - kCFNumberIntType, - &m_nManufacturerId - ); - - //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... - wxVERIFY((*m_ppDevice)->open(m_ppDevice, 0) == S_OK); - - // - //Now the hard part - in order to scan things we need "cookies" - - // - wxCFArray CookieArray = CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDElementKey)); - BuildCookies(CookieArray); - - //cleanup - CFRelease(pDictionary); - IOObjectRelease(pObject); - break; - } - //iterator cleanup - IOObjectRelease(pIterator); - - return true; + } + + if ( IORegistryEntryCreateCFProperties + ( + pObject, + &pDictionary, + kCFAllocatorDefault, + kNilOptions + ) != KERN_SUCCESS ) + { + wxLogDebug(_T("IORegistryEntryCreateCFProperties failed")); + } + + // + // Now we get the attributes of each "product" in the iterator + // + + //Get [product] name + CFStringRef cfsProduct = (CFStringRef) + CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey)); + m_szProductName = + wxMacCFStringHolder( cfsProduct, + false + ).AsString(); + + //Get the Product ID Key + CFNumberRef cfnProductId = (CFNumberRef) + CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey)); + if (cfnProductId) + { + CFNumberGetValue(cfnProductId, kCFNumberIntType, &m_nProductId); + } + + //Get the Vendor ID Key + CFNumberRef cfnVendorId = (CFNumberRef) + CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey)); + if (cfnVendorId) + { + CFNumberGetValue(cfnVendorId, kCFNumberIntType, &m_nManufacturerId); + } + + // + // End attribute getting + // + + //Create the interface (good grief - long function names!) + SInt32 nScore; + IOCFPlugInInterface** ppPlugin; + if(IOCreatePlugInInterfaceForService(pObject, + kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &ppPlugin, + &nScore) != kIOReturnSuccess) + { + wxLogSysError(wxT("Could not create HID Interface for product")); + return false; + } + + //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 + if((*ppPlugin)->QueryInterface(ppPlugin, + CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), + (void**) &m_ppDevice) != S_OK) + { + wxLogSysError(wxT("Could not get device interface from HID interface")); + return false; + } + + //release the plugin + (*ppPlugin)->Release(ppPlugin); + + //open the HID interface... + if ( (*m_ppDevice)->open(m_ppDevice, 0) != S_OK ) + wxLogDebug(_T("HID device: open failed")); + + // + //Now the hard part - in order to scan things we need "cookies" + // + CFArrayRef cfaCookies = (CFArrayRef)CFDictionaryGetValue(pDictionary, + CFSTR(kIOHIDElementKey)); + BuildCookies(cfaCookies); + + //cleanup + CFRelease(pDictionary); + IOObjectRelease(pObject); + + //iterator cleanup + IOObjectRelease(pIterator); + + return true; + } + + //iterator cleanup + IOObjectRelease(pIterator); + + return false; //no device }//end Create() - -int wxHIDDevice::GetCount (int nClass, int nType) + +// ---------------------------------------------------------------------------- +// wxHIDDevice::GetCount [static] +// +// Obtains the number of devices on a system for a given HID Page (nClass) +// and HID Usage (nType). +// ---------------------------------------------------------------------------- +size_t wxHIDDevice::GetCount (int nClass, int nType) { - mach_port_t m_pPort; - - //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)) - wxVERIFY((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"); - - if(pIterator == NULL) + //Create the mach port + mach_port_t pPort; + if(IOMasterPort(bootstrap_port, &pPort) != kIOReturnSuccess) + { + wxLogSysError(wxT("Could not create mach port")); + return false; + } + + //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 = IOServiceMatching(kIOHIDDeviceKey); + if(pDictionary == NULL) + { + wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") ); + return false; + } + + //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; + if( IOServiceGetMatchingServices(pPort, + pDictionary, &pIterator) != kIOReturnSuccess ) + { + wxLogSysError(_T("No Matching HID Services")); + return false; + } + + //If the iterator doesn't exist there are no devices :) + if ( !pIterator ) return 0; - //Now we iterate through them - io_object_t pObject; - - int nCount = 0; - - while ( (pObject = IOIteratorNext(pIterator)) != 0) + //Now we iterate through them + size_t nCount = 0; + io_object_t pObject; + while ( (pObject = IOIteratorNext(pIterator)) != 0) + { ++nCount; - - //iterator cleanup - IOObjectRelease(pIterator); - - return nCount; + IOObjectRelease(pObject); + } + + //cleanup + IOObjectRelease(pIterator); + mach_port_deallocate(mach_task_self(), pPort); + + return nCount; }//end Create() +// ---------------------------------------------------------------------------- +// wxHIDDevice::AddCookie +// +// Adds a cookie to the internal cookie array from a CFType +// ---------------------------------------------------------------------------- void wxHIDDevice::AddCookie(CFTypeRef Data, int i) { - CFNumberGetValue( - (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data - , CFSTR(kIOHIDElementCookieKey) - ), - kCFNumberIntType, - &m_pCookies[i] - ); + CFNumberGetValue( + (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data + , CFSTR(kIOHIDElementCookieKey) + ), + kCFNumberIntType, + &m_pCookies[i] + ); } +// ---------------------------------------------------------------------------- +// wxHIDDevice::AddCookieInQueue +// +// Adds a cookie to the internal cookie array from a CFType and additionally +// adds it to the internal HID Queue +// ---------------------------------------------------------------------------- void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, int i) { - AddCookie(Data, i); - wxVERIFY((*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) == S_OK);//3rd Param flags (none yet) + //3rd Param flags (none yet) + AddCookie(Data, i); + if ( (*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) != S_OK ) + wxLogDebug(_T("HID device: adding element failed")); } - + +// ---------------------------------------------------------------------------- +// wxHIDDevice::InitCookies +// +// Create the internal cookie array, optionally creating a HID Queue +// ---------------------------------------------------------------------------- void wxHIDDevice::InitCookies(size_t dwSize, bool bQueue) { - m_pCookies = new IOHIDElementCookie[dwSize]; - if (bQueue) - { - wxASSERT( m_ppQueue == NULL); - wxVERIFY( (m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice)) != NULL); - wxVERIFY( (*m_ppQueue)->create(m_ppQueue, 0, 512) == S_OK); //Param 2, flags, none yet - } + m_pCookies = new IOHIDElementCookie[dwSize]; + if (bQueue) + { + wxASSERT( m_ppQueue == NULL); + m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice); + if ( !m_ppQueue ) + { + wxLogDebug(_T("HID device: allocQueue failed")); + return; + } + + //Param 2, flags, none yet + if ( (*m_ppQueue)->create(m_ppQueue, 0, 512) != S_OK ) + { + wxLogDebug(_T("HID device: create failed")); + } + } + + //make sure that cookie array is clear + memset(m_pCookies, 0, sizeof(*m_pCookies) * dwSize); } +// ---------------------------------------------------------------------------- +// wxHIDDevice::IsActive +// +// Returns true if a cookie of the device is active - for example if a key is +// held down, joystick button pressed, caps lock active, etc.. +// ---------------------------------------------------------------------------- bool wxHIDDevice::IsActive(int nIndex) { - wxASSERT(m_pCookies[nIndex] != NULL); - IOHIDEventStruct Event; - (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event); -/* - wxString ss; - ss << _T("[") << (int) m_pCookies[nIndex] << _T("] = ") << Event.value << _T(" SIZE:") << Event.longValueSize; - - wxLogDebug(ss); -*/ - return !!Event.value; + if(!HasElement(nIndex)) + { + //cookie at index does not exist - getElementValue + //could return true which would be incorrect so we + //check here + return false; + } + + IOHIDEventStruct Event; + (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event); + return !!Event.value; } - + +// ---------------------------------------------------------------------------- +// wxHIDDevice::HasElement +// +// Returns true if the element in the internal cookie array exists +// ---------------------------------------------------------------------------- bool wxHIDDevice::HasElement(int nIndex) { return m_pCookies[nIndex] != NULL; } +// ---------------------------------------------------------------------------- +// wxHIDDevice Destructor +// +// Frees all memory and objects from the structure +// ---------------------------------------------------------------------------- wxHIDDevice::~wxHIDDevice() { - if (m_ppDevice != NULL) - { - if (m_ppQueue != NULL) - { - (*m_ppQueue)->stop(m_ppQueue); - (*m_ppQueue)->dispose(m_ppQueue); - (*m_ppQueue)->Release(m_ppQueue); - } - (*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_ppDevice != NULL) + { + if (m_ppQueue != NULL) + { + (*m_ppQueue)->stop(m_ppQueue); + (*m_ppQueue)->dispose(m_ppQueue); + (*m_ppQueue)->Release(m_ppQueue); + } + (*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; + } } -// --------------------------------------------------------------------------- +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// // wxHIDKeyboard -// --------------------------------------------------------------------------- +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//There are no right shift, alt etc. in the wx headers yet so just sort +//of "define our own" for now enum { - WXK_RSHIFT = 400, - WXK_RALT, - WXK_RCONTROL, - WXK_RMENU - + WXK_RSHIFT = 400, + WXK_RALT, + WXK_RCONTROL, + WXK_RMENU }; -bool wxHIDKeyboard::Create() +// ---------------------------------------------------------------------------- +// wxHIDKeyboard::GetCount [static] +// +// Get number of HID keyboards available +// ---------------------------------------------------------------------------- +int wxHIDKeyboard::GetCount() { - return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); + return wxHIDDevice::GetCount(kHIDPage_GenericDesktop, + kHIDUsage_GD_Keyboard); } -void wxHIDKeyboard::BuildCookies(wxCFArray& Array) +// ---------------------------------------------------------------------------- +// wxHIDKeyboard::Create +// +// Create the HID Keyboard +// ---------------------------------------------------------------------------- +bool wxHIDKeyboard::Create(int nDev /* = 1*/) { - Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey)); - InitCookies(500); - int i, - nUsage; - bool bEOTriggered = false; - for (i = 0; i < Array.Count(); ++i) - { - CFNumberGetValue( - (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)), - kCFNumberLongType, &nUsage); - + return wxHIDDevice::Create(kHIDPage_GenericDesktop, + kHIDUsage_GD_Keyboard, + nDev); +} + +// ---------------------------------------------------------------------------- +// wxHIDKeyboard::AddCookie +// +// Overloaded version of wxHIDDevice::AddCookie that simply does not +// add a cookie if a duplicate is found +// ---------------------------------------------------------------------------- +void wxHIDKeyboard::AddCookie(CFTypeRef Data, int i) +{ + if(!HasElement(i)) + wxHIDDevice::AddCookie(Data, i); +} + +// ---------------------------------------------------------------------------- +// wxHIDKeyboard::BuildCookies +// +// Callback from Create() to build the HID cookies for the internal cookie +// array +// ---------------------------------------------------------------------------- +void wxHIDKeyboard::BuildCookies(CFArrayRef Array) +{ + //Create internal cookie array + InitCookies(500); + + //Begin recursing in array + DoBuildCookies(Array); +} + +void wxHIDKeyboard::DoBuildCookies(CFArrayRef Array) +{ + //Now go through each possible cookie + int i, + nUsage; +// bool bEOTriggered = false; + for (i = 0; i < CFArrayGetCount(Array); ++i) + { + const void* ref = CFDictionaryGetValue( + (CFDictionaryRef)CFArrayGetValueAtIndex(Array, i), + CFSTR(kIOHIDElementKey) + ); + + if (ref != NULL) + { + DoBuildCookies((CFArrayRef) ref); + } + else + { + + // + // Get the usage # + // + CFNumberGetValue( + (CFNumberRef) + CFDictionaryGetValue((CFDictionaryRef) + CFArrayGetValueAtIndex(Array, i), + CFSTR(kIOHIDElementUsageKey) + ), + kCFNumberLongType, + &nUsage); + + // + // Now translate the usage # into a wx keycode + // + // - // OK, this is strange - basically this kind of strange - + // OK, this is strange - basically this kind of strange - // Starting from 0xEO these elements (like shift) appear twice in // the array! The ones at the end are bogus I guess - the funny part // is that besides the fact that the ones at the front have a Unit // and UnitExponent key with a value of 0 and a different cookie value, - // there is no discernable difference between the two... + // there is no discernable difference between the two... // // Will the real shift please stand up? // // Something to spend a support request on, if I had one, LOL. // - if(nUsage == 0xE0) + //if(nUsage == 0xE0) + //{ + // if(bEOTriggered) + // break; + // bEOTriggered = true; + //} + //Instead of that though we now just don't add duplicate keys + + if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ) + AddCookie(CFArrayGetValueAtIndex(Array, i), 'A' + (nUsage - kHIDUsage_KeyboardA) ); + else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9) + AddCookie(CFArrayGetValueAtIndex(Array, i), '1' + (nUsage - kHIDUsage_Keyboard1) ); + else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12) + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) ); + else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24) + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) ); + else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9) + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) ); + else switch (nUsage) { - if(bEOTriggered) - break; - bEOTriggered = true; - } -/* - wxString msg; - int cookie; - CFNumberGetValue( - (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Array[i] - , CFSTR(kIOHIDElementCookieKey) - ), - kCFNumberIntType, - &cookie - ); - - msg << wxT("KEY:") << nUsage << wxT("COOKIE:") << cookie; - wxLogDebug(msg); -*/ - - 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; - } - } + //0's (wx & ascii go 0-9, but HID goes 1-0) + case kHIDUsage_Keyboard0: + AddCookie(CFArrayGetValueAtIndex(Array, i), '0'); + break; + case kHIDUsage_Keypad0: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD0); + break; + + //Basic + case kHIDUsage_KeyboardReturnOrEnter: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RETURN); + break; + case kHIDUsage_KeyboardEscape: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_ESCAPE); + break; + case kHIDUsage_KeyboardDeleteOrBackspace: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_BACK); + break; + case kHIDUsage_KeyboardTab: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_TAB); + break; + case kHIDUsage_KeyboardSpacebar: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_SPACE); + break; + case kHIDUsage_KeyboardPageUp: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEUP); + break; + case kHIDUsage_KeyboardEnd: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_END); + break; + case kHIDUsage_KeyboardPageDown: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEDOWN); + break; + case kHIDUsage_KeyboardRightArrow: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RIGHT); + break; + case kHIDUsage_KeyboardLeftArrow: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_LEFT); + break; + case kHIDUsage_KeyboardDownArrow: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_DOWN); + break; + case kHIDUsage_KeyboardUpArrow: + AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_UP); + break; + + //LEDS + case kHIDUsage_KeyboardCapsLock: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CAPITAL); + break; + case kHIDUsage_KeypadNumLock: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_NUMLOCK); + break; + case kHIDUsage_KeyboardScrollLock: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SCROLL); + break; + + //Menu keys, Shift, other specials + case kHIDUsage_KeyboardLeftControl: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CONTROL); + break; + case kHIDUsage_KeyboardLeftShift: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SHIFT); + break; + case kHIDUsage_KeyboardLeftAlt: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_ALT); + break; + case kHIDUsage_KeyboardLeftGUI: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_MENU); + break; + case kHIDUsage_KeyboardRightControl: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RCONTROL); + break; + case kHIDUsage_KeyboardRightShift: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RSHIFT); + break; + case kHIDUsage_KeyboardRightAlt: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RALT); + break; + case kHIDUsage_KeyboardRightGUI: + AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RMENU); + break; + + //Default + default: + //not in wx keycodes - do nothing.... + break; + } //end mightly long switch + } //end if the current element is not an array... + } //end for loop for Array }//end buildcookies +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // -// wxGetKeyState +// wxHIDModule // - -#include "wx/utils.h" -#include "wx/module.h" +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class wxHIDModule : public wxModule { DECLARE_DYNAMIC_CLASS(wxHIDModule) - + public: - static wxHIDKeyboard* sm_keyboard; - + static wxArrayPtrVoid sm_keyboards; virtual bool OnInit() { - sm_keyboard = NULL; return true; } virtual void OnExit() { - if (sm_keyboard) - delete sm_keyboard; + for(size_t i = 0; i < sm_keyboards.GetCount(); ++i) + delete (wxHIDKeyboard*) sm_keyboards[i]; } }; IMPLEMENT_DYNAMIC_CLASS(wxHIDModule, wxModule) -wxHIDKeyboard* wxHIDModule::sm_keyboard; +wxArrayPtrVoid wxHIDModule::sm_keyboards; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// wxGetKeyState() +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool wxGetKeyState (wxKeyCode key) { wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key != WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons")); - if (!wxHIDModule::sm_keyboard) + if (wxHIDModule::sm_keyboards.GetCount() == 0) { - wxHIDModule::sm_keyboard = new wxHIDKeyboard(); - bool bOK = wxHIDModule::sm_keyboard->Create(); - wxASSERT(bOK); - if(!bOK) + int nKeyboards = wxHIDKeyboard::GetCount(); + + for(int i = 1; i <= nKeyboards; ++i) { - delete wxHIDModule::sm_keyboard; - wxHIDModule::sm_keyboard = NULL; - return false; + wxHIDKeyboard* keyboard = new wxHIDKeyboard(); + if(keyboard->Create(i)) + { + wxHIDModule::sm_keyboards.Add(keyboard); + } + else + { + delete keyboard; + break; + } } + + wxASSERT_MSG(wxHIDModule::sm_keyboards.GetCount() != 0, + wxT("No keyboards found!")); } - + + for(size_t i = 0; i < wxHIDModule::sm_keyboards.GetCount(); ++i) + { + wxHIDKeyboard* keyboard = (wxHIDKeyboard*) + wxHIDModule::sm_keyboards[i]; + switch(key) { case WXK_SHIFT: - return wxHIDModule::sm_keyboard->IsActive(WXK_SHIFT) || - wxHIDModule::sm_keyboard->IsActive(WXK_RSHIFT); + if( keyboard->IsActive(WXK_SHIFT) || + keyboard->IsActive(WXK_RSHIFT) ) + { + return true; + } break; - case WXK_ALT: - return wxHIDModule::sm_keyboard->IsActive(WXK_ALT) || - wxHIDModule::sm_keyboard->IsActive(WXK_RALT); + case WXK_ALT: + if( keyboard->IsActive(WXK_ALT) || + keyboard->IsActive(WXK_RALT) ) + { + return true; + } break; - case WXK_CONTROL: - return wxHIDModule::sm_keyboard->IsActive(WXK_CONTROL) || - wxHIDModule::sm_keyboard->IsActive(WXK_RCONTROL); + case WXK_CONTROL: + if( keyboard->IsActive(WXK_CONTROL) || + keyboard->IsActive(WXK_RCONTROL) ) + { + return true; + } break; - case WXK_MENU: - return wxHIDModule::sm_keyboard->IsActive(WXK_MENU) || - wxHIDModule::sm_keyboard->IsActive(WXK_RMENU); + case WXK_MENU: + if( keyboard->IsActive(WXK_MENU) || + keyboard->IsActive(WXK_RMENU) ) + { + return true; + } break; default: - return wxHIDModule::sm_keyboard->IsActive(key); + if( keyboard->IsActive(key) ) + { + return true; + } break; } -} - -// -// TODO: Find a better file to put this in -// -#include "wx/intl.h" - -#ifdef __WXCOCOA__ -#include -#include -#else -#include "wx/mac/private.h" -#include "LaunchServices.h" -#endif - -#include "wx/uri.h" -#include "wx/mac/corefoundation/cfstring.h" - -long wxMacExecute(wxChar **argv, - int flags, - wxProcess *process) -{ - CFIndex cfiCount = 0; - //get count - for(wxChar** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) - { - ++cfiCount; - } - - if(cfiCount == 0) //no file to launch? - { - wxLogDebug(wxT("wxMacExecute No file to launch!")); - return -1; - } - - CFURLRef cfurlApp = CFURLCreateWithString( - kCFAllocatorDefault, - wxMacCFStringHolder(*argv++, wxLocale::GetSystemEncoding()), - NULL); - wxASSERT(cfurlApp); - - CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp); - if(!cfbApp) - { - wxLogDebug(wxT("wxMacExecute Bad bundle")); - CFRelease(cfurlApp); - return -1; } - - - UInt32 dwBundleType, dwBundleCreator; - CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator); - //Only call wxMacExecute for .app bundles - others could be actual unix programs - if(dwBundleType != 'APPL') - { - CFRelease(cfurlApp); - return -1; - } - - // - // We have a good bundle - so let's launch it! - // - - CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault, cfiCount - 1, NULL); - - wxASSERT(cfaFiles); - - if(--cfiCount) - { - for( ; *argv != NULL ; ++argv) - { -// wxLogDebug(*argv); - wxString sCurrentFile; - - if(wxURI(*argv).IsReference()) - sCurrentFile = wxString(wxT("file://")) + *argv; - else - sCurrentFile = *argv; - - CFURLRef cfurlCurrentFile = CFURLCreateWithString( - kCFAllocatorDefault, - wxMacCFStringHolder(sCurrentFile, wxLocale::GetSystemEncoding()), - NULL); - wxASSERT(cfurlCurrentFile); - - CFArrayAppendValue( - cfaFiles, - cfurlCurrentFile - ); - } - } - - LSLaunchURLSpec launchspec; - launchspec.appURL = cfurlApp; - launchspec.itemURLs = cfaFiles; - launchspec.passThruParams = NULL; //AEDesc* - launchspec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch; //TODO: Possibly be smarter with flags - launchspec.asyncRefCon = NULL; - - OSStatus status = LSOpenFromURLSpec(&launchspec, - NULL); //2nd is CFURLRef* really launched - - //cleanup - CFRelease(cfurlApp); - CFRelease(cfaFiles); - - //check for error - if(status != noErr) - { - wxLogDebug(wxString::Format(wxT("wxMacExecute ERROR: %d")), (int)status); - return -1; - } - return 0; //success + return false; //not down/error } #endif //__DARWIN__