📄 hid.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// Name: src/mac/corefoundation/hid.cpp// Purpose: DARWIN HID layer for WX Implementation// Author: Ryan Norton// Modified by:// Created: 11/11/2003// RCS-ID: $Id: hid.cpp,v 1.24 2006/08/31 19:30:52 ABX Exp $// Copyright: (c) Ryan Norton// Licence: wxWindows licence/////////////////////////////////////////////////////////////////////////////// ===========================================================================// declarations// ===========================================================================// ---------------------------------------------------------------------------// headers// ---------------------------------------------------------------------------// For compilers that support precompilation, includes "wx.h".#include "wx/wxprec.h"#ifdef __BORLANDC__ #pragma hdrstop#endif//DARWIN _ONLY_#ifdef __DARWIN__#include "wx/mac/corefoundation/hid.h"#ifndef WX_PRECOMP #include "wx/dynarray.h" #include "wx/string.h" #include "wx/log.h" #include "wx/utils.h" #include "wx/module.h"#endif#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 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; } 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()// ----------------------------------------------------------------------------// 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){ //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 size_t nCount = 0; io_object_t pObject; while ( (pObject = IOIteratorNext(pIterator)) != 0) { ++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] );}// ----------------------------------------------------------------------------// 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){ //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); 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){ 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -