IOPlatformSensor.cpp [plain text]
#include <IOKit/IOLib.h>
#include "IOPlatformPluginDefs.h"
#include "IOPlatformPluginSymbols.h"
#include "IOPlatformCtrlLoop.h"
#include "IOPlatformSensor.h"
#define super OSObject
OSDefineMetaClassAndStructors(IOPlatformSensor, OSObject)
bool IOPlatformSensor::init( void )
{
if (!super::init()) return(false);
if ((infoDict = OSDictionary::withCapacity(7)) == NULL) return(false);
sensorDriver = NULL;
return( initSymbols() );
}
bool IOPlatformSensor::initSymbols( void )
{
return( true );
}
IOReturn IOPlatformSensor::initPlatformSensor( const OSDictionary *dict )
{
const OSNumber *number;
const OSString *string;
const OSData *data;
if ( !dict || !init() ) return(kIOReturnError);
if ((number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginSensorIDKey))) != NULL)
{
infoDict->setObject(gIOPPluginSensorIDKey, number);
}
else
{
IOLog("IOPlatformSensor::initPlatformSensor Invalid Thermal Profile omits Sensor ID\n");
return(kIOReturnBadArgument);
}
if ((string = OSDynamicCast(OSString, dict->getObject(gIOPPluginThermalLocalizedDescKey))) != NULL)
{
infoDict->setObject(gIOPPluginThermalLocalizedDescKey, string);
}
if ((number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginSensorFlagsKey))) != NULL)
{
infoDict->setObject(gIOPPluginSensorFlagsKey, number);
}
if ((string = OSDynamicCast(OSString, dict->getObject(gIOPPluginTypeKey))) != NULL)
{
infoDict->setObject( gIOPPluginTypeKey, string);
}
if ((number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginVersionKey))) != NULL)
{
infoDict->setObject(gIOPPluginVersionKey, number);
}
if ((string = OSDynamicCast(OSString, dict->getObject(gIOPPluginLocationKey))) != NULL)
{
infoDict->setObject( gIOPPluginLocationKey, string);
}
if ((data = OSDynamicCast(OSData, dict->getObject(gIOPPluginZoneKey))) != NULL)
{
infoDict->setObject( gIOPPluginZoneKey, data);
}
if ((number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginPollingPeriodKey))) != NULL)
{
setPollingPeriod( number->unsigned32BitValue() );
}
if ((number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginPollingPeriodNSKey))) != NULL)
{
setPollingPeriodNS( number->unsigned32BitValue() );
}
infoDict->setObject(gIOPPluginRegisteredKey, kOSBooleanFalse);
SensorValue zeroVal;
zeroVal.sensValue = 0x0;
setCurrentValue( zeroVal );
return(kIOReturnSuccess);
}
IOReturn IOPlatformSensor::initPlatformSensor( IOService * unknownSensor, const OSDictionary * dict )
{
const OSNumber *number;
if ( !unknownSensor || !init() ) return(kIOReturnError);
if ((number = OSDynamicCast(OSNumber, unknownSensor->getProperty(gIOPPluginSensorIDKey))) != NULL)
{
infoDict->setObject(gIOPPluginSensorIDKey, number);
}
else
{
IOLog("IOPlatformSensor::initPlatformSensor Unlisted Registrant %s omits Sensor ID\n", unknownSensor->getName());
return(kIOReturnBadArgument);
}
if ((number = OSDynamicCast(OSNumber, unknownSensor->getProperty(gIOPPluginPollingPeriodKey))) != NULL)
{
setPollingPeriod( number->unsigned32BitValue() );
}
if ((number = OSDynamicCast(OSNumber, unknownSensor->getProperty(gIOPPluginPollingPeriodNSKey))) != NULL)
{
setPollingPeriodNS( number->unsigned32BitValue() );
}
infoDict->setObject(gIOPPluginRegisteredKey, kOSBooleanFalse);
SensorValue zeroVal;
zeroVal.sensValue = 0x0;
setCurrentValue( zeroVal );
return(kIOReturnSuccess);
}
void IOPlatformSensor::free( void )
{
if (infoDict) { infoDict->release(); infoDict = NULL; }
if (sensorDriver) { sensorDriver->release(); sensorDriver = NULL; }
super::free();
}
SensorValue IOPlatformSensor::applyCurrentValueTransform( SensorValue hwReading ) const
{
return hwReading;
}
OSBoolean *IOPlatformSensor::isRegistered( void )
{
return(OSDynamicCast(OSBoolean, infoDict->getObject(gIOPPluginRegisteredKey)));
}
IOReturn IOPlatformSensor::registerDriver( IOService * driver, const OSDictionary * dict, bool notify )
{
const OSString * string;
SensorValue pluginValue, hwValue;
const OSNumber * hwReading;
SENSOR_DLOG("IOPlatformSensor::registerDriver ID 0x%08lX\n", getSensorID()->unsigned32BitValue());
if (isRegistered() == kOSBooleanTrue || driver == NULL)
return( kIOReturnError );
sensorDriver = driver;
sensorDriver->retain();
if (getSensorDescKey() == NULL)
{
string = OSSymbol::withCString("UNKNOWN_SENSOR");
infoDict->setObject(gIOPPluginThermalLocalizedDescKey, string);
string->release();
}
if (getSensorFlags() == NULL)
{
infoDict->setObject(gIOPPluginSensorFlagsKey, gIOPPluginZero);
}
if (getSensorType() == NULL)
infoDict->setObject( gIOPPluginTypeKey, sensorDriver->getProperty( gIOPPluginTypeKey ) );
if (getVersion() == NULL)
infoDict->setObject( gIOPPluginVersionKey, sensorDriver->getProperty( gIOPPluginVersionKey ));
if (getSensorLocation() == NULL)
infoDict->setObject( gIOPPluginLocationKey, sensorDriver->getProperty( gIOPPluginLocationKey ));
if (getSensorZone() == NULL)
infoDict->setObject( gIOPPluginZoneKey, sensorDriver->getProperty( gIOPPluginZoneKey ));
infoDict->setObject(gIOPPluginRegisteredKey, kOSBooleanTrue );
hwReading = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginCurrentValueKey));
if (hwReading)
{
hwValue.sensValue = (SInt32)hwReading->unsigned32BitValue();
pluginValue = applyCurrentValueTransform( hwValue );
setCurrentValue( pluginValue );
}
if (!sendPollingPeriod())
{
SENSOR_DLOG("IOPlatformSensor::registerDriver failed to send polling period to sensor\n");
}
if (notify) notifyCtrlLoops();
return( kIOReturnSuccess );
}
void IOPlatformSensor::notifyCtrlLoops( void )
{
IOPlatformCtrlLoop * loop;
int i, count;
if (ctrlLoops)
{
count = ctrlLoops->getCount();
for ( i=0; i<count; i++ )
{
loop = OSDynamicCast(IOPlatformCtrlLoop, ctrlLoops->getObject(i));
if (loop) loop->sensorRegistered( this );
}
}
}
bool IOPlatformSensor::joinedCtrlLoop( IOPlatformCtrlLoop * aCtrlLoop )
{
if (!aCtrlLoop)
{
SENSOR_DLOG("IOPlatformSensor::joinedCtrlLoop bad argument\n");
return(false);
}
if (!ctrlLoops)
{
ctrlLoops = OSArray::withObjects((const OSObject **) &aCtrlLoop, 1);
return(true);
}
else
{
unsigned index, count;
count = ctrlLoops->getCount();
for (index = 0; index < count; index++)
{
if (ctrlLoops->getObject(index) == aCtrlLoop)
{
SENSOR_DLOG("IOPlatformSensor::joinCtrlLoop already a member\n");
return(false);
}
}
ctrlLoops->setObject(aCtrlLoop);
return(true);
}
}
bool IOPlatformSensor::leftCtrlLoop( IOPlatformCtrlLoop * aCtrlLoop )
{
if (!aCtrlLoop)
{
SENSOR_DLOG("IOPlatformSensor::leftCtrlLoop bad argument\n");
return(false);
}
if (!ctrlLoops)
{
SENSOR_DLOG("IOPlatformSensor::leftCtrlLoop no control loops\n");
return(false);
}
bool removed = false;
int index, count;
count = ctrlLoops->getCount();
for (index = 0; index < count; index++)
{
if (ctrlLoops->getObject(index) == aCtrlLoop)
{
ctrlLoops->removeObject(index);
removed = true;
}
}
if (!removed)
SENSOR_DLOG("IOPlatformSensor::leftCtrlLoop not a member\n");
return(removed);
}
OSArray *IOPlatformSensor::memberOfCtrlLoops( void )
{
return ctrlLoops;
}
OSDictionary *IOPlatformSensor::getInfoDict( void )
{
return infoDict;
}
OSNumber *IOPlatformSensor::getVersion( void )
{
return OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginVersionKey));
}
OSNumber *IOPlatformSensor::getSensorID( void )
{
return OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginSensorIDKey));
}
OSString *IOPlatformSensor::getSensorType( void )
{
return OSDynamicCast(OSString, infoDict->getObject(gIOPPluginTypeKey));
}
UInt32 IOPlatformSensor::getSensorTypeID( void )
{
OSString * typeString;
typeString = getSensorType();
if (!typeString)
return kIOPSensorTypeUnknown;
else if (typeString->isEqualTo(gIOPPluginTypeTempSensor))
return kIOPSensorTypeTemp;
else if (typeString->isEqualTo(gIOPPluginTypePowerSensor))
return kIOPSensorTypePower;
else if (typeString->isEqualTo(gIOPPluginTypeVoltageSensor))
return kIOPSensorTypeVoltage;
else if (typeString->isEqualTo(gIOPPluginTypeCurrentSensor))
return kIOPSensorTypeCurrent;
else if (typeString->isEqualTo(gIOPPluginTypeADCSensor))
return kIOPSensorTypeADC;
else
return kIOPSensorTypeUnknown;
}
OSData *IOPlatformSensor::getSensorZone( void )
{
return OSDynamicCast(OSData, infoDict->getObject(gIOPPluginZoneKey));
}
OSString *IOPlatformSensor::getSensorLocation( void )
{
return OSDynamicCast(OSString, infoDict->getObject(gIOPPluginLocationKey));
}
OSString *IOPlatformSensor::getSensorDescKey( void )
{
return OSDynamicCast(OSString, infoDict->getObject(gIOPPluginThermalLocalizedDescKey));
}
const OSNumber *IOPlatformSensor::getSensorFlags( void )
{
return OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginSensorFlagsKey));
}
SensorValue IOPlatformSensor::getCurrentValue( void )
{
SensorValue value;
OSNumber * num;
num = OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginCurrentValueKey));
value.sensValue = num ? (SInt32) num->unsigned32BitValue() : 0 ;
return value;
}
void IOPlatformSensor::setCurrentValue( SensorValue newValue )
{
OSNumber * num;
if ((num = OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginCurrentValueKey))) != NULL)
{
num->setValue( (UInt32)newValue.sensValue );
}
else
{
num = OSNumber::withNumber( (UInt32)newValue.sensValue, 32 );
infoDict->setObject(gIOPPluginCurrentValueKey, num );
num->release();
}
if (ctrlLoops)
{
IOPlatformCtrlLoop * aCtrlLoop;
int index, count;
count = ctrlLoops->getCount();
for (index = 0; index < count; index++)
{
if ((aCtrlLoop = OSDynamicCast( IOPlatformCtrlLoop, ctrlLoops->getObject(index) )) != NULL)
aCtrlLoop->sensorCurrentValueWasSet( this, newValue );
}
}
}
SensorValue IOPlatformSensor::forceAndFetchCurrentValue( void )
{
#if SENSOR_DEBUG
if (kIOReturnSuccess != sendForceUpdate())
{
SENSOR_DLOG("IOPlatformSensor::forceAndFetchCurrentValue(0x%08lX) failed to force-update\n", getSensorID()->unsigned32BitValue());
}
#else
sendForceUpdate();
#endif
return(fetchCurrentValue());
}
SensorValue IOPlatformSensor::fetchCurrentValue( void )
{
SensorValue pluginValue;
const OSNumber * hwReading;
pluginValue.sensValue = 0x0;
if (!(isRegistered() == kOSBooleanTrue) || !sensorDriver)
{
SENSOR_DLOG("IOPlatformSensor::fetchCurrentValue(0x%08lX) not registered\n", getSensorID()->unsigned32BitValue());
return pluginValue;
}
hwReading = OSDynamicCast(OSNumber, sensorDriver->getProperty(gIOPPluginCurrentValueKey));
if (!hwReading)
{
SENSOR_DLOG("IOPlatformSensor::fetchCurrentValue(0x%08lX) failed to fetch IOHWSensor's current-value property\n", getSensorID()->unsigned32BitValue());
return pluginValue;
}
pluginValue.sensValue = (SInt32)hwReading->unsigned32BitValue();
pluginValue = applyCurrentValueTransform( pluginValue );
return pluginValue;
}
UInt32 IOPlatformSensor::getPollingPeriodPrimitive( const OSSymbol * key )
{
OSNumber * num;
num = OSDynamicCast(OSNumber, infoDict->getObject( key ));
if (num)
{
return num->unsigned32BitValue();
}
else
{
num = OSNumber::withNumber( (UInt32) kIOPPluginNoPolling, 32 );
infoDict->setObject( key, num );
num->release();
return (UInt32) kIOPPluginNoPolling;
}
}
void IOPlatformSensor::setPollingPeriodPrimitive( const OSSymbol * key, UInt32 value )
{
OSNumber * num;
num = OSDynamicCast(OSNumber, infoDict->getObject( key ));
if (num)
{
num->setValue( value );
}
else
{
num = OSNumber::withNumber( value, 32 );
infoDict->setObject( key, num );
num->release();
}
}
UInt32 IOPlatformSensor::getPollingPeriod( void )
{
return getPollingPeriodPrimitive( gIOPPluginPollingPeriodKey );
}
UInt32 IOPlatformSensor::getPollingPeriodNS( void )
{
return getPollingPeriodPrimitive( gIOPPluginPollingPeriodNSKey );
}
void IOPlatformSensor::setPollingPeriod( UInt32 sec )
{
setPollingPeriodPrimitive( gIOPPluginPollingPeriodKey, sec );
}
void IOPlatformSensor::setPollingPeriodNS( UInt32 nsec )
{
setPollingPeriodPrimitive( gIOPPluginPollingPeriodNSKey, nsec );
}
IOReturn IOPlatformSensor::sendMessage( OSDictionary * msg )
{
if (!(isRegistered() == kOSBooleanTrue) || !sensorDriver)
{
SENSOR_DLOG("IOPlatformSensor::sendMessage not registered\n");
return(kIOReturnOffline);
}
if ( !msg )
{
SENSOR_DLOG("IOPlatformSensor::sendMessage no message\n");
return(kIOReturnBadArgument);
}
return(sensorDriver->setProperties( msg ));
}
bool IOPlatformSensor::sendPollingPeriod( void )
{
OSDictionary * msgDict;
IOReturn status;
const OSNumber * num;
msgDict = OSDictionary::withCapacity(3);
msgDict->setObject(gIOPPluginSensorIDKey, getSensorID());
num = OSNumber::withNumber( getPollingPeriod(), 32 );
msgDict->setObject(gIOPPluginPollingPeriodKey, num );
num->release();
num = OSNumber::withNumber( getPollingPeriodNS(), 32 );
msgDict->setObject(gIOPPluginPollingPeriodNSKey, num );
num->release();
status = sendMessage( msgDict );
msgDict->release();
if (status != kIOReturnSuccess)
{
SENSOR_DLOG("IOPlatformSensor::sendPollingPeriod sendMessage() failed!!\n");
return(false);
}
else
{
return(true);
}
}
IOReturn IOPlatformSensor::sendForceUpdate( void )
{
IOReturn status;
OSDictionary *forceUpdateDict;
forceUpdateDict = OSDictionary::withCapacity(2);
if (!forceUpdateDict) return(kIOReturnNoMemory);
forceUpdateDict->setObject(gIOPPluginForceUpdateKey, gIOPPluginZero);
forceUpdateDict->setObject(gIOPPluginSensorIDKey, getSensorID());
status = sendMessage( forceUpdateDict );
forceUpdateDict->release();
return(status);
}
IOService *IOPlatformSensor::getSensorDriver( void )
{
return sensorDriver;
}