📄 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.23 2006/05/02 10:39:02 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"
#endif
#include "wx/mac/corefoundation/cfstring.h"
#include "wx/module.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 + -