#include <IOKit/system.h>
#include <IOKit/assert.h>
#include <libkern/c++/OSContainers.h>
#include <libkern/c++/OSCollectionIterator.h>
#include <kern/queue.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/hidsystem/IOHIDevice.h>
#include <IOKit/hidsystem/IOHIDShared.h>
#include <IOKit/hidsystem/IOHIDParameter.h>
#include <IOKit/usb/USB.h>
#include "IOHIDSystem.h"
#include "IOHIDEventService.h"
#include "IOHIDPointing.h"
#include "IOHIDKeyboard.h"
#include "IOHIDConsumer.h"
#include "IOHITablet.h"
#include "IOHIDPointingDevice.h"
#include "IOHIDKeyboardDevice.h"
#include "IOHIDKeys.h"
#include "IOHIDPrivate.h"
#include "IOHIDEventServiceQueue.h"
#include <IOKit/hidsystem/ev_private.h>
#include "IOHIDUserClient.h"
#include <sys/kdebug.h>
#ifdef __cplusplus
extern "C"
{
#include <UserNotification/KUNCUserNotifications.h>
void cons_cinput( char c);
}
#endif
bool displayWranglerUp( OSObject *, void *, IOService * );
static IOHIDSystem * evInstance = 0;
MasterAudioFunctions *masterAudioFunctions = 0;
#define xpr_ev_cursor(x, a, b, c, d, e)
#define PtInRect(ptp,rp) \
((ptp)->x >= (rp)->minx && (ptp)->x < (rp)->maxx && \
(ptp)->y >= (rp)->miny && (ptp)->y < (rp)->maxy)
#ifndef kIOFBWaitCursorFramesKey
#define kIOFBWaitCursorFramesKey "IOFBWaitCursorFrames"
#endif
#ifndef kIOFBWaitCursorPeriodKey
#define kIOFBWaitCursorPeriodKey "IOFBWaitCursorPeriod"
#endif
#ifndef kIOUserClientCrossEndianKey
#define kIOUserClientCrossEndianKey "IOUserClientCrossEndian"
#endif
#ifndef kIOUserClientCrossEndianCompatibleKey
#define kIOUserClientCrossEndianCompatibleKey "IOUserClientCrossEndianCompatible"
#endif
#ifndef abs
#define abs(_a) ((_a >= 0) ? _a : -_a)
#endif
#define NORMAL_MODIFIER_MASK (NX_COMMANDMASK | NX_CONTROLMASK | NX_SHIFTMASK | NX_ALTERNATEMASK)
static inline unsigned AbsoluteTimeToTick( AbsoluteTime * ts )
{
UInt64 nano;
absolutetime_to_nanoseconds(*ts, &nano);
return( nano >> 24 );
}
static inline void TickToAbsoluteTime( unsigned tick, AbsoluteTime * ts )
{
UInt64 nano = ((UInt64) tick) << 24;
nanoseconds_to_absolutetime(nano, ts);
}
static UInt8 ScalePressure(unsigned pressure)
{
return ((pressure * (unsigned long long)EV_MAXPRESSURE) / (unsigned)(65535LL));
}
#define EV_NS_TO_TICK(ns) AbsoluteTimeToTick(ns)
#define EV_TICK_TO_NS(tick,ns) TickToAbsoluteTime(tick,ns)
typedef struct _IOHIDCmdGateActionArgs {
void* arg0;
void* arg1;
void* arg2;
void* arg3;
void* arg4;
void* arg5;
void* arg6;
void* arg7;
void* arg8;
void* arg9;
void* arg10;
void* arg11;
} IOHIDCmdGateActionArgs;
static bool gKeySwitchLocked = false;
static bool gUseKeyswitch = true;
static IONotifier * gSwitchNotification = 0;
static bool keySwitchNotificationHandler(void *target, void *refCon, IOService *service) {
gKeySwitchLocked = (service->getProperty("Keyswitch") == kOSBooleanTrue);
return true;
}
#define kHIDConsumeCauseNone 0x00
#define kHIDConsumeCauseKeyLock 0x01
#define kHIDConsumeCauseDeadline 0x02
static inline UInt32 ShouldConsumeHIDEvent(AbsoluteTime ts, AbsoluteTime deadline, bool checkKeySwitch = true )
{
if (checkKeySwitch && gKeySwitchLocked && gUseKeyswitch)
return kHIDConsumeCauseKeyLock;
if ( AbsoluteTime_to_scalar(&ts) == 0 )
clock_get_uptime(&ts);
if (CMP_ABSOLUTETIME(&ts, &deadline) <= 0)
{
return kHIDConsumeCauseDeadline;
}
return kHIDConsumeCauseNone;
}
#define TICKLE_DISPLAY \
{ \
if (!evStateChanging && displayManager) \
displayManager->activityTickle(0,0); \
}
#define CONVERT_EV_TO_HW_BUTTONS(ev_buttons,hw_buttons) \
hw_buttons = ev_buttons & ~7; \
hw_buttons |= (ev_buttons & 3) << 1; \
hw_buttons |= (ev_buttons & 4) >> 2;
#define CONVERT_EV_TO_HW_DELTA(ev_buttons,hw_delta) \
hw_delta = ev_buttons & ~7; \
hw_delta |= (ev_buttons & 3) << 1; \
hw_delta |= (ev_buttons & 4) >> 2;
#define CONVERT_HW_TO_WV_BUTTONS(hw_buttons,ev_buttons) \
ev_buttons = hw_buttons & ~7; \
ev_buttons |= (hw_buttons & 6) >> 1; \
ev_buttons |= (hw_buttons & 1) << 2;
enum {
kIOHIDSetGlobalEventFlags = 0x00000001,
kIOHIDSetCursorPosition = 0x00000002,
kIOHIDSetRelativeCursorPosition = 0x00000004,
kIOHIDPostHIDManagerEvent = 0x00000008
};
#define kIOHIDPowerOnThresholdNS 1000000000ULL
#define kIOHIDRelativeTickleThresholdNS 50000000ULL
#define kIOHIDRelativeTickleThresholdPixel 20
static AbsoluteTime gIOHIDPowerOnThresoldAbsoluteTime;
static AbsoluteTime gIOHIDRelativeTickleThresholdAbsoluteTime;
enum {
kCachedMousePointingTabletEventDispFlag = 0x01,
kCachedMousePointingTabletEventPendFlag = 0x02,
kCachedMousePointingEventDispFlag = 0x04,
kCachedMouseTabletEventDispFlag = 0x08
};
typedef struct _CachedMouseEventStruct {
OSObject * service;
AbsoluteTime eventDeadline;
SInt32 lastButtons;
SInt32 accumX;
SInt32 accumY;
bool proximity;
UInt32 state;
UInt8 subType;
NXEventData tabletData;
NXEventData proximityData;
IOGPoint pointerFraction;
UInt8 lastPressure;
} CachedMouseEventStruct;
static SInt32 GetCachedMouseButtonStates(OSArray *events)
{
CachedMouseEventStruct * mouseEvent = 0;
OSData * data = 0;
SInt32 buttonState = 0;
UInt32 count = 0;
UInt32 i = 0;
if ( events )
{
count = events->getCount();
for ( i=0; i<count; i++ )
{
if ( (data = (OSData *)events->getObject(i)) &&
(mouseEvent = (CachedMouseEventStruct *)data->getBytesNoCopy()))
{
buttonState |= mouseEvent->lastButtons;
}
}
}
return buttonState;
}
static CachedMouseEventStruct * GetCachedMouseEventForService(OSArray *events, OSObject *service, UInt32 * index = 0)
{
CachedMouseEventStruct * mouseEvent = 0;
OSData * data = 0;
UInt32 count = 0;
UInt32 i = 0;
if ( events )
{
count = events->getCount();
for ( i=0; i<count; i++ )
{
if ( (data = (OSData *)events->getObject(i)) &&
(mouseEvent = (CachedMouseEventStruct *)data->getBytesNoCopy()) &&
(mouseEvent->service == service) )
{
if ( index ) *index = i;
return mouseEvent;
}
}
}
return NULL;
}
static void AppendNewCachedMouseEventForService(OSArray *events, OSObject *service)
{
CachedMouseEventStruct temp;
OSData * data;
bzero(&temp, sizeof(CachedMouseEventStruct));
temp.service = service;
data = OSData::withBytes(&temp, sizeof(CachedMouseEventStruct));
events->setObject(data);
data->release();
}
static void RemoveCachedMouseEventForService(OSArray *events, OSObject *service)
{
UInt32 index;
if ( events && GetCachedMouseEventForService(events, service, &index) )
{
events->removeObject(index);
}
}
#define kNXSystemInfoKey "NXSystemInfo"
static void AppendNewNXSystemInfoForService(OSArray *systemInfo, IOService *service)
{
OSDictionary * deviceInfo = NULL;
OSNumber * deviceID = NULL;
IOHIDevice * hiDevice = NULL;
OSObject * object = NULL;
if ( !systemInfo || !(hiDevice = OSDynamicCast(IOHIDevice, service)))
return;
deviceInfo = OSDictionary::withCapacity(4);
if ( !deviceInfo )
return;
if (deviceID = OSNumber::withNumber((UInt32) hiDevice, 64))
{
deviceInfo->setObject("serviceID", deviceID);
deviceID->release();
}
object = hiDevice->copyProperty(kIOHIDKindKey);
if ( object )
{
deviceInfo->setObject(kIOHIDKindKey, object);
object->release();
}
object = hiDevice->copyProperty(kIOHIDInterfaceIDKey);
if ( object )
{
deviceInfo->setObject(kIOHIDInterfaceIDKey, object);
object->release();
}
object = hiDevice->copyProperty(kIOHIDSubinterfaceIDKey);
if ( object )
{
deviceInfo->setObject(kIOHIDSubinterfaceIDKey, object);
object->release();
}
if ( hiDevice->metaCast("AppleADBKeyboard") || (hiDevice->getProvider() && hiDevice->getProvider()->metaCast("AppleEmbeddedKeyboard")) )
deviceInfo->setObject("built-in", kOSBooleanTrue);
OSDictionary * tempSystemInfo;
OSNumber * number;
if ( ((hiDevice->hidKind() == kHIKeyboardDevice) && (hiDevice->deviceType() != 0))&&
( (deviceInfo->getObject("built-in") == kOSBooleanTrue) ||
!((tempSystemInfo = OSDynamicCast(OSDictionary, systemInfo->getObject(0))) && (number = OSDynamicCast(OSNumber,tempSystemInfo->getObject(kIOHIDKindKey))) && (number->unsigned32BitValue() == kHIKeyboardDevice)) ||
((number = OSDynamicCast(OSNumber, hiDevice->getProperty(kIOHIDVendorIDKey))) && (number->unsigned32BitValue() == kIOUSBVendorIDAppleComputer) && (tempSystemInfo->getObject("built-in") != kOSBooleanTrue)) ) )
{
systemInfo->setObject(0, deviceInfo);
}
else
{
systemInfo->setObject(deviceInfo);
}
deviceInfo->release();
}
static void RemoveNXSystemInfoForService(OSArray *systemInfo, IOService *service)
{
OSDictionary * deviceInfo = NULL;
OSNumber * serviceID = NULL;
UInt32 i, count;
if ( !systemInfo || !OSDynamicCast(IOHIDevice, service))
return;
count = systemInfo->getCount();
for ( i=0; i<count; i++ )
{
if ( (deviceInfo = (OSDictionary *)systemInfo->getObject(i)) &&
(serviceID = (OSNumber *)deviceInfo->getObject("serviceID")) &&
(serviceID->unsigned32BitValue() == (UInt32)service) )
{
systemInfo->removeObject(i);
break;
}
}
}
static queue_head_t gKeyboardEQ;
static IOLock * gKeyboardEQLock = 0;
typedef IOReturn (*KeyboardEQAction)(IOHIDSystem * self, void *args);
typedef struct _KeyboardEQElement {
queue_chain_t link;
KeyboardEQAction action;
OSObject * sender;
AbsoluteTime ts;
union {
struct {
unsigned eventType;
unsigned flags;
unsigned key;
unsigned charCode;
unsigned charSet;
unsigned origCharCode;
unsigned origCharSet;
unsigned keyboardType;
bool repeat;
} keyboard;
struct {
unsigned eventType;
unsigned flags;
unsigned key;
unsigned flavor;
UInt64 guid;
bool repeat;
} keyboardSpecial;
struct {
unsigned flags;
} flagsChanged;
} event;
} KeyboardEQElement;
#define KEYBOARD_EQ_LOCK if (gKeyboardEQLock) IOLockLock(gKeyboardEQLock);
#define KEYBOARD_EQ_UNLOCK if (gKeyboardEQLock) IOLockUnlock(gKeyboardEQLock);
static UInt8 stickyKeysState = false;
static void notifyHIDevices(IOService *service, OSArray *hiDevices, UInt32 type)
{
IOHIKeyboard *keyboard;
if(!stickyKeysState || !hiDevices)
return;
switch ( type )
{
case kIOHIDSystem508MouseClickMessage:
case kIOHIDSystem508SpecialKeyDownMessage:
for(unsigned index=0; index<hiDevices->getCount(); index++)
{
if (keyboard = OSDynamicCast(IOHIKeyboard, hiDevices->getObject(index)))
keyboard->IOHIKeyboard::message(type, service);
}
break;
}
}
#define super IOService
OSDefineMetaClassAndStructors(IOHIDSystem, IOService);
IOHIDSystem * IOHIDSystem::instance()
{
return evInstance;
}
bool IOHIDSystem::init(OSDictionary * properties)
{
if (!super::init(properties)) return false;
evScreen = NULL;
timerES = 0;
eventConsumerES = 0;
keyboardEQES = 0;
cmdGate = 0;
workLoop = 0;
cachedEventFlags = 0;
consumedKeyCode = (unsigned)-1;
displayState = IOPMDeviceUsable;
AbsoluteTime_to_scalar(&lastEventTime) = 0;
AbsoluteTime_to_scalar(&lastUndimEvent) = 0;
AbsoluteTime_to_scalar(&stateChangeDeadline) = 0;
ioHIDevices = OSArray::withCapacity(2);
cachedButtonStates = OSArray::withCapacity(3);
AppendNewCachedMouseEventForService(cachedButtonStates, 0);
nanoseconds_to_absolutetime(kIOHIDPowerOnThresholdNS, &gIOHIDPowerOnThresoldAbsoluteTime);
nanoseconds_to_absolutetime(kIOHIDRelativeTickleThresholdNS, &gIOHIDRelativeTickleThresholdAbsoluteTime);
queue_init(&gKeyboardEQ);
gKeyboardEQLock = IOLockAlloc();
return true;
}
IOHIDSystem * IOHIDSystem::probe(IOService * provider,
SInt32 * score)
{
if (!super::probe(provider,score)) return 0;
return this;
}
IOWorkLoop * IOHIDSystem::getWorkLoop() const
{
return workLoop;
}
bool IOHIDSystem::start(IOService * provider)
{
bool iWasStarted = false;
do {
if (!super::start(provider)) break;
evInstance = this;
pointerLoc.x = INIT_CURSOR_X;
pointerLoc.y = INIT_CURSOR_Y;
pointerDelta.x = 0;
pointerDelta.y = 0;
evScreenSize = sizeof(EvScreen) * 32;
evScreen = (void *) IOMalloc(evScreenSize);
savedParameters = OSDictionary::withCapacity(4);
if (!evScreen ||
!savedParameters) break;
bzero(evScreen, evScreenSize);
firstWaitCursorFrame = EV_WAITCURSOR;
maxWaitCursorFrame = EV_MAXCURSOR;
createParameters();
workLoop = IOWorkLoop::workLoop();
cmdGate = IOCommandGate::commandGate
(this);
timerES = IOTimerEventSource::timerEventSource
(this, (IOTimerEventSource::Action) &_periodicEvents );
eventConsumerES = IOInterruptEventSource::interruptEventSource
(this, (IOInterruptEventSource::Action) &doKickEventConsumer);
keyboardEQES = IOInterruptEventSource::interruptEventSource
(this, (IOInterruptEventSource::Action) &doProcessKeyboardEQ);
vblES = IOTimerEventSource::timerEventSource
(this, &_vblEvent );
if (!workLoop || !cmdGate || !timerES || !eventConsumerES || !keyboardEQES || !vblES)
break;
if ((workLoop->addEventSource(cmdGate) != kIOReturnSuccess)
|| (workLoop->addEventSource(timerES) != kIOReturnSuccess)
|| (workLoop->addEventSource(vblES) != kIOReturnSuccess)
|| (workLoop->addEventSource(eventConsumerES) != kIOReturnSuccess)
|| (workLoop->addEventSource(keyboardEQES) != kIOReturnSuccess))
break;
publishNotify = addNotification(
gIOPublishNotification, serviceMatching("IOHIDevice"),
&IOHIDSystem::genericNotificationHandler,
this, (void *)&IOHIDSystem::handlePublishNotification );
if (!publishNotify) break;
eventPublishNotify = addNotification(
gIOPublishNotification, serviceMatching("IOHIDEventService"),
&IOHIDSystem::genericNotificationHandler,
this, (void *)&IOHIDSystem::handlePublishNotification );
if (!eventPublishNotify) break;
terminateNotify = addNotification(
gIOTerminatedNotification, serviceMatching("IOHIDevice"),
&IOHIDSystem::genericNotificationHandler,
this, (void *)&IOHIDSystem::handleTerminateNotification );
if (!terminateNotify) break;
eventTerminateNotify = addNotification(
gIOTerminatedNotification, serviceMatching("IOHIDEventService"),
&IOHIDSystem::genericNotificationHandler,
this, (void *)&IOHIDSystem::handleTerminateNotification );
if (!eventTerminateNotify) break;
rootDomain = (IOService *)getPMRootDomain();
if (rootDomain)
rootDomain->registerInterestedDriver(this);
if ( systemInfo = OSArray::withCapacity(4) )
{
setProperty(kNXSystemInfoKey, systemInfo);
systemInfo->release();
}
registerService();
addNotification( gIOPublishNotification, serviceMatching("IODisplayWrangler"),
&IOHIDSystem::genericNotificationHandler,
this, (void *)&IOHIDSystem::handlePublishNotification );
gSwitchNotification = addNotification(gIOPublishNotification, nameMatching("AppleKeyswitch"),
(IOServiceNotificationHandler)keySwitchNotificationHandler, this, 0);
iWasStarted = true;
registryName = getName();
} while(false);
if (!iWasStarted) evInstance = 0;
return iWasStarted;
}
IOReturn IOHIDSystem::powerStateDidChangeTo( IOPMPowerFlags theFlags, unsigned long, IOService * service)
{
if (service == displayManager)
{
displayState = theFlags;
}
else if (service == rootDomain)
{
if (theFlags & kIOPMPowerOn)
{
clock_get_uptime(&stateChangeDeadline);
ADD_ABSOLUTETIME(&stateChangeDeadline, &gIOHIDPowerOnThresoldAbsoluteTime);
}
}
return IOPMNoErr;
}
bool IOHIDSystem::genericNotificationHandler(
void * target,
void * handler,
IOService * newService )
{
IOHIDSystem * self = (IOHIDSystem *) target;
return self->cmdGate->runAction((IOCommandGate::Action)handler, newService);
}
bool IOHIDSystem::handlePublishNotification(
void * target,
IOService * newService )
{
IOHIDSystem * self = (IOHIDSystem *) target;
if( newService->metaCast("IODisplayWrangler")) {
if( !self->displayManager) {
self->displayManager = newService;
self->displayState = newService->registerInterestedDriver(self);
}
return true;
}
self->attach( newService );
if( OSDynamicCast(IOHIDevice, newService) ||
OSDynamicCast(IOHIDEventService, newService)) {
if (self->ioHIDevices) {
if (self->ioHIDevices->getNextIndexOfObject(newService, 0) == (unsigned)-1)
self->ioHIDevices->setObject(newService);
}
if (OSDynamicCast(IOHIPointing, newService))
{
AppendNewCachedMouseEventForService(self->cachedButtonStates, newService);
}
OSArray * newSystemInfo = OSArray::withArray(self->systemInfo);
if ( newSystemInfo )
{
AppendNewNXSystemInfoForService(newSystemInfo, newService);
self->setProperty(kNXSystemInfoKey, newSystemInfo);
newSystemInfo->release();
self->systemInfo = newSystemInfo;
}
if(self->eventsOpen || OSDynamicCast(IOHIKeyboard, newService))
self->registerEventSource( newService );
}
return true;
}
bool IOHIDSystem::handleTerminateNotification(
void * target,
IOService * service )
{
IOHIDSystem * self = (IOHIDSystem *) target;
int index;
if( self->eventsOpen && (
OSDynamicCast(IOHIDevice, service) ||
OSDynamicCast(IOHIDEventService, service)))
{
service->close(self);
}
self->detach(service);
if (self->ioHIDevices) {
if ((index = self->ioHIDevices->getNextIndexOfObject(service, 0)) != -1)
self->ioHIDevices->removeObject(index);
}
OSArray * newSystemInfo = OSArray::withArray(self->systemInfo);
if ( newSystemInfo )
{
RemoveNXSystemInfoForService(newSystemInfo, service);
self->setProperty(kNXSystemInfoKey, newSystemInfo);
newSystemInfo->release();
self->systemInfo = newSystemInfo;
}
if (OSDynamicCast(IOHIPointing, service))
{
AbsoluteTime ts;
clock_get_uptime(&ts);
self->relativePointerEvent(0, 0, 0, ts, service);
CachedMouseEventStruct *cachedMouseEvent;
if ((cachedMouseEvent = GetCachedMouseEventForService(self->cachedButtonStates, service)) &&
(cachedMouseEvent->proximityData.proximity.enterProximity))
{
cachedMouseEvent->proximityData.proximity.enterProximity = false;
cachedMouseEvent->state |= kCachedMousePointingTabletEventPendFlag;
self->proximityEvent(&(cachedMouseEvent->proximityData), ts, service);
cachedMouseEvent->state &= ~kCachedMousePointingTabletEventPendFlag;
IOGBounds bounds = {0, 0, 0, 0};
IOGPoint newLoc = {0, 0};
self->absolutePointerEvent(0, &newLoc, &bounds, false, 0, 0, ts, service);
}
RemoveCachedMouseEventForService(self->cachedButtonStates, service);
}
return true;
}
void IOHIDSystem::free()
{
if (evScreen) IOFree( (void *)evScreen, evScreenSize );
evScreen = (void *)0;
evScreenSize = 0;
if (timerES)
{
timerES->release();
timerES = 0;
}
if (eventConsumerES)
{
eventConsumerES->release();
eventConsumerES = 0;
}
if (keyboardEQES)
{
keyboardEQES->release();
keyboardEQES = 0;
}
if (cmdGate)
{
evClose();
cmdGate->release();
cmdGate = 0;
}
if (workLoop)
{
workLoop->release();
workLoop = 0;
}
if (publishNotify)
{
publishNotify->remove();
publishNotify = 0;
}
if (gSwitchNotification)
{
gSwitchNotification->remove();
gSwitchNotification = 0;
}
if (terminateNotify)
{
terminateNotify->remove();
terminateNotify = 0;
}
if (eventPublishNotify)
{
eventPublishNotify->remove();
eventPublishNotify = 0;
}
if (eventTerminateNotify)
{
eventTerminateNotify->remove();
eventTerminateNotify = 0;
}
if (ioHIDevices)
{
ioHIDevices->release();
ioHIDevices = 0;
}
if (cachedButtonStates)
{
cachedButtonStates->release();
cachedButtonStates = 0;
}
if ( gKeyboardEQLock )
{
IOLock * lock = gKeyboardEQLock;
IOLockLock(lock);
gKeyboardEQLock = 0;
IOLockUnlock(lock);
IOLockFree(lock);
}
if (_hidKeyboardDevice)
{
_hidKeyboardDevice->release();
_hidKeyboardDevice = 0;
}
if (_hidPointingDevice)
{
_hidPointingDevice->release();
_hidPointingDevice = 0;
}
super::free();
}
IOReturn IOHIDSystem::evOpen(void)
{
IOReturn r = kIOReturnSuccess;
if ( evOpenCalled == true )
{
r = kIOReturnBusy;
goto done;
}
evOpenCalled = true;
if (!evInitialized)
{
evInitialized = true;
}
done:
return r;
}
IOReturn IOHIDSystem::evClose(void){
return cmdGate->runAction((IOCommandGate::Action)doEvClose);
}
IOReturn IOHIDSystem::doEvClose(IOHIDSystem *self)
{
return self->evCloseGated();
}
IOReturn IOHIDSystem::evCloseGated(void)
{
if ( evOpenCalled == false )
return kIOReturnBadArgument;
evStateChanging = true;
if( cursorEnabled)
hideCursor();
cursorStarted = false;
cursorEnabled = false;
detachEventSources();
if ( evScreen != (void *)0 )
{
screens = 0;
lastShmemPtr = (void *)0;
}
setEventPort(MACH_PORT_NULL);
evStateChanging = false;
evOpenCalled = false;
eventsOpen = false;
return kIOReturnSuccess;
}
void IOHIDSystem::evDispatch(
EvCmd evcmd)
{
IOGPoint p;
if( !eventsOpen)
return;
for( int i = 0; i < screens; i++ ) {
EvScreen *esp = &((EvScreen*)evScreen)[i];
if ( esp->instance )
{
p.x = evg->cursorLoc.x; p.y = evg->cursorLoc.y;
bool onscreen = (0 != (cursorScreens & (1 << i)));
switch ( evcmd )
{
case EVMOVE:
if (onscreen)
esp->instance->moveCursor(&p, evg->frame);
break;
case EVSHOW:
if (onscreen)
esp->instance->showCursor(&p, evg->frame);
break;
case EVHIDE:
if (onscreen)
esp->instance->hideCursor();
break;
case EVLEVEL:
case EVNOP:
break;
}
}
}
}
void IOHIDSystem::evSpecialKeyMsg(unsigned key,
unsigned dir,
unsigned f,
unsigned l)
{
mach_port_t dst_port;
struct evioSpecialKeyMsg *msg;
static const struct evioSpecialKeyMsg init_msg =
{ { MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND), sizeof (struct evioSpecialKeyMsg), MACH_PORT_NULL, MACH_PORT_NULL, 0, EV_SPECIAL_KEY_MSG_ID },
0,
0,
0,
0
};
if ( (dst_port = specialKeyPort(key)) == MACH_PORT_NULL )
return;
msg = (struct evioSpecialKeyMsg *) IOMalloc(
sizeof (struct evioSpecialKeyMsg) );
if ( msg == NULL )
return;
bcopy( &init_msg, msg, sizeof (struct evioSpecialKeyMsg) );
msg->Head.msgh_remote_port = dst_port;
msg->key = key;
msg->direction = dir;
msg->flags = f;
msg->level = l;
cmdGate->runAction((IOCommandGate::Action)doSpecialKeyMsg,(void*)msg);
}
void IOHIDSystem::_resetMouseParameters(void)
{
if ( eventsOpen == false )
return;
OSDictionary *tempDict = OSDictionary::withCapacity(3);
UInt64 nano;
nanoseconds_to_absolutetime( EV_DCLICKTIME, &clickTimeThresh);
clickSpaceThresh.x = clickSpaceThresh.y = EV_DCLICKSPACE;
AbsoluteTime_to_scalar( &clickTime) = 0;
clickLoc.x = clickLoc.y = -EV_DCLICKSPACE;
clickState = 1;
if (tempDict) {
UInt32 tempClickSpace[] = {clickSpaceThresh.x, clickSpaceThresh.y};
makeInt32ArrayParamProperty( tempDict, kIOHIDClickSpaceKey,
tempClickSpace, sizeof(tempClickSpace)/sizeof(UInt32) );
nano = EV_DCLICKTIME;
makeNumberParamProperty( tempDict, kIOHIDClickTimeKey,
nano, 64 );
setParamProperties(tempDict);
tempDict->release();
}
}
int IOHIDSystem::registerScreen(IOGraphicsDevice * instance,
IOGBounds * bp)
{
EvScreen *esp;
OSNumber *num;
if( (false == eventsOpen) || (0 == bp) )
{
return -1;
}
if ( lastShmemPtr == (void *)0 )
lastShmemPtr = evs;
esp = &((EvScreen*)evScreen)[screens];
esp->instance = instance;
esp->bounds = bp;
if ( bp->minx < workSpace.minx )
workSpace.minx = bp->minx;
if ( bp->miny < workSpace.miny )
workSpace.miny = bp->miny;
if ( bp->maxx < workSpace.maxx )
workSpace.maxx = bp->maxx;
if ( esp->bounds->maxy < workSpace.maxy )
workSpace.maxy = bp->maxy;
if( (num = OSDynamicCast(OSNumber, instance->getProperty(kIOFBWaitCursorFramesKey)))
&& (num->unsigned32BitValue() > maxWaitCursorFrame)) {
firstWaitCursorFrame = 0;
maxWaitCursorFrame = num->unsigned32BitValue();
evg->lastFrame = maxWaitCursorFrame;
}
if( (num = OSDynamicCast(OSNumber, instance->getProperty(kIOFBWaitCursorPeriodKey))))
clock_interval_to_absolutetime_interval(num->unsigned32BitValue(), kNanosecondScale,
&waitFrameRate);
return(SCREENTOKEN + screens++);
}
void IOHIDSystem::unregisterScreen(int index) {
cmdGate->runAction((IOCommandGate::Action)doUnregisterScreen, (void *)index);
}
IOReturn IOHIDSystem::doUnregisterScreen (IOHIDSystem *self, void * arg0)
{
int index = (int) arg0;
self->unregisterScreenGated(index);
return kIOReturnSuccess;
}
void IOHIDSystem::unregisterScreenGated(int index)
{
index -= SCREENTOKEN;
if ( eventsOpen == false || index < 0 || index >= screens )
return;
hideCursor();
((EvScreen*)evScreen)[index].instance = 0;
cursorScreens &= ~(1 << index);
setCursorPosition((IOGPoint *)&evg->cursorLoc, true);
showCursor();
}
IOGBounds * IOHIDSystem::workspaceBounds()
{
return &workSpace;
}
IOReturn IOHIDSystem::registerEventQueue(IODataQueue * queue)
{
return cmdGate->runAction((IOCommandGate::Action)doRegisterEventQueue, (void *)queue);
}
IOReturn IOHIDSystem::doRegisterEventQueue (IOHIDSystem *self, void * arg0)
{
return self->registerEventQueueGated((IODataQueue *)arg0);
}
IOReturn IOHIDSystem::registerEventQueueGated(void * p1)
{
IODataQueue * queue = (IODataQueue *)p1;
if ( !queue )
return kIOReturnBadArgument;
if ( !dataQueueSet )
dataQueueSet = OSSet::withCapacity(4);
dataQueueSet->setObject(queue);
return kIOReturnSuccess;
}
IOReturn IOHIDSystem::unregisterEventQueue(IODataQueue * queue)
{
return cmdGate->runAction((IOCommandGate::Action)doUnregisterEventQueue, (void *)queue);
}
IOReturn IOHIDSystem::doUnregisterEventQueue (IOHIDSystem *self, void * arg0)
{
return self->unregisterEventQueueGated((IODataQueue *)arg0);
}
IOReturn IOHIDSystem::unregisterEventQueueGated(void * p1)
{
IODataQueue * queue = (IODataQueue *)p1;
if ( !queue )
return kIOReturnBadArgument;
if ( dataQueueSet )
dataQueueSet->removeObject(queue);
return kIOReturnSuccess;
}
IOReturn IOHIDSystem::createShmem(void* p1, void*, void*, void*, void*, void*)
{ return cmdGate->runAction((IOCommandGate::Action)doCreateShmem, p1);
}
IOReturn IOHIDSystem::doCreateShmem (IOHIDSystem *self, void * arg0)
{
return self->createShmemGated(arg0);
}
IOReturn IOHIDSystem::createShmemGated(void* p1)
{
int shmemVersion = (int)p1;
IOByteCount size;
if( shmemVersion != kIOHIDCurrentShmemVersion)
return kIOReturnUnsupported;
if( 0 == globalMemory) {
size = sizeof(EvOffsets) + sizeof(EvGlobals);
globalMemory = IOBufferMemoryDescriptor::withOptions( kIODirectionNone | kIOMemoryKernelUserShared, size );
if( !globalMemory)
return kIOReturnNoMemory;
shmem_addr = (vm_offset_t) globalMemory->getBytesNoCopy();
shmem_size = size;
}
initShmem();
return kIOReturnSuccess;
}
void IOHIDSystem::initShmem()
{
int i;
EvOffsets *eop;
eop = (EvOffsets *) shmem_addr;
bzero( (void*)shmem_addr, shmem_size);
eop->evGlobalsOffset = sizeof(EvOffsets);
eop->evShmemOffset = eop->evGlobalsOffset + sizeof(EvGlobals);
evg = (EvGlobals *)((char *)shmem_addr + eop->evGlobalsOffset);
evs = (void *)((char *)shmem_addr + eop->evShmemOffset);
evg->version = kIOHIDCurrentShmemVersion;
evg->structSize = sizeof( EvGlobals);
evg->waitCursorEnabled = TRUE;
evg->globalWaitCursorEnabled = TRUE;
evg->lastFrame = maxWaitCursorFrame;
evg->waitThreshold = (12 * EV_TICKS_PER_SEC) / 10;
clock_interval_to_absolutetime_interval(DefaultWCFrameRate, kNanosecondScale, &waitFrameRate);
clock_interval_to_absolutetime_interval(DefaultWCSustain, kNanosecondScale, &waitSustain);
AbsoluteTime_to_scalar(&waitSusTime) = 0;
AbsoluteTime_to_scalar(&waitFrameTime) = 0;
EV_TICK_TO_NS(10,&periodicEventDelta);
evg->buttons = 0;
evg->eNum = INITEVENTNUM;
evg->eventFlags = 0;
AbsoluteTime ts;
unsigned tick;
clock_get_uptime( &ts);
tick = EV_NS_TO_TICK(&ts);
if ( tick == 0 )
tick = 1; evg->VertRetraceClock = tick;
evg->cursorLoc.x = pointerLoc.x;
evg->cursorLoc.y = pointerLoc.y;
evg->dontCoalesce = 0;
evg->dontWantCoalesce = 0;
evg->wantPressure = 0;
evg->wantPrecision = 0;
evg->mouseRectValid = 0;
evg->movedMask = 0;
ev_init_lock( &evg->cursorSema );
ev_init_lock( &evg->waitCursorSema );
lleqSize = LLEQSIZE;
for (i=lleqSize; --i != -1; ) {
evg->lleq[i].event.type = 0;
AbsoluteTime_to_scalar(&evg->lleq[i].event.time) = 0;
evg->lleq[i].event.flags = 0;
ev_init_lock(&evg->lleq[i].sema);
evg->lleq[i].next = i+1;
}
evg->LLELast = 0;
evg->lleq[lleqSize-1].next = 0;
evg->LLEHead = evg->lleq[evg->LLELast].next;
evg->LLETail = evg->lleq[evg->LLELast].next;
eventsOpen = true;
}
void IOHIDSystem::setEventPort(mach_port_t port)
{
static struct _eventMsg init_msg = { {
MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0),
sizeof (struct _eventMsg),
MACH_PORT_NULL,
MACH_PORT_NULL,
0,
0
} };
if ( eventMsg == NULL )
eventMsg = IOMalloc( sizeof (struct _eventMsg) );
eventPort = port;
*((struct _eventMsg *)eventMsg) = init_msg;
((struct _eventMsg *)eventMsg)->h.msgh_remote_port = port;
if (EventsInQueue())
kickEventConsumer();
}
IOReturn IOHIDSystem::setSpecialKeyPort(
int special_key,
mach_port_t key_port)
{
if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS )
_specialKeyPort[special_key] = key_port;
return kIOReturnSuccess;
}
mach_port_t IOHIDSystem::specialKeyPort(int special_key)
{
if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS )
return _specialKeyPort[special_key];
return MACH_PORT_NULL;
}
void IOHIDSystem::setStackShotPort(mach_port_t port)
{
stackShotPort = port;
static struct _eventMsg init_msg = { {
MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0),
sizeof (struct _eventMsg),
MACH_PORT_NULL,
MACH_PORT_NULL,
0,
0
} };
if ( stackShotMsg ) {
IOFree(stackShotMsg, sizeof (struct _eventMsg));
stackShotMsg = NULL;
}
if ( stackShotPort ) {
if ( !(stackShotMsg = IOMalloc( sizeof(struct _eventMsg))) )
return;
*((struct _eventMsg *)stackShotMsg) = init_msg;
((struct _eventMsg *)stackShotMsg)->h.msgh_remote_port = stackShotPort;
}
}
UInt32 IOHIDSystem::eventFlags()
{
return evg ? evg->eventFlags : 0;
}
void IOHIDSystem::dispatchEvent(IOHIDEvent *event, IOOptionBits options)
{
if ( !event || !dataQueueSet)
return;
OSCollectionIterator * iterator = OSCollectionIterator::withCollection(dataQueueSet);
IOHIDEventServiceQueue * dataQueue = NULL;
if ( !iterator )
return;
while ((dataQueue = OSDynamicCast(IOHIDEventServiceQueue, iterator->getNextObject()))) {
dataQueue->enqueueEvent(event);
}
iterator->release();
}
static inline int myAbs(int a) { return(a > 0 ? a : -a); }
short IOHIDSystem::getUniqueEventNum()
{
while (++evg->eNum == NULLEVENTNUM)
;
return(evg->eNum);
}
void IOHIDSystem::postEvent(int what,
IOGPoint * location,
AbsoluteTime ts,
NXEventData * myData,
OSObject * sender,
UInt32 extPID,
bool processKEQ)
{
if ( processKEQ )
processKeyboardEQ(this, &ts);
NXEQElement * theHead = (NXEQElement *) &evg->lleq[evg->LLEHead];
NXEQElement * theLast = (NXEQElement *) &evg->lleq[evg->LLELast];
NXEQElement * theTail = (NXEQElement *) &evg->lleq[evg->LLETail];
int wereEvents;
unsigned theClock = EV_NS_TO_TICK(&ts);
if(CMP_ABSOLUTETIME(&ts, &lastEventTime) < 0)
{
ts = lastEventTime;
}
lastEventTime = ts;
IOHIDEvent * event = IOHIDEvent::withEventData(ts, what, myData);
if ( event ) {
dispatchEvent(event);
event->release();
}
if (EventCodeMask(what) & NX_UNDIMMASK)
{
lastUndimEvent = ts;
}
if ( theClock > (unsigned)evg->VertRetraceClock && theClock < (unsigned)(evg->VertRetraceClock + (20 * EV_TICK_TIME)) )
evg->VertRetraceClock = theClock;
wereEvents = EventsInQueue();
xpr_ev_post("postEvent: what %d, X %d Y %d Q %d, needKick %d\n", what,location->x,location->y, EventsInQueue(), needToKickEventConsumer);
if ((!evg->dontCoalesce)
&& (theHead != theTail)
&& (theLast->event.type == what)
&& (EventCodeMask(what) & COALESCEEVENTMASK)
&& ev_try_lock(&theLast->sema)) {
theLast->event.location.x = location->x;
theLast->event.location.y = location->y;
absolutetime_to_nanoseconds(ts, &theLast->event.time);
if (myData != NULL)
theLast->event.data = *myData;
ev_unlock(&theLast->sema);
} else if (theTail->next != evg->LLEHead) {
theTail->event.type = what;
theTail->event.service_id = (UInt32)sender;
theTail->event.ext_pid = extPID;
theTail->event.location.x = location->x;
theTail->event.location.y = location->y;
theTail->event.flags = evg->eventFlags;
absolutetime_to_nanoseconds(ts, &theLast->event.time);
theTail->event.window = 0;
if (myData != NULL)
theTail->event.data = *myData;
switch(what) {
case NX_LMOUSEDOWN:
theTail->event.data.mouse.eventNum =
leftENum = getUniqueEventNum();
break;
case NX_RMOUSEDOWN:
theTail->event.data.mouse.eventNum =
rightENum = getUniqueEventNum();
break;
case NX_LMOUSEUP:
theTail->event.data.mouse.eventNum = leftENum;
leftENum = NULLEVENTNUM;
notifyHIDevices(this, ioHIDevices, kIOHIDSystem508MouseClickMessage);
break;
case NX_RMOUSEUP:
theTail->event.data.mouse.eventNum = rightENum;
rightENum = NULLEVENTNUM;
notifyHIDevices(this, ioHIDevices, kIOHIDSystem508MouseClickMessage);
break;
}
if (EventCodeMask(what) & PRESSUREEVENTMASK)
{
if (!((EventCodeMask(what) & MOUSEEVENTMASK) || (EventCodeMask(what) & MOVEDEVENTMASK)))
IOLog("%s: postEvent unknown pressure event, cannot fill pressure.\n", registryName);
}
if (EventCodeMask(what) & MOUSEEVENTMASK) {
AbsoluteTime delta = ts;
SUB_ABSOLUTETIME( &delta, &clickTime);
if ((CMP_ABSOLUTETIME(&delta, &clickTimeThresh) <= 0)
&& (myAbs(location->x - clickLoc.x) <= clickSpaceThresh.x)
&& (myAbs(location->y - clickLoc.y) <= clickSpaceThresh.y)) {
if ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) {
clickTime = ts;
theTail->event.data.mouse.click = ++clickState;
} else {
theTail->event.data.mouse.click = clickState;
}
} else if ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) {
clickLoc = *location;
clickTime = ts;
clickState = 1;
theTail->event.data.mouse.click = clickState;
} else
theTail->event.data.mouse.click = 0;
}
#if PMON
pmon_log_event(PMON_SOURCE_EV,
KP_EV_POST_EVENT,
what,
evg->eventFlags,
theClock);
#endif
evg->LLETail = theTail->next;
evg->LLELast = theLast->next;
if ( ! wereEvents ) kickEventConsumer();
}
else
{
IOLog("%s: postEvent LLEventQueue overflow.\n", registryName);
kickEventConsumer();
#if PMON
pmon_log_event( PMON_SOURCE_EV,
KP_EV_QUEUE_FULL,
what,
evg->eventFlags,
theClock);
#endif
}
}
void IOHIDSystem::kickEventConsumer()
{
xpr_ev_post("kickEventConsumer (need == %d)\n",
needToKickEventConsumer,2,3,4,5);
if ( needToKickEventConsumer == true )
return;
needToKickEventConsumer = true;
eventConsumerES->interruptOccurred(0, 0, 0);
}
void IOHIDSystem::sendStackShotMessage()
{
kern_return_t r;
mach_msg_header_t *msgh;
xpr_ev_post("sendStackShotMessage\n", 1,2,3,4,5);
msgh = (mach_msg_header_t *)stackShotMsg;
if( msgh) {
r = mach_msg_send_from_kernel( msgh, msgh->msgh_size);
switch ( r ) {
case MACH_SEND_TIMED_OUT:
case MACH_MSG_SUCCESS:
break;
default:
IOLog("%s: sendStackShotMessage msg_send returned %d\n", registryName, r);
break;
}
}
}
void IOHIDSystem::doSpecialKeyMsg(IOHIDSystem * self,
struct evioSpecialKeyMsg *msg)
{
kern_return_t r;
xpr_ev_post("doSpecialKeyMsg 0x%x\n", msg,2,3,4,5);
r = mach_msg_send_from_kernel( &msg->Head, msg->Head.msgh_size);
xpr_ev_post("doSpecialKeyMsg: msg_send() == %d\n",r,2,3,4,5);
if ( r != MACH_MSG_SUCCESS )
{
IOLog("%s: doSpecialKeyMsg msg_send returned %d\n",
self->registryName, r);
}
if ( r == MACH_SEND_INVALID_DEST )
{
self->setSpecialKeyPort(
msg->key,
MACH_PORT_NULL);
}
IOFree( (void *)msg, sizeof (struct evioSpecialKeyMsg) );
}
void IOHIDSystem::doKickEventConsumer(IOHIDSystem * self)
{
kern_return_t r;
mach_msg_header_t *msgh;
self->needToKickEventConsumer = false;
if ( self->eventPort == MACH_PORT_NULL )
return;
xpr_ev_post("doKickEventConsumer\n", 1,2,3,4,5);
msgh = (mach_msg_header_t *)self->eventMsg;
if( msgh) {
r = mach_msg_send_from_kernel( msgh, msgh->msgh_size);
switch ( r )
{
case MACH_SEND_TIMED_OUT:
case MACH_MSG_SUCCESS:
break;
default:
IOLog("%s: doKickEventConsumer msg_send returned %d\n",
self->registryName, r);
break;
}
}
}
void IOHIDSystem::scheduleNextPeriodicEvent()
{
if (CMP_ABSOLUTETIME( &waitFrameTime, &thisPeriodicRun) > 0)
{
AbsoluteTime time_for_next_run;
clock_get_uptime(&time_for_next_run);
ADD_ABSOLUTETIME( &time_for_next_run, &periodicEventDelta);
if (CMP_ABSOLUTETIME( &waitFrameTime, &time_for_next_run) < 0) {
timerES->wakeAtTime(waitFrameTime);
return;
}
}
timerES->setTimeout(periodicEventDelta);
}
void IOHIDSystem::_periodicEvents(IOHIDSystem * self,
IOTimerEventSource *timer)
{
self->periodicEvents(timer);
}
void IOHIDSystem::periodicEvents(IOTimerEventSource * )
{
unsigned int tick;
if ( eventsOpen == false )
return;
clock_get_uptime(&thisPeriodicRun);
tick = EV_NS_TO_TICK(&thisPeriodicRun);
if ( tick == 0 )
tick = 1;
evg->VertRetraceClock = tick;
if ( needSetCursorPosition == true )
_setCursorPosition(&pointerLoc, false);
if ( ev_try_lock(&evg->waitCursorSema) )
{
if ( ev_try_lock(&evg->cursorSema) )
{
if ( (evg->AALastEventSent != evg->AALastEventConsumed)
&& ((evg->VertRetraceClock - evg->AALastEventSent >
evg->waitThreshold)))
evg->ctxtTimedOut = TRUE;
if (evg->waitCursorEnabled && evg->globalWaitCursorEnabled &&
evg->ctxtTimedOut)
{
if (!evg->waitCursorUp)
showWaitCursor();
} else
{
if (evg->waitCursorUp &&
CMP_ABSOLUTETIME(&waitSusTime, &thisPeriodicRun) <= 0)
hideWaitCursor();
}
if (evg->waitCursorUp &&
CMP_ABSOLUTETIME(&waitFrameTime, &thisPeriodicRun) <= 0)
animateWaitCursor();
ev_unlock(&evg->cursorSema);
}
ev_unlock(&evg->waitCursorSema);
}
scheduleNextPeriodicEvent();
return;
}
bool IOHIDSystem::resetCursor()
{
volatile IOGPoint * p;
UInt32 newScreens = 0;
SInt32 candidate = 0;
SInt32 pinScreen = -1L;
p = &evg->cursorLoc;
EvScreen *screen = (EvScreen *)evScreen;
for (int i = 0; i < screens; i++ ) {
if (!screen[i].instance)
continue;
if ((screen[i].bounds->maxx - screen[i].bounds->minx) < 128)
continue;
candidate = i;
if ((screen[i].instance) && PtInRect(p, screen[i].bounds)) {
pinScreen = i;
newScreens |= (1 << i);
}
}
if (newScreens == 0)
pinScreen = candidate;
if (!cursorPinned) {
cursorPin = *(((EvScreen*)evScreen)[pinScreen].bounds);
cursorPin.maxx--;
cursorPin.maxy--;
cursorPinScreen = pinScreen;
}
if (newScreens == 0) {
p->x = (p->x < cursorPin.minx) ?
cursorPin.minx : ((p->x > cursorPin.maxx) ?
cursorPin.maxx : p->x);
p->y = (p->y < cursorPin.miny) ?
cursorPin.miny : ((p->y > cursorPin.maxy) ?
cursorPin.maxy : p->y);
for (int i = 0; i < screens; i++ ) {
if ((screen[i].instance) && PtInRect(p, screen[i].bounds))
newScreens |= (1 << i);
}
}
cursorScreens = newScreens;
pointerDelta.x += (evg->cursorLoc.x - pointerLoc.x);
pointerDelta.y += (evg->cursorLoc.y - pointerLoc.y);
pointerLoc.x = evg->cursorLoc.x;
pointerLoc.y = evg->cursorLoc.y;
postDeltaX = postDeltaY = accumDX = accumDY = 0;
vblES->cancelTimeout();
return( true );
}
bool IOHIDSystem::startCursor()
{
bool ok;
if (0 == screens) return( false );
cursorPinned = false;
resetCursor();
showCursor();
ok = (kIOReturnSuccess ==
cmdGate->runAction((IOCommandGate::Action)_periodicEvents, timerES));
cursorStarted = ok;
return( ok );
}
void IOHIDSystem::showWaitCursor()
{
xpr_ev_cursor("showWaitCursor\n",1,2,3,4,5);
evg->waitCursorUp = true;
hideCursor();
evg->frame = EV_WAITCURSOR;
showCursor();
waitSusTime = waitFrameTime = thisPeriodicRun;
ADD_ABSOLUTETIME( &waitFrameTime, &waitFrameRate);
ADD_ABSOLUTETIME( &waitSusTime, &waitSustain);
}
void IOHIDSystem::hideWaitCursor()
{
xpr_ev_cursor("hideWaitCursor\n",1,2,3,4,5);
evg->waitCursorUp = false;
hideCursor();
evg->frame = EV_STD_CURSOR;
showCursor();
AbsoluteTime_to_scalar(&waitFrameTime) = 0;
AbsoluteTime_to_scalar(&waitSusTime ) = 0;
}
void IOHIDSystem::animateWaitCursor()
{
xpr_ev_cursor("animateWaitCursor\n",1,2,3,4,5);
changeCursor(evg->frame + 1);
waitFrameTime = thisPeriodicRun;
ADD_ABSOLUTETIME( &waitFrameTime, &waitFrameRate);
}
void IOHIDSystem::changeCursor(int frame)
{
evg->frame =
((frame > (int)maxWaitCursorFrame) || (frame > evg->lastFrame)) ? firstWaitCursorFrame : frame;
xpr_ev_cursor("changeCursor %d\n",evg->frame,2,3,4,5);
moveCursor();
}
int IOHIDSystem::pointToScreen(IOGPoint * p)
{
int i;
EvScreen *screen = (EvScreen *)evScreen;
for (i=screens; --i != -1; ) {
if (screen[i].instance != 0
&& (p->x >= screen[i].bounds->minx)
&& (p->x < screen[i].bounds->maxx)
&& (p->y >= screen[i].bounds->miny)
&& (p->y < screen[i].bounds->maxy))
return i;
}
return(-1);
}
inline void IOHIDSystem::showCursor()
{
evDispatch( EVSHOW);
}
inline void IOHIDSystem::hideCursor()
{
evDispatch( EVHIDE);
}
inline void IOHIDSystem::moveCursor()
{
evDispatch( EVMOVE);
}
void IOHIDSystem::attachDefaultEventSources()
{
IOService * source;
OSIterator * sources;
sources = getProviderIterator();
if (!sources) return;
while( (source = (IOService *)sources->getNextObject())) {
if ((OSDynamicCast(IOHIDevice, source) && !OSDynamicCast(IOHIKeyboard, source))
|| OSDynamicCast(IOHIDEventService, source)) {
registerEventSource(source);
}
}
sources->release();
}
void IOHIDSystem::detachEventSources()
{
OSIterator * iter;
IOService * srcInstance;
iter = getOpenProviderIterator();
if( iter) {
while( (srcInstance = (IOService *) iter->getNextObject())) {
if ( ! OSDynamicCast(IOHIKeyboard, srcInstance) ) {
#ifdef DEBUG
kprintf("detachEventSource:%s\n", srcInstance->getName());
#endif
srcInstance->close(this);
}
}
iter->release();
}
}
bool IOHIDSystem::registerEventSource(IOService * source)
{
bool success = false;
#ifdef DEBUG
kprintf("registerEventSource:%s\n", source->getName());
#endif
if ( OSDynamicCast(IOHIKeyboard, source) ) {
success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize,0,
(KeyboardEventCallback) _keyboardEvent,
(KeyboardSpecialEventCallback) _keyboardSpecialEvent,
(UpdateEventFlagsCallback) _updateEventFlags);
} else if ( OSDynamicCast(IOHIPointing, source) ) {
if ( OSDynamicCast(IOHITablet, source) ) {
success = ((IOHITablet*)source)->open(this, kIOServiceSeize,0,
(RelativePointerEventCallback) _relativePointerEvent,
(AbsolutePointerEventCallback) _absolutePointerEvent,
(ScrollWheelEventCallback) _scrollWheelEvent,
(TabletEventCallback) _tabletEvent,
(ProximityEventCallback) _proximityEvent);
} else {
success = ((IOHIPointing*)source)->open(this, kIOServiceSeize,0,
(RelativePointerEventCallback) _relativePointerEvent,
(AbsolutePointerEventCallback) _absolutePointerEvent,
(ScrollWheelEventCallback) _scrollWheelEvent);
}
} else {
success = source->open(this, kIOServiceSeize, 0);
}
if ( success )
{
OSDictionary * newParams = OSDictionary::withDictionary( savedParameters );
if( newParams) {
if ( OSDynamicCast(IOHIDevice, source) )
((IOHIDevice *)source)->setParamProperties( newParams );
else if ( OSDynamicCast(IOHIDEventService, source) )
((IOHIDEventService *)source)->setSystemProperties( newParams );
setProperty( kIOHIDParametersKey, newParams );
newParams->release();
savedParameters = newParams;
}
}
else
IOLog("%s: Seize of %s failed.\n", registryName, source->getName());
return success;
}
IOReturn IOHIDSystem::message(UInt32 type, IOService * provider,
void * argument)
{
IOReturn status = kIOReturnSuccess;
switch (type)
{
case kIOMessageServiceIsTerminated:
#ifdef DEBUG
kprintf("detachEventSource:%s\n", provider->getName());
#endif
provider->close( this );
case kIOMessageServiceWasClosed:
break;
default:
status = super::message(type, provider, argument);
break;
}
return status;
}
void IOHIDSystem::scaleLocationToCurrentScreen(IOGPoint *location, IOGBounds *bounds)
{
IOHIDSystem * hidsystem = instance();
IOGPoint fraction;
if ( hidsystem ) hidsystem->_scaleLocationToCurrentScreen(location, &fraction, bounds);
}
void IOHIDSystem::_scaleLocationToCurrentScreen(IOGPoint *location, IOGPoint *fraction, IOGBounds *bounds)
{
IOFixed result, locationScale, deviceScale, screenScale;
locationScale = (location->x - bounds->minx) << 16;
screenScale = (cursorPin.maxx - cursorPin.minx + 1) << 16;
deviceScale = (bounds->maxx - bounds->minx) << 16;
result = (deviceScale) ? IOFixedDivide ( locationScale, deviceScale ) : 0;
result = IOFixedMultiply ( result, screenScale );
location->x = (result >> 16);
fraction->x = result;
locationScale = (location->y - bounds->miny) << 16;
screenScale = (cursorPin.maxy - cursorPin.miny + 1) << 16;
deviceScale = (bounds->maxy - bounds->miny) << 16;
result = (deviceScale) ? IOFixedDivide ( locationScale, deviceScale ) : 0;
result = IOFixedMultiply ( result, screenScale );
location->y = (result >> 16);
fraction->y = result;
return;
}
void IOHIDSystem::_relativePointerEvent(IOHIDSystem * self,
int buttons,
int dx,
int dy,
AbsoluteTime ts,
OSObject * sender,
void * refcon)
{
self->relativePointerEvent(buttons, dx, dy, ts, sender);
}
void IOHIDSystem::relativePointerEvent(int buttons,
int dx,
int dy,
AbsoluteTime ts)
{
relativePointerEvent(buttons, dx, dy, ts, 0);
}
void IOHIDSystem::relativePointerEvent(int buttons,
int dx,
int dy,
AbsoluteTime ts,
OSObject * sender)
{
IOHIDCmdGateActionArgs args;
args.arg0 = &buttons;
args.arg1 = &dx;
args.arg2 = &dy;
args.arg3 = &ts;
args.arg4 = sender;
cmdGate->runAction((IOCommandGate::Action)doRelativePointerEvent, &args);
}
IOReturn IOHIDSystem::doRelativePointerEvent(IOHIDSystem *self, void * args)
{
int buttons = *(int *)((IOHIDCmdGateActionArgs *)args)->arg0;
int dx = *(int *)((IOHIDCmdGateActionArgs *)args)->arg1;
int dy = *(int *)((IOHIDCmdGateActionArgs *)args)->arg2;
AbsoluteTime ts = *(AbsoluteTime *)((IOHIDCmdGateActionArgs *)args)->arg3;
OSObject * sender = (OSObject *)((IOHIDCmdGateActionArgs *)args)->arg4;
self->relativePointerEventGated(buttons, dx, dy, ts, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::relativePointerEventGated(int buttons, int dx, int dy, AbsoluteTime ts, OSObject * sender)
{
UnsignedWide nextVBL, vblDeltaTime, eventDeltaTime, moveDeltaTime;
bool haveVBL;
if ( eventsOpen == false )
return;
if (ShouldConsumeHIDEvent(ts, stateChangeDeadline))
return;
if ( !(displayState & IOPMDeviceUsable) ) { if ( buttons ) {
return;
}
TICKLE_DISPLAY;
return;
}
CachedMouseEventStruct *cachedMouseEvent;
if (cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, sender)) {
do {
if ((cachedMouseEvent->lastButtons == buttons) && (displayState == 0)) {
if (CMP_ABSOLUTETIME(&ts, &(cachedMouseEvent->eventDeadline)) > 0) {
cachedMouseEvent->eventDeadline = ts;
ADD_ABSOLUTETIME(&(cachedMouseEvent->eventDeadline), &gIOHIDRelativeTickleThresholdAbsoluteTime);
cachedMouseEvent->accumX = 0;
cachedMouseEvent->accumY = 0;
}
cachedMouseEvent->accumX += dx;
cachedMouseEvent->accumY += dy;
if ((abs(cachedMouseEvent->accumX) < kIOHIDRelativeTickleThresholdPixel) &&
(abs(cachedMouseEvent->accumY) < kIOHIDRelativeTickleThresholdPixel)) {
break;
}
}
TICKLE_DISPLAY;
cachedMouseEvent->lastButtons = buttons;
cachedMouseEvent->eventDeadline = ts;
if ( (buttons & EV_LB) != (evg->buttons & EV_LB) ) {
cachedMouseEvent->lastPressure = ( buttons & EV_LB ) ? MAXPRESSURE : MINPRESSURE;
}
}
while (false);
}
_setButtonState(buttons, ts, sender);
int oldDx = dx;
int oldDy = dy;
if ( dx || dy ) {
eventDeltaTime = *((UnsignedWide *)(&ts));
SUB_ABSOLUTETIME( &eventDeltaTime, &lastRelativeEventTime );
lastRelativeEventTime = ts;
IOGraphicsDevice * instance = ((EvScreen*)evScreen)[cursorPinScreen].instance;
if ( instance) {
instance->getVBLTime( (AbsoluteTime *)&nextVBL, (AbsoluteTime *)&vblDeltaTime );
}
else
nextVBL.hi = nextVBL.lo = vblDeltaTime.hi = vblDeltaTime.lo = 0;
if ( dx && ((dx ^ accumDX) < 0))
accumDX = 0;
if ( dy && ((dy ^ accumDY) < 0))
accumDY = 0;
KERNEL_DEBUG(0x0c000060 | DBG_FUNC_NONE,
nextVBL.hi, nextVBL.lo, lastRelativeEventTime.hi, lastRelativeEventTime.lo, 0);
haveVBL = (nextVBL.lo || nextVBL.hi);
if (haveVBL && (postDeltaX || postDeltaY)) {
accumDX += dx;
accumDY += dy;
}
else {
SInt32 num = 0, div = 0;
dx += accumDX;
dy += accumDY;
moveDeltaTime = *((UnsignedWide *)(&ts));
SUB_ABSOLUTETIME( &moveDeltaTime, &lastRelativeMoveTime );
lastRelativeMoveTime = ts;
if ( (eventDeltaTime.lo < vblDeltaTime.lo) && (0 == eventDeltaTime.hi)
&& vblDeltaTime.lo && moveDeltaTime.lo) {
num = vblDeltaTime.lo;
div = moveDeltaTime.lo;
dx = ((SInt64)num * dx) / div;
dy = ((SInt64)num * dy) / div;
}
KERNEL_DEBUG(0x0c000000 | DBG_FUNC_NONE, dx, dy, num, div, 0);
accumDX = accumDY = 0;
if ( dx || dy ) {
if (((oldDx < 0) && (dx > 0)) || ((oldDx > 0) && (dx < 0))) {
IOLog("IOHIDSystem::relativePointerEventGated: Unwanted Direction Change X: oldDx=%d dx=%d\n", oldDx, dx);
}
if (((oldDy < 0) && (dy > 0)) || ((oldDy > 0) && (dy < 0))) {
IOLog("IOHIDSystem::relativePointerEventGated: Unwanted Direction Change Y: oldDy=%d dy=%d\n", oldDy, dy);
}
if ( haveVBL ) {
static UInt64 resonableVBL = 0;
static UInt32 logLimit = 0;
if (!resonableVBL)
nanoseconds_to_absolutetime(20000000, (AbsoluteTime*)(&resonableVBL));
if (AbsoluteTime_to_scalar(&vblDeltaTime) > resonableVBL) {
if (0 == logLimit++ % 100)
IOLog("IOHIDSystem::relativePointerEventGated: Capping VBL time to %lld (was %lld)\n",
resonableVBL, AbsoluteTime_to_scalar(&vblDeltaTime));
AbsoluteTime_to_scalar(&vblDeltaTime) = resonableVBL;
}
postDeltaX = dx;
postDeltaY = dy;
vblDeltaTime.lo += (vblDeltaTime.lo >> 4);
ADD_ABSOLUTETIME(&nextVBL, &vblDeltaTime);
vblES->wakeAtTime(nextVBL);
lastSender = sender;
}
else {
pointerLoc.x += dx;
pointerLoc.y += dy;
pointerDelta.x += dx;
pointerDelta.y += dy;
_setCursorPosition(&pointerLoc, false, false, sender);
}
}
}
}
}
void IOHIDSystem::vblEvent(void)
{
if (postDeltaX || postDeltaY) {
pointerLoc.x += postDeltaX;
pointerLoc.y += postDeltaY;
pointerDelta.x += postDeltaX;
pointerDelta.y += postDeltaY;
_setCursorPosition(&pointerLoc, false, false, lastSender);
postDeltaX = postDeltaY = 0;
}
}
void IOHIDSystem::_vblEvent(OSObject *self, IOTimerEventSource *sender)
{
((IOHIDSystem *)self)->vblEvent();
}
void IOHIDSystem::_absolutePointerEvent(
IOHIDSystem * self,
int buttons,
IOGPoint * newLoc,
IOGBounds * bounds,
bool proximity,
int pressure,
int stylusAngle,
AbsoluteTime ts,
OSObject * sender,
void * refcon)
{
self->absolutePointerEvent(buttons, newLoc, bounds, proximity,
pressure, stylusAngle, ts, sender);
}
void IOHIDSystem::absolutePointerEvent(
int buttons,
IOGPoint * newLoc,
IOGBounds * bounds,
bool proximity,
int pressure,
int stylusAngle,
AbsoluteTime ts)
{
absolutePointerEvent(buttons, newLoc, bounds, proximity,
pressure, stylusAngle, ts, 0);
}
void IOHIDSystem::absolutePointerEvent(
int buttons,
IOGPoint * newLoc,
IOGBounds * bounds,
bool proximity,
int pressure,
int stylusAngle,
AbsoluteTime ts,
OSObject * sender)
{
IOHIDCmdGateActionArgs args;
args.arg0 = &buttons;
args.arg1 = (void *)newLoc;
args.arg2 = (void *)bounds;
args.arg3 = &proximity;
args.arg4 = &pressure;
args.arg5 = &stylusAngle;
args.arg6 = &ts;
args.arg7 = sender;
cmdGate->runAction((IOCommandGate::Action)doAbsolutePointerEvent, &args);
}
IOReturn IOHIDSystem::doAbsolutePointerEvent(IOHIDSystem *self, void * args)
{
int buttons = *(int *) ((IOHIDCmdGateActionArgs *)args)->arg0;
IOGPoint * newLoc = (IOGPoint *) ((IOHIDCmdGateActionArgs *)args)->arg1;
IOGBounds * bounds = (IOGBounds *) ((IOHIDCmdGateActionArgs *)args)->arg2;
bool proximity = *(bool *) ((IOHIDCmdGateActionArgs *)args)->arg3;
int pressure = *(int *) ((IOHIDCmdGateActionArgs *)args)->arg4;
int stylusAngle = *(int *) ((IOHIDCmdGateActionArgs *)args)->arg5;
AbsoluteTime ts = *(AbsoluteTime *) ((IOHIDCmdGateActionArgs *)args)->arg6;
OSObject * sender = (OSObject *)((IOHIDCmdGateActionArgs *)args)->arg7;
self->absolutePointerEventGated(buttons, newLoc, bounds, proximity, pressure, stylusAngle, ts, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::absolutePointerEventGated(
int buttons,
IOGPoint * newLoc,
IOGBounds * bounds,
bool proximity,
int pressure,
int stylusAngle,
AbsoluteTime ts,
OSObject * sender)
{
NXEventData outData;
bool proximityChange = false;
CachedMouseEventStruct *cachedMouseEvent = 0;
IOGPoint pointerFraction;
if ( !eventsOpen )
return;
if(ShouldConsumeHIDEvent(ts, stateChangeDeadline))
return;
if ( !(displayState & IOPMDeviceUsable) ) { if ( buttons ) {
return;
}
TICKLE_DISPLAY;
return;
}
TICKLE_DISPLAY;
_scaleLocationToCurrentScreen(newLoc, &pointerFraction, bounds);
if (cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, sender))
{
bcopy(&pointerFraction, &(cachedMouseEvent->pointerFraction), sizeof(IOGPoint));
proximityChange = (cachedMouseEvent->proximity != proximity);
cachedMouseEvent->state |= kCachedMousePointingEventDispFlag;
cachedMouseEvent->proximity = proximity;
cachedMouseEvent->lastPressure = ScalePressure(pressure);
if ( !(cachedMouseEvent->state & kCachedMouseTabletEventDispFlag) )
{
if ( !(cachedMouseEvent->state & kCachedMousePointingTabletEventDispFlag) )
{
cachedMouseEvent->state |= kCachedMousePointingTabletEventDispFlag;
cachedMouseEvent->proximityData.proximity.capabilityMask = (
NX_TABLET_CAPABILITY_DEVICEIDMASK |
NX_TABLET_CAPABILITY_ABSXMASK |
NX_TABLET_CAPABILITY_ABSYMASK |
NX_TABLET_CAPABILITY_BUTTONSMASK |
NX_TABLET_CAPABILITY_PRESSUREMASK);
cachedMouseEvent->proximityData.proximity.pointerType = NX_TABLET_POINTER_PEN;
cachedMouseEvent->proximityData.proximity.systemTabletID = IOHITablet::generateTabletID();
cachedMouseEvent->proximityData.proximity.deviceID =
cachedMouseEvent->tabletData.tablet.deviceID = IOHIDPointing::generateDeviceID();
}
if ( proximityChange )
{
cachedMouseEvent->proximityData.proximity.enterProximity = proximity;
cachedMouseEvent->subType = NX_SUBTYPE_TABLET_PROXIMITY;
cachedMouseEvent->state |= kCachedMousePointingTabletEventPendFlag;
proximityEventGated(&(cachedMouseEvent->proximityData), ts, sender);
cachedMouseEvent->state &= ~kCachedMousePointingTabletEventPendFlag;
}
else if ( proximity )
{
cachedMouseEvent->tabletData.tablet.buttons = buttons & ~0x7;
if (buttons & 2)
cachedMouseEvent->tabletData.tablet.buttons |= 4;
if (buttons & EV_RB)
cachedMouseEvent->tabletData.tablet.buttons |= 2;
if (buttons & EV_LB)
cachedMouseEvent->tabletData.tablet.buttons |= 1;
cachedMouseEvent->tabletData.tablet.x = newLoc->x;
cachedMouseEvent->tabletData.tablet.y = newLoc->y;
cachedMouseEvent->tabletData.tablet.pressure = pressure;
cachedMouseEvent->subType = NX_SUBTYPE_TABLET_POINT;
}
}
}
if ( (newLoc->x != pointerLoc.x) || (newLoc->y != pointerLoc.y) || proximityChange)
{
pointerDelta.x += (newLoc->x - pointerLoc.x);
pointerDelta.y += (newLoc->y - pointerLoc.y);
pointerLoc = *newLoc;
_setCursorPosition(&pointerLoc, false, proximityChange, sender);
}
if ( proximityChange && proximity == true )
{
evg->eventFlags |= NX_STYLUSPROXIMITYMASK;
bzero( (char *)&outData, sizeof outData );
postEvent( NX_FLAGSCHANGED,
&pointerLoc,
ts,
&outData,
sender);
}
if ( proximityChange || proximity == true )
_setButtonState(buttons, ts, sender);
if ( proximityChange && proximity == false )
{
evg->eventFlags &= ~NX_STYLUSPROXIMITYMASK;
bzero( (char *)&outData, sizeof outData );
postEvent( NX_FLAGSCHANGED,
&pointerLoc,
ts,
&outData,
sender);
}
if (cachedMouseEvent)
{
cachedMouseEvent->subType = NX_SUBTYPE_DEFAULT;
bzero(&cachedMouseEvent->pointerFraction, sizeof(IOGPoint));
}
}
void IOHIDSystem::_scrollWheelEvent(IOHIDSystem * self,
short deltaAxis1,
short deltaAxis2,
short deltaAxis3,
IOFixed fixedDelta1,
IOFixed fixedDelta2,
IOFixed fixedDelta3,
SInt32 pointDeltaAxis1,
SInt32 pointDeltaAxis2,
SInt32 pointDeltaAxis3,
UInt32 options,
AbsoluteTime ts,
OSObject * sender,
void * refcon)
{
self->scrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, fixedDelta1, fixedDelta2, fixedDelta3, pointDeltaAxis1, pointDeltaAxis2, pointDeltaAxis3, options, ts, sender);
}
void IOHIDSystem::scrollWheelEvent(short deltaAxis1,
short deltaAxis2,
short deltaAxis3,
AbsoluteTime ts)
{
scrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, deltaAxis1<<16, deltaAxis2<<16, deltaAxis3<<16, 0, 0, 0, 0, ts, 0);
}
void IOHIDSystem::scrollWheelEvent(short deltaAxis1,
short deltaAxis2,
short deltaAxis3,
IOFixed fixedDelta1,
IOFixed fixedDelta2,
IOFixed fixedDelta3,
SInt32 pointDeltaAxis1,
SInt32 pointDeltaAxis2,
SInt32 pointDeltaAxis3,
UInt32 options,
AbsoluteTime ts,
OSObject * sender)
{
IOHIDCmdGateActionArgs args;
args.arg0 = &deltaAxis1;
args.arg1 = &deltaAxis2;
args.arg2 = &deltaAxis3;
args.arg3 = &fixedDelta1;
args.arg4 = &fixedDelta2;
args.arg5 = &fixedDelta3;
args.arg6 = &pointDeltaAxis1;
args.arg7 = &pointDeltaAxis2;
args.arg8 = &pointDeltaAxis3;
args.arg9 = &options;
args.arg10 = &ts;
args.arg11 = sender;
cmdGate->runAction((IOCommandGate::Action)doScrollWheelEvent, (void *)&args);
}
IOReturn IOHIDSystem::doScrollWheelEvent(IOHIDSystem *self, void * args)
{
short deltaAxis1 = *(short *)((IOHIDCmdGateActionArgs *)args)->arg0;
short deltaAxis2 = *(short *)((IOHIDCmdGateActionArgs *)args)->arg1;
short deltaAxis3 = *(short *)((IOHIDCmdGateActionArgs *)args)->arg2;
IOFixed fixedDelta1 = *(IOFixed *)((IOHIDCmdGateActionArgs *)args)->arg3;
IOFixed fixedDelta2 = *(IOFixed *)((IOHIDCmdGateActionArgs *)args)->arg4;
IOFixed fixedDelta3 = *(IOFixed *)((IOHIDCmdGateActionArgs *)args)->arg5;
SInt32 pointDeltaAxis1 = *(IOFixed *)((IOHIDCmdGateActionArgs *)args)->arg6;
SInt32 pointDeltaAxis2 = *(IOFixed *)((IOHIDCmdGateActionArgs *)args)->arg7;
SInt32 pointDeltaAxis3 = *(IOFixed *)((IOHIDCmdGateActionArgs *)args)->arg8;
UInt32 options = *(UInt32 *)((IOHIDCmdGateActionArgs *)args)->arg9;
AbsoluteTime ts = *(AbsoluteTime *)((IOHIDCmdGateActionArgs *)args)->arg10;
OSObject * sender= (OSObject *)((IOHIDCmdGateActionArgs *)args)->arg11;
self->scrollWheelEventGated(deltaAxis1, deltaAxis2, deltaAxis3, fixedDelta1, fixedDelta2, fixedDelta3, pointDeltaAxis1, pointDeltaAxis2, pointDeltaAxis3, options, ts, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::scrollWheelEventGated(short deltaAxis1,
short deltaAxis2,
short deltaAxis3,
IOFixed fixedDelta1,
IOFixed fixedDelta2,
IOFixed fixedDelta3,
SInt32 pointDeltaAxis1,
SInt32 pointDeltaAxis2,
SInt32 pointDeltaAxis3,
UInt32 options,
AbsoluteTime ts,
OSObject * sender)
{
NXEventData wheelData;
if (!eventsOpen)
return;
if(ShouldConsumeHIDEvent(ts, stateChangeDeadline))
return;
if ((deltaAxis1 == 0) && (deltaAxis2 == 0) && (deltaAxis3 == 0) &&
(pointDeltaAxis1 == 0) && (pointDeltaAxis2 == 0) && (pointDeltaAxis3 == 0))
{
return;
}
TICKLE_DISPLAY;
bzero((char *)&wheelData, sizeof wheelData);
wheelData.scrollWheel.deltaAxis1 = deltaAxis1;
wheelData.scrollWheel.deltaAxis2 = deltaAxis2;
wheelData.scrollWheel.deltaAxis3 = deltaAxis3;
wheelData.scrollWheel.fixedDeltaAxis1 = fixedDelta1;
wheelData.scrollWheel.fixedDeltaAxis2 = fixedDelta2;
wheelData.scrollWheel.fixedDeltaAxis3 = fixedDelta3;
wheelData.scrollWheel.pointDeltaAxis1 = pointDeltaAxis1;
wheelData.scrollWheel.pointDeltaAxis2 = pointDeltaAxis2;
wheelData.scrollWheel.pointDeltaAxis3 = pointDeltaAxis3;
wheelData.scrollWheel.reserved1 = (UInt16)options & kScrollTypeContinuous;
postEvent( (options & kScrollTypeZoom) ? NX_ZOOM : NX_SCROLLWHEELMOVED,
(IOGPoint *)&evg->cursorLoc,
ts,
&wheelData,
sender);
return;
}
void IOHIDSystem::_tabletEvent(IOHIDSystem *self,
NXEventData *tabletData,
AbsoluteTime ts,
OSObject * sender,
void * refcon)
{
self->tabletEvent(tabletData, ts, sender);
}
void IOHIDSystem::tabletEvent(NXEventData *tabletData,
AbsoluteTime ts)
{
tabletEvent(tabletData, ts, 0);
}
void IOHIDSystem::tabletEvent(NXEventData *tabletData,
AbsoluteTime ts,
OSObject * sender)
{
cmdGate->runAction((IOCommandGate::Action)doTabletEvent, tabletData, &ts, sender);
}
IOReturn IOHIDSystem::doTabletEvent(IOHIDSystem *self, void * arg0, void * arg1, void * arg2)
{
NXEventData *tabletData = (NXEventData *) arg0;
AbsoluteTime ts = *(AbsoluteTime *) arg1;
OSObject * sender = (OSObject *) arg2;
self->tabletEventGated(tabletData, ts, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::tabletEventGated(NXEventData *tabletData,
AbsoluteTime ts,
OSObject * sender)
{
CachedMouseEventStruct *cachedMouseEvent;
if (!eventsOpen)
return;
if(ShouldConsumeHIDEvent(ts, stateChangeDeadline))
return;
if ((cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, sender)) &&
!(cachedMouseEvent->state & kCachedMousePointingTabletEventPendFlag))
{
cachedMouseEvent->state |= kCachedMouseTabletEventDispFlag;
cachedMouseEvent->subType = NX_SUBTYPE_TABLET_POINT;
bcopy( tabletData, &(cachedMouseEvent->tabletData), sizeof(NXEventData));
if ( cachedMouseEvent->state & kCachedMousePointingEventDispFlag )
return;
}
postEvent(NX_TABLETPOINTER,
(IOGPoint *)&evg->cursorLoc,
ts,
tabletData,
sender);
return;
}
void IOHIDSystem::_proximityEvent(IOHIDSystem *self,
NXEventData *proximityData,
AbsoluteTime ts,
OSObject * sender,
void * refcon)
{
self->proximityEvent(proximityData, ts, sender);
}
void IOHIDSystem::proximityEvent(NXEventData *proximityData,
AbsoluteTime ts)
{
proximityEvent(proximityData, ts, 0);
}
void IOHIDSystem::proximityEvent(NXEventData *proximityData,
AbsoluteTime ts,
OSObject * sender)
{
cmdGate->runAction((IOCommandGate::Action)doProximityEvent, proximityData, &ts, sender);
}
IOReturn IOHIDSystem::doProximityEvent(IOHIDSystem *self, void * arg0, void *arg1, void * arg2)
{
NXEventData *proximityData = (NXEventData *)arg0;
AbsoluteTime ts = *(AbsoluteTime *)arg1;
OSObject * sender = (OSObject *)arg2;
self->proximityEventGated(proximityData, ts, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::proximityEventGated(NXEventData *proximityData,
AbsoluteTime ts,
OSObject * sender)
{
CachedMouseEventStruct *cachedMouseEvent;
if (!eventsOpen)
return;
if(ShouldConsumeHIDEvent(ts, stateChangeDeadline))
return;
if ((cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, sender)) &&
!(cachedMouseEvent->state & kCachedMousePointingTabletEventPendFlag))
{
cachedMouseEvent->state |= kCachedMouseTabletEventDispFlag;
cachedMouseEvent->subType = NX_SUBTYPE_TABLET_PROXIMITY;
bcopy( proximityData, &(cachedMouseEvent->proximityData), sizeof(NXEventData));
}
postEvent(NX_TABLETPROXIMITY,
(IOGPoint *)&evg->cursorLoc,
ts,
proximityData,
sender);
return;
}
void IOHIDSystem::doProcessKeyboardEQ(IOHIDSystem * self)
{
processKeyboardEQ(self);
}
void IOHIDSystem::processKeyboardEQ(IOHIDSystem * self, AbsoluteTime * deadline)
{
KeyboardEQElement * keyboardEQElement;
KEYBOARD_EQ_LOCK;
while ( ((keyboardEQElement = (KeyboardEQElement *)dequeue_head(&gKeyboardEQ)) != NULL)
&& !(deadline && (CMP_ABSOLUTETIME(&(keyboardEQElement->ts), deadline) > 0)))
{
KEYBOARD_EQ_UNLOCK;
if (keyboardEQElement->action)
(*(keyboardEQElement->action))(self, keyboardEQElement);
IOFree(keyboardEQElement, sizeof(KeyboardEQElement));
KEYBOARD_EQ_LOCK;
}
KEYBOARD_EQ_UNLOCK;
}
void IOHIDSystem::_keyboardEvent(IOHIDSystem * self,
unsigned eventType,
unsigned flags,
unsigned key,
unsigned charCode,
unsigned charSet,
unsigned origCharCode,
unsigned origCharSet,
unsigned keyboardType,
bool repeat,
AbsoluteTime ts,
OSObject * sender,
void * refcon)
{
self->keyboardEvent(eventType, flags, key, charCode, charSet,
origCharCode, origCharSet, keyboardType, repeat, ts, sender);
}
void IOHIDSystem::keyboardEvent(unsigned eventType,
unsigned flags,
unsigned key,
unsigned charCode,
unsigned charSet,
unsigned origCharCode,
unsigned origCharSet,
unsigned keyboardType,
bool repeat,
AbsoluteTime ts)
{
keyboardEvent(eventType, flags, key, charCode, charSet,
origCharCode, origCharSet, keyboardType, repeat, ts, 0);
}
void IOHIDSystem::keyboardEvent(unsigned eventType,
unsigned flags,
unsigned key,
unsigned charCode,
unsigned charSet,
unsigned origCharCode,
unsigned origCharSet,
unsigned keyboardType,
bool repeat,
AbsoluteTime ts,
OSObject * sender)
{
KeyboardEQElement * keyboardEQElement = (KeyboardEQElement *)IOMalloc(sizeof(KeyboardEQElement));
if ( !keyboardEQElement )
return;
bzero(keyboardEQElement, sizeof(KeyboardEQElement));
keyboardEQElement->action = IOHIDSystem::doKeyboardEvent;
keyboardEQElement->ts = ts;
keyboardEQElement->sender = sender;
keyboardEQElement->event.keyboard.eventType = eventType;
keyboardEQElement->event.keyboard.flags = flags;
keyboardEQElement->event.keyboard.key = key;
keyboardEQElement->event.keyboard.charCode = charCode;
keyboardEQElement->event.keyboard.charSet = charSet;
keyboardEQElement->event.keyboard.origCharCode = origCharCode;
keyboardEQElement->event.keyboard.origCharSet = origCharSet;
keyboardEQElement->event.keyboard.keyboardType = keyboardType;
keyboardEQElement->event.keyboard.repeat = repeat;
KEYBOARD_EQ_LOCK;
enqueue_tail(&gKeyboardEQ, (queue_entry_t)keyboardEQElement);
KEYBOARD_EQ_UNLOCK;
keyboardEQES->interruptOccurred(0, 0, 0);
}
IOReturn IOHIDSystem::doKeyboardEvent(IOHIDSystem *self, void * args)
{
KeyboardEQElement * keyboardEQElement = (KeyboardEQElement *)args;
AbsoluteTime ts = keyboardEQElement->ts;
OSObject * sender = keyboardEQElement->sender;
unsigned eventType = keyboardEQElement->event.keyboard.eventType;
unsigned flags = keyboardEQElement->event.keyboard.flags;
unsigned key = keyboardEQElement->event.keyboard.key;
unsigned charCode = keyboardEQElement->event.keyboard.charCode;
unsigned charSet = keyboardEQElement->event.keyboard.charSet;
unsigned origCharCode = keyboardEQElement->event.keyboard.origCharCode;
unsigned origCharSet = keyboardEQElement->event.keyboard.origCharSet;
unsigned keyboardType = keyboardEQElement->event.keyboard.keyboardType;
bool repeat = keyboardEQElement->event.keyboard.repeat;
self->keyboardEventGated(eventType, flags, key, charCode, charSet,
origCharCode, origCharSet, keyboardType, repeat, ts, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::keyboardEventGated(unsigned eventType,
unsigned flags,
unsigned key,
unsigned charCode,
unsigned charSet,
unsigned origCharCode,
unsigned origCharSet,
unsigned keyboardType,
bool repeat,
AbsoluteTime ts,
OSObject * sender)
{
UInt32 consumeCause;
NXEventData outData;
consumeCause = ShouldConsumeHIDEvent(ts, stateChangeDeadline);
if (consumeCause == kHIDConsumeCauseKeyLock)
return;
else if(consumeCause == kHIDConsumeCauseDeadline) {
if (consumedKeyCode != (unsigned)-1) {
if ((consumedKeyCode != key) && (eventType != NX_KEYUP)) {
AbsoluteTime_to_scalar(&stateChangeDeadline) = 0;
displayState |= IOPMDeviceUsable;
goto KEYBOARD_EVENT_PROCESS;
} else if ((consumedKeyCode == key) && (eventType == NX_KEYUP)) {
AbsoluteTime_to_scalar(&stateChangeDeadline) = 0;
displayState |= IOPMDeviceUsable;
consumedKeyCode = (unsigned)-1;
return;
}
} else if ( eventType == NX_KEYDOWN ) {
consumedKeyCode = key;
return;
}
}
consumedKeyCode = (unsigned)-1;
KEYBOARD_EVENT_PROCESS:
if ( ! (displayState & IOPMDeviceUsable) ) { if ( eventType == NX_KEYDOWN ) {
return;
} else if ( eventType == NX_KEYUP ) {
TICKLE_DISPLAY;
return;
}
}
TICKLE_DISPLAY;
if( !repeat && (key == 0x35) &&
(eventType == NX_KEYDOWN) &&
((flags & NORMAL_MODIFIER_MASK) == NORMAL_MODIFIER_MASK))
{
PE_enter_debugger("USB Programmer Key");
}
if( !repeat && ((key == 0x41) || (key == 0x2f)) &&
((flags & NORMAL_MODIFIER_MASK) == NORMAL_MODIFIER_MASK))
{
if (eventType == NX_KEYDOWN)
sendStackShotMessage();
return;
}
if ( eventsOpen ) {
outData.key.repeat = repeat;
outData.key.keyCode = key;
outData.key.charSet = charSet;
outData.key.charCode = charCode;
outData.key.origCharSet = origCharSet;
outData.key.origCharCode = origCharCode;
outData.key.keyboardType = keyboardType;
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
if (cachedEventFlags != evg->eventFlags) {
cachedEventFlags = evg->eventFlags;
nanoseconds_to_absolutetime(0, &clickTime);
}
postEvent( eventType,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
} else {
static const char cursorCodes[] = { 'D', 'A', 'C', 'B' };
if( (eventType == NX_KEYDOWN) && ((flags & NX_ALTERNATEMASK) != NX_ALTERNATEMASK)) {
if( (charSet == NX_SYMBOLSET)
&& (charCode >= 0xac) && (charCode <= 0xaf)) {
cons_cinput( '\033');
cons_cinput( 'O');
charCode = cursorCodes[ charCode - 0xac ];
}
cons_cinput( charCode );
}
}
}
void IOHIDSystem::_keyboardSpecialEvent( IOHIDSystem * self,
unsigned eventType,
unsigned flags,
unsigned key,
unsigned flavor,
UInt64 guid,
bool repeat,
AbsoluteTime ts,
OSObject * sender,
void * refcon)
{
self->keyboardSpecialEvent(eventType, flags, key, flavor, guid, repeat, ts, sender);
}
void IOHIDSystem::keyboardSpecialEvent( unsigned eventType,
unsigned flags,
unsigned key,
unsigned flavor,
UInt64 guid,
bool repeat,
AbsoluteTime ts)
{
keyboardSpecialEvent(eventType, flags, key, flavor, guid, repeat, ts, 0);
}
void IOHIDSystem::keyboardSpecialEvent( unsigned eventType,
unsigned flags,
unsigned key,
unsigned flavor,
UInt64 guid,
bool repeat,
AbsoluteTime ts,
OSObject * sender)
{
KeyboardEQElement * keyboardEQElement = NULL;
keyboardEQElement = (KeyboardEQElement *)IOMalloc(sizeof(KeyboardEQElement));
if ( !keyboardEQElement )
return;
bzero(keyboardEQElement, sizeof(KeyboardEQElement));
keyboardEQElement->action = IOHIDSystem::doKeyboardSpecialEvent;
keyboardEQElement->ts = ts;
keyboardEQElement->sender = sender;
keyboardEQElement->event.keyboardSpecial.eventType = eventType;
keyboardEQElement->event.keyboardSpecial.flags = flags;
keyboardEQElement->event.keyboardSpecial.key = key;
keyboardEQElement->event.keyboardSpecial.flavor = flavor;
keyboardEQElement->event.keyboardSpecial.guid = guid;
keyboardEQElement->event.keyboardSpecial.repeat = repeat;
KEYBOARD_EQ_LOCK;
enqueue_tail(&gKeyboardEQ, (queue_entry_t)keyboardEQElement);
KEYBOARD_EQ_UNLOCK;
keyboardEQES->interruptOccurred(0, 0, 0);
}
IOReturn IOHIDSystem::doKeyboardSpecialEvent(IOHIDSystem *self, void * args)
{
KeyboardEQElement * keyboardEQElement = (KeyboardEQElement *)args;
AbsoluteTime ts = keyboardEQElement->ts;
OSObject * sender = keyboardEQElement->sender;
unsigned eventType = keyboardEQElement->event.keyboardSpecial.eventType;
unsigned flags = keyboardEQElement->event.keyboardSpecial.flags;
unsigned key = keyboardEQElement->event.keyboardSpecial.key;
unsigned flavor = keyboardEQElement->event.keyboardSpecial.flavor;
UInt64 guid = keyboardEQElement->event.keyboardSpecial.guid;
bool repeat = keyboardEQElement->event.keyboardSpecial.repeat;
self->keyboardSpecialEventGated(eventType, flags, key, flavor, guid, repeat, ts, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::keyboardSpecialEventGated(
unsigned eventType,
unsigned flags,
unsigned key,
unsigned flavor,
UInt64 guid,
bool repeat,
AbsoluteTime ts,
OSObject * sender)
{
NXEventData outData;
int level = -1;
if(ShouldConsumeHIDEvent(ts, stateChangeDeadline))
return;
TICKLE_DISPLAY;
if ( eventType == NX_KEYDOWN && flavor == NX_POWER_KEY && !repeat) {
if ( (flags & NORMAL_MODIFIER_MASK) == NX_COMMANDMASK )
PE_enter_debugger("USB Programmer Key");
else if ( (flags & NORMAL_MODIFIER_MASK) == ( NX_COMMANDMASK | NX_CONTROLMASK ) )
PEHaltRestart(kPERestartCPU);
}
if ( !eventsOpen )
return;
bzero( (void *)&outData, sizeof outData );
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
if ( eventType == NX_KEYDOWN )
{
notifyHIDevices(this, ioHIDevices, kIOHIDSystem508SpecialKeyDownMessage);
switch ( flavor )
{
case NX_KEYTYPE_EJECT:
if( (evg->eventFlags & NX_COMMANDMASK) &&
!(evg->eventFlags & NX_CONTROLMASK) &&
!(evg->eventFlags & NX_SHIFTMASK) &&
!(evg->eventFlags & NX_ALTERNATEMASK) )
{
outData.compound.subType = NX_SUBTYPE_POWER_KEY;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
else if( (evg->eventFlags & NX_COMMANDMASK) &&
!(evg->eventFlags & NX_CONTROLMASK) &&
!(evg->eventFlags & NX_SHIFTMASK) &&
(evg->eventFlags & NX_ALTERNATEMASK) )
{
outData.compound.subType = NX_SUBTYPE_SLEEP_EVENT;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
else if( (evg->eventFlags & NX_COMMANDMASK) &&
(evg->eventFlags & NX_CONTROLMASK) &&
!(evg->eventFlags & NX_SHIFTMASK) &&
(evg->eventFlags & NX_ALTERNATEMASK) )
{
outData.compound.subType = NX_SUBTYPE_SHUTDOWN_EVENT;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
else if( (evg->eventFlags & NX_COMMANDMASK) &&
(evg->eventFlags & NX_CONTROLMASK) &&
!(evg->eventFlags & NX_SHIFTMASK) &&
!(evg->eventFlags & NX_ALTERNATEMASK) )
{
outData.compound.subType = NX_SUBTYPE_RESTART_EVENT;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
else if( !(evg->eventFlags & NX_COMMANDMASK) &&
(evg->eventFlags & NX_CONTROLMASK) &&
!(evg->eventFlags & NX_SHIFTMASK) &&
!(evg->eventFlags & NX_ALTERNATEMASK) )
{
evg->eventFlags = 0;
outData.compound.subType = NX_SUBTYPE_POWER_KEY;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
else
{
outData.compound.subType = NX_SUBTYPE_EJECT_KEY;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
break;
case NX_POWER_KEY:
outData.compound.subType = NX_SUBTYPE_POWER_KEY;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
break;
}
}
#if 0
else if ( eventType == NX_KEYUP )
{
switch ( flavor )
{
case NX_KEYTYPE_SOUND_UP:
break;
case NX_KEYTYPE_SOUND_DOWN:
break;
case NX_KEYTYPE_MUTE:
break;
case NX_POWER_KEY:
break;
}
}
#endif
else if ( eventType == NX_SYSDEFINED )
{
outData.compound.subType = flavor;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
if ( eventType != NX_SYSDEFINED )
{
if( (flags & SPECIALKEYS_MODIFIER_MASK)
&& (flavor == NX_POWER_KEY))
{
}
else
{
outData.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
outData.compound.misc.L[0] = (flavor << 16) | (eventType << 8) | repeat;
outData.compound.misc.L[1] = guid & 0xffffffff;
outData.compound.misc.L[2] = guid >> 32;
postEvent( NX_SYSDEFINED,
&pointerLoc,
ts,
&outData,
sender,
0,
false);
}
}
if ( level != -1 ) {
evSpecialKeyMsg( flavor,
eventType,
flags,
level);
}
}
void IOHIDSystem::_updateEventFlags(IOHIDSystem * self,
unsigned flags,
OSObject * sender,
void * refcon)
{
self->updateEventFlags(flags, sender);
}
void IOHIDSystem::updateEventFlags(unsigned flags)
{
updateEventFlags(flags, 0);
}
void IOHIDSystem::updateEventFlags(unsigned flags, OSObject * sender)
{
KeyboardEQElement * keyboardEQElement = (KeyboardEQElement *)IOMalloc(sizeof(KeyboardEQElement));
if ( !keyboardEQElement )
return;
bzero(keyboardEQElement, sizeof(KeyboardEQElement));
keyboardEQElement->action = IOHIDSystem::doUpdateEventFlags;
keyboardEQElement->sender = sender;
keyboardEQElement->event.flagsChanged.flags = flags;
KEYBOARD_EQ_LOCK;
enqueue_tail(&gKeyboardEQ, (queue_entry_t)keyboardEQElement);
KEYBOARD_EQ_UNLOCK;
keyboardEQES->interruptOccurred(0, 0, 0);
}
IOReturn IOHIDSystem::doUpdateEventFlags(IOHIDSystem *self, void * args)
{
KeyboardEQElement * keyboardEQElement = (KeyboardEQElement *)args;
OSObject * sender = keyboardEQElement->sender;
unsigned flags = keyboardEQElement->event.flagsChanged.flags;
self->updateEventFlagsGated(flags, sender);
return kIOReturnSuccess;
}
void IOHIDSystem::updateEventFlagsGated(unsigned flags, OSObject * sender)
{
if ( eventsOpen ) {
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
nanoseconds_to_absolutetime(0, &clickTime);
}
}
void IOHIDSystem::_setButtonState(int buttons,
AbsoluteTime ts,
OSObject * sender)
{
CachedMouseEventStruct *cachedMouseEvent = NULL;
if ( cachedButtonStates )
{
cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, sender);
if (cachedMouseEvent)
{
cachedMouseEvent->lastButtons = buttons;
}
if(evg->buttons == buttons)
return;
buttons = GetCachedMouseButtonStates(cachedButtonStates);
}
if(evg->buttons == buttons)
return;
NXEventData evData;
unsigned long hwButtons, hwDelta;
CONVERT_EV_TO_HW_BUTTONS(buttons, hwButtons);
CONVERT_EV_TO_HW_DELTA((evg->buttons ^ buttons), hwDelta);
evData.compound.reserved = 0;
evData.compound.subType = NX_SUBTYPE_AUX_MOUSE_BUTTONS;
evData.compound.misc.L[0] = hwDelta;
evData.compound.misc.L[1] = hwButtons;
postEvent( NX_SYSDEFINED,
(IOGPoint *)&evg->cursorLoc,
ts,
&evData,
sender);
bzero(&evData, sizeof(NXEventData));
if (cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, sender))
{
evData.mouse.subType = cachedMouseEvent->subType;
evData.mouse.subx = (cachedMouseEvent->pointerFraction.x >> 8) & 0xff;
evData.mouse.suby = (cachedMouseEvent->pointerFraction.y >> 8) & 0xff;
evData.mouse.pressure = cachedMouseEvent->lastPressure;
if (cachedMouseEvent->subType == NX_SUBTYPE_TABLET_POINT)
{
bcopy(&(cachedMouseEvent->tabletData), &(evData.mouse.tablet.point), sizeof(NXTabletPointData));
}
else if (cachedMouseEvent->subType == NX_SUBTYPE_TABLET_PROXIMITY)
{
bcopy(&(cachedMouseEvent->proximityData), &(evData.mouse.tablet.proximity), sizeof(NXTabletProximityData));
}
}
if ((evg->buttons & EV_LB) != (buttons & EV_LB))
{
if (buttons & EV_LB)
{
postEvent( NX_LMOUSEDOWN,
(IOGPoint *)&evg->cursorLoc,
ts,
&evData,
sender);
}
else
{
postEvent( NX_LMOUSEUP,
(IOGPoint *)&evg->cursorLoc,
ts,
&evData,
sender);
}
evg->dontCoalesce = evg->dontWantCoalesce;
if (evg->dontCoalesce)
evg->eventFlags |= NX_NONCOALSESCEDMASK;
else
evg->eventFlags &= ~NX_NONCOALSESCEDMASK;
}
if ((evg->buttons & EV_RB) != (buttons & EV_RB)) {
if (buttons & EV_RB) {
postEvent( NX_RMOUSEDOWN,
(IOGPoint *)&evg->cursorLoc,
ts,
&evData,
sender);
} else {
postEvent( NX_RMOUSEUP,
(IOGPoint *)&evg->cursorLoc,
ts,
&evData,
sender);
}
}
evg->buttons = buttons;
}
void IOHIDSystem::setCursorPosition(IOGPoint * newLoc, bool external, OSObject * sender)
{
if ( eventsOpen == true )
{
pointerDelta.x += (newLoc->x - pointerLoc.x);
pointerDelta.y += (newLoc->y - pointerLoc.y);
pointerLoc = *newLoc;
_setCursorPosition(newLoc, external, false, sender);
}
}
void IOHIDSystem::_setCursorPosition(IOGPoint * newLoc, bool external, bool proximityChange, OSObject * sender)
{
bool cursorMoved = true;
if (!screens)
return;
if( ev_try_lock(&evg->cursorSema) == 0 ) {
needSetCursorPosition = true; return;
}
needSetCursorPosition = false;
if (cursorCoupled || external)
{
UInt32 newScreens = 0;
SInt32 pinScreen = -1L;
EvScreen *screen = (EvScreen *)evScreen;
if (!cursorPinned) {
for (int i = 0; i < screens; i++ ) {
if ((screen[i].instance) && PtInRect(newLoc, screen[i].bounds)) {
pinScreen = i;
newScreens |= (1 << i);
}
}
}
if (newScreens == 0) {
newLoc->x = (newLoc->x < cursorPin.minx) ?
cursorPin.minx : ((newLoc->x > cursorPin.maxx) ?
cursorPin.maxx : newLoc->x);
newLoc->y = (newLoc->y < cursorPin.miny) ?
cursorPin.miny : ((newLoc->y > cursorPin.maxy) ?
cursorPin.maxy : newLoc->y);
for (int i = 0; i < screens; i++ ) {
if ((screen[i].instance) && PtInRect(newLoc, screen[i].bounds)) {
pinScreen = i;
newScreens |= (1 << i);
}
}
}
pointerLoc = *newLoc;
if ((evg->cursorLoc.x == newLoc->x) && (evg->cursorLoc.y == newLoc->y)) {
if ((proximityChange == 0) && (pointerDelta.x == 0) && (pointerDelta.y == 0)) {
ev_unlock(&evg->cursorSema);
return;
}
cursorMoved = false; } else {
evg->cursorLoc.x = newLoc->x;
evg->cursorLoc.y = newLoc->y;
if (newScreens != cursorScreens) {
hideCursor();
cursorScreens = newScreens;
cursorPin = *(((EvScreen*)evScreen)[pinScreen].bounds);
cursorPin.maxx--;
cursorPin.maxy--;
cursorPinScreen = pinScreen;
showCursor();
} else {
moveCursor();
}
}
} else {
pointerLoc.x = evg->cursorLoc.x;
pointerLoc.y = evg->cursorLoc.y;
}
AbsoluteTime ts;
clock_get_uptime(&ts);
if (evg->movedMask) {
if ((evg->movedMask&NX_LMOUSEDRAGGEDMASK)&&(evg->buttons& EV_LB)) {
_postMouseMoveEvent(NX_LMOUSEDRAGGED, newLoc, ts, sender);
} else if ((evg->movedMask&NX_RMOUSEDRAGGEDMASK) && (evg->buttons & EV_RB)) {
_postMouseMoveEvent(NX_RMOUSEDRAGGED, newLoc, ts, sender);
} else if (evg->movedMask & NX_MOUSEMOVEDMASK) {
_postMouseMoveEvent(NX_MOUSEMOVED, newLoc, ts, sender);
}
}
if (cursorMoved && evg->mouseRectValid && (!PtInRect(newLoc, &evg->mouseRect)))
{
if (evg->mouseRectValid)
{
postEvent( NX_MOUSEEXITED,
newLoc,
ts,
NULL,
sender);
evg->mouseRectValid = 0;
}
}
ev_unlock(&evg->cursorSema);
}
void IOHIDSystem::_postMouseMoveEvent(int what,
IOGPoint * location,
AbsoluteTime ts,
OSObject * sender)
{
NXEventData data;
CachedMouseEventStruct *cachedMouseEvent = 0;
bzero( &data, sizeof(data) );
data.mouseMove.dx = pointerDelta.x;
data.mouseMove.dy = pointerDelta.y;
pointerDelta.x = 0;
pointerDelta.y = 0;
if (sender && (cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, sender)))
{
data.mouseMove.subType = cachedMouseEvent->subType;
data.mouseMove.subx = (cachedMouseEvent->pointerFraction.x >> 8) & 0xff;
data.mouseMove.suby = (cachedMouseEvent->pointerFraction.y >> 8) & 0xff;
data.mouseMove.reserved1 = cachedMouseEvent->lastPressure;
if (cachedMouseEvent->subType == NX_SUBTYPE_TABLET_PROXIMITY)
{
bcopy(&(cachedMouseEvent->proximityData), &(data.mouseMove.tablet.proximity), sizeof(NXTabletProximityData));
}
else if (cachedMouseEvent->subType == NX_SUBTYPE_TABLET_POINT)
{
bcopy(&(cachedMouseEvent->tabletData), &(data.mouseMove.tablet.point), sizeof(NXTabletPointData));
}
}
postEvent(what, location, ts, &data, sender);
}
IOReturn IOHIDSystem::newUserClient(task_t owningTask,
void * security_id,
UInt32 type,
OSDictionary * properties,
IOUserClient ** handler)
{
IOHIDCmdGateActionArgs args;
args.arg0 = &owningTask;
args.arg1 = security_id;
args.arg2 = &type;
args.arg3 = properties;
args.arg4 = handler;
return cmdGate->runAction((IOCommandGate::Action)doNewUserClient, &args);
}
IOReturn IOHIDSystem::doNewUserClient(IOHIDSystem *self, void * args)
{
task_t owningTask = *(task_t *) ((IOHIDCmdGateActionArgs *)args)->arg0;
void * security_id = ((IOHIDCmdGateActionArgs *)args)->arg1;
UInt32 type = *(UInt32 *) ((IOHIDCmdGateActionArgs *)args)->arg2;
OSDictionary * properties = (OSDictionary *) ((IOHIDCmdGateActionArgs *)args)->arg3;
IOUserClient ** handler = (IOUserClient **) ((IOHIDCmdGateActionArgs *)args)->arg4;
return self->newUserClientGated(owningTask, security_id, type, properties, handler);
}
IOReturn IOHIDSystem::newUserClientGated(task_t owningTask,
void * security_id,
UInt32 type,
OSDictionary * properties,
IOUserClient ** handler)
{
IOUserClient * newConnect = 0;
IOReturn err = kIOReturnNoMemory;
do {
if( type == kIOHIDParamConnectType) {
if( paramConnect) {
newConnect = paramConnect;
newConnect->retain();
} else if( eventsOpen) {
newConnect = new IOHIDParamUserClient;
} else {
err = kIOReturnNotOpen;
continue;
}
} else if( type == kIOHIDServerConnectType) {
newConnect = new IOHIDUserClient;
} else if( type == kIOHIDStackShotConnectType ) {
newConnect = new IOHIDStackShotUserClient;
} else if ( type == kIOHIDEventSystemConnectType ) {
newConnect = new IOHIDEventSystemUserClient;
} else
err = kIOReturnUnsupported;
if( !newConnect)
continue;
if( (newConnect != paramConnect) && (
(false == newConnect->initWithTask(owningTask, security_id, type, properties))
|| (false == newConnect->setProperty(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue))
|| (false == newConnect->attach( this ))
|| (false == newConnect->start( this ))
|| ((type == kIOHIDServerConnectType)
&& (err = evOpen()))
)) {
newConnect->detach( this );
newConnect->release();
newConnect = 0;
continue;
}
if( type == kIOHIDParamConnectType)
paramConnect = newConnect;
err = kIOReturnSuccess;
} while( false );
*handler = newConnect;
return err;
}
IOReturn IOHIDSystem::setEventsEnable(void*p1,void*,void*,void*,void*,void*)
{ IOReturn ret;
ret = cmdGate->runAction((IOCommandGate::Action)doSetEventsEnablePre, p1);
if ( ret == kIOReturnSuccess ) {
_resetMouseParameters();
}
ret = cmdGate->runAction((IOCommandGate::Action)doSetEventsEnablePost, p1);
return ret;
}
IOReturn IOHIDSystem::doSetEventsEnablePre(IOHIDSystem *self, void *p1)
{
return self->setEventsEnablePreGated(p1);
}
IOReturn IOHIDSystem::setEventsEnablePreGated(void*p1)
{
bool enable = (bool)p1;
if( enable) {
while ( evStateChanging )
cmdGate->commandSleep(&evStateChanging);
evStateChanging = true;
attachDefaultEventSources();
}
return( kIOReturnSuccess);
}
IOReturn IOHIDSystem::doSetEventsEnablePost(IOHIDSystem *self, void *p1)
{
return self->setEventsEnablePostGated(p1);
}
IOReturn IOHIDSystem::setEventsEnablePostGated(void*p1)
{
bool enable = (bool)p1;
if( enable) {
evStateChanging = false;
cmdGate->commandWakeup(&evStateChanging);
}
return( kIOReturnSuccess);
}
IOReturn IOHIDSystem::setCursorEnable(void*p1,void*,void*,void*,void*,void*)
{
return cmdGate->runAction((IOCommandGate::Action)doSetCursorEnable, p1);
}
IOReturn IOHIDSystem::doSetCursorEnable(IOHIDSystem *self, void * arg0)
{
return self->setCursorEnableGated(arg0);
}
IOReturn IOHIDSystem::setCursorEnableGated(void* p1)
{
bool enable = (bool)p1;
IOReturn err = kIOReturnSuccess;
if ( eventsOpen == false )
return kIOReturnNotOpen;
if( 0 == screens) return kIOReturnNoDevice;
if( enable) {
if( cursorStarted) {
hideCursor();
cursorEnabled = resetCursor();
showCursor();
} else
cursorEnabled = startCursor();
} else
cursorEnabled = enable;
cursorCoupled = cursorEnabled;
return err;
}
IOReturn IOHIDSystem::extSetBounds( IOGBounds * bounds )
{
if( bounds->minx != bounds->maxx) {
cursorPin = *bounds;
cursorPin.maxx--;
cursorPin.maxy--;
cursorPinned = true;
} else
cursorPinned = false;
return( kIOReturnSuccess );
}
IOReturn IOHIDSystem::extPostEvent(void*p1,void*p2,void*,void*,void*,void*)
{ AbsoluteTime ts;
clock_get_uptime(&ts);
return cmdGate->runAction((IOCommandGate::Action)doExtPostEvent, p1, p2, &ts);
}
IOReturn IOHIDSystem::doExtPostEvent(IOHIDSystem *self, void * arg0, void * arg1, void * arg2, void * arg3)
{
return self->extPostEventGated(arg0, arg1, arg2);
}
IOReturn IOHIDSystem::extPostEventGated(void *p1,void *p2, void *p3)
{
struct evioLLEvent * event = (struct evioLLEvent *)p1;
UInt32 count = (UInt32) p2;
bool isMoveOrDragEvent = false;
bool isSeized = false;
int oldMovedMask = 0;
int extPID = (count > sizeof(evioLLEvent)) ? *(int *)((struct evioLLEvent *)(event + 1)) : 0;
UInt32 buttonState = 0;
UInt32 newFlags = 0;
AbsoluteTime ts = *(AbsoluteTime *)p3;
CachedMouseEventStruct *cachedMouseEvent;
if ( eventsOpen == false )
return kIOReturnNotOpen;
if(ShouldConsumeHIDEvent(ts, stateChangeDeadline, false))
return kIOReturnSuccess;
TICKLE_DISPLAY;
if (EventCodeMask(event->type) & MOVEDEVENTMASK)
{
isMoveOrDragEvent = true;
if ((event->data.mouseMove.subType == NX_SUBTYPE_TABLET_POINT) && (event->data.mouseMove.reserved1 == 0))
{
event->data.mouseMove.reserved1 = ScalePressure(event->data.mouseMove.tablet.point.pressure);
}
}
else if ((EventCodeMask(event->type) & MOUSEEVENTMASK) &&
(event->data.mouse.subType == NX_SUBTYPE_TABLET_POINT) && (event->data.mouse.pressure == 0))
{
event->data.mouse.pressure = ScalePressure(event->data.mouse.tablet.point.pressure);
}
if( event->setCursor)
{
if (isMoveOrDragEvent)
{
oldMovedMask = evg->movedMask;
evg->movedMask = 0;
}
if (( event->type == NX_MOUSEMOVED ) &&
( event->setCursor & kIOHIDSetRelativeCursorPosition ))
{
pointerLoc.x += event->data.mouseMove.dx;
pointerLoc.y += event->data.mouseMove.dy;
pointerDelta.x += event->data.mouseMove.dx;
pointerDelta.y += event->data.mouseMove.dy;
_setCursorPosition(&pointerLoc, false);
}
else if ( event->setCursor & kIOHIDSetCursorPosition )
{
setCursorPosition(&event->location, false);
}
if (isMoveOrDragEvent)
evg->movedMask = oldMovedMask;
}
else
{
UInt32 newScreens = 0;
EvScreen *screen = (EvScreen *)evScreen;
if (!cursorPinned) {
for (int i = 0; i < screens; i++ ) {
if ((screen[i].instance) && PtInRect(&event->location, screen[i].bounds)) {
newScreens |= (1 << i);
}
}
}
if (newScreens == 0)
{
event->location.x = (event->location.x < cursorPin.minx) ?
cursorPin.minx : ((event->location.x > cursorPin.maxx) ?
cursorPin.maxx : event->location.x);
event->location.y = (event->location.y < cursorPin.miny) ?
cursorPin.miny : ((event->location.y > cursorPin.maxy) ?
cursorPin.maxy : event->location.y);
}
}
if ((EventCodeMask(event->type) & (NX_LMOUSEDOWNMASK | NX_RMOUSEDOWNMASK | NX_LMOUSEUPMASK | NX_RMOUSEUPMASK)) ||
((event->type == NX_SYSDEFINED) && (event->data.compound.subType == NX_SUBTYPE_AUX_MOUSE_BUTTONS)))
{
if (cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, 0))
{
buttonState = cachedMouseEvent->lastButtons;
switch ( event->type )
{
case NX_LMOUSEDOWN:
buttonState |= EV_LB;
break;
case NX_RMOUSEDOWN:
buttonState |= EV_RB;
break;
case NX_LMOUSEUP:
buttonState &= ~EV_LB;
break;
case NX_RMOUSEUP:
buttonState &= ~EV_RB;
break;
case NX_SYSDEFINED:
CONVERT_HW_TO_WV_BUTTONS(event->data.compound.misc.L[1], buttonState);
}
cachedMouseEvent->lastButtons = buttonState;
evg->buttons = GetCachedMouseButtonStates(cachedButtonStates);
}
}
if( event->setFlags & kIOHIDSetGlobalEventFlags)
{
newFlags = evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (event->flags & KEYBOARD_FLAGSMASK);
}
if ( event->setFlags & kIOHIDPostHIDManagerEvent )
{
if ((EventCodeMask(event->type) & (MOUSEEVENTMASK | MOVEDEVENTMASK | NX_SCROLLWHEELMOVEDMASK)) &&
(_hidPointingDevice || (_hidPointingDevice = IOHIDPointingDevice::newPointingDeviceAndStart(this, 8, 400, true, 2))))
{
SInt32 dx = 0;
SInt32 dy = 0;
SInt32 wheel = 0;
buttonState = 0;
if (EventCodeMask(event->type) & MOVEDEVENTMASK)
{
dx = event->data.mouseMove.dx;
dy = event->data.mouseMove.dy;
}
else if ( event->type == NX_SCROLLWHEELMOVED )
{
wheel = event->data.scrollWheel.deltaAxis1;
}
if (cachedMouseEvent = GetCachedMouseEventForService(cachedButtonStates, 0))
CONVERT_EV_TO_HW_BUTTONS((cachedMouseEvent->lastButtons), buttonState);
_hidPointingDevice->postMouseEvent(buttonState, dx, dy, wheel);
isSeized |= _hidPointingDevice->isSeized();
}
if ((EventCodeMask(event->type) & (NX_KEYDOWNMASK | NX_KEYUPMASK | NX_FLAGSCHANGEDMASK)) &&
(_hidKeyboardDevice || (_hidKeyboardDevice = IOHIDKeyboardDevice::newKeyboardDeviceAndStart(this, 1))))
{
_hidKeyboardDevice->postFlagKeyboardEvent(newFlags & KEYBOARD_FLAGSMASK);
if ((event->type != NX_FLAGSCHANGED) && (event->data.key.repeat == 0))
{
_hidKeyboardDevice->postKeyboardEvent(event->data.key.keyCode, (event->type == NX_KEYDOWN));
}
isSeized |= _hidKeyboardDevice->isSeized();
}
}
if ( !isSeized )
{
postEvent( event->type,
&event->location,
ts,
&event->data,
0,
extPID);
}
return kIOReturnSuccess;
}
IOReturn IOHIDSystem::extSetMouseLocation(void*p1,void*,void*,void*,void*,void*)
{ return cmdGate->runAction((IOCommandGate::Action)doExtSetMouseLocation, p1);
}
IOReturn IOHIDSystem::doExtSetMouseLocation(IOHIDSystem *self, void * arg0)
{
return self->extSetMouseLocationGated(arg0);
}
IOReturn IOHIDSystem::extSetMouseLocationGated(void *p1)
{
IOGPoint * loc = (IOGPoint *)p1;
setCursorPosition(loc, true);
return kIOReturnSuccess;
}
IOReturn IOHIDSystem::extGetButtonEventNum(void*p1,void*p2,void*,void*,void*,void*)
{ return cmdGate->runAction((IOCommandGate::Action)doExtGetButtonEventNum, p1, p2);
}
IOReturn IOHIDSystem::doExtGetButtonEventNum(IOHIDSystem *self, void * arg0, void * arg1)
{
return self->extGetButtonEventNumGated(arg0, arg1);
}
IOReturn IOHIDSystem::extGetButtonEventNumGated(void *p1, void* p2)
{
NXMouseButton button = (NXMouseButton)(int)p1;
int * eventNum = (int *)p2;
IOReturn err = kIOReturnSuccess;
switch( button) {
case NX_LeftButton:
*eventNum = leftENum;
break;
case NX_RightButton:
*eventNum = rightENum;
break;
default:
err = kIOReturnBadArgument;
}
return err;
}
void IOHIDSystem::makeNumberParamProperty( OSDictionary * dict, const char * key,
unsigned long long number, unsigned int bits )
{
OSNumber * numberRef;
numberRef = OSNumber::withNumber(number, bits);
if( numberRef) {
dict->setObject( key, numberRef);
numberRef->release();
}
}
void IOHIDSystem::makeInt32ArrayParamProperty( OSDictionary * dict, const char * key,
UInt32 * intArray, unsigned int count )
{
OSArray * array;
OSNumber * number;
array = OSArray::withCapacity(count);
if ( !array )
return;
for (unsigned i=0; i<count; i++)
{
number = OSNumber::withNumber(intArray[i], sizeof(UInt32) << 3);
if (number)
{
array->setObject(number);
number->release();
}
}
dict->setObject( key, array);
array->release();
}
void IOHIDSystem::createParameters( void )
{
UInt64 nano;
IOFixed fixed;
UInt32 int32;
savedParameters->setObject(kIOHIDDefaultParametersKey, kOSBooleanTrue);
nano = EV_DCLICKTIME;
makeNumberParamProperty( savedParameters, kIOHIDClickTimeKey,
nano, 64 );
UInt32 tempClickSpace[] = {clickSpaceThresh.x, clickSpaceThresh.y};
makeInt32ArrayParamProperty( savedParameters, kIOHIDClickSpaceKey,
tempClickSpace, sizeof(tempClickSpace)/sizeof(UInt32) );
nano = EV_DEFAULTKEYREPEAT;
makeNumberParamProperty( savedParameters, kIOHIDKeyRepeatKey,
nano, 64 );
nano = EV_DEFAULTINITIALREPEAT;
makeNumberParamProperty( savedParameters, kIOHIDInitialKeyRepeatKey,
nano, 64 );
fixed = EV_DEFAULTPOINTERACCELLEVEL;
makeNumberParamProperty( savedParameters, kIOHIDPointerAccelerationKey,
fixed, sizeof(fixed) << 3);
fixed = EV_DEFAULTSCROLLACCELLEVEL;
makeNumberParamProperty( savedParameters, kIOHIDScrollAccelerationKey,
fixed, sizeof(fixed) << 3);
fixed = kIOHIDButtonMode_EnableRightClick;
makeNumberParamProperty( savedParameters, kIOHIDPointerButtonMode,
fixed, sizeof(fixed) << 3);
int32 = 250;
makeNumberParamProperty( savedParameters, kIOHIDF12EjectDelayKey,
int32, 32 );
int32 = 0;
makeNumberParamProperty( savedParameters, kIOHIDSlowKeysDelayKey,
int32, 32 );
int32 = 0; makeNumberParamProperty( savedParameters, kIOHIDStickyKeysDisabledKey,
int32, 32 );
int32 = 0; makeNumberParamProperty( savedParameters, kIOHIDStickyKeysOnKey,
int32, 32 );
int32 = 0; makeNumberParamProperty( savedParameters, kIOHIDStickyKeysShiftTogglesKey,
int32, 32 );
int32 = 0; makeNumberParamProperty( savedParameters, kIOHIDMouseKeysOptionTogglesKey,
int32, 32 );
int32 = 0;
makeNumberParamProperty( savedParameters, kIOHIDFKeyModeKey,
int32, 32 );
setProperty( kIOHIDParametersKey, savedParameters );
savedParameters->release();
OSSerializer * idleTimeSerializer = OSSerializer::forTarget(this, IOHIDSystem::_idleTimeSerializerCallback);
if (idleTimeSerializer)
{
setProperty( kIOHIDIdleTimeKey, idleTimeSerializer);
idleTimeSerializer->release();
}
}
bool IOHIDSystem::_idleTimeSerializerCallback(void * target, void * ref, OSSerialize *s)
{
IOHIDSystem * self = (IOHIDSystem *) target;
AbsoluteTime currentTime;
OSNumber * number;
UInt64 idleTimeNano = 0;
bool retValue = false;
if( self->eventsOpen )
{
clock_get_uptime( ¤tTime);
SUB_ABSOLUTETIME( ¤tTime, &(self->lastUndimEvent));
absolutetime_to_nanoseconds( currentTime, &idleTimeNano);
}
if (number = OSNumber::withNumber(idleTimeNano, 64))
{
retValue = number->serialize( s );
number->release();
}
return retValue;
}
IOReturn IOHIDSystem::setProperties( OSObject * properties )
{
OSDictionary * dict;
IOReturn err = kIOReturnSuccess;
IOReturn ret;
dict = OSDynamicCast( OSDictionary, properties );
if( dict) {
if (dict->getObject(kIOHIDUseKeyswitchKey) &&
( IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator) != kIOReturnSuccess)) {
dict->removeObject(kIOHIDUseKeyswitchKey);
}
ret = setParamProperties( dict );
}
else
err = kIOReturnBadArgument;
return( err );
}
IOReturn IOHIDSystem::setParamProperties( OSDictionary * dict )
{
OSIterator * iter = NULL;
IOReturn ret = kIOReturnSuccess;
IOReturn err = kIOReturnSuccess;
dict->setObject(kIOHIDDefaultParametersKey, kOSBooleanTrue);
ret = cmdGate->runAction((IOCommandGate::Action)doSetParamPropertiesPre, dict, &iter);
if ( ret == kIOReturnSuccess ) {
if( iter) {
IOService * eventSrc;
OSDictionary * validParameters;
while( (eventSrc = (IOService *) iter->getNextObject())) {
if ( OSDynamicCast(IOHIDKeyboard, eventSrc) || OSDynamicCast(IOHIDPointing, eventSrc) || OSDynamicCast(IOHIDConsumer, eventSrc))
continue;
validParameters = createFilteredParamPropertiesForService(eventSrc, dict);
if ( validParameters ) {
if ( OSDynamicCast(IOHIDevice, eventSrc) )
ret = ((IOHIDevice *)eventSrc)->setParamProperties( validParameters );
else if ( OSDynamicCast( IOHIDEventService, eventSrc ) )
ret = ((IOHIDEventService *)eventSrc)->setSystemProperties( validParameters );
if( (ret != kIOReturnSuccess) && (ret != kIOReturnBadArgument))
err = ret;
dict->merge(validParameters);
validParameters->release();
}
}
iter->release();
}
cmdGate->runAction((IOCommandGate::Action)doSetParamPropertiesPost, dict);
}
return err;
}
OSDictionary * IOHIDSystem::createFilteredParamPropertiesForService(IOService * service, OSDictionary * dict)
{
OSDictionary * validParameters = OSDictionary::withCapacity(4);
if ( !validParameters )
return NULL;
OSDictionary * deviceParameters = NULL;
if ( OSDynamicCast(IOHIDevice, service) )
deviceParameters = OSDynamicCast(OSDictionary, service->getProperty(kIOHIDParametersKey));
else if ( OSDynamicCast( IOHIDEventService, service ) )
deviceParameters = OSDynamicCast(OSDictionary, service->getProperty(kIOHIDEventServicePropertiesKey));
OSCollectionIterator * iterator = OSCollectionIterator::withCollection(dict);
if ( iterator ) {
OSSymbol * key;
while ( key = (OSSymbol*)iterator->getNextObject() ) {
if ( !deviceParameters || !deviceParameters->getObject(key) )
validParameters->setObject(key, dict->getObject(key));
}
iterator->release();
}
if ( validParameters->getCount() == 0 ) {
validParameters->release();
validParameters = NULL;
} else
validParameters->setObject(kIOHIDDefaultParametersKey, kOSBooleanTrue);
return validParameters;
}
IOReturn IOHIDSystem::doSetParamPropertiesPre(IOHIDSystem *self, void * arg0, void * arg1)
{
return self->setParamPropertiesPreGated((OSDictionary *)arg0, (OSIterator**)arg1);
}
IOReturn IOHIDSystem::setParamPropertiesPreGated( OSDictionary * dict, OSIterator ** pOpenIter)
{
OSArray * array;
OSNumber * number;
if (dict == NULL)
return kIOReturnError;
while ( setParamPropertiesInProgress )
cmdGate->commandSleep(&setParamPropertiesInProgress);
setParamPropertiesInProgress = true;
if( (number = OSDynamicCast( OSNumber, dict->getObject(kIOHIDUseKeyswitchKey))))
{
gUseKeyswitch = number->unsigned32BitValue();
}
if( (number = OSDynamicCast( OSNumber, dict->getObject(kIOHIDClickTimeKey))))
{
UInt64 nano = number->unsigned64BitValue();
nanoseconds_to_absolutetime(nano, &clickTimeThresh);
}
if( (array = OSDynamicCast( OSArray,
dict->getObject(kIOHIDClickSpaceKey)))) {
if ((number = OSDynamicCast( OSNumber,
array->getObject(EVSIOSCS_X))))
{
clickSpaceThresh.x = number->unsigned32BitValue();
}
if ((number = OSDynamicCast( OSNumber,
array->getObject(EVSIOSCS_Y))))
{
clickSpaceThresh.y = number->unsigned32BitValue();
}
}
if( (number = OSDynamicCast( OSNumber, dict->getObject(kIOHIDWaitCursorFrameIntervalKey))))
clock_interval_to_absolutetime_interval(number->unsigned32BitValue(), kNanosecondScale,
&waitFrameRate);
if( (number = OSDynamicCast( OSNumber, dict->getObject(kIOHIDStickyKeysOnKey)))) {
if (number->unsigned32BitValue())
stickyKeysState |= (1 << 0);
else
stickyKeysState &= ~(1 << 0);
}
if( (number = OSDynamicCast( OSNumber, dict->getObject(kIOHIDStickyKeysShiftTogglesKey)))) {
if (number->unsigned32BitValue())
stickyKeysState |= (1 << 1);
else
stickyKeysState &= ~(1 << 1);
}
if ( dict->getObject(kIOHIDResetKeyboardKey) ) {
UInt64 nano = EV_DEFAULTKEYREPEAT;
makeNumberParamProperty( dict, kIOHIDKeyRepeatKey, nano, 64 );
nano = EV_DEFAULTINITIALREPEAT;
makeNumberParamProperty( dict, kIOHIDInitialKeyRepeatKey, nano, 64 );
}
if ( dict->getObject(kIOHIDResetPointerKey) ) {
IOFixed fixed = EV_DEFAULTPOINTERACCELLEVEL;
makeNumberParamProperty( dict, kIOHIDPointerAccelerationKey, fixed, sizeof(fixed) << 3);
fixed = kIOHIDButtonMode_EnableRightClick;
makeNumberParamProperty( dict, kIOHIDPointerButtonMode, fixed, sizeof(fixed) << 3);
}
if ( dict->getObject(kIOHIDScrollResetKey) ) {
IOFixed fixed = EV_DEFAULTSCROLLACCELLEVEL;
makeNumberParamProperty( dict, kIOHIDScrollAccelerationKey, fixed, sizeof(fixed) << 3);
}
if ( pOpenIter )
*pOpenIter = getOpenProviderIterator();
return kIOReturnSuccess;
}
IOReturn IOHIDSystem::doSetParamPropertiesPost(IOHIDSystem *self, void * arg0)
{
return self->setParamPropertiesPostGated((OSDictionary *)arg0);
}
IOReturn IOHIDSystem::setParamPropertiesPostGated( OSDictionary * dict)
{
if ( dict->getObject(kIOHIDTemporaryParametersKey) == NULL ) {
bool resetKeyboard = dict->getObject(kIOHIDResetKeyboardKey) != NULL;
bool resetPointer = dict->getObject(kIOHIDResetPointerKey) != NULL;
bool resetScroll = dict->getObject(kIOHIDScrollResetKey) != NULL;
OSDictionary * newParams = OSDictionary::withDictionary( savedParameters );
if( newParams) {
if ( resetKeyboard ) {
dict->removeObject(kIOHIDResetKeyboardKey);
}
if ( resetPointer ) {
dict->removeObject(kIOHIDResetPointerKey);
newParams->removeObject(kIOHIDTrackpadAccelerationType);
newParams->removeObject(kIOHIDMouseAccelerationType);
}
if ( resetScroll ) {
dict->removeObject(kIOHIDScrollResetKey);
newParams->removeObject(kIOHIDTrackpadScrollAccelerationKey);
newParams->removeObject(kIOHIDMouseScrollAccelerationKey);
}
newParams->merge( dict );
setProperty( kIOHIDParametersKey, newParams );
newParams->release();
savedParameters = newParams;
}
struct evioLLEvent event;
AbsoluteTime ts;
bzero( (void *)&event, sizeof event);
event.data.compound.subType = NX_SUBTYPE_HIDPARAMETER_MODIFIED;
clock_get_uptime(&ts);
postEvent(NX_SYSDEFINED, &(event.location), ts, &(event.data));
}
setParamPropertiesInProgress = false;
cmdGate->commandWakeup(&setParamPropertiesInProgress);
return kIOReturnSuccess;
}