IOHIDEventService.cpp [plain text]
#include <AssertMacros.h>
#include <TargetConditionals.h>
#include <stdint.h>
#include <IOKit/hid/IOHIDUsageTables.h>
#include <IOKit/IOLib.h>
#include <IOKit/usb/USB.h>
#include "IOHIDKeys.h"
#include "IOHIDSystem.h"
#include "IOHIDEventService.h"
#include "IOHIDInterface.h"
#include "IOHIDPrivateKeys.h"
#include "AppleHIDUsageTables.h"
#include "OSStackRetain.h"
#include <sys/sysctl.h>
#include <kern/debug.h>
#if !TARGET_OS_EMBEDDED
#include "IOHIDPointing.h"
#include "IOHIDKeyboard.h"
#include "IOHIDConsumer.h"
#include "IOHIDEvent.h"
#endif
#include "IOHIDEventData.h"
#include "IOHIDPrivate.h"
#include "IOHIDFamilyPrivate.h"
#include "IOHIDevicePrivateKeys.h"
#include "ev_private.h"
#include "IOHIDFamilyTrace.h"
#include "IOHIDDebug.h"
#include "IOHIDEventServiceUserClient.h"
extern "C" int kern_stack_snapshot_with_reason(char *reason);
extern "C" kern_return_t sysdiagnose_notify_user(uint32_t keycode);
enum {
kBootProtocolNone = 0,
kBootProtocolKeyboard,
kBootProtocolMouse
};
enum {
kShimEventProcessor = 0x01
};
#define kDefaultFixedResolution (400 << 16)
#define kDefaultScrollFixedResolution (9 << 16)
#define kMaxSystemAbsoluteRangeUnsigned 65535
#define kMaxSystemAbsoluteRangeSigned 32767
#define kMaxSystemBarrelPressure kMaxSystemAbsoluteRangeSigned
#define kMaxSystemTipPressure kMaxSystemAbsoluteRangeUnsigned
#define kDelayedOption (1<<31)
#define NUB_LOCK if (_nubLock) IORecursiveLockLock(_nubLock)
#define NUB_UNLOCK if (_nubLock) IORecursiveLockUnlock(_nubLock)
#if TARGET_OS_EMBEDDED
#define SET_HID_PROPERTIES_EMBEDDED(service) \
service->setProperty(kIOHIDPrimaryUsagePageKey, getPrimaryUsagePage(), 32); \
service->setProperty(kIOHIDPrimaryUsageKey, getPrimaryUsage(), 32);
#else
#define SET_HID_PROPERTIES_EMBEDDED(service) \
{};
#endif
#define SET_HID_PROPERTIES(service) \
service->setProperty(kIOHIDTransportKey, getTransport()); \
service->setProperty(kIOHIDLocationIDKey, getLocationID(), 32); \
service->setProperty(kIOHIDVendorIDKey, getVendorID(), 32); \
service->setProperty(kIOHIDVendorIDSourceKey, getVendorIDSource(), 32); \
service->setProperty(kIOHIDProductIDKey, getProductID(), 32); \
service->setProperty(kIOHIDVersionNumberKey, getVersion(), 32); \
service->setProperty(kIOHIDCountryCodeKey, getCountryCode(), 32); \
service->setProperty(kIOHIDManufacturerKey, getManufacturer()); \
service->setProperty(kIOHIDProductKey, getProduct()); \
service->setProperty(kIOHIDSerialNumberKey, getSerialNumber()); \
service->setProperty(kIOHIDDeviceUsagePairsKey, getDeviceUsagePairs()); \
service->setProperty(kIOHIDReportIntervalKey, getReportInterval(), 32);
#define _provider _reserved->provider
#define _workLoop _reserved->workLoop
#define _deviceUsagePairs _reserved->deviceUsagePairs
#define _commandGate _reserved->commandGate
#define _keyboard _reserved->keyboard
#define _multiAxis _reserved->multiAxis
#define _digitizer _reserved->digitizer
#define _relativePointer _reserved->relativePointer
#define _absolutePointer _reserved->absolutePointer
#define _keyboardShim _reserved->keyboardShim
#define _pointingShim _reserved->pointingShim
#define _clientDict _reserved->clientDict
#define kDebuggerDelayMS 2500
#define kDebuggerLongDelayMS 5000
#define kShutdownDelayForStackshot 4000
#define kShutdownDelayForPanic 3500
#define kATVChordDelayMS 5000
#define kDelayedStackshotMask (1 << 31)
#define STACKSHOT_MASK_ATV 0x30 // ATV PlayPause + Volume-)
#define STACKSHOT_MASK_WATCH 0x0C // Menu (Crown) + Help (Pill)
#if TARGET_OS_WATCH
#define DELAYED_STACKSHOT_TIMEOUT 1000
#define DELAYED_STACKSHOT_MASK (STACKSHOT_MASK_WATCH | kDelayedStackshotMask)
#else
#define DELAYED_STACKSHOT_TIMEOUT 5000
#define DELAYED_STACKSHOT_MASK (STACKSHOT_MASK_ATV | kDelayedStackshotMask)
#endif
enum {
kLegacyShimDisabled,
kLegacyShimEnabledForSingleUserMode,
kLegacyShimEnabled
};
class IOHIDClientData : public OSObject
{
OSDeclareDefaultStructors(IOHIDClientData)
IOService * client;
void * context;
void * action;
public:
static IOHIDClientData* withClientInfo(IOService *client, void* context, void * action);
inline IOService * getClient() { return client; }
inline void * getContext() { return context; }
inline void * getAction() { return action; }
};
#define super IOService
OSDefineMetaClassAndAbstractStructors( IOHIDEventService, IOService )
bool IOHIDEventService::init ( OSDictionary * properties )
{
if (!super::init(properties))
return false;
_reserved = IONew(ExpansionData, 1);
bzero(_reserved, sizeof(ExpansionData));
_nubLock = IORecursiveLockAlloc();
_clientDict = OSDictionary::withCapacity(2);
if ( _clientDict == 0 )
return false;
return true;
}
bool IOHIDEventService::start ( IOService * provider )
{
UInt32 bootProtocol = 0;
OSObject *obj = NULL;
OSNumber *number = NULL;
OSString *string = NULL;
OSBoolean *boolean = NULL;
_provider = provider;
if ( !super::start(provider) )
return false;
if ( !handleStart(provider) )
return false;
_workLoop = getWorkLoop();
if ( !_workLoop )
return false;
_workLoop->retain();
_keyboard.appleVendorSupported = (getProperty(kIOHIDAppleVendorSupported, gIOServicePlane) == kOSBooleanTrue);
_multiAxis.timer =
IOTimerEventSource::timerEventSource(this,
OSMemberFunctionCast(IOTimerEventSource::Action,
this,
&IOHIDEventService::multiAxisTimerCallback));
if (!_multiAxis.timer || (_workLoop->addEventSource(_multiAxis.timer) != kIOReturnSuccess))
return false;
_commandGate = IOCommandGate::commandGate(this);
if (!_commandGate || (_workLoop->addEventSource(_commandGate) != kIOReturnSuccess))
return false;
calculateStandardType();
SET_HID_PROPERTIES(this);
SET_HID_PROPERTIES_EMBEDDED(this);
obj = copyProperty("BootProtocol");
number = OSDynamicCast(OSNumber, obj);
if (number)
bootProtocol = number->unsigned32BitValue();
OSSafeReleaseNULL(obj);
obj = copyProperty(kIOHIDPhysicalDeviceUniqueIDKey);
string = OSDynamicCast(OSString, obj);
if (string)
setProperty(kIOHIDPhysicalDeviceUniqueIDKey, string);
OSSafeReleaseNULL(obj);
obj = provider->copyProperty(kIOHIDBuiltInKey);
boolean = OSDynamicCast(OSBoolean, obj);
if (boolean)
setProperty(kIOHIDBuiltInKey, boolean);
OSSafeReleaseNULL(obj);
#if !TARGET_OS_EMBEDDED
int legacy_shim;
if (!PE_parse_boot_argn("hid-legacy-shim", &legacy_shim, sizeof (legacy_shim))) {
legacy_shim = 0;
}
IOLog("HID: Legacy shim %d\n", kLegacyShimEnabled);
if (legacy_shim) {
_keyboardShim = kLegacyShimEnabled;
_pointingShim = kLegacyShimEnabled;
} else {
char namep[16];
boolean_t singleUser = false;
if ( PE_parse_boot_argn("-s", namep, sizeof (namep))) {
singleUser = true;
}
_pointingShim = kLegacyShimDisabled;
_keyboardShim = singleUser ? kLegacyShimEnabledForSingleUserMode : kLegacyShimDisabled;
}
#endif
parseSupportedElements (getReportElements(), bootProtocol);
#if !TARGET_OS_EMBEDDED
if ((!_consumerNub && _keyboardNub) || (!_keyboardNub && _consumerNub)) {
OSDictionary * matchingDictionary = IOService::serviceMatching( "IOHIDEventService" );
if ( matchingDictionary ) {
OSDictionary * propertyMatch = OSDictionary::withCapacity(4);
if (propertyMatch) {
OSObject * object;
object = copyProperty(kIOHIDTransportKey);
if (object) propertyMatch->setObject(kIOHIDTransportKey, object);
OSSafeReleaseNULL(object);
object = copyProperty(kIOHIDVendorIDKey);
if (object) propertyMatch->setObject(kIOHIDVendorIDKey, object);
OSSafeReleaseNULL(object);
object = copyProperty(kIOHIDProductIDKey);
if (object) propertyMatch->setObject(kIOHIDProductIDKey, object);
OSSafeReleaseNULL(object);
object = copyProperty(kIOHIDLocationIDKey);
if (object) propertyMatch->setObject(kIOHIDLocationIDKey, object);
OSSafeReleaseNULL(object);
matchingDictionary->setObject(gIOPropertyMatchKey, propertyMatch);
propertyMatch->release();
}
_publishNotify = addMatchingNotification( gIOPublishNotification,
matchingDictionary,
&IOHIDEventService::_publishMatchingNotificationHandler,
this, 0 );
matchingDictionary->release();
}
}
#endif
_readyForInputReports = true;
registerService(kIOServiceAsynchronous);
return true;
}
#if !TARGET_OS_EMBEDDED
static void stopAndReleaseShim ( IOService * service, IOService * provider )
{
if ( !service )
return;
IOService * serviceProvider = service->getProvider();
if ( serviceProvider == provider )
{
service->stop(provider);
service->detach(provider);
}
service->release();
}
#endif
void IOHIDEventService::stop( IOService * provider )
{
handleStop ( provider );
_provider = NULL;
if (_multiAxis.timer) {
_multiAxis.timer->cancelTimeout();
if ( _workLoop )
_workLoop->removeEventSource(_multiAxis.timer);
_multiAxis.timer->release();
_multiAxis.timer = 0;
}
if (_commandGate) {
if ( _workLoop )
_workLoop->removeEventSource(_commandGate);
_commandGate->release();
_commandGate = 0;
}
#if TARGET_OS_EMBEDDED
if ( _keyboard.debug.nmiTimer ) {
_keyboard.debug.nmiTimer->cancelTimeout();
if ( _workLoop )
_workLoop->removeEventSource(_keyboard.debug.nmiTimer);
_keyboard.debug.nmiTimer->release();
_keyboard.debug.nmiTimer = 0;
}
if ( _keyboard.debug.stackshotTimer ) {
_keyboard.debug.stackshotTimer->cancelTimeout();
if ( _workLoop )
_workLoop->removeEventSource(_keyboard.debug.stackshotTimer);
_keyboard.debug.stackshotTimer->release();
_keyboard.debug.stackshotTimer = 0;
}
#else
NUB_LOCK;
stopAndReleaseShim ( _keyboardNub, this );
_keyboardNub = 0;
stopAndReleaseShim ( _pointingNub, this );
_pointingNub = 0;
stopAndReleaseShim ( _consumerNub, this );
_consumerNub = 0;
if (_publishNotify) {
_publishNotify->remove();
_publishNotify = 0;
}
NUB_UNLOCK;
#endif
super::stop( provider );
}
bool IOHIDEventService::matchPropertyTable(OSDictionary * table, SInt32 * score)
{
RETAIN_ON_STACK(this);
if (super::matchPropertyTable(table, score) == false)
return false;
return MatchPropertyTable(this, table, score);
}
bool IOHIDEventService::_publishMatchingNotificationHandler(
void * target,
void * ,
IOService * newService,
IONotifier * )
{
#if !TARGET_OS_EMBEDDED
IOHIDEventService * self = (IOHIDEventService *) target;
if (self && self->_keyboardShim == kLegacyShimEnabled) {
IOHIDEventService * service = (IOHIDEventService *) newService;
IONotifier * publishNotify = NULL;
if (self->_nubLock) IORecursiveLockLock(self->_nubLock);
if (self->_publishNotify) {
if ( service->_keyboardNub ) {
if ( self->_keyboardNub
&& self->_keyboardNub->isDispatcher()
&& !service->_keyboardNub->isDispatcher() ) {
stopAndReleaseShim ( self->_keyboardNub, self );
self->_keyboardNub = 0;
}
if ( !self->_keyboardNub ) {
self->_keyboardNub = service->_keyboardNub;
self->_keyboardNub->retain();
if (self->_publishNotify) {
publishNotify = self->_publishNotify;
self->_publishNotify = 0;
}
}
}
if ( service->_consumerNub ) {
if ( self->_consumerNub
&& self->_consumerNub->isDispatcher()
&& !service->_consumerNub->isDispatcher() ) {
stopAndReleaseShim ( self->_consumerNub, self );
self->_consumerNub = 0;
}
if ( !self->_consumerNub ) {
self->_consumerNub = service->_consumerNub;
self->_consumerNub->retain();
if (self->_publishNotify) {
publishNotify = self->_publishNotify;
self->_publishNotify = 0;
}
}
}
}
if (self->_nubLock) IORecursiveLockUnlock(self->_nubLock);
if (publishNotify) publishNotify->remove();
}
#endif
return true;
}
void IOHIDEventService::calculateStandardType()
{
IOHIDStandardType result = kIOHIDStandardTypeANSI;
OSNumber * number;
OSObject * obj;
obj = copyProperty(kIOHIDStandardTypeKey);
number = OSDynamicCast(OSNumber, obj);
if ( number ) {
result = number->unsigned32BitValue();
}
else {
UInt16 productID = getProductID();
UInt16 vendorID = getVendorID();
if (vendorID == kIOUSBVendorIDAppleComputer) {
switch (productID) {
case kprodUSBCosmoISOKbd: case kprodUSBAndyISOKbd: case kprodQ6ISOKbd: case kprodQ30ISOKbd: #if TARGET_OS_EMBEDDED
_keyboard.swapISO = true;
#endif
case kprodFountainISOKbd: case kprodSantaISOKbd: result = kIOHIDStandardTypeISO;
break;
case kprodUSBCosmoJISKbd: case kprodUSBAndyJISKbd: case kprodQ6JISKbd: case kprodQ30JISKbd: case kprodFountainJISKbd: case kprodSantaJISKbd: result = kIOHIDStandardTypeJIS;
break;
}
setProperty(kIOHIDStandardTypeKey, result, 32);
}
}
OSSafeReleaseNULL(obj);
#if TARGET_OS_EMBEDDED
if ( !_keyboard.swapISO && result == kIOHIDStandardTypeISO ) {
obj = copyProperty("alt_handler_id");
number = OSDynamicCast(OSNumber, obj);
if ( number ) {
switch (number->unsigned32BitValue()) {
case kgestUSBCosmoISOKbd:
case kgestUSBAndyISOKbd:
case kgestQ6ISOKbd:
case kgestQ30ISOKbd:
case kgestM89ISOKbd:
case kgestUSBGenericISOkd:
_keyboard.swapISO = true;
break;
}
}
OSSafeReleaseNULL(obj);
}
#endif
}
IOReturn IOHIDEventService::setSystemProperties( OSDictionary * properties )
{
OSDictionary * dict = NULL;
OSArray * array = NULL;
OSNumber * number = NULL;
if ( !properties )
return kIOReturnBadArgument;
if ( ( array = OSDynamicCast(OSArray, properties->getObject(kIOHIDKeyboardModifierMappingPairsKey)) ) ) {
UInt32 srcVirtualCode, dstVirtualCode;
Boolean capsMap = FALSE;
for (UInt32 index=0; index<array->getCount(); index++) {
dict = OSDynamicCast(OSDictionary, array->getObject(index));
if ( !dict )
continue;
number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDKeyboardModifierMappingSrcKey));
if ( !number )
continue;
srcVirtualCode = number->unsigned32BitValue();
if ( srcVirtualCode != NX_MODIFIERKEY_ALPHALOCK )
continue;
number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDKeyboardModifierMappingDstKey));
if ( !number )
continue;
dstVirtualCode = number->unsigned32BitValue();
if ( dstVirtualCode == srcVirtualCode )
continue;
capsMap = TRUE;
break;
}
}
if ( properties->getObject(kIOHIDDeviceParametersKey) == kOSBooleanTrue ) {
OSObject *obj = copyProperty(kIOHIDEventServicePropertiesKey);
OSDictionary * eventServiceProperties = OSDynamicCast(OSDictionary, obj);
if ( eventServiceProperties ) {
if (eventServiceProperties->setOptions(0, 0) & OSDictionary::kImmutable) {
OSDictionary * copyEventServiceProperties = (OSDictionary*)eventServiceProperties->copyCollection();
obj->release();
eventServiceProperties = copyEventServiceProperties;
}
} else {
OSSafeReleaseNULL(obj);
eventServiceProperties = OSDictionary::withCapacity(4);
}
if ( eventServiceProperties ) {
eventServiceProperties->merge(properties);
eventServiceProperties->removeObject(kIOHIDResetKeyboardKey);
eventServiceProperties->removeObject(kIOHIDResetPointerKey);
eventServiceProperties->removeObject(kIOHIDDeviceParametersKey);
setProperty(kIOHIDEventServicePropertiesKey, eventServiceProperties);
eventServiceProperties->release();
}
}
return kIOReturnSuccess;
}
IOReturn IOHIDEventService::setProperties( OSObject * properties )
{
OSDictionary * propertyDict = OSDynamicCast(OSDictionary, properties);
IOReturn ret = kIOReturnBadArgument;
if (propertyDict) {
propertyDict->setObject(kIOHIDDeviceParametersKey, kOSBooleanTrue);
ret = setSystemProperties( propertyDict );
propertyDict->removeObject(kIOHIDDeviceParametersKey);
}
return ret;
}
void IOHIDEventService::parseSupportedElements ( OSArray * elementArray, UInt32 bootProtocol )
{
UInt32 count = 0;
UInt32 index = 0;
UInt32 usage = 0;
UInt32 usagePage = 0;
UInt32 supportedModifiers = 0;
UInt32 buttonCount = 0;
IOHIDElement * element = 0;
OSArray * functions = 0;
IOFixed pointingResolution = 0;
IOFixed scrollResolution = 0;
bool pointingDevice = false;
bool keyboardDevice = false;
bool consumerDevice = false;
switch ( bootProtocol )
{
case kBootProtocolMouse:
pointingDevice = true;
break;
case kBootProtocolKeyboard:
keyboardDevice = true;
break;
}
if ( elementArray )
{
count = elementArray->getCount();
for ( index = 0; index < count; index++ )
{
element = OSDynamicCast(IOHIDElement, elementArray->getObject(index));
if ( !element )
continue;
usagePage = element->getUsagePage();
usage = element->getUsage();
switch ( usagePage )
{
case kHIDPage_GenericDesktop:
switch ( usage )
{
case kHIDUsage_GD_Mouse:
pointingDevice = true;
break;
case kHIDUsage_GD_X:
if ( !(pointingResolution = determineResolution(element)) )
pointingResolution = kDefaultFixedResolution;
break;
case kHIDUsage_GD_Z:
case kHIDUsage_GD_Wheel:
if ( !(scrollResolution = determineResolution(element)) )
scrollResolution = kDefaultScrollFixedResolution;
break;
case kHIDUsage_GD_SystemPowerDown:
case kHIDUsage_GD_SystemSleep:
case kHIDUsage_GD_SystemWakeUp:
consumerDevice = true;
break;
}
break;
case kHIDPage_Button:
buttonCount ++;
break;
case kHIDPage_KeyboardOrKeypad:
keyboardDevice = true;
switch ( usage )
{
case kHIDUsage_KeyboardLeftControl:
supportedModifiers |= NX_CONTROLMASK;
supportedModifiers |= NX_DEVICELCTLKEYMASK;
break;
case kHIDUsage_KeyboardLeftShift:
supportedModifiers |= NX_SHIFTMASK;
supportedModifiers |= NX_DEVICELSHIFTKEYMASK;
break;
case kHIDUsage_KeyboardLeftAlt:
supportedModifiers |= NX_ALTERNATEMASK;
supportedModifiers |= NX_DEVICELALTKEYMASK;
break;
case kHIDUsage_KeyboardLeftGUI:
supportedModifiers |= NX_COMMANDMASK;
supportedModifiers |= NX_DEVICELCMDKEYMASK;
break;
case kHIDUsage_KeyboardRightControl:
supportedModifiers |= NX_CONTROLMASK;
supportedModifiers |= NX_DEVICERCTLKEYMASK;
break;
case kHIDUsage_KeyboardRightShift:
supportedModifiers |= NX_SHIFTMASK;
supportedModifiers |= NX_DEVICERSHIFTKEYMASK;
break;
case kHIDUsage_KeyboardRightAlt:
supportedModifiers |= NX_ALTERNATEMASK;
supportedModifiers |= NX_DEVICERALTKEYMASK;
break;
case kHIDUsage_KeyboardRightGUI:
supportedModifiers |= NX_COMMANDMASK;
supportedModifiers |= NX_DEVICERCMDKEYMASK;
break;
case kHIDUsage_KeyboardCapsLock:
supportedModifiers |= NX_ALPHASHIFT_STATELESS_MASK;
supportedModifiers |= NX_DEVICE_ALPHASHIFT_STATELESS_MASK;
break;
}
break;
case kHIDPage_Consumer:
consumerDevice = true;
break;
case kHIDPage_Digitizer:
pointingDevice = true;
switch ( usage )
{
case kHIDUsage_Dig_Pen:
case kHIDUsage_Dig_LightPen:
case kHIDUsage_Dig_TouchScreen:
setProperty(kIOHIDDisplayIntegratedKey, true);
break;
case kHIDUsage_Dig_TipSwitch:
case kHIDUsage_Dig_BarrelSwitch:
case kHIDUsage_Dig_Eraser:
buttonCount ++;
default:
break;
}
break;
case kHIDPage_AppleVendorTopCase:
if ((usage == kHIDUsage_AV_TopCase_KeyboardFn) &&
(_keyboard.appleVendorSupported))
{
supportedModifiers |= NX_SECONDARYFNMASK;
}
break;
}
if ((element->getType() == kIOHIDElementTypeCollection) &&
((element->getCollectionType() == kIOHIDElementCollectionTypeApplication) ||
(element->getCollectionType() == kIOHIDElementCollectionTypePhysical)))
{
OSNumber * usagePageRef, * usageRef;
OSDictionary * pairRef;
if(!functions) functions = OSArray::withCapacity(2);
pairRef = OSDictionary::withCapacity(2);
usageRef = OSNumber::withNumber(usage, 32);
usagePageRef= OSNumber::withNumber(usagePage, 32);
pairRef->setObject(kIOHIDDeviceUsageKey, usageRef);
pairRef->setObject(kIOHIDDeviceUsagePageKey, usagePageRef);
UInt32 pairCount = functions->getCount();
bool found = false;
for(unsigned i=0; i<pairCount; i++)
{
OSDictionary *tempPair = (OSDictionary *)functions->getObject(i);
if ( NULL != (found = tempPair->isEqualTo(pairRef)) )
break;
}
if (!found)
{
functions->setObject(functions->getCount(), pairRef);
}
pairRef->release();
usageRef->release();
usagePageRef->release();
}
}
if (_deviceUsagePairs) {
_deviceUsagePairs->release();
}
_deviceUsagePairs = functions;
}
if ( pointingDevice )
{
if ( pointingResolution )
setProperty(kIOHIDPointerResolutionKey, pointingResolution, 32);
if ( scrollResolution )
setProperty(kIOHIDScrollResolutionKey, scrollResolution, 32);
if (buttonCount) {
setProperty(kIOHIDPointerButtonCountKey, buttonCount, 32);
}
}
if (keyboardDevice) {
setProperty(kIOHIDKeyboardSupportedModifiersKey, supportedModifiers, 32);
setProperty("HIDKeyboardKeysDefined", true);
}
#if !TARGET_OS_EMBEDDED
NUB_LOCK;
#ifdef POINTING_SHIM_SUPPORT
if ( pointingDevice && _pointingShim != kLegacyShimDisabled) {
_pointingNub = newPointingShim(buttonCount, pointingResolution, scrollResolution, kShimEventProcessor);
}
#endif
if (keyboardDevice && _keyboardShim != kLegacyShimDisabled) {
_keyboardNub = newKeyboardShim(supportedModifiers, kShimEventProcessor);
}
if (consumerDevice && _keyboardShim != kLegacyShimDisabled) {
_consumerNub = newConsumerShim(kShimEventProcessor);
}
NUB_UNLOCK;
#endif
}
IOHIDPointing * IOHIDEventService::newPointingShim (
UInt32 buttonCount,
IOFixed pointerResolution,
IOFixed scrollResolution,
IOOptionBits options)
{
#if !TARGET_OS_EMBEDDED // {
bool isDispatcher = ((options & kShimEventProcessor) == 0);
IOHIDPointing *pointingNub = IOHIDPointing::Pointing(buttonCount, pointerResolution, scrollResolution, isDispatcher);;
OSNumber *value;
require(pointingNub, no_nub);
SET_HID_PROPERTIES(pointingNub);
require(pointingNub->attach(this), no_attach);
require(pointingNub->start(this), no_start);
value = OSNumber::withNumber(getRegistryEntryID(), 64);
if (value) {
pointingNub->setProperty(kIOHIDAltSenderIdKey, value);
value->release();
}
return pointingNub;
no_start:
pointingNub->detach(this);
no_attach:
pointingNub->release();
pointingNub = NULL;
no_nub:
#endif // } TARGET_OS_EMBEDDED
return NULL;
}
IOHIDKeyboard * IOHIDEventService::newKeyboardShim (
UInt32 supportedModifiers,
IOOptionBits options)
{
#if !TARGET_OS_EMBEDDED // {
bool isDispatcher = ((options & kShimEventProcessor) == 0);
IOHIDKeyboard *keyboardNub = IOHIDKeyboard::Keyboard(supportedModifiers, isDispatcher);
require(keyboardNub, no_nub);
SET_HID_PROPERTIES(keyboardNub);
require(keyboardNub->attach(this), no_attach);
require(keyboardNub->start(this), no_start);
keyboardNub->setProperty(kIOHIDAltSenderIdKey, OSNumber::withNumber(getRegistryEntryID(), 64));
return keyboardNub;
no_start:
keyboardNub->detach(this);
no_attach:
keyboardNub->release();
keyboardNub = NULL;
no_nub:
#endif // } TARGET_OS_EMBEDDED
return NULL;
}
IOHIDConsumer * IOHIDEventService::newConsumerShim ( IOOptionBits options )
{
#if !TARGET_OS_EMBEDDED // {
bool isDispatcher = ((options & kShimEventProcessor) == 0);
IOHIDConsumer *consumerNub = IOHIDConsumer::Consumer(isDispatcher);;
require(consumerNub, no_nub);
SET_HID_PROPERTIES(consumerNub);
require(consumerNub->attach(this), no_attach);
require(consumerNub->start(this), no_start);
consumerNub->setProperty(kIOHIDAltSenderIdKey, OSNumber::withNumber(getRegistryEntryID(), 64));
return consumerNub;
no_start:
consumerNub->detach(this);
no_attach:
consumerNub->release();
consumerNub = NULL;
no_nub:
#endif // } TARGET_OS_EMBEDDED
return NULL;
}
IOFixed IOHIDEventService::determineResolution ( IOHIDElement * element )
{
IOFixed resolution = 0;
bool supportResolution = true;
#if !TARGET_OS_EMBEDDED
if ((element->getFlags() & kIOHIDElementFlagsRelativeMask) != 0) {
if ( element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController) )
supportResolution = false;
}
else {
supportResolution = false;
}
#endif
if ( supportResolution ) {
if ((element->getPhysicalMin() != element->getLogicalMin()) &&
(element->getPhysicalMax() != element->getLogicalMax()))
{
SInt32 logicalDiff = (element->getLogicalMax() - element->getLogicalMin());
SInt32 physicalDiff = (element->getPhysicalMax() - element->getPhysicalMin());
SInt32 resExponent = element->getUnitExponent() & 0x0F;
if (resExponent < 8)
{
for (int i = resExponent; i > 0; i--)
{
physicalDiff *= 10;
}
}
else
{
for (int i = 0x10 - resExponent; i > 0; i--)
{
logicalDiff *= 10;
}
}
resolution = (logicalDiff / physicalDiff) << 16;
}
}
return resolution;
}
void IOHIDEventService::free()
{
IORecursiveLock* tempLock = NULL;
if ( _nubLock ) {
IORecursiveLockLock(_nubLock);
tempLock = _nubLock;
_nubLock = NULL;
}
if (_commandGate) {
if ( _workLoop )
_workLoop->removeEventSource(_commandGate);
_commandGate->release();
_commandGate = 0;
}
if ( _deviceUsagePairs ) {
_deviceUsagePairs->release();
_deviceUsagePairs = NULL;
}
if ( _clientDict ) {
assert(_clientDict->getCount() == 0);
_clientDict->release();
_clientDict = NULL;
}
#if TARGET_OS_EMBEDDED
if (_keyboard.debug.nmiTimer) {
if ( _workLoop )
_workLoop->removeEventSource(_keyboard.debug.nmiTimer);
_keyboard.debug.nmiTimer->release();
_keyboard.debug.nmiTimer = 0;
}
if (_keyboard.debug.stackshotTimer) {
if ( _workLoop )
_workLoop->removeEventSource(_keyboard.debug.stackshotTimer);
_keyboard.debug.stackshotTimer->release();
_keyboard.debug.stackshotTimer = 0;
}
#endif
if ( _workLoop ) {
_workLoop->release();
_workLoop = NULL;
}
if (_reserved) {
IODelete(_reserved, ExpansionData, 1);
_reserved = NULL;
}
if ( tempLock ) {
IORecursiveLockUnlock(tempLock);
IORecursiveLockFree(tempLock);
}
super::free();
}
bool IOHIDEventService::handleOpen(IOService * client,
IOOptionBits options,
void * argument)
{
bool accept = false;
do {
if ( _clientDict->getObject((const OSSymbol *)client) ) {
accept = true;
break;
}
if ( !OSDynamicCast(IOHIDClientData, (OSObject *)argument) ||
!_clientDict->setObject((const OSSymbol *)client, (IOHIDClientData *)argument))
break;
accept = true;
} while (false);
return accept;
}
void IOHIDEventService::handleClose(IOService * client, IOOptionBits options)
{
if ( _clientDict->getObject((const OSSymbol *)client) )
_clientDict->removeObject((const OSSymbol *)client);
}
bool IOHIDEventService::handleIsOpen(const IOService * client) const
{
if (client)
return _clientDict->getObject((const OSSymbol *)client) != NULL;
else
return (_clientDict->getCount() > 0);
}
bool IOHIDEventService::handleStart( IOService * provider __unused )
{
return true;
}
void IOHIDEventService::handleStop( IOService * provider __unused )
{}
OSString * IOHIDEventService::getTransport ()
{
return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDTransportKey)) : 0;
}
OSString * IOHIDEventService::getManufacturer ()
{
return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDManufacturerKey)) : 0;
}
OSString * IOHIDEventService::getProduct ()
{
return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDProductKey)) : 0;
}
OSString * IOHIDEventService::getSerialNumber ()
{
return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDSerialNumberKey)) : 0;
}
UInt32 IOHIDEventService::getLocationID ()
{
UInt32 value = 0;
if ( _provider ) {
OSObject *obj = _provider->copyProperty(kIOHIDLocationIDKey);
OSNumber * number = OSDynamicCast(OSNumber, obj);
if ( number )
value = number->unsigned32BitValue();
OSSafeReleaseNULL(obj);
}
return value;
}
UInt32 IOHIDEventService::getVendorID ()
{
UInt32 value = 0;
if ( _provider ) {
OSObject *obj = _provider->copyProperty(kIOHIDVendorIDKey);
OSNumber * number = OSDynamicCast(OSNumber, obj);
if ( number )
value = number->unsigned32BitValue();
OSSafeReleaseNULL(obj);
}
return value;
}
UInt32 IOHIDEventService::getVendorIDSource ()
{
UInt32 value = 0;
if ( _provider ) {
OSObject *obj = _provider->copyProperty(kIOHIDVendorIDSourceKey);
OSNumber * number = OSDynamicCast(OSNumber, obj);
if ( number )
value = number->unsigned32BitValue();
OSSafeReleaseNULL(obj);
}
return value;
}
UInt32 IOHIDEventService::getProductID ()
{
UInt32 value = 0;
if ( _provider ) {
OSObject *obj = _provider->copyProperty(kIOHIDProductIDKey);
OSNumber * number = OSDynamicCast(OSNumber, obj);
if ( number )
value = number->unsigned32BitValue();
OSSafeReleaseNULL(obj);
}
return value;
}
UInt32 IOHIDEventService::getVersion ()
{
UInt32 value = 0;
if ( _provider ) {
OSObject *obj = _provider->copyProperty(kIOHIDVersionNumberKey);
OSNumber * number = OSDynamicCast(OSNumber, obj);
if ( number )
value = number->unsigned32BitValue();
OSSafeReleaseNULL(obj);
}
return value;
}
UInt32 IOHIDEventService::getCountryCode ()
{
UInt32 value = 0;
if ( _provider ) {
OSObject *obj = _provider->copyProperty(kIOHIDCountryCodeKey);
OSNumber * number = OSDynamicCast(OSNumber, obj);
if ( number )
value = number->unsigned32BitValue();
OSSafeReleaseNULL(obj);
}
return value;
}
OSArray * IOHIDEventService::getReportElements()
{
return 0;
}
IOReturn IOHIDEventService::setElementValue (
UInt32 usagePage __unused,
UInt32 usage __unused,
UInt32 value __unused )
{
return kIOReturnUnsupported;
}
UInt32 IOHIDEventService::getElementValue (
UInt32 usagePage __unused,
UInt32 usage __unused )
{
return 0;
}
#if TARGET_OS_EMBEDDED
void IOHIDEventService::debuggerTimerCallback(IOTimerEventSource *sender)
{
if ( _keyboard.debug.mask && _keyboard.debug.mask == _keyboard.debug.startMask && _keyboard.debug.mask == _keyboard.debug.nmiMask) {
PE_enter_debugger("NMI");
}
}
#endif
#if TARGET_OS_EMBEDDED
void IOHIDEventService::stackshotTimerCallback(IOTimerEventSource *sender)
{
if ( _keyboard.debug.mask && _keyboard.debug.mask == _keyboard.debug.startMask ) {
_keyboard.debug.stackshotHeld = 1;
}
}
#endif
void IOHIDEventService::multiAxisTimerCallback(IOTimerEventSource *sender __unused)
{
AbsoluteTime timestamp;
clock_get_uptime(×tamp);
dispatchMultiAxisPointerEvent(timestamp, _multiAxis.buttonState, _multiAxis.x, _multiAxis.y, _multiAxis.z, _multiAxis.rX, _multiAxis.rY, _multiAxis.rZ, _multiAxis.options | kIOHIDEventOptionIsRepeat);
}
#if !TARGET_OS_EMBEDDED
KeyValueMask IOHIDEventService::keyMonitorTable[] = {
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardLeftControl ), kKeyMaskCtrl},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardRightControl), kKeyMaskCtrl},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardLeftShift ), kKeyMaskShift},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardRightShift ), kKeyMaskShift},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardLeftAlt ), kKeyMaskAlt},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardRightAlt ), kKeyMaskAlt},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardLeftGUI ), kKeyMaskCommand},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardRightGUI ), kKeyMaskCommand},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardPeriod ), kKeyMaskPeriod},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeypadPeriod ), kKeyMaskPeriod},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardComma ), kKeyMaskComma},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeypadComma ), kKeyMaskComma},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardSlash ), kKeyMaskSlash},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeypadSlash ), kKeyMaskSlash},
{Key(kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardEscape ), kKeyMaskEsc}
};
DebugKeyAction IOHIDEventService::debugKeyActionTable[] = {
{ (kKeyMaskCtrl | kKeyMaskShift | kKeyMaskAlt | kKeyMaskCommand | kKeyMaskPeriod),
IOHIDEventService::debugActionSysdiagnose,
(void*)kHIDUsage_KeyboardPeriod
},
{ (kKeyMaskCtrl | kKeyMaskShift | kKeyMaskAlt | kKeyMaskCommand | kKeyMaskComma),
IOHIDEventService::debugActionSysdiagnose,
(void*)kHIDUsage_KeyboardComma
},
{ (kKeyMaskCtrl | kKeyMaskShift | kKeyMaskAlt | kKeyMaskCommand | kKeyMaskSlash),
IOHIDEventService::debugActionSysdiagnose,
(void*)kHIDUsage_KeyboardSlash
},
{ kKeyMaskCtrl | kKeyMaskShift | kKeyMaskAlt | kKeyMaskCommand | kKeyMaskEsc,
debugActionNMI,
NULL
},
};
void IOHIDEventService::debugActionNMI (IOHIDEventService *self, void * parameter) {
PE_enter_debugger("HID: USB Programmer Key");
}
void IOHIDEventService::debugActionSysdiagnose (IOHIDEventService *self, void * parameter) {
uint32_t keyCode = (uint32_t)(uintptr_t)parameter;
kern_stack_snapshot_with_reason("HID: Stackshot triggered using keycombo");
sysdiagnose_notify_user(keyCode);
HIDLog("HID: Posted stackshot event 0x%08x", keyCode);
}
#endif
void IOHIDEventService::dispatchKeyboardEvent(
AbsoluteTime timeStamp,
UInt32 usagePage,
UInt32 usage,
UInt32 value,
IOOptionBits options)
{
if ( ! _readyForInputReports )
return;
IOHIDEvent * event = NULL;
#if TARGET_OS_EMBEDDED // {
UInt32 debugMask = 0;
if ( !_keyboard.debug.nmiMask ) {
OSData * nmi_mask = OSDynamicCast(OSData, getProperty("button-nmi_mask", gIOServicePlane));
if ( nmi_mask) {
_keyboard.debug.nmiMask = *(UInt32 *) nmi_mask->getBytesNoCopy();
_keyboard.debug.nmiDelay = kDebuggerLongDelayMS;
} else {
#if TARGET_OS_TV // Apple TV NMI keychord: FAV (List button) + PlayPause
_keyboard.debug.nmiMask = 0x50;
_keyboard.debug.nmiDelay = kATVChordDelayMS;
#else
_keyboard.debug.nmiMask = 0x3;
_keyboard.debug.nmiDelay = kDebuggerDelayMS;
#endif // TARGET_OS_TV
}
}
switch (usagePage) {
case kHIDPage_KeyboardOrKeypad:
if ( _keyboard.swapISO ) {
switch ( usage ) {
case kHIDUsage_KeyboardGraveAccentAndTilde:
usage = kHIDUsage_KeyboardNonUSBackslash;
break;
case kHIDUsage_KeyboardNonUSBackslash:
usage = kHIDUsage_KeyboardGraveAccentAndTilde;
break;
}
}
break;
case kHIDPage_Consumer:
switch (usage) {
case kHIDUsage_Csmr_Power:
debugMask = 0x1;
break;
case kHIDUsage_Csmr_VolumeDecrement:
debugMask = 0x20;
break;
case kHIDUsage_Csmr_VolumeIncrement:
debugMask = 0x2;
break;
case kHIDUsage_Csmr_Menu:
debugMask = 0x4;
break;
case kHIDUsage_Csmr_Help:
debugMask = 0x8;
break;
case kHIDUsage_Csmr_PlayOrPause:
debugMask = 0x10;
break;
case kHIDUsage_Csmr_DataOnScreen:
debugMask = 0x40;
break;
};
break;
case kHIDPage_Telephony:
switch (usage) {
case kHIDUsage_Tfon_Hold:
debugMask = 0x1;
break;
};
break;
};
if ( value )
_keyboard.debug.mask |= debugMask;
else
_keyboard.debug.mask &= ~debugMask;
if ( _keyboard.debug.mask == _keyboard.debug.nmiMask ) {
if ( !_keyboard.debug.nmiTimer ) {
_keyboard.debug.nmiTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &IOHIDEventService::debuggerTimerCallback));
if (_keyboard.debug.nmiTimer) {
if ((_workLoop->addEventSource(_keyboard.debug.nmiTimer) != kIOReturnSuccess)) {
_keyboard.debug.nmiTimer->release();
_keyboard.debug.nmiTimer = NULL;
}
}
}
if ( _keyboard.debug.nmiTimer ) {
_keyboard.debug.nmiTimer->setTimeoutMS( _keyboard.debug.nmiDelay );
_keyboard.debug.startMask = _keyboard.debug.mask;
}
}
if(_keyboard.debug.mask == 0x3 || _keyboard.debug.mask == 0x6 || _keyboard.debug.mask == 0x24 || _keyboard.debug.mask == STACKSHOT_MASK_WATCH ||
_keyboard.debug.mask == STACKSHOT_MASK_ATV) {
if (_keyboard.debug.mask == STACKSHOT_MASK_WATCH || _keyboard.debug.mask == STACKSHOT_MASK_ATV) {
if ( !_keyboard.debug.stackshotTimer ) {
_keyboard.debug.stackshotTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &IOHIDEventService::stackshotTimerCallback));
if ( _keyboard.debug.stackshotTimer ) {
if ((_workLoop->addEventSource(_keyboard.debug.stackshotTimer) != kIOReturnSuccess)) {
_keyboard.debug.stackshotTimer->release();
_keyboard.debug.stackshotTimer = NULL;
}
}
}
if ( _keyboard.debug.stackshotTimer ) {
_keyboard.debug.stackshotTimer->setTimeoutMS(DELAYED_STACKSHOT_TIMEOUT);
_keyboard.debug.startMask = _keyboard.debug.mask;
}
}
handle_stackshot_keychord(_keyboard.debug.mask);
}
if ( _keyboard.debug.mask == 0x0 ) {
if ( _keyboard.debug.stackshotHeld ) {
handle_stackshot_keychord(DELAYED_STACKSHOT_MASK);
}
if ( _keyboard.debug.stackshotTimer ) {
_keyboard.debug.stackshotTimer->cancelTimeout();
}
_keyboard.debug.stackshotHeld = 0;
}
event = IOHIDEvent::keyboardEvent(timeStamp, usagePage, usage, value!=0, options);
if ( event ) {
dispatchEvent(event);
event->release();
}
#endif
#if !TARGET_OS_EMBEDDED
for (int index = 0 ; index < sizeof(_keyboard.pressedKeys)/sizeof(_keyboard.pressedKeys[0]); index++) {
if (value) {
if (!_keyboard.pressedKeys[index].isValid()) {
_keyboard.pressedKeys[index] = Key (usagePage, usage);
break;
}
} else {
if (_keyboard.pressedKeys[index].usage() == usage && _keyboard.pressedKeys[index].usagePage() == usagePage) {
_keyboard.pressedKeys[index] = Key (0, 0);
break;
}
}
}
_keyboard.pressedKeysMask = 0;
for (int index = 0 ; index < sizeof(_keyboard.pressedKeys)/sizeof(_keyboard.pressedKeys[0]); index++) {
uint32_t maskForKey = 0;
if (_keyboard.pressedKeys[index].isValid()) {
maskForKey = kKeyMaskUnknown;
for (int i = 0 ; i < sizeof (keyMonitorTable)/sizeof(keyMonitorTable[0]); i++) {
if (keyMonitorTable[i].key == _keyboard.pressedKeys[index]) {
maskForKey = keyMonitorTable[i].mask;
break;
}
}
}
_keyboard.pressedKeysMask |= maskForKey;
}
uint32_t debugMask = (_keyboard.pressedKeysMask & kKeyMaskUnknown) ? 0 : _keyboard.pressedKeysMask;
if (debugMask && value != 0) {
for (int index = 0 ; index < sizeof (debugKeyActionTable)/sizeof(debugKeyActionTable[0]); index++) {
if (debugKeyActionTable[index].mask == debugMask) {
HIDLogError ("HID: taking action for debug key mask %x", debugMask);
debugKeyActionTable[index].action(this, debugKeyActionTable[index].parameter);
return;
}
}
}
event = IOHIDEvent::keyboardEvent(timeStamp, usagePage, usage, (value != 0), options);
if ( event ) {
dispatchEvent(event);
event->release();
}
if (_keyboardShim != kLegacyShimDisabled) {
NUB_LOCK;
IOHID_DEBUG(kIOHIDDebugCode_DispatchKeyboard, usagePage, usage, value, options);
if (usagePage == kHIDPage_KeyboardOrKeypad ||
(_keyboard.appleVendorSupported && (usagePage == kHIDPage_AppleVendorKeyboard || (usagePage == kHIDPage_AppleVendorTopCase && usage == kHIDUsage_AV_TopCase_KeyboardFn)))) {
if ( !_keyboardNub ) {
_keyboardNub = newKeyboardShim();
}
if ( _keyboardNub ) {
_keyboardNub->dispatchKeyboardEvent(timeStamp, usagePage, usage, (value != 0), options);
}
}
if (usagePage == kHIDPage_Consumer) {
if ( !_consumerNub )
_consumerNub = newConsumerShim();
if ( _consumerNub ) {
_consumerNub->dispatchConsumerEvent(_keyboardNub, timeStamp, usagePage, usage, value, options);
}
}
NUB_UNLOCK;
}
#endif // }
}
void IOHIDEventService::dispatchRelativePointerEventWithFixed(
AbsoluteTime timeStamp,
IOFixed dx,
IOFixed dy,
UInt32 buttonState,
IOOptionBits options)
{
IOHID_DEBUG(kIOHIDDebugCode_DispatchRelativePointer, dx, dy, buttonState, options);
if ( ! _readyForInputReports )
return;
if ( !dx && !dy && buttonState == _relativePointer.buttonState )
return;
IOHIDEvent *event = IOHIDEvent::relativePointerEventWithFixed(timeStamp, dx, dy, 0, buttonState, _relativePointer.buttonState);
if ( event ) {
dispatchEvent(event);
event->release();
}
#ifdef POINTING_SHIM_SUPPORT
if (_pointingShim != kLegacyShimDisabled) {
NUB_LOCK;
if (!_pointingNub ) {
_pointingNub = newPointingShim();
}
if (_pointingNub) {
_pointingNub->dispatchRelativePointerEvent(timeStamp, dx, dy, buttonState, options);
}
NUB_UNLOCK;
}
#endif
_relativePointer.buttonState = buttonState;
}
void IOHIDEventService::dispatchRelativePointerEvent(
AbsoluteTime timeStamp,
SInt32 dx,
SInt32 dy,
UInt32 buttonState,
IOOptionBits options)
{
dispatchRelativePointerEventWithFixed (timeStamp, dx << 16, dy << 16, buttonState, options);
}
static IOFixed __ScaleToFixed(int32_t value, int32_t min, int32_t max)
{
int32_t range = max - min;
int32_t offset = value - min;
return IOFixedDivide(offset<<16, range<<16);
}
void IOHIDEventService::dispatchAbsolutePointerEvent(
AbsoluteTime timeStamp,
SInt32 x,
SInt32 y,
IOGBounds * bounds,
UInt32 buttonState,
bool inRange,
SInt32 tipPressure,
SInt32 tipPressureMin,
SInt32 tipPressureMax,
IOOptionBits options)
{
#if TARGET_OS_EMBEDDED
dispatchDigitizerEvent(timeStamp, 0, kDigitizerTransducerTypeStylus, inRange, buttonState, __ScaleToFixed(x, bounds->minx, bounds->maxx), __ScaleToFixed(y, bounds->miny, bounds->maxy), __ScaleToFixed(tipPressure, tipPressureMin, tipPressureMax));
#else
IOHID_DEBUG(kIOHIDDebugCode_DispatchAbsolutePointer, x, y, buttonState, options);
IOHIDEvent *event = IOHIDEvent::absolutePointerEvent(timeStamp, __ScaleToFixed(x, bounds->minx, bounds->maxx), __ScaleToFixed(y, bounds->miny, bounds->maxy), _absolutePointer.buttonState, buttonState);
if (event) {
dispatchEvent(event);
}
#ifdef POINTING_SHIM_SUPPORT
if (_pointingShim != kLegacyShimDisabled) {
NUB_LOCK;
if ( !_pointingNub )
_pointingNub = newPointingShim();
NUB_UNLOCK;
}
#endif
_absolutePointer.buttonState = buttonState;
#endif
}
void IOHIDEventService::dispatchScrollWheelEventWithFixed(
AbsoluteTime timeStamp,
IOFixed deltaAxis1,
IOFixed deltaAxis2,
IOFixed deltaAxis3,
IOOptionBits options)
{
uint8_t momentumOrPhase = (options & kHIDDispatchOptionPhaseAny) >> 4 | ((options & kHIDDispatchOptionScrollMomentumAny) << (4 - 1));
IOHID_DEBUG(kIOHIDDebugCode_DispatchScroll, deltaAxis1, deltaAxis2, deltaAxis3, options);
if ( ! _readyForInputReports )
return;
if ( !deltaAxis1 && !deltaAxis2 && !deltaAxis3 && !momentumOrPhase )
return;
IOHIDEvent *event = IOHIDEvent::scrollEventWithFixed(timeStamp, deltaAxis2, deltaAxis1, deltaAxis3); if ( event ) {
if (momentumOrPhase) {
event->setPhase (momentumOrPhase);
}
dispatchEvent(event);
event->release();
}
#ifdef POINTING_SHIM_SUPPORT
if (_pointingShim != kLegacyShimDisabled) {
NUB_LOCK;
if ( !_pointingNub )
_pointingNub = newPointingShim();
if (_pointingNub)
_pointingNub->dispatchScrollWheelEvent(timeStamp, deltaAxis1 >> 16, deltaAxis2 >> 16, deltaAxis3 >> 16, options);
NUB_UNLOCK;
}
#endif
}
void IOHIDEventService::dispatchScrollWheelEvent(
AbsoluteTime timeStamp,
SInt32 deltaAxis1,
SInt32 deltaAxis2,
SInt32 deltaAxis3,
IOOptionBits options)
{
dispatchScrollWheelEventWithFixed (timeStamp, deltaAxis1 << 16, deltaAxis2 << 16, deltaAxis3 << 16);
}
#if !TARGET_OS_EMBEDDED
static void ScalePressure(SInt32 *pressure, SInt32 pressureMin, SInt32 pressureMax, SInt32 systemPressureMin, SInt32 systemPressureMax)
{
SInt64 systemScale = systemPressureMax - systemPressureMin;
*pressure = ((pressureMin != pressureMax)) ?
(((unsigned)(*pressure - pressureMin) * systemScale) /
(unsigned)( pressureMax - pressureMin)) + systemPressureMin: 0;
}
#endif
void IOHIDEventService::dispatchTabletPointerEvent(
AbsoluteTime timeStamp,
UInt32 transducerID __unused,
SInt32 x,
SInt32 y,
SInt32 z,
IOGBounds * bounds __unused,
UInt32 buttonState,
SInt32 tipPressure,
SInt32 tipPressureMin,
SInt32 tipPressureMax,
SInt32 barrelPressure,
SInt32 barrelPressureMin,
SInt32 barrelPressureMax,
SInt32 tiltX,
SInt32 tiltY,
UInt32 twist,
IOOptionBits options)
{
IOHID_DEBUG(kIOHIDDebugCode_DispatchTabletPointer, x, y, buttonState, options);
if ( ! _readyForInputReports )
return;
#ifdef POINTING_SHIM_SUPPORT
if (_pointingShim != kLegacyShimDisabled) {
NUB_LOCK;
if ( !_pointingNub )
_pointingNub = newPointingShim();
NUB_UNLOCK;
}
#endif
}
void IOHIDEventService::dispatchTabletProximityEvent(
AbsoluteTime timeStamp,
UInt32 transducerID,
bool inRange,
bool invert,
UInt32 vendorTransducerUniqueID,
UInt32 vendorTransducerSerialNumber,
IOOptionBits options)
{
IOHID_DEBUG(kIOHIDDebugCode_DispatchTabletProx, transducerID, vendorTransducerUniqueID, vendorTransducerSerialNumber, options);
if ( ! _readyForInputReports )
return;
#ifdef POINTING_SHIM_SUPPORT
if (_pointingShim != kLegacyShimDisabled) {
NUB_LOCK;
if ( !_pointingNub )
_pointingNub = newPointingShim();
NUB_UNLOCK;
}
#endif
}
bool IOHIDEventService::readyForReports()
{
return _readyForInputReports;
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 0);
OSArray * IOHIDEventService::getDeviceUsagePairs()
{
OSObject *obj = _provider->copyProperty(kIOHIDDeviceUsagePairsKey);
OSArray * providerUsagePairs = _provider ? OSDynamicCast(OSArray, obj) : NULL;
if ( providerUsagePairs && ( providerUsagePairs != _deviceUsagePairs ) ) {
setProperty(kIOHIDDeviceUsagePairsKey, providerUsagePairs);
if ( _deviceUsagePairs )
_deviceUsagePairs->release();
_deviceUsagePairs = providerUsagePairs;
_deviceUsagePairs->retain();
} else if ( !_deviceUsagePairs ) {
_deviceUsagePairs = OSArray::withCapacity(2);
if ( _deviceUsagePairs ) {
OSDictionary * pair = OSDictionary::withCapacity(2);
if ( pair ) {
OSNumber * number;
number = OSNumber::withNumber(getPrimaryUsagePage(), 32);
if ( number ) {
pair->setObject(kIOHIDDeviceUsagePageKey, number);
number->release();
}
number = OSNumber::withNumber(getPrimaryUsage(), 32);
if ( number ) {
pair->setObject(kIOHIDDeviceUsageKey, number);
number->release();
}
_deviceUsagePairs->setObject(pair);
pair->release();
}
}
}
OSSafeReleaseNULL(obj);
return _deviceUsagePairs;
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 1);
UInt32 IOHIDEventService::getReportInterval()
{
UInt32 interval = 8000; OSObject *object = copyProperty(kIOHIDReportIntervalKey, gIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents);
OSNumber *num = OSDynamicCast(OSNumber, object);
if ( num )
interval = num->unsigned32BitValue();
OSSafeReleaseNULL(object);
return interval;
}
#define kCenteredPointerMaxRelativeValue 8
#define GET_RELATIVE_VALUE_FROM_CENTERED(centered,relative) \
relative = (centered * kCenteredPointerMaxRelativeValue) >> 16;\
OSMetaClassDefineReservedUsed(IOHIDEventService, 2);
void IOHIDEventService::dispatchMultiAxisPointerEvent(
AbsoluteTime timeStamp,
UInt32 buttonState,
IOFixed x,
IOFixed y,
IOFixed z,
IOFixed rX,
IOFixed rY,
IOFixed rZ,
IOOptionBits options)
{
bool validAxis = false;
bool validRelative = false;
bool validScroll = false;
bool isZButton = false;
UInt32 interval = 0;
if ( ! _readyForInputReports )
return;
validRelative = ( options & kMultiAxisOptionRotationForTranslation ) ? rX || rY || _multiAxis.rX || _multiAxis.rY : x || y || _multiAxis.x || _multiAxis.y;
validScroll = rZ || _multiAxis.rZ;
validAxis = x || y || z || rX || rY || rZ || _multiAxis.x || _multiAxis.y || _multiAxis.z || _multiAxis.rX || _multiAxis.rY || _multiAxis.rZ;
if ( options & kMultiAxisOptionZForScroll ) {
validScroll |= z || _multiAxis.z;
}
else if ( z > 0xc000 ){
isZButton = true;
buttonState |= 1;
}
validRelative |= buttonState != _multiAxis.buttonState;
if ( validAxis || validRelative || validScroll ) {
SInt32 dx = 0;
SInt32 dy = 0;
SInt32 sx = 0;
SInt32 sy = 0;
if ( !isZButton && (options & kMultiAxisOptionRotationForTranslation) ) {
GET_RELATIVE_VALUE_FROM_CENTERED(-rY, dx);
GET_RELATIVE_VALUE_FROM_CENTERED(rX, dy);
} else {
GET_RELATIVE_VALUE_FROM_CENTERED(x, dx);
GET_RELATIVE_VALUE_FROM_CENTERED(y, dy);
}
GET_RELATIVE_VALUE_FROM_CENTERED(rZ, sy);
if ( options & kMultiAxisOptionZForScroll )
GET_RELATIVE_VALUE_FROM_CENTERED(z, sx);
#if TARGET_OS_EMBEDDED
IOHIDEvent * subEvent = IOHIDEvent::multiAxisPointerEvent(timeStamp, x, y, z, rX, rY, rZ, buttonState, _multiAxis.buttonState, options);
if ( subEvent ) {
IOHIDEvent * event;
if ( validRelative || (!validRelative && !validScroll) ) {
event = IOHIDEvent::relativePointerEvent(timeStamp, dx, dy, 0, buttonState);
if ( event ) {
if ( subEvent ) {
event->appendChild(subEvent);
}
dispatchEvent(event);
event->release();
}
}
if ( validScroll ) {
event = IOHIDEvent::scrollEvent(timeStamp, sx, sy, 0);
if ( event ) {
if ( subEvent ) {
event->appendChild(subEvent);
}
dispatchEvent(event);
event->release();
}
}
subEvent->release();
}
#else
dispatchRelativePointerEvent(timeStamp, dx, dy, buttonState, options);
dispatchScrollWheelEvent(timeStamp, sy, sx, 0, options);
#endif
if ( (options & kIOHIDEventOptionIsRepeat) == 0 ) {
_multiAxis.timer->cancelTimeout();
if ( validAxis )
interval = getReportInterval() + getReportInterval()/2;
} else if ( validAxis ) {
interval = getReportInterval();
}
if ( interval )
_multiAxis.timer->setTimeoutUS(interval);
}
_multiAxis.x = x;
_multiAxis.y = y;
_multiAxis.z = z;
_multiAxis.rX = rX;
_multiAxis.rY = rY;
_multiAxis.rZ = rZ;
_multiAxis.buttonState = buttonState;
_multiAxis.options = (options & ~kIOHIDEventOptionIsRepeat);
}
void IOHIDEventService::dispatchDigitizerEventWithOrientation(
AbsoluteTime timeStamp,
UInt32 transducerID,
DigitizerTransducerType type __unused,
bool inRange,
UInt32 buttonState,
IOFixed x,
IOFixed y,
IOFixed z,
IOFixed tipPressure,
IOFixed auxPressure,
IOFixed twist,
DigitizerOrientationType orientationType,
IOFixed * orientationParams,
UInt32 orientationParamCount,
IOOptionBits options)
{
IOHID_DEBUG(kIOHIDDebugCode_DispatchDigitizer, x, y, buttonState, options);
IOFixed params[5] = {};
bool touch = false;
if ( ! _readyForInputReports )
return;
if ( !inRange ) {
buttonState = 0;
tipPressure = 0;
}
if ( orientationParams ) {
orientationParamCount = min(5, orientationParamCount);
bcopy(orientationParams, params, sizeof(IOFixed) * orientationParamCount);
}
#if TARGET_OS_EMBEDDED
IOHIDEvent * collectionEvent = NULL;
IOHIDEvent * childEvent = NULL;
SInt32 eventMask = 0; UInt32 eventOptions = 0;
if ( options & kDigitizerInvert )
eventOptions |= kIOHIDTransducerInvert;
childEvent = IOHIDEvent::digitizerEvent(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, eventOptions);
require(childEvent, exit);
buttonState |= (tipPressure>>16) & 1;
if ( tipPressure )
touch |= 1;
else
touch |= buttonState & 1;
childEvent->setIntegerValue(kIOHIDEventFieldDigitizerTouch, touch);
if (touch != _digitizer.touch) {
eventMask |= kIOHIDDigitizerEventTouch;
}
if (inRange != _digitizer.range) {
eventMask |= kIOHIDDigitizerEventRange;
if ( inRange ) {
_digitizer.x = x;
_digitizer.y = y;
eventMask |= kIOHIDDigitizerEventIdentity;
}
}
if (inRange && ( (_digitizer.x != x) || (_digitizer.y != y) || (_digitizer.z != z) ) ) {
eventMask |= kIOHIDDigitizerEventPosition;
}
childEvent->setIntegerValue(kIOHIDEventFieldDigitizerEventMask, eventMask);
collectionEvent = IOHIDEvent::digitizerEvent(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, eventOptions);
require(collectionEvent, exit);
collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerCollection, TRUE);
collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerRange, childEvent->getIntegerValue(kIOHIDEventFieldDigitizerRange));
collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerEventMask, childEvent->getIntegerValue(kIOHIDEventFieldDigitizerEventMask));
collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerTouch, childEvent->getIntegerValue(kIOHIDEventFieldDigitizerTouch));
collectionEvent->appendChild(childEvent);
dispatchEvent(collectionEvent);
exit:
if ( collectionEvent )
collectionEvent->release();
if ( childEvent )
childEvent->release();
#else
bool invert = options & kDigitizerInvert;
if ( inRange && inRange != _digitizer.range ) {
dispatchTabletProximityEvent(timeStamp, transducerID, inRange, invert, options);
}
if ( inRange ) {
Bounds bounds = {0, kMaxSystemAbsoluteRangeSigned, 0, kMaxSystemAbsoluteRangeSigned};
SInt32 scaledX = ((SInt64)x * kMaxSystemAbsoluteRangeSigned) >> 16;
SInt32 scaledY = ((SInt64)y * kMaxSystemAbsoluteRangeSigned) >> 16;
SInt32 scaledZ = ((SInt64)z * kMaxSystemAbsoluteRangeSigned) >> 16;
SInt32 scaledTP = ((SInt64)tipPressure * EV_MAXPRESSURE) >> 16;
SInt32 scaledBP = ((SInt64)auxPressure * EV_MAXPRESSURE) >> 16;
SInt32 scaledTiltX = (((SInt64)params[0] * kMaxSystemAbsoluteRangeSigned)/90) >> 16;
SInt32 scaledTiltY = (((SInt64)params[1] * kMaxSystemAbsoluteRangeSigned)/90) >> 16;
if ( orientationType != kDigitizerOrientationTypeTilt )
bzero(params, sizeof(params));
dispatchTabletPointerEvent(timeStamp, transducerID, scaledX, scaledY, scaledZ, &bounds, buttonState, scaledTP, 0, EV_MAXPRESSURE, scaledBP, 0, EV_MAXPRESSURE, scaledTiltX, scaledTiltY, twist>>10 );
dispatchAbsolutePointerEvent(timeStamp, scaledX, scaledY, &bounds, buttonState, inRange, scaledTP, 0, EV_MAXPRESSURE);
}
if ( !inRange && inRange != _digitizer.range ) {
dispatchTabletProximityEvent(timeStamp, transducerID, inRange, invert, options);
}
#endif
_digitizer.range = inRange;
_digitizer.x = x;
_digitizer.y = y;
_digitizer.z = z;
_digitizer.touch = touch;
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 3);
void IOHIDEventService::dispatchDigitizerEvent(
AbsoluteTime timeStamp,
UInt32 transducerID,
DigitizerTransducerType type,
bool inRange,
UInt32 buttonState,
IOFixed x,
IOFixed y,
IOFixed z,
IOFixed tipPressure,
IOFixed auxPressure,
IOFixed twist,
IOOptionBits options )
{
dispatchDigitizerEventWithOrientation(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, kDigitizerOrientationTypeTilt, NULL, 0, options);
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 4);
void IOHIDEventService::dispatchDigitizerEventWithTiltOrientation(
AbsoluteTime timeStamp,
UInt32 transducerID,
DigitizerTransducerType type,
bool inRange,
UInt32 buttonState,
IOFixed x,
IOFixed y,
IOFixed z,
IOFixed tipPressure,
IOFixed auxPressure,
IOFixed twist,
IOFixed tiltX,
IOFixed tiltY,
IOOptionBits options)
{
IOFixed params[] = {tiltX, tiltY};
dispatchDigitizerEventWithOrientation(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, kDigitizerOrientationTypeTilt, params, sizeof(params)/sizeof(IOFixed), options);
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 5);
void IOHIDEventService::dispatchDigitizerEventWithPolarOrientation(
AbsoluteTime timeStamp,
UInt32 transducerID,
DigitizerTransducerType type,
bool inRange,
UInt32 buttonState,
IOFixed x,
IOFixed y,
IOFixed z,
IOFixed tipPressure,
IOFixed auxPressure,
IOFixed twist,
IOFixed altitude,
IOFixed azimuth,
IOOptionBits options)
{
IOFixed params[] = {altitude, azimuth};
dispatchDigitizerEventWithOrientation(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, kDigitizerOrientationTypePolar, params, sizeof(params)/sizeof(IOFixed), options);
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 6);
void IOHIDEventService::dispatchUnicodeEvent(AbsoluteTime timeStamp, UInt8 * payload, UInt32 length, UnicodeEncodingType encoding, IOFixed quality, IOOptionBits options)
{
#if TARGET_OS_EMBEDDED
IOHIDEvent * event = IOHIDEvent::unicodeEvent(timeStamp, payload, length, encoding, quality, options);
if ( event ) {
dispatchEvent(event);
event->release();
}
#else
#pragma unused(timeStamp, payload, length, encoding, quality, options)
#endif
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 12);
void IOHIDEventService::dispatchStandardGameControllerEvent(
AbsoluteTime timeStamp,
IOFixed dpadUp,
IOFixed dpadDown,
IOFixed dpadLeft,
IOFixed dpadRight,
IOFixed faceX,
IOFixed faceY,
IOFixed faceA,
IOFixed faceB,
IOFixed shoulderL,
IOFixed shoulderR,
IOOptionBits options)
{
IOHIDEvent * event = IOHIDEvent::standardGameControllerEvent(timeStamp, dpadUp, dpadDown, dpadLeft, dpadRight, faceX, faceY, faceA, faceB, shoulderL, shoulderR, options);
if ( event ) {
dispatchEvent(event);
event->release();
}
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 13);
void IOHIDEventService::dispatchExtendedGameControllerEvent(
AbsoluteTime timeStamp,
IOFixed dpadUp,
IOFixed dpadDown,
IOFixed dpadLeft,
IOFixed dpadRight,
IOFixed faceX,
IOFixed faceY,
IOFixed faceA,
IOFixed faceB,
IOFixed shoulderL1,
IOFixed shoulderR1,
IOFixed shoulderL2,
IOFixed shoulderR2,
IOFixed joystickX,
IOFixed joystickY,
IOFixed joystickZ,
IOFixed joystickRz,
IOOptionBits options)
{
IOHIDEvent * event = IOHIDEvent::extendedGameControllerEvent(timeStamp, dpadUp, dpadDown, dpadLeft, dpadRight, faceX, faceY, faceA, faceB, shoulderL1, shoulderR1, shoulderL2, shoulderR2, joystickX, joystickY, joystickZ, joystickRz, options);
if ( event ) {
dispatchEvent(event);
event->release();
}
}
void IOHIDEventService::close(IOService *forClient, IOOptionBits options)
{
_commandGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOHIDEventService::closeGated), forClient, &options);
}
void IOHIDEventService::closeGated(IOService *forClient, IOOptionBits * pOptions)
{
super::close(forClient, *pOptions);
}
OSDefineMetaClassAndStructors(IOHIDClientData, OSObject)
IOHIDClientData * IOHIDClientData::withClientInfo(IOService *client, void* context, void * action)
{
IOHIDClientData * data = new IOHIDClientData;
if (!data) { }
else if (data->init()) {
data->client = client;
data->context = context;
data->action = action;
} else {
data->release();
data = NULL;
}
return data;
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 7);
bool IOHIDEventService::open( IOService * client,
IOOptionBits options,
void * context,
Action action)
{
return _commandGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOHIDEventService::openGated), client, &options, context, (void*)action);
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 7);
void IOHIDEventService::dispatchEvent(IOHIDEvent * event, IOOptionBits options)
{
OSCollectionIterator * iterator = OSCollectionIterator::withCollection(_clientDict);
IOHIDClientData * clientData;
OSObject * clientKey;
IOService * client;
void * context;
Action action;
event->setSenderID(getRegistryEntryID());
#if !TARGET_OS_EMBEDDED
if (event->getType() == kIOHIDEventTypeKeyboard &&
event->getIntegerValue(kIOHIDEventFieldKeyboardDown)) {
_sleepDisplayTickle();
}
#endif
IOHID_DEBUG(kIOHIDDebugCode_DispatchHIDEvent, options, 0, 0, 0);
if ( !iterator )
return;
while ((clientKey = iterator->getNextObject())) {
clientData = OSDynamicCast(IOHIDClientData, _clientDict->getObject((const OSSymbol *)clientKey));
if ( !clientData )
continue;
client = clientData->getClient();
context = clientData->getContext();
action = (Action)clientData->getAction();
if ( action )
(*action)(client, this, context, event, options);
}
iterator->release();
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 7);
UInt32 IOHIDEventService::getPrimaryUsagePage ()
{
UInt32 primaryUsagePage = 0;
OSArray * deviceUsagePairs = getDeviceUsagePairs();
if ( deviceUsagePairs && deviceUsagePairs->getCount() ) {
OSDictionary * pair = OSDynamicCast(OSDictionary, deviceUsagePairs->getObject(0));
if ( pair ) {
OSNumber * number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDDeviceUsagePageKey));
if ( number )
primaryUsagePage = number->unsigned32BitValue();
}
}
return primaryUsagePage;
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 10);
UInt32 IOHIDEventService::getPrimaryUsage ()
{
UInt32 primaryUsage = 0;
OSArray * deviceUsagePairs = getDeviceUsagePairs();
if ( deviceUsagePairs && deviceUsagePairs->getCount() ) {
OSDictionary * pair = OSDynamicCast(OSDictionary, deviceUsagePairs->getObject(0));
if ( pair ) {
OSNumber * number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDDeviceUsageKey));
if ( number )
primaryUsage = number->unsigned32BitValue();
}
}
return primaryUsage;
}
OSMetaClassDefineReservedUsed(IOHIDEventService, 11);
IOHIDEvent * IOHIDEventService::copyEvent(
IOHIDEventType type,
IOHIDEvent * matching,
IOOptionBits options)
{
return NULL;
}
bool IOHIDEventService::openGated(IOService * client,
IOOptionBits * pOptions,
void * context,
Action action)
{
IOHIDClientData * clientData = IOHIDClientData::withClientInfo(client, context, (void*)action);
bool ret = false;
if ( clientData ) {
if (super::open(client, *pOptions, clientData)) {
ret = true;
}
clientData->release();
}
#if !TARGET_OS_EMBEDDED
if (_keyboardShim == kLegacyShimEnabledForSingleUserMode) {
NUB_LOCK;
_keyboardShim = kLegacyShimDisabled;
if (_keyboardNub) {
stopAndReleaseShim ( _keyboardNub, this );
_keyboardNub = NULL;
}
if (_consumerNub) {
stopAndReleaseShim ( _consumerNub, this );
_consumerNub = NULL;
}
NUB_UNLOCK;
}
#endif
return ret;
}
IOReturn IOHIDEventService::newUserClient (
task_t owningTask,
void * securityID,
UInt32 type,
OSDictionary * properties,
IOUserClient ** handler )
{
if (type == kIOHIDEventServiceUserClientType) {
IOHIDEventServiceUserClient * client = OSTypeAlloc(IOHIDEventServiceUserClient);
if (client) {
if (!client->initWithTask(owningTask, securityID, type)) {
client->release();
return kIOReturnBadArgument;
}
if ( !client->attach(this) ) {
client->release();
return kIOReturnUnsupported;
}
if ( !client->start(this) ) {
client->detach(this);
client->release();
return kIOReturnUnsupported;
}
*handler = client;
return kIOReturnSuccess;
}
return kIOReturnNoMemory;
}
return super::newUserClient(owningTask, securityID, type, properties, handler);
}
OSMetaClassDefineReservedUnused(IOHIDEventService, 14);
OSMetaClassDefineReservedUnused(IOHIDEventService, 15);
OSMetaClassDefineReservedUnused(IOHIDEventService, 16);
OSMetaClassDefineReservedUnused(IOHIDEventService, 17);
OSMetaClassDefineReservedUnused(IOHIDEventService, 18);
OSMetaClassDefineReservedUnused(IOHIDEventService, 19);
OSMetaClassDefineReservedUnused(IOHIDEventService, 20);
OSMetaClassDefineReservedUnused(IOHIDEventService, 21);
OSMetaClassDefineReservedUnused(IOHIDEventService, 22);
OSMetaClassDefineReservedUnused(IOHIDEventService, 23);
OSMetaClassDefineReservedUnused(IOHIDEventService, 24);
OSMetaClassDefineReservedUnused(IOHIDEventService, 25);
OSMetaClassDefineReservedUnused(IOHIDEventService, 26);
OSMetaClassDefineReservedUnused(IOHIDEventService, 27);
OSMetaClassDefineReservedUnused(IOHIDEventService, 28);
OSMetaClassDefineReservedUnused(IOHIDEventService, 29);
OSMetaClassDefineReservedUnused(IOHIDEventService, 30);
OSMetaClassDefineReservedUnused(IOHIDEventService, 31);