AppleHWMonitor.cpp [plain text]
#include <sys/cdefs.h>
#include "AppleHWMonitor.h"
#include <libkern/c++/OSContainers.h>
#include <libkern/OSByteOrder.h>
OSDefineMetaClass( IOHWMonitor, IOService )
OSDefineAbstractStructors(IOHWMonitor, IOService)
bool IOHWMonitor::systemIsRestarting = FALSE;
static const IOPMPowerState ourPowerStates[kIOHWMonitorNumPowerStates] =
{
{kIOPMPowerStateVersion1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{kIOPMPowerStateVersion1, kIOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
};
#ifdef APPLEHWMONITOR_DEBUG
void IOHWMonitor::initDebugID( IOService *provider )
{
IOService *provider2, *provider3;
OSData *regData;
const char *name;
UInt32 reg;
fDebugID[0] = '\0';
if ((provider2 = provider->getProvider()) == NULL ||
(provider3 = provider2->getProvider()) == NULL)
return;
if ((name = provider3->getName()) == NULL)
return;
if ((regData = OSDynamicCast(OSData, provider3->getProperty("reg"))) == NULL)
return;
reg = *((UInt32 *)regData->getBytesNoCopy());
sprintf(fDebugID, "%s@%lx", name, reg);
}
#endif
bool IOHWMonitor::start(IOService *provider)
{
mach_timespec_t WaitTimeOut;
IOService *service;
if ( !(IOService::start(provider)) )
return false;
#ifdef APPLEHWMONITOR_DEBUG
initDebugID(provider);
#endif
DLOG("IOHWMonitor::start(%s) - entered\n", fDebugID);
OSObject *obj;
OSNumber *num;
OSData *data;
char *ptr, type[32];
data = OSDynamicCast(OSData, provider->getProperty("version"));
if (!data)
{
IOLog("IOHWMonitor - no Params Version !!\n");
return false;
}
UInt32 version;
version = OSReadBigInt32(data->getBytesNoCopy(),0);
num = OSNumber::withNumber(version, 32);
if (!num)
{
IOLog("IOHWMonitor - can't set Params Version !!\n");
return false;
}
setProperty("version", num);
num->release();
obj = provider->getProperty("zone");
if (!obj)
{
IOLog("IOHWMonitor - no Zone !!\n");
return false;
}
setProperty("zone", obj);
obj = provider->getProperty("location");
if (!obj)
{
IOLog("IOHWMonitor - no Location !!\n");
return false;
}
data = OSDynamicCast(OSData, obj); if (data)
{
ptr = (char *)data->getBytesNoCopy();
DLOG("IOHWMonitor::start(%s) - found location '%s'\n", fDebugID, ptr);
setProperty("location", ptr); }
else
setProperty("location", obj);
obj = provider->getProperty("type");
if (!obj)
{
obj = provider->getProperty("device_type"); data = OSDynamicCast(OSData, obj);
if (!data)
{
IOLog("IOHWMonitor - no Type !!\n");
return false;
}
ptr = (char *)data->getBytesNoCopy();
strcpy(type, ptr);
DLOG("IOHWMonitor::start(%s) - found device_type '%s'\n", fDebugID, type);
for(unsigned int i = strlen(type); i >= 0; i--)
{
if (type[i] == '-')
{
type[i] = '\0';
break;
}
}
setProperty("type", type);
}
else
setProperty("type", obj);
DLOG("IOHWMonitor::start(%s) - waiting for pmon\n", fDebugID);
WaitTimeOut.tv_sec = 60;
WaitTimeOut.tv_nsec = 0;
service = waitForService(resourceMatching("IOPlatformMonitor"), &WaitTimeOut);
if(!service)
{
service = waitForService(resourceMatching("IOPlatformPlugin"), &WaitTimeOut);
}
if (service)
fIOPMon = OSDynamicCast (IOService, service->getProperty("IOPlatformMonitor"));
PMinit();
IOReturn status = registerPowerDriver( this, (IOPMPowerState *) ourPowerStates, kIOHWMonitorNumPowerStates );
if (status != kIOReturnSuccess)
{
IOLog("%s: Failed to registerPowerDriver.\n", getName());
}
provider->joinPMtree( this);
DLOG("IOHWMonitor::start register insterest in power changes\n");
registerPrioritySleepWakeInterest(&sysPowerDownHandler, this, 0);
DLOG("IOHWMonitor::start(%s) - done\n", fDebugID);
return true;
}
IOReturn IOHWMonitor::setPowerState(unsigned long whatState, IOService *policyMaker)
{
powerPolicyMaker = policyMaker;
sleeping = (whatState == kIOHWMonitorOffState);
if ( sleeping )
return busy ? kHWMonitorPowerAckLimit : IOPMAckImplied;
else
return IOPMAckImplied;
}
IOReturn IOHWMonitor::sysPowerDownHandler(void *target, void *refCon, UInt32 messageType, IOService *service, void *messageArgument, vm_size_t argSize )
{
IOReturn ret;
switch (messageType)
{
#if 0
case kIOMessageSystemWillSleep:
break;
#endif
case kIOMessageSystemWillPowerOff:
case kIOMessageSystemWillRestart:
systemIsRestarting = TRUE; ret = kIOReturnSuccess;
break;
default:
ret = kIOReturnUnsupported;
break;
}
return ret;
}
IOReturn IOHWMonitor::updateValue(const OSSymbol *func, const OSSymbol *key)
{
SInt32 val;
IOReturn ret;
if (sleeping || systemIsRestarting)
return kIOReturnOffline;
busy = true;
ret = callPlatformFunction(func, FALSE, (void *)fChannel, &val, NULL, NULL);
busy = false;
if (sleeping && powerPolicyMaker)
powerPolicyMaker->acknowledgePowerChange (this);
if(ret != kIOReturnSuccess)
return ret;
setNumber( key, val );
return ret;
}
void IOHWMonitor::setNumber( const OSSymbol * key, UInt32 val )
{
OSObject * obj;
OSNumber * num;
obj = getProperty( key );
num = OSDynamicCast(OSNumber, obj);
if (num)
{
num->setValue( val );
}
else if (!obj)
{
num = OSNumber::withNumber( val, 32 );
setProperty( key, num );
num->release();
}
}