Files
wxWidgets/src/mac/carbon/hid.cpp
Stefan Csomor 3d1a4878f3 pragma and prec-header patch applied
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31606 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2005-01-27 21:05:47 +00:00

370 lines
10 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: hid.cpp
// Purpose: DARWIN HID layer for WX Implementation
// Author: Ryan Norton
// Modified by:
// Created: 11/11/2003
// RCS-ID: $Id$
// Copyright: (c) Ryan Norton
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ===========================================================================
// declarations
// ===========================================================================
// ---------------------------------------------------------------------------
// 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"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
//DARWIN _ONLY_
#ifdef __DARWIN__
#include "wx/mac/carbon/private/hid.h"
#include "wx/string.h"
#include "wx/log.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
#endif
/*
void CFShowTypeIDDescription(CFTypeRef pData)
{
if(!pData)
{
wxASSERT(false);
return;
}
wxMessageBox(
CFStringGetCStringPtr(
CFCopyTypeIDDescription(CFGetTypeID(pData)),CFStringGetSystemEncoding()
)
);
}
*/
// ============================================================================
// implementation
// ============================================================================
// ---------------------------------------------------------------------------
// wxHIDDevice
// ---------------------------------------------------------------------------
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))
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(pIterator != NULL);
//Now we iterate through them
io_object_t pObject;
while ( (pObject = IOIteratorNext(pIterator)) != NULL)
{
wxVERIFY(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)
wxVERIFY((*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...
wxVERIFY((*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);
wxVERIFY((*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);
wxVERIFY( (m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice)) != NULL);
wxVERIFY( (*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);
}
}
}
// ---------------------------------------------------------------------------
// wxHIDKeyboard
// ---------------------------------------------------------------------------
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
#endif //__DARWIN__