IOPlatformControl.cpp [plain text]
#include <IOKit/IOLib.h>
#include "IOPlatformPluginDefs.h"
#include "IOPlatformPluginSymbols.h"
#include "IOPlatformCtrlLoop.h"
#include "IOPlatformControl.h"
#define super OSObject
OSDefineMetaClassAndStructors(IOPlatformControl, OSObject)
bool IOPlatformControl::init( void )
{
if (!super::init()) return(false);
if ((infoDict = OSDictionary::withCapacity(7)) == NULL) return(false);
controlDriver = NULL;
ctrlLoops = NULL;
return( initSymbols() );
}
bool IOPlatformControl::initSymbols( void )
{
return( true );
}
void IOPlatformControl::free( void )
{
if (infoDict) { infoDict->release(); infoDict = NULL; }
if (controlDriver) { controlDriver->release(); controlDriver = NULL; }
if (ctrlLoops) { ctrlLoops->release(); ctrlLoops = NULL; }
super::free();
}
ControlValue IOPlatformControl::applyCurrentValueTransform( ControlValue hwReading )
{
return hwReading;
}
ControlValue IOPlatformControl::applyTargetValueTransform( ControlValue hwReading )
{
return hwReading;
}
ControlValue IOPlatformControl::applyTargetValueInverseTransform( ControlValue pluginReading )
{
return pluginReading;
}
IOReturn IOPlatformControl::initPlatformControl( const OSDictionary *dict )
{
const OSNumber *number;
const OSData *data;
const OSString *string;
if ( !dict || !init() ) return(kIOReturnError);
if ((number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginControlIDKey))) != NULL)
{
infoDict->setObject(gIOPPluginControlIDKey, number );
}
else
{
IOLog("IOPlatformControl::initPlatformControl Invalid Thermal Profile omits Control ID\n");
return(kIOReturnBadArgument);
}
if ((string = OSDynamicCast(OSString, dict->getObject(gIOPPluginThermalLocalizedDescKey))) != NULL)
{
infoDict->setObject(gIOPPluginThermalLocalizedDescKey, string);
}
if ((number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginControlFlagsKey))) != NULL)
{
infoDict->setObject(gIOPPluginControlFlagsKey, 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);
}
infoDict->setObject(gIOPPluginRegisteredKey, kOSBooleanFalse);
setCurrentValue( 0x0 );
setTargetValue( 0x0 );
if ((number = OSDynamicCast(OSNumber, dict->getObject(kIOPPluginInitialTargetKey))) != NULL)
{
infoDict->setObject(kIOPPluginInitialTargetKey, number);
}
return(kIOReturnSuccess);
}
IOReturn IOPlatformControl::initPlatformControl( IOService * unknownControl, const OSDictionary * dict )
{
const OSNumber *number;
if ( !unknownControl || !dict || !init() ) return(kIOReturnError);
if ((number = OSDynamicCast(OSNumber, unknownControl->getProperty(gIOPPluginControlIDKey))) != NULL ||
(number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginControlIDKey))) != NULL)
{
infoDict->setObject(gIOPPluginControlIDKey, number );
}
else
{
IOLog("IOPlatformControl::initPlatformControl Unlisted Registrant %s omits Control ID\n", unknownControl->getName());
return(kIOReturnBadArgument);
}
infoDict->setObject(gIOPPluginRegisteredKey, kOSBooleanFalse);
setCurrentValue( 0x0 );
setTargetValue( 0x0 );
return(kIOReturnSuccess);
}
bool IOPlatformControl::isManaged( void )
{
return(!(getControlFlags()->unsigned32BitValue() & IOPControlFlagExternallyManaged));
}
OSBoolean *IOPlatformControl::isRegistered( void )
{
return(OSDynamicCast(OSBoolean, infoDict->getObject(gIOPPluginRegisteredKey)));
}
IOReturn IOPlatformControl::registerDriver( IOService * driver, const OSDictionary * dict, bool notify )
{
const OSData * data;
const OSString * string;
const OSNumber * number;
ControlValue controlValue;
if (isRegistered() == kOSBooleanTrue || driver == NULL)
{
return(kIOReturnError);
}
controlDriver = driver;
controlDriver->retain();
if (getControlDescKey() == NULL)
{
string = OSSymbol::withCString("UNKNOWN_CONTROL");
infoDict->setObject(gIOPPluginThermalLocalizedDescKey, string);
string->release();
}
if (getControlFlags() == NULL)
{
infoDict->setObject(kIOPPluginControlFlagsKey, gIOPPluginZero);
}
if (getControlType() == NULL)
{
if ((string = OSDynamicCast(OSString, controlDriver->getProperty(gIOPPluginTypeKey))) != NULL ||
(string = OSDynamicCast(OSString, dict->getObject(gIOPPluginTypeKey))) != NULL)
{
infoDict->setObject( gIOPPluginTypeKey, string );
}
else
{
IOLog("IOPlatformControl::registerDriver can't register Control ID %08X (%s) with unknown Control Type!\n",
getControlID()->unsigned32BitValue(), controlDriver->getName());
return(kIOReturnBadArgument);
}
}
if (getVersion() == NULL)
{
if ((number = OSDynamicCast(OSNumber, controlDriver->getProperty(gIOPPluginVersionKey))) != NULL ||
(number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginVersionKey))) != NULL)
{
infoDict->setObject(gIOPPluginVersionKey, number);
}
else
{
infoDict->setObject(gIOPPluginVersionKey, gIOPPluginOne);
IOLog("IOPlatformControl::registerDriver Control Driver %s did not supply version property, using default\n",
controlDriver->getName());
}
}
if ( infoDict->getObject( gIOPPluginControlMinValueKey ) == NULL )
{
if ( ( ( number = OSDynamicCast( OSNumber, controlDriver->getProperty( gIOPPluginControlMinValueKey ) ) ) != NULL ) ||
( ( number = OSDynamicCast( OSNumber, dict->getObject( gIOPPluginControlMinValueKey ) ) ) != NULL ) )
{
infoDict->setObject( gIOPPluginControlMinValueKey, number );
}
}
if ( infoDict->getObject( gIOPPluginControlMaxValueKey ) == NULL )
{
if ( ( ( number = OSDynamicCast( OSNumber, controlDriver->getProperty( gIOPPluginControlMaxValueKey ) ) ) != NULL ) ||
( ( number = OSDynamicCast( OSNumber, dict->getObject( gIOPPluginControlMaxValueKey ) ) ) != NULL ) )
{
infoDict->setObject( gIOPPluginControlMaxValueKey, number );
}
}
if ( infoDict->getObject( gIOPPluginControlSafeValueKey ) == NULL )
{
if ( ( ( number = OSDynamicCast( OSNumber, controlDriver->getProperty( gIOPPluginControlSafeValueKey ) ) ) != NULL ) ||
( ( number = OSDynamicCast( OSNumber, dict->getObject( gIOPPluginControlSafeValueKey ) ) ) != NULL ) )
{
infoDict->setObject( gIOPPluginControlSafeValueKey, number );
}
}
if (getControlLocation() == NULL)
{
if ((string = OSDynamicCast(OSString, controlDriver->getProperty(gIOPPluginLocationKey))) != NULL ||
(string = OSDynamicCast(OSString, dict->getObject(gIOPPluginLocationKey))) != NULL)
{
infoDict->setObject(gIOPPluginLocationKey, string);
}
else
{
string = OSSymbol::withCString("Unknown Control");
infoDict->setObject(gIOPPluginLocationKey, string);
string->release();
IOLog("IOPlatformControl::registerDriver Control Driver %s did not supply location property, using default\n",
controlDriver->getName());
}
}
if (getControlZone() == NULL)
{
if ((data = OSDynamicCast(OSData, controlDriver->getProperty(gIOPPluginZoneKey))) != NULL ||
(data = OSDynamicCast(OSData, dict->getObject(gIOPPluginZoneKey))) != NULL)
{
infoDict->setObject(gIOPPluginZoneKey, data);
}
else
{
UInt32 zero = 0;
data = OSData::withBytes( &zero, sizeof(UInt32) );
infoDict->setObject(gIOPPluginZoneKey, data);
data->release();
IOLog("IOPlatformControl::registerDriver Control Driver %s did not supply zone property, using default\n",
controlDriver->getName());
}
}
number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginCurrentValueKey));
if (number)
{
controlValue = number->unsigned32BitValue();
controlValue = applyCurrentValueTransform( controlValue );
setCurrentValue( controlValue );
}
else
{
setCurrentValue( 0x0 );
IOLog("IOPlatformControl::registerDriver Control Driver %s did not supply current-value, using default\n",
controlDriver->getName());
}
infoDict->setObject(gIOPPluginRegisteredKey, kOSBooleanTrue );
if ((number = OSDynamicCast(OSNumber, infoDict->getObject(kIOPPluginInitialTargetKey))) != NULL)
{
controlValue = number->unsigned32BitValue();
if (sendTargetValue(controlValue))
{
setTargetValue(controlValue);
}
else
{
IOLog("IOPlatformControl::registerDriver failed to send target-value to Control Driver %s\n",
controlDriver->getName());
}
}
else
{
number = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginTargetValueKey));
if (number)
{
controlValue = number->unsigned32BitValue();
controlValue = applyTargetValueTransform( controlValue );
setTargetValue( controlValue );
}
else
{
setTargetValue( 0x0 );
IOLog("IOPlatformControl::registerDriver Control Driver %s did not supply target-value, using default\n",
controlDriver->getName());
}
}
if (notify) notifyCtrlLoops();
return(kIOReturnSuccess);
}
void IOPlatformControl::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->controlRegistered( this );
}
}
}
bool IOPlatformControl::joinedCtrlLoop( IOPlatformCtrlLoop * aCtrlLoop )
{
if (!aCtrlLoop)
{
CONTROL_DLOG("IOPlatformControl::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)
{
CONTROL_DLOG("IOPlatformControl::joingCtrlLoop already a member\n");
return(false);
}
}
ctrlLoops->setObject(aCtrlLoop);
return(true);
}
}
bool IOPlatformControl::leftCtrlLoop( IOPlatformCtrlLoop * aCtrlLoop )
{
if (!aCtrlLoop)
{
CONTROL_DLOG("IOPlatformControl::leftCtrlLoop bad argument\n");
return(false);
}
if (!ctrlLoops)
{
CONTROL_DLOG("IOPlatformControl::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)
CONTROL_DLOG("IOPlatformControl::leftCtrlLoop not a member\n");
return(removed);
}
OSArray *IOPlatformControl::memberOfCtrlLoops( void )
{
return ctrlLoops;
}
OSDictionary *IOPlatformControl::getInfoDict( void )
{
return infoDict;
}
OSNumber *IOPlatformControl::getVersion( void )
{
return OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginVersionKey));
}
OSNumber *IOPlatformControl::getControlID( void )
{
return OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginControlIDKey));
}
OSString *IOPlatformControl::getControlType( void )
{
return OSDynamicCast(OSString, infoDict->getObject(gIOPPluginTypeKey));
}
UInt32 IOPlatformControl::getControlTypeID( void )
{
OSString * typeString;
typeString = getControlType();
if (!typeString)
return kIOPControlTypeUnknown;
else if (typeString->isEqualTo(gIOPPluginTypeSlewControl))
return kIOPControlTypeSlew;
else if (typeString->isEqualTo(gIOPPluginTypeFanRPMControl))
return kIOPControlTypeFanRPM;
else if (typeString->isEqualTo(gIOPPluginTypeFanPWMControl))
return kIOPControlTypeFanPWM;
else
return kIOPControlTypeUnknown;
}
OSData *IOPlatformControl::getControlZone( void )
{
return OSDynamicCast(OSData, infoDict->getObject(gIOPPluginZoneKey));
}
OSString *IOPlatformControl::getControlLocation( void )
{
return OSDynamicCast(OSString, infoDict->getObject(gIOPPluginLocationKey));
}
OSString *IOPlatformControl::getControlDescKey( void )
{
return OSDynamicCast(OSString, infoDict->getObject(gIOPPluginThermalLocalizedDescKey));
}
OSNumber *IOPlatformControl::getControlFlags( void )
{
return OSDynamicCast(OSNumber, infoDict->getObject(gIOPPluginControlFlagsKey));
}
ControlValue IOPlatformControl::getValue( const OSSymbol * key, ControlValue defaultValue )
{
ControlValue value;
OSNumber * num;
num = OSDynamicCast(OSNumber, infoDict->getObject(key));
value = num ? num->unsigned32BitValue() : defaultValue;
return value;
}
void IOPlatformControl::setValue( const OSSymbol * key, ControlValue newValue )
{
OSNumber * num;
num = OSDynamicCast(OSNumber, infoDict->getObject(key));
if (num)
{
num->setValue( newValue );
}
else
{
num = OSNumber::withNumber( newValue, 32 );
infoDict->setObject( key, num );
num->release();
}
}
ControlValue IOPlatformControl::getControlMinValue( void )
{
return getValue( gIOPPluginControlMinValueKey, 0x0 );
}
ControlValue IOPlatformControl::getControlMaxValue( void )
{
return getValue( gIOPPluginControlMaxValueKey, 0xFFFFFFFF );
}
ControlValue IOPlatformControl::getControlSafeValue( void )
{
return getValue( gIOPPluginControlSafeValueKey, 0xFFFF );
}
void IOPlatformControl::setControlMinValue( ControlValue min )
{
setValue( gIOPPluginControlMinValueKey, min );
}
void IOPlatformControl::setControlMaxValue( ControlValue max )
{
setValue( gIOPPluginControlMaxValueKey, max );
}
void IOPlatformControl::setControlSafeValue( ControlValue safe )
{
setValue( gIOPPluginControlSafeValueKey, safe );
}
ControlValue IOPlatformControl::getCurrentValue( void )
{
return getValue( gIOPPluginCurrentValueKey, 0x0 );
}
void IOPlatformControl::setCurrentValue( ControlValue newValue )
{
setValue( gIOPPluginCurrentValueKey, newValue );
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->controlCurrentValueWasSet( this, newValue );
}
}
}
ControlValue IOPlatformControl::forceAndFetchCurrentValue( void )
{
#if CONTROL_DEBUG
if (kIOReturnSuccess != sendForceUpdate())
{
CONTROL_DLOG("IOPlatformControl::forceAndFetchCurrentValue(0x%08lX) failed to force-update\n", getControlID()->unsigned32BitValue());
}
#else
sendForceUpdate();
#endif
return(fetchCurrentValue());
}
ControlValue IOPlatformControl::fetchCurrentValue( void )
{
OSDictionary * dict;
OSArray * controlInfo;
ControlValue pluginValue;
const OSNumber * hwReading, * myID, * tmpID;
if (!(isRegistered() == kOSBooleanTrue) || !controlDriver)
{
CONTROL_DLOG("IOPlatformControl::fetchCurrentValue not registered\n");
return 0x0;
}
if ((hwReading = OSDynamicCast(OSNumber, controlDriver->getProperty(gIOPPluginCurrentValueKey))) == NULL)
{
if ((controlInfo = OSDynamicCast(OSArray, controlDriver->getProperty("control-info"))) == NULL)
{
CONTROL_DLOG("IOPlatformControl::fetchCurrentValue can't find current value in controlDriver!!\n");
return 0x0;
}
int i, count;
myID = getControlID();
count = controlInfo->getCount();
for (i=0; i<count; i++)
{
if ((dict = OSDynamicCast(OSDictionary, controlInfo->getObject(i))) == NULL ||
(tmpID = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginControlIDKey))) == NULL ||
!myID->isEqualTo(tmpID) ||
(hwReading = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginCurrentValueKey))) == NULL)
{
continue;
}
}
if (!hwReading)
{
CONTROL_DLOG("IOPlatformControl::fetchCurrentValue can't find current value in control-info array!!\n");
return 0x0;
}
}
pluginValue = hwReading->unsigned32BitValue();
pluginValue = applyCurrentValueTransform( pluginValue );
return(pluginValue);
}
ControlValue IOPlatformControl::getTargetValue( void )
{
return getValue( gIOPPluginTargetValueKey, 0x0 );
}
void IOPlatformControl::setTargetValue( ControlValue target )
{
setValue( gIOPPluginTargetValueKey, target );
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->controlTargetValueWasSet( this, target );
}
}
}
IOReturn IOPlatformControl::sendMessage( OSDictionary * msg )
{
if (!(isRegistered() == kOSBooleanTrue) || !controlDriver)
{
CONTROL_DLOG("IOPlatformControl::sendMessage not registered\n");
return(kIOReturnOffline);
}
if ( !msg )
{
CONTROL_DLOG("IOPlatformControl::sendMessage no message\n");
return(kIOReturnBadArgument);
}
return(controlDriver->setProperties( msg ));
}
bool IOPlatformControl::sendTargetValue( ControlValue target, bool forced )
{
IOReturn status;
OSDictionary * dict;
const OSNumber * num;
if (!forced && infoDict->getObject(gIOPPluginForceControlTargetValKey))
{
return(true);
}
dict = OSDictionary::withCapacity(2);
if (!dict) return(false);
target = applyTargetValueInverseTransform(target);
num = OSNumber::withNumber( target, 32 );
dict->setObject(gIOPPluginTargetValueKey, num );
num->release();
dict->setObject(gIOPPluginControlIDKey, getControlID());
status = sendMessage( dict );
dict->release();
return ( status == kIOReturnSuccess );
}
IOReturn IOPlatformControl::sendForceUpdate( void )
{
IOReturn status;
OSDictionary *forceUpdateDict;
forceUpdateDict = OSDictionary::withCapacity(2);
if (!forceUpdateDict) return(kIOReturnNoMemory);
forceUpdateDict->setObject(gIOPPluginForceUpdateKey, gIOPPluginZero);
forceUpdateDict->setObject(gIOPPluginControlIDKey, getControlID());
status = sendMessage( forceUpdateDict );
forceUpdateDict->release();
return(status);
}
IOService *IOPlatformControl::getControlDriver( void )
{
return controlDriver;
}