AppleKeyswitch.cpp [plain text]
#include "AppleKeyswitch.h"
#define super IOService
OSDefineMetaClassAndStructors(AppleKeyswitch, IOService);
bool AppleKeyswitch::start(IOService *provider)
{
UInt8 val;
OSData *tempOSData;
IOReturn status;
DLOG("AppleKeyswitch::start entered.\n");
if (!super::start(provider))
return false;
myWorkLoop = (IOWorkLoop *)getWorkLoop();
if(myWorkLoop == NULL)
{
IOLog("AppleKeyswitch::start failed to get WorkLoop.\n");
return false;
}
interruptSource = IOInterruptEventSource::interruptEventSource(this, (IOInterruptEventAction)&AppleKeyswitch::interruptOccurred, provider, 0);
if (interruptSource == NULL)
{
IOLog("AppleKeyswitch::start failed to create interrupt event source.\n");
return false;
}
status = myWorkLoop->addEventSource(interruptSource);
if (status != kIOReturnSuccess)
{
IOLog("AppleKeyswitch::start failed to add interrupt event source to work loop.\n");
return false;
}
keyLargo_safeWriteRegUInt8 = OSSymbol::withCString("keyLargo_safeWriteRegUInt8");
keyLargo_safeReadRegUInt8 = OSSymbol::withCString("keyLargo_safeReadRegUInt8");
tempOSData = OSDynamicCast(OSData, provider->getProperty("reg"));
if (tempOSData == NULL)
{
IOLog("AppleKeyswitch::start failed to get 'reg' property.\n");
return false;
}
extIntGPIO = (UInt32*)tempOSData->getBytesNoCopy();
callPlatformFunction(keyLargo_safeWriteRegUInt8, false, (void *)(kKeyLargoGPIOBaseAddr + *extIntGPIO), (void *)0xFF, (void *)0x80, (void *)0);
IOSleep(100);
callPlatformFunction(keyLargo_safeReadRegUInt8, false, (void *)(kKeyLargoGPIOBaseAddr + *extIntGPIO), (void *)&val, (void *)0, (void *)0);
val = (val&0x2)>>1;
if(val)
{
state = 0;
setProperty("Keyswitch", false);
}
else
{
state = 1;
setProperty("Keyswitch", true);
}
interruptSource->enable();
registerService();
return true;
}
void AppleKeyswitch::stop(IOService *provider)
{
interruptSource->disable();
myWorkLoop->removeEventSource(interruptSource);
if (interruptSource != NULL)
{
interruptSource->release();
interruptSource = NULL;
}
if (myWorkLoop != NULL)
{
myWorkLoop->release();
myWorkLoop = NULL;
}
super::stop(provider);
}
void AppleKeyswitch::interruptOccurred(OSObject* obj, IOInterruptEventSource * source, int count)
{
AppleKeyswitch *AppleKeyswitchPtr = (AppleKeyswitch *)obj;
if (AppleKeyswitchPtr != NULL)
AppleKeyswitchPtr->toggle(false);
return;
}
void AppleKeyswitch::toggle(bool disableInts = false)
{
UInt8 i, val, total;
val = total = 0;
if (disableInts)
interruptSource->disable();
for(i=0; i<=100; i++)
{
callPlatformFunction(keyLargo_safeReadRegUInt8, false, (void *)(kKeyLargoGPIOBaseAddr + *extIntGPIO), (void *)&val, (void *)0, (void *)0);
val = (val&0x2)>>1;
total += val;
IOSleep(1);
}
if(total>80)
state = 1;
if(total<20)
state = 0;
if (state)
{
state = 0;
setProperty("Keyswitch", false);
registerService();
}
else
{
state = 1;
setProperty("Keyswitch", true);
registerService();
}
if (disableInts)
interruptSource->enable();
return;
}