#include <IOKit/system.h>
#include <IOKit/assert.h>
#include <libkern/c++/OSContainers.h>
#include <libkern/c++/OSCollectionIterator.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/hidsystem/IOHIDevice.h>
#include <IOKit/hidsystem/IOHIDShared.h>
#include <IOKit/hidsystem/IOHIDSystem.h>
#include <IOKit/hidsystem/IOHIKeyboard.h>
#include <IOKit/hidsystem/IOHIPointing.h>
#include <IOKit/hidsystem/IOHIDParameter.h>
#include <IOKit/hidsystem/ev_private.h>
#include "IOHIDUserClient.h"
#include <sys/kdebug.h>
#ifdef __cplusplus
extern "C"
{
#include <UserNotification/KUNCUserNotifications.h>
}
#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
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);
}
#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;
} IOHIDCmdGateActionArgs;
static bool keySwitchLocked = false;
static IONotifier * switchNotification = 0;
static bool keySwitchNotificationHandler(void *target, void *refCon, IOService *service) {
keySwitchLocked = (service->getProperty("Keyswitch") == kOSBooleanTrue) ? true : false;
return true;
}
static thread_call_t activity_tickle_call = 0;
static void actvityTickle_funct(IOService *displayManager)
{
if (displayManager != NULL)
displayManager->activityTickle(0,0);
}
static bool isStickyKeysOn = false;
static void notifyHIDevices(IOService *service, OSArray *hiDevices, UInt32 type)
{
IOHIKeyboard *keyboard;
if((type != kIOHIDSystem508MouseClickMessage) ||
!isStickyKeysOn || !hiDevices)
return;
for(int index=0; index<hiDevices->getCount(); index++)
{
if (keyboard = OSDynamicCast(IOHIKeyboard, hiDevices->getObject(index)))
keyboard->IOHIKeyboard::message(kIOHIDSystem508MouseClickMessage, service);
}
}
#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;
cmdGate = 0;
workLoop = 0;
ioHIDevices = OSArray::withCapacity(2);
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);
if (!workLoop || !cmdGate || !timerES || !eventConsumerES)
break;
if ((workLoop->addEventSource(cmdGate) != kIOReturnSuccess)
|| (workLoop->addEventSource(timerES) != kIOReturnSuccess)
|| (workLoop->addEventSource(eventConsumerES) != kIOReturnSuccess))
break;
publishNotify = addNotification(
gIOPublishNotification, serviceMatching("IOHIDevice"),
&IOHIDSystem::publishNotificationHandler,
this, 0 );
if (!publishNotify) break;
terminateNotify = addNotification(
gIOTerminatedNotification, serviceMatching("IOHIDevice"),
&IOHIDSystem::terminateNotificationHandler,
this, 0 );
if (!terminateNotify) break;
registerService();
addNotification( gIOPublishNotification, serviceMatching("IODisplayWrangler"),
&IOHIDSystem::publishNotificationHandler,
this, 0 );
switchNotification = 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 * )
{
displayState = theFlags;
return IOPMNoErr;
}
bool IOHIDSystem::publishNotificationHandler(
void * target,
void * ,
IOService * newService )
{
IOHIDSystem * self = (IOHIDSystem *) target;
if( newService->metaCast("IODisplayWrangler")) {
if( !self->displayManager) {
self->displayManager = newService;
self->displayState = newService->registerInterestedDriver(self);
activity_tickle_call = thread_call_allocate(actvityTickle_funct, newService);
}
return true;
}
self->attach( newService );
if(OSDynamicCast(IOHIDevice, newService)) {
if (self->ioHIDevices) {
if (self->ioHIDevices->getNextIndexOfObject(newService, 0) == -1)
self->ioHIDevices->setObject(newService);
}
if(self->eventsOpen)
self->registerEventSource((IOHIDevice *) newService);
}
return true;
}
bool IOHIDSystem::terminateNotificationHandler(
void * target,
void * ,
IOService * service )
{
IOHIDSystem * self = (IOHIDSystem *) target;
int index;
if( self->eventsOpen && OSDynamicCast(IOHIDevice, service)) {
service->close(self);
}
self->detach(service);
if (self->ioHIDevices) {
if ((index = self->ioHIDevices->getNextIndexOfObject(service, 0)) != -1)
self->ioHIDevices->removeObject(index);
}
return true;
}
void IOHIDSystem::free()
{
if (evScreen) IOFree( (void *)evScreen, evScreenSize );
evScreen = (void *)0;
evScreenSize = 0;
if (timerES) timerES->release();
if (eventConsumerES) eventConsumerES->release();
if (cmdGate) {evClose(); cmdGate->release();}
if (workLoop) workLoop->release();
if (publishNotify) publishNotify->release();
if (switchNotification) switchNotification->release();
if (ioHIDevices) ioHIDevices->release();
if (activity_tickle_call) thread_call_free(activity_tickle_call);
super::free();
}
IOReturn IOHIDSystem::evOpen(void)
{
IOReturn r = kIOReturnSuccess;
if ( evOpenCalled == true )
{
r = kIOReturnBusy;
goto done;
}
evOpenCalled = true;
if (!evInitialized)
{
evInitialized = true;
curBright = EV_SCREEN_MAX_BRIGHTNESS; curVolume = EV_AUDIO_MAX_VOLUME / 2; }
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;
forceAutoDimState(false);
if( cursorEnabled)
hideCursor();
cursorStarted = false;
cursorEnabled = false;
detachEventSources();
if ( evScreen != (void *)0 )
{
screens = 0;
lastShmemPtr = (void *)0;
}
setEventPort(MACH_PORT_NULL);
evOpenCalled = false;
eventsOpen = false;
return kIOReturnSuccess;
}
void IOHIDSystem::evDispatch(
EvCmd evcmd)
{
Point 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() {
cmdGate->runAction((IOCommandGate::Action)doResetMouseParameters);
}
IOReturn IOHIDSystem::doResetMouseParameters(IOHIDSystem *self)
{
self->resetMouseParametersGated();
return kIOReturnSuccess;
}
void IOHIDSystem::resetMouseParametersGated(void)
{
if ( eventsOpen == false )
return;
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;
nanoseconds_to_absolutetime( DAUTODIMPERIOD, &autoDimPeriod);
clock_get_uptime( &autoDimTime);
ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
dimmedBrightness = DDIMBRIGHTNESS;
}
void IOHIDSystem::_resetKeyboardParameters()
{
}
int IOHIDSystem::registerScreen(IOGraphicsDevice * instance,
Bounds * 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((Point *)&evg->cursorLoc, true);
showCursor();
}
Bounds * IOHIDSystem::workspaceBounds()
{
return &workSpace;
}
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);
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;
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 );
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;
}
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,
Point * location,
AbsoluteTime ts,
NXEventData * myData)
{
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 (EventCodeMask(what) & NX_UNDIMMASK) {
autoDimTime = ts;
ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
if (autoDimmed)
undoAutoDim();
}
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.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();
notifyHIDevices(this, ioHIDevices, kIOHIDSystem508MouseClickMessage);
break;
case NX_RMOUSEDOWN:
theTail->event.data.mouse.eventNum =
rightENum = getUniqueEventNum();
notifyHIDevices(this, ioHIDevices, kIOHIDSystem508MouseClickMessage);
break;
case NX_LMOUSEUP:
theTail->event.data.mouse.eventNum = leftENum;
leftENum = NULLEVENTNUM;
break;
case NX_RMOUSEUP:
theTail->event.data.mouse.eventNum = rightENum;
rightENum = NULLEVENTNUM;
break;
}
if (EventCodeMask(what) & PRESSUREEVENTMASK)
{
if (EventCodeMask(what) & MOUSEEVENTMASK)
theTail->event.data.mouse.pressure = lastPressure;
else if (EventCodeMask(what) & MOVEDEVENTMASK)
theTail->event.data.mouseMove.reserved1 = lastPressure;
else
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::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
xpr_ev_post("doKickEventConsumer\n", 1,2,3,4,5);
self->needToKickEventConsumer = false;
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);
if ((CMP_ABSOLUTETIME(&thisPeriodicRun, &autoDimTime) > 0)
&& (!autoDimmed))
doAutoDim();
}
ev_unlock(&evg->waitCursorSema);
}
scheduleNextPeriodicEvent();
return;
}
bool IOHIDSystem::resetCursor()
{
volatile Point * 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;
return( true );
}
bool IOHIDSystem::startCursor()
{
bool ok;
if (0 == screens) return( false );
cursorPinned = false;
resetCursor();
setBrightness();
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 > maxWaitCursorFrame) || (frame > evg->lastFrame)) ? firstWaitCursorFrame : frame;
xpr_ev_cursor("changeCursor %d\n",evg->frame,2,3,4,5);
moveCursor();
}
int IOHIDSystem::pointToScreen(Point * 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);
}
void IOHIDSystem::setBrightness(int b)
{
if ( b < EV_SCREEN_MIN_BRIGHTNESS )
b = EV_SCREEN_MIN_BRIGHTNESS;
else if ( b > EV_SCREEN_MAX_BRIGHTNESS )
b = EV_SCREEN_MAX_BRIGHTNESS;
if ( b != curBright )
{
curBright = b;
if ( autoDimmed == false )
setBrightness();
}
}
int IOHIDSystem::brightness()
{
return curBright;
}
void IOHIDSystem::setAutoDimBrightness(int b)
{
if ( b < EV_SCREEN_MIN_BRIGHTNESS )
b = EV_SCREEN_MIN_BRIGHTNESS;
else if ( b > EV_SCREEN_MAX_BRIGHTNESS )
b = EV_SCREEN_MAX_BRIGHTNESS;
if ( b != dimmedBrightness )
{
dimmedBrightness = b;
if ( autoDimmed == true )
setBrightness();
}
}
int IOHIDSystem::autoDimBrightness()
{
return dimmedBrightness;
}
int IOHIDSystem::currentBrightness() {
if ( autoDimmed == true && dimmedBrightness < curBright )
return dimmedBrightness;
else
return curBright;
}
void IOHIDSystem::doAutoDim()
{
autoDimmed = true;
setBrightness();
}
void IOHIDSystem::undoAutoDim()
{
autoDimmed = false;
setBrightness();
}
void IOHIDSystem::forceAutoDimState(bool dim)
{
if ( dim == true )
{
if ( autoDimmed == false )
{
if ( eventsOpen == true )
clock_get_uptime( &autoDimTime);
doAutoDim();
}
}
else
{
if ( autoDimmed == true )
{
if ( eventsOpen == true ) {
clock_get_uptime( &autoDimTime);
ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
}
undoAutoDim();
}
}
}
void IOHIDSystem::setAudioVolume(int v)
{
if ( v < EV_AUDIO_MIN_VOLUME )
v = EV_AUDIO_MIN_VOLUME;
else if ( v > EV_AUDIO_MAX_VOLUME )
v = EV_AUDIO_MAX_VOLUME;
curVolume = v;
}
void IOHIDSystem::setUserAudioVolume(int v)
{
setAudioVolume(v);
evSpecialKeyMsg( NX_KEYTYPE_SOUND_UP,
NX_KEYDOWN,
0,
curVolume);
}
int IOHIDSystem::audioVolume()
{
return curVolume;
}
inline void IOHIDSystem::setBrightness() {
evDispatch( EVLEVEL);
}
inline void IOHIDSystem::showCursor()
{
evDispatch( EVSHOW);
}
inline void IOHIDSystem::hideCursor()
{
evDispatch( EVHIDE);
}
inline void IOHIDSystem::moveCursor()
{
evDispatch( EVMOVE);
}
void IOHIDSystem::attachDefaultEventSources()
{
OSObject * source;
OSIterator * sources;
sources = getProviderIterator();
if (!sources) return;
while( (source = sources->getNextObject())) {
if (OSDynamicCast(IOHIDevice, source)) {
registerEventSource((IOHIDevice *)source);
}
}
sources->release();
}
void IOHIDSystem::detachEventSources()
{
OSIterator * iter;
IOHIDevice * srcInstance;
iter = getOpenProviderIterator();
if( iter) {
while( (srcInstance = (IOHIDevice *) iter->getNextObject())) {
#ifdef DEBUG
kprintf("detachEventSource:%s\n", srcInstance->getName());
#endif
srcInstance->close(this);
}
iter->release();
}
}
bool IOHIDSystem::registerEventSource(IOHIDevice * source)
{
bool success = false;
#ifdef DEBUG
kprintf("registerEventSource:%s\n", ((IOHIDevice*)source)->getName());
#endif
if ( OSDynamicCast(IOHIKeyboard, source) ) {
success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize,
(KeyboardEventAction) _keyboardEvent,
(KeyboardSpecialEventAction) _keyboardSpecialEvent,
(UpdateEventFlagsAction) _updateEventFlags);
} else if ( OSDynamicCast(IOHIPointing, source) ) {
success = ((IOHIPointing*)source)->open(this, kIOServiceSeize,
(RelativePointerEventAction) _relativePointerEvent,
(AbsolutePointerEventAction) _absolutePointerEvent,
(ScrollWheelEventAction) _scrollWheelEvent);
}
if ( success )
source->setParamProperties( savedParameters );
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(Point *location, Bounds *bounds)
{
location->x = ((location->x - bounds->minx) * (cursorPin.maxx - cursorPin.minx + 1)
/ (bounds->maxx - bounds->minx)) + cursorPin.minx;
location->y = ((location->y - bounds->miny) * (cursorPin.maxy - cursorPin.miny + 1)
/ (bounds->maxy - bounds->miny)) + cursorPin.miny;
return;
}
void IOHIDSystem::_relativePointerEvent(IOHIDSystem * self,
int buttons,
int dx,
int dy,
AbsoluteTime ts)
{
self->relativePointerEvent(buttons, dx, dy, ts);
}
void IOHIDSystem::relativePointerEvent(int buttons,
int dx,
int dy,
AbsoluteTime ts)
{
cmdGate->runAction((IOCommandGate::Action)doRelativePointerEvent, (void *)buttons,
(void *)dx, (void *)dy, (void *)&ts);
}
IOReturn IOHIDSystem::doRelativePointerEvent(IOHIDSystem *self, void * arg0, void * arg1, void * arg2, void * arg3)
{
int buttons = (int)arg0;
int dx = (int)arg1;
int dy = (int)arg2;
AbsoluteTime ts = *(AbsoluteTime *)arg3;
self->relativePointerEventGated(buttons, dx, dy, ts);
return kIOReturnSuccess;
}
void IOHIDSystem::relativePointerEventGated(int buttons, int dx, int dy, AbsoluteTime ts)
{
AbsoluteTime nextVBL, vblDeltaTime, eventDeltaTime, moveDeltaTime;
if(keySwitchLocked)
return;
if( activity_tickle_call != NULL ) thread_call_enter(activity_tickle_call);
if( eventsOpen == false )
return;
if( (buttons & EV_LB) != (evg->buttons & EV_LB) )
{
if ( buttons & EV_LB )
lastPressure = MAXPRESSURE;
else
lastPressure = MINPRESSURE;
}
_setButtonState(buttons, ts);
if( dx || dy )
{
eventDeltaTime = ts;
SUB_ABSOLUTETIME( &eventDeltaTime, &lastEventTime );
lastEventTime = ts;
IOGraphicsDevice * instance = ((EvScreen*)evScreen)[cursorPinScreen].instance;
if( instance)
instance->getVBLTime( &nextVBL, &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, postedVBLTime.hi, postedVBLTime.lo, 0);
if( (nextVBL.lo || nextVBL.hi)
&& (nextVBL.lo == postedVBLTime.lo) && (nextVBL.hi == postedVBLTime.hi)) {
accumDX += dx;
accumDY += dy;
} else {
SInt32 num = 0, div = 0;
dx += accumDX;
dy += accumDY;
moveDeltaTime = ts;
SUB_ABSOLUTETIME( &moveDeltaTime, &lastMoveTime );
lastMoveTime = ts;
if( (eventDeltaTime.lo < vblDeltaTime.lo) && (0 == eventDeltaTime.hi)
&& vblDeltaTime.lo && moveDeltaTime.lo) {
num = vblDeltaTime.lo;
div = moveDeltaTime.lo;
dx = (num * dx) / div;
dy = (num * dy) / div;
}
KERNEL_DEBUG(0x0c000000 | DBG_FUNC_NONE,
dx, dy, num, div, 0);
postedVBLTime = nextVBL; accumDX = accumDY = 0;
if( dx || dy ) {
pointerLoc.x += dx;
pointerLoc.y += dy;
pointerDelta.x += dx;
pointerDelta.y += dy;
_setCursorPosition(&pointerLoc, false);
}
}
}
}
void IOHIDSystem::_absolutePointerEvent(IOHIDSystem * self,
int buttons,
Point * newLoc,
Bounds * bounds,
bool proximity,
int pressure,
int stylusAngle,
AbsoluteTime ts)
{
self->absolutePointerEvent(buttons, newLoc, bounds, proximity,
pressure, stylusAngle, ts);
}
void IOHIDSystem::absolutePointerEvent(int buttons,
Point * newLoc,
Bounds * bounds,
bool proximity,
int pressure,
int stylusAngle,
AbsoluteTime ts)
{
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;
cmdGate->runAction((IOCommandGate::Action)doAbsolutePointerEvent, &args);
}
IOReturn IOHIDSystem::doAbsolutePointerEvent(IOHIDSystem *self, void * args)
{
int buttons = *(int *) ((IOHIDCmdGateActionArgs *)args)->arg0;
Point * newLoc = (Point *) ((IOHIDCmdGateActionArgs *)args)->arg1;
Bounds * bounds = (Bounds *) ((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;
self->absolutePointerEventGated(buttons, newLoc, bounds, proximity, pressure, stylusAngle, ts);
return kIOReturnSuccess;
}
void IOHIDSystem::absolutePointerEventGated(int buttons,
Point * newLoc,
Bounds * bounds,
bool proximity,
int pressure,
int stylusAngle,
AbsoluteTime ts)
{
NXEventData outData;
if(keySwitchLocked)
return;
if( activity_tickle_call != NULL ) thread_call_enter(activity_tickle_call);
if ( eventsOpen == false )
return;
lastPressure = pressure;
_scaleLocationToCurrentScreen(newLoc, bounds);
if ( newLoc->x != pointerLoc.x || newLoc->y != pointerLoc.y )
{
pointerDelta.x += (newLoc->x - pointerLoc.x);
pointerDelta.y += (newLoc->y - pointerLoc.y);
pointerLoc = *newLoc;
_setCursorPosition(&pointerLoc, false);
}
if ( lastProximity != proximity && proximity == true )
{
evg->eventFlags |= NX_STYLUSPROXIMITYMASK;
bzero( (char *)&outData, sizeof outData );
postEvent( NX_FLAGSCHANGED,
(Point *)&pointerLoc,
ts,
&outData);
}
if ( proximity == true )
_setButtonState(buttons, ts);
if ( lastProximity != proximity && proximity == false )
{
evg->eventFlags &= ~NX_STYLUSPROXIMITYMASK;
bzero( (char *)&outData, sizeof outData );
postEvent( NX_FLAGSCHANGED,
(Point *)&pointerLoc,
ts,
&outData);
}
lastProximity = proximity;
}
void IOHIDSystem::_scrollWheelEvent(IOHIDSystem * self,
short deltaAxis1,
short deltaAxis2,
short deltaAxis3,
AbsoluteTime ts)
{
self->scrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, ts);
}
void IOHIDSystem::scrollWheelEvent(short deltaAxis1,
short deltaAxis2,
short deltaAxis3,
AbsoluteTime ts)
{
cmdGate->runAction((IOCommandGate::Action)doScrollWheelEvent, (void *)deltaAxis1,
(void *)deltaAxis2, (void *)deltaAxis3, &ts);
}
IOReturn IOHIDSystem::doScrollWheelEvent(IOHIDSystem *self, void * arg0, void * arg1, void * arg2, void * arg3)
{
short deltaAxis1 = (short)arg0;
short deltaAxis2 = (short)arg1;
short deltaAxis3 = (short)arg2;
AbsoluteTime ts = *(AbsoluteTime *)arg3;
self->scrollWheelEventGated(deltaAxis1, deltaAxis2, deltaAxis3, ts);
return kIOReturnSuccess;
}
void IOHIDSystem::scrollWheelEventGated(short deltaAxis1,
short deltaAxis2,
short deltaAxis3,
AbsoluteTime ts)
{
NXEventData wheelData;
if(keySwitchLocked)
return;
if ((deltaAxis1 == 0) && (deltaAxis2 == 0) && (deltaAxis3 == 0)) {
return;
}
if (!eventsOpen)
return;
bzero((char *)&wheelData, sizeof wheelData);
wheelData.scrollWheel.deltaAxis1 = deltaAxis1;
wheelData.scrollWheel.deltaAxis2 = deltaAxis2;
wheelData.scrollWheel.deltaAxis3 = deltaAxis3;
postEvent( NX_SCROLLWHEELMOVED,
(Point *)&evg->cursorLoc,
ts,
&wheelData);
return;
}
void IOHIDSystem::_tabletEvent(IOHIDSystem *self,
NXEventData *tabletData,
AbsoluteTime ts)
{
self->tabletEvent(tabletData, ts);
}
void IOHIDSystem::tabletEvent(NXEventData *tabletData,
AbsoluteTime ts)
{
cmdGate->runAction((IOCommandGate::Action)doTabletEvent, tabletData, &ts);
}
IOReturn IOHIDSystem::doTabletEvent(IOHIDSystem *self, void * arg0, void * arg1)
{
NXEventData *tabletData = (NXEventData *) arg0;
AbsoluteTime ts = *(AbsoluteTime *) arg1;
self->tabletEventGated(tabletData, ts);
return kIOReturnSuccess;
}
void IOHIDSystem::tabletEventGated(NXEventData *tabletData,
AbsoluteTime ts)
{
if(keySwitchLocked)
return;
#if 0 // FIXME - NX_TABLETPOINTER has been deprecated.
if (eventsOpen) {
postEvent(NX_TABLETPOINTER,
(Point *)&evg->cursorLoc,
ts,
tabletData);
}
#endif
return;
}
void IOHIDSystem::_proximityEvent(IOHIDSystem *self,
NXEventData *proximityData,
AbsoluteTime ts)
{
self->proximityEvent(proximityData, ts);
}
void IOHIDSystem::proximityEvent(NXEventData *proximityData,
AbsoluteTime ts)
{
cmdGate->runAction((IOCommandGate::Action)doProximityEvent, proximityData, &ts);
}
IOReturn IOHIDSystem::doProximityEvent(IOHIDSystem *self, void * arg0, void *arg1)
{
NXEventData *proximityData = (NXEventData *)arg0;
AbsoluteTime ts = *(AbsoluteTime *)arg1;
self->proximityEventGated(proximityData, ts);
return kIOReturnSuccess;
}
void IOHIDSystem::proximityEventGated(NXEventData *proximityData,
AbsoluteTime ts)
{
if(keySwitchLocked)
return;
#if 0 // FIXME - NX_TABLETPROXIMITY has been deprecated.
if (eventsOpen) {
postEvent(NX_TABLETPROXIMITY,
(Point *)&evg->cursorLoc,
ts,
proximityData);
}
#endif
return;
}
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)
{
self->keyboardEvent(eventType, flags, key, charCode, charSet,
origCharCode, origCharSet, keyboardType, repeat, ts);
}
void IOHIDSystem::keyboardEvent(unsigned eventType,
unsigned flags,
unsigned key,
unsigned charCode,
unsigned charSet,
unsigned origCharCode,
unsigned origCharSet,
unsigned keyboardType,
bool repeat,
AbsoluteTime ts)
{
IOHIDCmdGateActionArgs args;
args.arg0 = &eventType;
args.arg1 = &flags;
args.arg2 = &key;
args.arg3 = &charCode;
args.arg4 = &charSet;
args.arg5 = &origCharCode;
args.arg6 = &origCharSet;
args.arg7 = &keyboardType;
args.arg8 = &repeat;
args.arg9 = &ts;
cmdGate->runAction((IOCommandGate::Action)doKeyboardEvent, &args);
}
IOReturn IOHIDSystem::doKeyboardEvent(IOHIDSystem *self, void * args)
{
unsigned eventType = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg0;
unsigned flags = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg1;
unsigned key = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg2;
unsigned charCode = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg3;
unsigned charSet = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg4;
unsigned origCharCode = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg5;
unsigned origCharSet = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg6;
unsigned keyboardType = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg7;
bool repeat = *(bool *) ((IOHIDCmdGateActionArgs *)args)->arg8;
AbsoluteTime ts = *(AbsoluteTime *) ((IOHIDCmdGateActionArgs *)args)->arg9;
self->keyboardEventGated(eventType, flags, key, charCode, charSet,
origCharCode, origCharSet, keyboardType, repeat, ts);
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)
{
NXEventData outData;
if(keySwitchLocked)
return;
if ( ! (displayState & IOPMDeviceUsable) ) { if ( eventType == NX_KEYDOWN ) {
return;
}
if( activity_tickle_call != NULL ) { thread_call_enter(activity_tickle_call); }
return;
}
if( activity_tickle_call != NULL ) { thread_call_enter(activity_tickle_call); }
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;
if ( eventsOpen == false )
return;
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
postEvent( eventType,
(Point *)&pointerLoc,
ts,
&outData);
}
void IOHIDSystem::_keyboardSpecialEvent( IOHIDSystem * self,
unsigned eventType,
unsigned flags,
unsigned key,
unsigned flavor,
UInt64 guid,
bool repeat,
AbsoluteTime ts)
{
self->keyboardSpecialEvent(eventType, flags, key, flavor, guid, repeat, ts);
}
void IOHIDSystem::keyboardSpecialEvent( unsigned eventType,
unsigned flags,
unsigned key,
unsigned flavor,
UInt64 guid,
bool repeat,
AbsoluteTime ts)
{
IOHIDCmdGateActionArgs args;
args.arg0 = &eventType;
args.arg1 = &flags;
args.arg2 = &key;
args.arg3 = &flavor;
args.arg4 = &guid;
args.arg5 = &repeat;
args.arg6 = &ts;
cmdGate->runAction((IOCommandGate::Action)doKeyboardSpecialEvent, &args);
}
IOReturn IOHIDSystem::doKeyboardSpecialEvent(IOHIDSystem *self, void * args)
{
unsigned eventType= *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg0;
unsigned flags = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg1;
unsigned key = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg2;
unsigned flavor = *(unsigned *) ((IOHIDCmdGateActionArgs *)args)->arg3;
UInt64 guid = *(UInt64 *) ((IOHIDCmdGateActionArgs *)args)->arg4;
bool repeat = *(bool *) ((IOHIDCmdGateActionArgs *)args)->arg5;
AbsoluteTime ts = *(AbsoluteTime *)((IOHIDCmdGateActionArgs *)args)->arg6;
self->keyboardSpecialEventGated(eventType, flags, key, flavor, guid, repeat, ts);
return kIOReturnSuccess;
}
void IOHIDSystem::keyboardSpecialEventGated(
unsigned eventType,
unsigned flags,
unsigned key,
unsigned flavor,
UInt64 guid,
bool repeat,
AbsoluteTime ts)
{
NXEventData outData;
int level = -1;
if(keySwitchLocked)
return;
bzero( (void *)&outData, sizeof outData );
if ( eventsOpen == false )
return;
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
if ( eventType == NX_KEYDOWN )
{
switch ( flavor )
{
case NX_KEYTYPE_SOUND_UP: case NX_KEYTYPE_SOUND_DOWN:
case NX_KEYTYPE_MUTE:
if( !(evg->eventFlags & NX_COMMANDMASK) &&
!(evg->eventFlags & NX_CONTROLMASK) &&
!(evg->eventFlags & NX_SHIFTMASK) &&
(evg->eventFlags & NX_ALTERNATEMASK) )
{
KUNCExecute( "Sound.preference", kOpenAppAsConsoleUser, kOpenPreferencePanel );
}
break;
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,
(Point *)&pointerLoc,
ts,
&outData);
}
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,
(Point *)&pointerLoc,
ts,
&outData);
}
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,
(Point *)&pointerLoc,
ts,
&outData);
}
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,
(Point *)&pointerLoc,
ts,
&outData);
}
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,
(Point *)&pointerLoc,
ts,
&outData);
}
else
{
outData.compound.subType = NX_SUBTYPE_EJECT_KEY;
postEvent( NX_SYSDEFINED,
(Point *)&pointerLoc,
ts,
&outData);
}
break;
case NX_POWER_KEY:
outData.compound.subType = NX_SUBTYPE_POWER_KEY;
postEvent( NX_SYSDEFINED,
(Point *)&pointerLoc,
ts,
&outData);
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,
(Point *)&pointerLoc,
ts,
&outData);
}
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.S[0] = flavor;
outData.compound.misc.C[2] = eventType;
outData.compound.misc.C[3] = repeat;
outData.compound.misc.L[1] = guid & 0xffffffff;
outData.compound.misc.L[2] = guid >> 32;
postEvent( NX_SYSDEFINED,
(Point *)&pointerLoc,
ts,
&outData);
}
}
if ( level != -1 ) {
evSpecialKeyMsg( flavor,
eventType,
flags,
level);
}
}
void IOHIDSystem::_updateEventFlags(IOHIDSystem * self, unsigned flags)
{
self->updateEventFlags(flags);
}
void IOHIDSystem::updateEventFlags(unsigned flags)
{
cmdGate->runAction((IOCommandGate::Action)doUpdateEventFlags, (void *)flags);
}
IOReturn IOHIDSystem::doUpdateEventFlags(IOHIDSystem *self, void * arg0)
{
unsigned flags = (unsigned)arg0;
self->updateEventFlagsGated(flags);
return kIOReturnSuccess;
}
void IOHIDSystem::updateEventFlagsGated(unsigned flags)
{
if ( eventsOpen )
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
}
void IOHIDSystem::_setButtonState(int buttons,
AbsoluteTime ts)
{
if(evg->buttons ^ buttons)
{
NXEventData evData;
unsigned long hwButtons, hwDelta, temp;
hwButtons = buttons & ~7;
hwButtons |= (buttons & 3) << 1;
hwButtons |= (buttons & 4) >> 2;
temp = evg->buttons ^ buttons;
hwDelta = temp & ~7;
hwDelta |= (temp & 3) << 1;
hwDelta |= (temp & 4) >> 2;
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,
(Point *)&evg->cursorLoc,
ts,
&evData);
}
if ((evg->buttons & EV_LB) != (buttons & EV_LB))
{
if (buttons & EV_LB)
{
postEvent( NX_LMOUSEDOWN,
(Point *)&evg->cursorLoc,
ts,
NULL);
}
else
{
postEvent( NX_LMOUSEUP,
(Point *)&evg->cursorLoc,
ts,
NULL);
}
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,
(Point *)&evg->cursorLoc,
ts,
NULL);
} else {
postEvent( NX_RMOUSEUP,
(Point *)&evg->cursorLoc,
ts,
NULL);
}
}
evg->buttons = buttons;
}
void IOHIDSystem::setCursorPosition(Point * newLoc, bool external)
{
if ( eventsOpen == true )
{
pointerDelta.x += (newLoc->x - pointerLoc.x);
pointerDelta.y += (newLoc->y - pointerLoc.y);
pointerLoc = *newLoc;
_setCursorPosition(newLoc, external);
}
}
void IOHIDSystem::_setCursorPosition(Point * newLoc, bool external)
{
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 ((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);
} else if ((evg->movedMask&NX_RMOUSEDRAGGEDMASK) && (evg->buttons & EV_RB)) {
_postMouseMoveEvent(NX_RMOUSEDRAGGED, newLoc, ts);
} else if (evg->movedMask & NX_MOUSEMOVEDMASK) {
_postMouseMoveEvent(NX_MOUSEMOVED, newLoc, ts);
}
}
if (cursorMoved && evg->mouseRectValid && (!PtInRect(newLoc, &evg->mouseRect)))
{
if (evg->mouseRectValid)
{
postEvent( NX_MOUSEEXITED,
newLoc,
ts,
NULL);
evg->mouseRectValid = 0;
}
}
ev_unlock(&evg->cursorSema);
}
void IOHIDSystem::_postMouseMoveEvent(int what,
Point * location,
AbsoluteTime ts)
{
NXEventData data;
bzero( &data, sizeof(data) );
data.mouseMove.dx = pointerDelta.x;
data.mouseMove.dy = pointerDelta.y;
pointerDelta.x = 0;
pointerDelta.y = 0;
postEvent(what, location, ts, &data);
}
IOReturn IOHIDSystem::newUserClient(task_t owningTask,
void * security_id,
UInt32 type,
IOUserClient ** handler)
{
return cmdGate->runAction((IOCommandGate::Action)doNewUserClient,
&owningTask, security_id, &type, handler);
}
IOReturn IOHIDSystem::doNewUserClient(IOHIDSystem *self, void * arg0, void * arg1,
void * arg2, void * arg3)
{
task_t owningTask = *(task_t *) arg0;
void * security_id = arg1;
UInt32 type = *(UInt32 *) arg2;
IOUserClient ** handler = (IOUserClient **) arg3;
return self->newUserClientGated(owningTask, security_id, type, handler);
}
IOReturn IOHIDSystem::newUserClientGated(task_t owningTask,
void * security_id,
UInt32 type,
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
err = kIOReturnUnsupported;
if( !newConnect)
continue;
if( (newConnect != paramConnect) && (
(false == newConnect->init())
|| (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*)
{ bool enable = (bool)p1;
if( enable) {
attachDefaultEventSources();
_resetMouseParameters();
_resetKeyboardParameters();
}
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*,void*,void*,void*,void*)
{ return cmdGate->runAction((IOCommandGate::Action)doExtPostEvent, p1);
}
IOReturn IOHIDSystem::doExtPostEvent(IOHIDSystem *self, void * arg0)
{
return self->extPostEventGated(arg0);
}
IOReturn IOHIDSystem::extPostEventGated(void *p1)
{
struct evioLLEvent * event = (struct evioLLEvent *)p1;
bool isMoveOrDragEvent = false;
int oldMovedMask;
if( activity_tickle_call != NULL ) { thread_call_enter(activity_tickle_call); }
if (event->type == NX_LMOUSEDRAGGED ||
event->type == NX_RMOUSEDRAGGED ||
event->type == NX_MOUSEMOVED)
isMoveOrDragEvent = true;
if( event->setCursor)
{
if (isMoveOrDragEvent)
{
oldMovedMask = evg->movedMask;
evg->movedMask = 0;
}
setCursorPosition(&event->location, true);
if (isMoveOrDragEvent)
evg->movedMask = oldMovedMask;
}
if( event->setFlags)
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (event->flags & KEYBOARD_FLAGSMASK);
AbsoluteTime ts;
clock_get_uptime(&ts);
postEvent( event->type,
&event->location,
ts,
&event->data);
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)
{
Point * loc = (Point *)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::makeParamProperty( OSDictionary * dict, const char * key,
const void * bytes, unsigned int length )
{
OSData * data;
data = OSData::withBytes( bytes, length );
if( data) {
dict->setObject( key, data);
data->release();
}
}
void IOHIDSystem::createParameters( void )
{
UInt64 nano;
IOFixed fixed;
UInt32 int32;
nano = EV_DCLICKTIME;
makeParamProperty( savedParameters, kIOHIDClickTimeKey,
&nano, sizeof(nano) );
nano = DAUTODIMPERIOD;
makeParamProperty( savedParameters, kIOHIDAutoDimThresholdKey,
&nano, sizeof(nano) );
makeParamProperty( savedParameters, kIOHIDAutoDimBrightnessKey,
&dimmedBrightness, sizeof(dimmedBrightness) );
makeParamProperty( savedParameters, kIOHIDClickSpaceKey,
&clickSpaceThresh, sizeof(clickSpaceThresh) );
nano = EV_DEFAULTKEYREPEAT;
makeParamProperty( savedParameters, kIOHIDKeyRepeatKey,
&nano, sizeof(nano) );
nano = EV_DEFAULTINITIALREPEAT;
makeParamProperty( savedParameters, kIOHIDInitialKeyRepeatKey,
&nano, sizeof(nano) );
fixed = 0x8000;
makeParamProperty( savedParameters, kIOHIDPointerAccelerationKey,
&fixed, sizeof(fixed) );
fixed = 0x5000;
makeParamProperty( savedParameters, kIOHIDScrollAccelerationKey,
&fixed, sizeof(fixed) );
fixed = kIOHIDButtonMode_EnableRightClick;
makeParamProperty( savedParameters, kIOHIDPointerButtonMode,
&fixed, sizeof(fixed) );
int32 = 250;
makeParamProperty( savedParameters, kIOHIDF12EjectDelayKey,
&int32, sizeof(int32) );
int32 = 0;
makeParamProperty( savedParameters, kIOHIDSlowKeysDelayKey,
&int32, sizeof(int32) );
int32 = 0; makeParamProperty( savedParameters, kIOHIDStickyKeysDisabledKey,
&int32, sizeof(int32) );
int32 = 0; makeParamProperty( savedParameters, kIOHIDStickyKeysOnKey,
&int32, sizeof(int32) );
int32 = 0; makeParamProperty( savedParameters, kIOHIDStickyKeysShiftTogglesKey,
&int32, sizeof(int32) );
setProperty( kIOHIDParametersKey, savedParameters );
savedParameters->release();
}
bool IOHIDSystem::updateProperties( void )
{
return cmdGate->runAction((IOCommandGate::Action)doUpdateProperties);
}
bool IOHIDSystem::doUpdateProperties(IOHIDSystem *self)
{
return self->updatePropertiesGated();
}
bool IOHIDSystem::updatePropertiesGated( void )
{
UInt64 autoDimTimeNano;
UInt64 idleTimeNano;
AbsoluteTime time1, time2;
if( eventsOpen) {
clock_get_uptime( &time1);
if( autoDimmed) {
autoDimTimeNano = 0;
SUB_ABSOLUTETIME( &time1, &autoDimTime);
ADD_ABSOLUTETIME( &time1, &autoDimPeriod);
absolutetime_to_nanoseconds( time1, &idleTimeNano);
} else {
time2 = autoDimTime;
SUB_ABSOLUTETIME( &time2, &time1);
absolutetime_to_nanoseconds( time2, &autoDimTimeNano);
time1 = autoDimPeriod;
SUB_ABSOLUTETIME( &time1, &time2);
absolutetime_to_nanoseconds( time1, &idleTimeNano);
}
} else {
absolutetime_to_nanoseconds( autoDimPeriod, &autoDimTimeNano);
idleTimeNano = 0; }
setProperty( kIOHIDAutoDimTimeKey,
&autoDimTimeNano, sizeof( UInt64));
setProperty( kIOHIDIdleTimeKey,
&idleTimeNano, sizeof( UInt64));
setProperty( kIOHIDAutoDimStateKey,
&autoDimmed, sizeof( autoDimmed));
setProperty( kIOHIDBrightnessKey,
&curBright, sizeof( curBright));
return true;
}
bool IOHIDSystem::serializeProperties( OSSerialize * s ) const
{
((IOHIDSystem *) this)->updateProperties();
return( super::serializeProperties( s ));
}
IOReturn IOHIDSystem::setProperties( OSObject * properties )
{
OSDictionary * dict;
IOReturn err = kIOReturnSuccess;
IOReturn ret;
dict = OSDynamicCast( OSDictionary, properties );
if( dict)
ret = setParamProperties( dict );
else
err = kIOReturnBadArgument;
return( err );
}
IOReturn IOHIDSystem::setParamProperties( OSDictionary * dict )
{
return cmdGate->runAction((IOCommandGate::Action)doSetParamProperties, dict);
}
IOReturn IOHIDSystem::doSetParamProperties(IOHIDSystem *self, void * arg0)
{
OSDictionary * dict = (OSDictionary *)arg0;
return self->setParamPropertiesGated(dict);
}
IOReturn IOHIDSystem::setParamPropertiesGated( OSDictionary * dict )
{
OSIterator * iter;
IOHIDevice * eventSrc;
OSData * data;
IOReturn ret;
IOReturn err = kIOReturnSuccess;
if (dict == NULL)
return kIOReturnError;
if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDClickTimeKey))))
{
UInt64 nano = *((UInt64 *)(data->getBytesNoCopy()));
nanoseconds_to_absolutetime(nano, &clickTimeThresh);
}
if( (data = OSDynamicCast( OSData,
dict->getObject(kIOHIDClickSpaceKey)))) {
clickSpaceThresh.x = ((UInt32 *) (data->getBytesNoCopy()))[EVSIOSCS_X];
clickSpaceThresh.y = ((UInt32 *) (data->getBytesNoCopy()))[EVSIOSCS_Y];
}
if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimThresholdKey)))) {
AbsoluteTime oldPeriod = autoDimPeriod;
UInt64 nano = *((UInt64 *)(data->getBytesNoCopy()));
nanoseconds_to_absolutetime(nano, &autoDimPeriod);
SUB_ABSOLUTETIME( &autoDimTime, &oldPeriod);
ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
}
if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimStateKey))))
forceAutoDimState( 0 != *((SInt32 *) (data->getBytesNoCopy())));
if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDBrightnessKey))))
setBrightness( *((SInt32 *) (data->getBytesNoCopy())));
if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimBrightnessKey))))
setAutoDimBrightness( *((SInt32 *) (data->getBytesNoCopy())));
if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDWaitCursorFrameIntervalKey))))
clock_interval_to_absolutetime_interval(*((UInt32 *)data->getBytesNoCopy()), kNanosecondScale,
&waitFrameRate);
if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDStickyKeysOnKey))))
isStickyKeysOn = *((UInt32 *)(data->getBytesNoCopy()));
iter = getOpenProviderIterator();
if( iter) {
while( (eventSrc = (IOHIDevice *) iter->getNextObject())) {
ret = eventSrc->setParamProperties( dict );
if( (ret != kIOReturnSuccess) && (ret != kIOReturnBadArgument))
err = ret;
}
iter->release();
}
dict->removeObject(kIOHIDResetKeyboardKey);
dict->removeObject(kIOHIDResetPointerKey);
OSDictionary * newParams = OSDictionary::withDictionary( savedParameters );
if( newParams) {
newParams->merge( dict );
setProperty( kIOHIDParametersKey, newParams );
newParams->release();
savedParameters = newParams;
}
return err;
}