#include <IOKit/system.h>
#include <IOKit/assert.h>
#include <libkern/c++/OSContainers.h>
#include <libkern/c++/OSCollectionIterator.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IOCommandQueue.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)
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)
#define super IOService
OSDefineMetaClassAndStructors(IOHIDSystem, IOService);
IOHIDSystem * IOHIDSystem::instance()
{
return evInstance;
}
bool IOHIDSystem::init(OSDictionary * properties)
{
if (!super::init(properties)) return false;
driverLock = NULL;
kickConsumerLock = NULL;
evScreen = NULL;
timerES = 0;
cmdQ = 0;
workLoop = 0;
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;
driverLock = IOLockAlloc(); kickConsumerLock = IOLockAlloc();
pointerLoc.x = INIT_CURSOR_X;
pointerLoc.y = INIT_CURSOR_Y;
pointerDelta.x = 0;
pointerDelta.y = 0;
evScreenSize = sizeof(EvScreen) * 6; evScreen = (void *) IOMalloc(evScreenSize);
if (!driverLock ||
!kickConsumerLock ||
!evScreenSize) break;
IOLockInit(driverLock);
IOLockInit(kickConsumerLock);
bzero(evScreen, evScreenSize);
workLoop = IOWorkLoop::workLoop();
cmdQ = IOCommandQueue::commandQueue
(this, (IOCommandQueueAction) &_doPerformInIOThread );
timerES = IOTimerEventSource::timerEventSource
(this, (IOTimerEventSource::Action) &_periodicEvents );
if (!workLoop || !cmdQ || !timerES)
break;
if ((workLoop->addEventSource(cmdQ) != kIOReturnSuccess)
|| (workLoop->addEventSource(timerES) != kIOReturnSuccess))
break;
publishNotify = addNotification(
gIOPublishNotification, serviceMatching("IOHIDevice"),
(IOServiceNotificationHandler) &publishNotificationHandler,
this, 0 );
if (!publishNotify) break;
registerService();
addNotification( gIOPublishNotification,serviceMatching("IODisplayWrangler"), (IOServiceNotificationHandler)displayWranglerUp, this, 0 );
iWasStarted = true;
} while(false);
if (!iWasStarted) evInstance = 0;
return iWasStarted;
}
bool displayWranglerUp( OSObject * us, void * ref, IOService * yourDevice )
{
if ( yourDevice != NULL ) {
((IOHIDSystem *)us)->displayManager = yourDevice;
((IOHIDSystem *)us)->displayState = yourDevice->registerInterestedDriver((IOService *)us);
}
return true;
}
IOReturn IOHIDSystem::powerStateDidChangeTo ( IOPMPowerFlags theFlags, unsigned long, IOService*)
{
displayState = theFlags;
return IOPMNoErr;
}
bool IOHIDSystem::publishNotificationHandler(
IOHIDSystem * self,
void * ,
IOService * newService )
{
self->attach( newService );
if( self->eventsOpen
&& OSDynamicCast(IOHIDevice, newService)) {
self->registerEventSource((IOHIDevice *) newService);
}
return true;
}
void IOHIDSystem::free()
{
if( driverLock)
evClose();
if (evScreen) IOFree( (void *)evScreen, evScreenSize );
evScreen = (void *)0;
evScreenSize = 0;
if (timerES) timerES->release();
if (cmdQ) cmdQ->release();
if (workLoop) workLoop->release();
if (publishNotify) publishNotify->release();
if (kickConsumerLock) IOLockFree( kickConsumerLock);
if (driverLock) IOLockFree( driverLock);
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)
{
IOTakeLock( driverLock);
if ( evOpenCalled == false )
{
IOUnlock( driverLock);
return kIOReturnBadArgument;
}
forceAutoDimState(false);
if( cursorEnabled)
hideCursor();
cursorStarted = false;
cursorEnabled = false;
IOUnlock( driverLock);
detachEventSources();
IOTakeLock( driverLock);
if ( evScreen != (void *)0 )
{
screens = 0;
lastShmemPtr = (void *)0;
}
setEventPort(MACH_PORT_NULL);
evOpenCalled = false;
eventsOpen = false;
IOUnlock( driverLock);
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;
sendWorkLoopCommand(this,(IOHIDAction)_performSpecialKeyMsg,(void*)msg);
}
void IOHIDSystem::_resetMouseParameters()
{
IOTakeLock( driverLock);
if ( eventsOpen == false )
{
IOUnlock( driverLock);
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;
IOUnlock( driverLock);
}
void IOHIDSystem::_resetKeyboardParameters()
{
}
int IOHIDSystem::registerScreen(IOGraphicsDevice * instance,
Bounds * bp)
{
EvScreen *esp;
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;
return(SCREENTOKEN + screens++);
}
void IOHIDSystem::unregisterScreen(int index)
{
index -= SCREENTOKEN;
IOTakeLock( driverLock);
if ( eventsOpen == false || index < 0 || index >= screens )
{
IOUnlock( driverLock);
return;
}
hideCursor();
((EvScreen*)evScreen)[index].instance = 0;
cursorScreens &= ~(1 << index);
setCursorPosition((Point *)&evg->cursorLoc, true);
showCursor();
IOUnlock( driverLock);
}
Bounds * IOHIDSystem::workspaceBounds()
{
return &workSpace;
}
IOReturn IOHIDSystem::createShmem(void* p1, void*, void*, void*, void*, void*)
{ int shmemVersion = (int)p1;
IOByteCount size;
if( shmemVersion != kIOHIDCurrentShmemVersion)
return( kIOReturnUnsupported);
IOTakeLock( driverLock);
if( 0 == globalMemory) {
size = sizeof(EvOffsets) + sizeof(EvGlobals);
globalMemory = IOBufferMemoryDescriptor::withOptions(
kIODirectionNone | kIOMemoryKernelUserShared, size );
if( !globalMemory) {
IOUnlock( driverLock);
return( kIOReturnNoMemory );
}
shmem_addr = (vm_offset_t) globalMemory->getBytesNoCopy();
shmem_size = size;
}
initShmem();
IOUnlock( driverLock);
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->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;
}
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();
break;
case NX_RMOUSEDOWN:
theTail->event.data.mouse.eventNum =
rightENum = getUniqueEventNum();
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) {
theTail->event.data.mouse.pressure = lastPressure;
}
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", getName());
kickEventConsumer();
#if PMON
pmon_log_event( PMON_SOURCE_EV,
KP_EV_QUEUE_FULL,
what,
evg->eventFlags,
theClock);
#endif
}
}
void IOHIDSystem::kickEventConsumer()
{
IOReturn err;
IOTakeLock( kickConsumerLock);
xpr_ev_post("kickEventConsumer (need == %d)\n",
needToKickEventConsumer,2,3,4,5);
if ( needToKickEventConsumer == true )
{
IOUnlock( kickConsumerLock);
return; }
needToKickEventConsumer = true; IOUnlock( kickConsumerLock);
err = sendWorkLoopCommand(this, (IOHIDAction)_performKickEventConsumer,
NULL);
if( err)
IOLog("%s: cmdQ fail %d\n", getName(), err);
}
IOReturn IOHIDSystem::sendWorkLoopCommand(OSObject * target,
IOHIDAction action,
void * data)
{
kern_return_t err;
err = cmdQ->enqueueCommand( true,
target,
(void *) action,
data );
return (err == KERN_SUCCESS) ? kIOReturnSuccess : kIOReturnNoMemory;
}
void IOHIDSystem::_doPerformInIOThread(void* self,
void* target,
void* action,
void* data,
void* )
{
(*((IOHIDAction)action))((OSObject *)target, data);
}
void IOHIDSystem::_performSpecialKeyMsg(IOHIDSystem * self,
struct evioSpecialKeyMsg *msg)
{
kern_return_t r;
xpr_ev_post("_performSpecialKeyMsg 0x%x\n", msg,2,3,4,5);
r = mach_msg_send_from_kernel( &msg->Head, msg->Head.msgh_size);
xpr_ev_post("_performSpecialKeyMsg: msg_send() == %d\n",r,2,3,4,5);
if ( r != MACH_MSG_SUCCESS )
{
IOLog("%s: _performSpecialKeyMsg msg_send returned %d\n",
self->getName(), r);
}
if ( r == MACH_SEND_INVALID_DEST )
{
self->setSpecialKeyPort(
msg->key,
MACH_PORT_NULL);
}
IOFree( (void *)msg, sizeof (struct evioSpecialKeyMsg) );
}
void IOHIDSystem::_performKickEventConsumer(IOHIDSystem * self, void *)
{
kern_return_t r;
mach_msg_header_t *msgh
xpr_ev_post("_performKickEventConsumer\n", 1,2,3,4,5);
IOTakeLock( self->kickConsumerLock);
self->needToKickEventConsumer = false; IOUnlock( self->kickConsumerLock);
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: _performKickEventConsumer msg_send returned %d\n",
self->getName(), 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;
IOTakeLock( driverLock);
if ( eventsOpen == false )
{
IOUnlock( driverLock);
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();
IOUnlock( driverLock);
return;
}
bool IOHIDSystem::resetCursor()
{
volatile Point * p;
UInt32 newScreens = 0;
SInt32 pinScreen = -1L;
p = &evg->cursorLoc;
EvScreen *screen = (EvScreen *)evScreen;
for (int i = 0; i < screens; i++ ) {
if ((screen[i].instance) && PtInRect(p, screen[i].bounds)) {
pinScreen = i;
newScreens |= (1 << i);
}
}
if (newScreens == 0)
pinScreen = 0;
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 );
resetCursor();
setBrightness();
showCursor();
ok = (kIOReturnSuccess ==
sendWorkLoopCommand(this, (IOHIDAction)_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 > EV_MAXCURSOR) ? EV_WAITCURSOR : 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 == false )
IOLog("%s: Seize of %s failed.\n", getName(), 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)
{
AbsoluteTime nextVBL, vblDeltaTime, eventDeltaTime, moveDeltaTime;
if( displayManager != NULL ) displayManager->activityTickle(0,0);
IOTakeLock( driverLock);
if( eventsOpen == false )
{
IOUnlock( driverLock);
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);
}
}
}
IOUnlock( driverLock);
}
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 ,
AbsoluteTime ts)
{
NXEventData outData;
if ( displayManager != NULL ) { displayManager->activityTickle(0,0); }
IOTakeLock( driverLock);
if ( eventsOpen == false )
{
IOUnlock( driverLock);
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;
IOUnlock( driverLock);
}
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)
{
NXEventData wheelData;
if ((deltaAxis1 == 0) && (deltaAxis2 == 0) && (deltaAxis3 == 0)) {
return;
}
IOTakeLock( driverLock);
if (!eventsOpen)
{
IOUnlock(driverLock);
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);
IOUnlock(driverLock);
return;
}
void IOHIDSystem::_tabletEvent(IOHIDSystem *self,
NXEventData *tabletData,
AbsoluteTime ts)
{
self->tabletEvent(tabletData, ts);
}
void IOHIDSystem::tabletEvent(NXEventData *tabletData,
AbsoluteTime ts)
{
IOTakeLock(driverLock);
if (eventsOpen) {
postEvent(NX_TABLETPOINTER,
(Point *)&evg->cursorLoc,
ts,
tabletData);
}
IOUnlock(driverLock);
return;
}
void IOHIDSystem::_proximityEvent(IOHIDSystem *self,
NXEventData *proximityData,
AbsoluteTime ts)
{
self->proximityEvent(proximityData, ts);
}
void IOHIDSystem::proximityEvent(NXEventData *proximityData,
AbsoluteTime ts)
{
IOTakeLock(driverLock);
if (eventsOpen) {
postEvent(NX_TABLETPROXIMITY,
(Point *)&evg->cursorLoc,
ts,
proximityData);
}
IOUnlock(driverLock);
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)
{
NXEventData outData;
if ( ! (displayState & IOPMDeviceUsable) ) { if ( eventType == NX_KEYDOWN ) {
return;
}
if ( displayManager != NULL ) { displayManager->activityTickle(0,0); }
return;
}
if ( displayManager != NULL ) { displayManager->activityTickle(0,0); }
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;
IOTakeLock( driverLock);
if ( eventsOpen == false )
{
IOUnlock( driverLock);
return;
}
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
postEvent( eventType,
(Point *)&pointerLoc,
ts,
&outData);
IOUnlock( driverLock);
}
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)
{
NXEventData outData;
int level = -1;
bzero( (void *)&outData, sizeof outData );
IOTakeLock( driverLock);
if ( eventsOpen == false )
{
IOUnlock( driverLock);
return;
}
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
if ( eventType == NX_KEYDOWN )
{
switch ( flavor )
{
case NX_KEYTYPE_SOUND_UP:
if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 )
{
if (masterAudioFunctions && masterAudioFunctions->incrementMasterVolume)
{
masterAudioFunctions->incrementMasterVolume();
}
}
else
{
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_SOUND_DOWN:
if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 )
{
if (masterAudioFunctions && masterAudioFunctions->decrementMasterVolume)
{
masterAudioFunctions->decrementMasterVolume();
}
}
else
{
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_MUTE:
if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 )
{
if (masterAudioFunctions && masterAudioFunctions->toggleMasterMute)
{
masterAudioFunctions->toggleMasterMute();
}
}
else
{
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
if( (0 == (flags & SPECIALKEYS_MODIFIER_MASK))
&& ((1 << flavor) & NX_SPECIALKEY_POST_MASK)) {
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);
}
IOUnlock( driverLock);
if ( level != -1 ) {
evSpecialKeyMsg( flavor,
eventType,
flags,
level);
}
}
void IOHIDSystem::_updateEventFlags(IOHIDSystem * self, unsigned flags)
{
self->updateEventFlags(flags);
}
void IOHIDSystem::updateEventFlags(unsigned flags)
{
IOTakeLock( driverLock);
if ( eventsOpen )
evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
| (flags & KEYBOARD_FLAGSMASK);
IOUnlock( driverLock);
}
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;
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;
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 ,
void * ,
UInt32 type,
IOUserClient ** handler)
{
IOUserClient * newConnect = 0;
IOReturn err = kIOReturnNoMemory;
IOTakeLock( driverLock);
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 );
IOUnlock( driverLock);
*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*)
{ bool enable = (bool)p1;
IOReturn err = kIOReturnSuccess;
IOTakeLock( driverLock);
if ( eventsOpen == false ) {
IOUnlock( driverLock);
return( kIOReturnNotOpen );
}
if( 0 == screens) { IOUnlock( driverLock);
return( kIOReturnNoDevice );
}
if( enable) {
if( cursorStarted) {
hideCursor();
cursorEnabled = resetCursor();
showCursor();
} else
cursorEnabled = startCursor();
} else
cursorEnabled = enable;
cursorCoupled = cursorEnabled;
IOUnlock( driverLock);
return( err);
}
IOReturn IOHIDSystem::extPostEvent(void*p1,void*,void*,void*,void*,void*)
{ struct evioLLEvent * event = (struct evioLLEvent *)p1;
IOTakeLock( driverLock);
if( event->setCursor)
setCursorPosition(&event->location, true);
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);
IOUnlock( driverLock);
return( kIOReturnSuccess);
}
IOReturn IOHIDSystem::extSetMouseLocation(void*p1,void*,void*,void*,void*,void*)
{ Point * loc = (Point *)p1;
IOTakeLock( driverLock);
setCursorPosition(loc, true);
IOUnlock( driverLock);
return( kIOReturnSuccess);
}
IOReturn IOHIDSystem::extGetButtonEventNum(void*p1,void*p2,void*,void*,void*,void*)
{ NXMouseButton button = (NXMouseButton)(int)p1;
int * eventNum = (int *)p2;
IOReturn err = kIOReturnSuccess;
IOTakeLock( driverLock);
switch( button) {
case NX_LeftButton:
*eventNum = leftENum;
break;
case NX_RightButton:
*eventNum = rightENum;
break;
default:
err = kIOReturnBadArgument;
}
IOUnlock( driverLock);
return( err);
}
bool IOHIDSystem::updateProperties( void )
{
UInt64 clickTimeThreshNano;
UInt64 autoDimThresholdNano;
UInt64 autoDimTimeNano;
UInt64 idleTimeNano;
AbsoluteTime time1, time2;
bool ok;
absolutetime_to_nanoseconds( clickTimeThresh, &clickTimeThreshNano);
absolutetime_to_nanoseconds( autoDimPeriod, &autoDimThresholdNano);
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; }
ok = setProperty( kIOHIDClickTimeKey, &clickTimeThreshNano,
sizeof( UInt64))
& setProperty( kIOHIDClickSpaceKey, &clickSpaceThresh,
sizeof( clickSpaceThresh))
& setProperty( kIOHIDAutoDimThresholdKey, &autoDimThresholdNano,
sizeof( UInt64))
& setProperty( kIOHIDAutoDimTimeKey, &autoDimTimeNano,
sizeof( UInt64))
& setProperty( kIOHIDIdleTimeKey, &idleTimeNano,
sizeof( UInt64))
& setProperty( kIOHIDAutoDimStateKey, &autoDimmed,
sizeof( autoDimmed))
& setProperty( kIOHIDBrightnessKey, &curBright,
sizeof( curBright))
& setProperty( kIOHIDAutoDimBrightnessKey, &dimmedBrightness,
sizeof( dimmedBrightness));
return( ok );
}
bool IOHIDSystem::serializeProperties( OSSerialize * s ) const
{
((IOHIDSystem *) this)->updateProperties();
return( super::serializeProperties( s ));
}
IOReturn IOHIDSystem::setParamProperties( OSDictionary * dict )
{
OSData * data;
IOReturn err = kIOReturnSuccess;
IOTakeLock( driverLock);
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())));
IOUnlock( driverLock);
return( err );
}