IODisplayWrangler.cpp [plain text]
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IOUserClient.h>
#include <IOKit/graphics/IOGraphicsPrivate.h>
#include <IOKit/graphics/IOGraphicsTypesPrivate.h>
#include "IODisplayWrangler.h"
enum {
kIODisplayWranglerNumPowerStates = kIODisplayNumPowerStates + 1,
kIODisplayWranglerMaxPowerState = kIODisplayWranglerNumPowerStates - 1,
};
#define kIODisplayWrangler_AnnoyancePenalties "AnnoyancePenalties"
#define kIODisplayWrangler_AnnoyanceCaps "AnnoyanceCaps"
#define kIODisplayWrangler_IdleTimeoutMin "IdleTimeoutMin"
#define kIODisplayWrangler_IdleTimeoutMax "IdleTimeoutMax"
static int gCOMPRESS_TIME = 0;
#undef super
#define super IOService
OSDefineMetaClassAndStructors(IODisplayConnect, IOService)
bool IODisplayConnect::initWithConnection( IOIndex _connection )
{
char name[ 12 ];
if (!super::init())
return (false);
connection = _connection;
snprintf( name, sizeof(name), "display%d", (int)connection);
setName( name);
return (true);
}
IOFramebuffer * IODisplayConnect::getFramebuffer( void )
{
return ((IOFramebuffer *) getProvider());
}
IOIndex IODisplayConnect::getConnection( void )
{
return (connection);
}
IOReturn IODisplayConnect::getAttributeForConnection( IOSelect selector, uintptr_t * value )
{
if (!getProvider())
return (kIOReturnNotReady);
return ((IOFramebuffer *) getProvider())->getAttributeForConnection(connection, selector, value);
}
IOReturn IODisplayConnect::setAttributeForConnection( IOSelect selector, uintptr_t value )
{
if (!getProvider())
return (kIOReturnNotReady);
return ((IOFramebuffer *) getProvider())->setAttributeForConnection(connection, selector, value);
}
void IODisplayConnect::joinPMtree ( IOService * driver )
{
getProvider()->addPowerChild(driver);
}
#define super IOService
OSDefineMetaClassAndStructors(IODisplayWrangler, IOService);
IODisplayWrangler * gIODisplayWrangler;
enum { kStaticAnnoyanceEventArrayLength = 4 };
UInt32 IODisplayWrangler::staticAnnoyanceEventArrayLength = kStaticAnnoyanceEventArrayLength;
IODisplayWrangler::annoyance_event_t IODisplayWrangler::staticAnnoyanceEventArray[ kStaticAnnoyanceEventArrayLength ];
IODisplayWrangler::annoyance_cap_t IODisplayWrangler::staticAnnoyanceCapsArray[]
=
{
{ 120, 4 },
{ 300, 8 },
{ 600, 12 },
{ 900, 16 }
};
UInt32 IODisplayWrangler::staticAnnoyanceCapsArrayLength = sizeof(IODisplayWrangler::staticAnnoyanceCapsArray) / sizeof(*IODisplayWrangler::staticAnnoyanceCapsArray);
IODisplayWrangler::annoyance_penalty_t IODisplayWrangler::staticAnnoyancePenaltiesArray[]
=
{
{ 3, 8 },
{ 10, 4 },
{ 30, 2 },
{ 90, 1 }
};
UInt32 IODisplayWrangler::staticAnnoyancePenaltiesArrayLength = sizeof(staticAnnoyancePenaltiesArray) / sizeof(*staticAnnoyancePenaltiesArray);
void IODisplayWrangler::enqueueAnnoyance( UInt64 dim_time_secs, UInt64 wake_time_secs, UInt32 penalty )
{
annoyance_event_t * annoyance = & fAnnoyanceEventArray[ fAnnoyanceEventArrayQHead ];
annoyance->dim_time_secs = fLastDimTime_secs;
annoyance->wake_time_secs = fLastWakeTime_secs;
annoyance->penalty = penalty;
fAnnoyanceEventArrayQHead ++;
fAnnoyanceEventArrayQHead %= fAnnoyanceEventArrayLength;
}
IODisplayWrangler::annoyance_event_t * IODisplayWrangler::getNthAnnoyance( int i )
{
int j = ( fAnnoyanceEventArrayLength + fAnnoyanceEventArrayQHead - i - 1 ) % fAnnoyanceEventArrayLength;
return & fAnnoyanceEventArray[ j ];
}
bool IODisplayWrangler::serverStart(void)
{
mach_timespec_t timeout = { 120, 0 };
if (!gIODisplayWrangler)
waitForService(serviceMatching("IODisplayWrangler"), &timeout);
if (gIODisplayWrangler)
{
gIODisplayWrangler->fOpen = true;
if (gIODisplayWrangler->fMinutesToDim)
gIODisplayWrangler->setIdleTimerPeriod(gIODisplayWrangler->fMinutesToDim*60 / 2);
gIODisplayWrangler->activityTickle(0, 0);
}
return (gIODisplayWrangler != 0);
}
bool IODisplayWrangler::start( IOService * provider )
{
AbsoluteTime current_time;
UInt64 current_time_ns;
OSObject * notify;
if (!super::start(provider))
return (false);
assert( gIODisplayWrangler == 0 );
setProperty(kIOUserClientClassKey, "IOAccelerationUserClient");
fMatchingLock = IOLockAlloc();
fFramebuffers = OSSet::withCapacity( 1 );
fDisplays = OSSet::withCapacity( 1 );
AbsoluteTime_to_scalar(¤t_time) = mach_absolute_time();
absolutetime_to_nanoseconds(current_time, ¤t_time_ns);
fLastWakeTime_secs = current_time_ns / NSEC_PER_SEC;
fLastDimTime_secs = 0;
fAnnoyanceEventArrayLength = staticAnnoyanceEventArrayLength;
fAnnoyanceEventArray = staticAnnoyanceEventArray;
fAnnoyanceEventArrayQHead = 0;
fAnnoyanceCapsArrayLength = staticAnnoyanceCapsArrayLength;
fAnnoyanceCapsArray = staticAnnoyanceCapsArray;
fAnnoyancePenaltiesArrayLength = staticAnnoyancePenaltiesArrayLength;
fAnnoyancePenaltiesArray = staticAnnoyancePenaltiesArray;
fIdleTimeoutMin = 30; fIdleTimeoutMax = 600;
assert( fMatchingLock && fFramebuffers && fDisplays );
notify = addMatchingNotification( gIOPublishNotification,
serviceMatching("IODisplay"), _displayHandler,
this, fDisplays );
assert( notify );
notify = addMatchingNotification( gIOPublishNotification,
serviceMatching("IODisplayConnect"), _displayConnectHandler,
this, 0, 50000 );
assert( notify );
gIODisplayWrangler = this;
gIODisplayWrangler->initForPM();
getPMRootDomain()->publishFeature("AdaptiveDimming");
return (true);
}
bool IODisplayWrangler::_displayHandler( void * target, void * ref,
IOService * newService, IONotifier * notifier )
{
return (((IODisplayWrangler *)target)->displayHandler((OSSet *) ref,
(IODisplay *) newService));
}
bool IODisplayWrangler::_displayConnectHandler( void * target, void * ref,
IOService * newService, IONotifier * notifier )
{
return (((IODisplayWrangler *)target)->displayConnectHandler(ref,
(IODisplayConnect *) newService));
}
bool IODisplayWrangler::displayHandler( OSSet * set,
IODisplay * newDisplay )
{
assert( OSDynamicCast( IODisplay, newDisplay ));
IOTakeLock( fMatchingLock );
set->setObject( newDisplay );
IOUnlock( fMatchingLock );
return (true);
}
bool IODisplayWrangler::displayConnectHandler( void * ,
IODisplayConnect * connect )
{
SInt32 score = 50000;
OSIterator * iter;
IODisplay * display;
bool found = false;
assert( OSDynamicCast( IODisplayConnect, connect ));
IOTakeLock( fMatchingLock );
iter = OSCollectionIterator::withCollection( fDisplays );
if (iter)
{
while (!found && (display = (IODisplay *) iter->getNextObject()))
{
if (display->getConnection())
continue;
do
{
if (!display->attach(connect))
continue;
found = ((display->probe( connect, &score ))
&& (display->start( connect )));
if (!found)
display->detach( connect );
}
while (false);
}
iter->release();
}
IOUnlock( fMatchingLock );
return (true);
}
bool IODisplayWrangler::makeDisplayConnects( IOFramebuffer * fb )
{
IODisplayConnect * connect;
IOItemCount i;
for (i = 0; i < 1 ; i++)
{
connect = new IODisplayConnect;
if (0 == connect)
continue;
if ((connect->initWithConnection(i))
&& (connect->attach(fb)))
{
connect->registerService( kIOServiceSynchronous );
}
connect->release();
}
return (true);
}
void IODisplayWrangler::destroyDisplayConnects( IOFramebuffer * fb )
{
OSIterator * iter;
OSObject * next;
IODisplayConnect * connect;
IODisplay * display;
fb->removeProperty(kIOFBBuiltInKey);
iter = fb->getClientIterator();
if (iter)
{
while ((next = iter->getNextObject()))
{
if ((connect = OSDynamicCast(IODisplayConnect, next)))
{
if (connect->isInactive())
continue;
display = OSDynamicCast( IODisplay, connect->getClient());
if (display)
{
gIODisplayWrangler->fDisplays->removeObject( display );
display->PMstop();
}
connect->terminate( kIOServiceSynchronous );
}
}
iter->release();
}
}
void IODisplayWrangler::connectChange( IOFramebuffer * fb )
{
gIODisplayWrangler->activityTickle(0,0);
}
IODisplayConnect * IODisplayWrangler::getDisplayConnect(
IOFramebuffer * fb, IOIndex connect )
{
OSIterator * iter;
OSObject * next;
IODisplayConnect * connection = 0;
iter = fb->getClientIterator();
if (iter)
{
while ((next = iter->getNextObject()))
{
connection = OSDynamicCast( IODisplayConnect, next);
if (connection)
{
if (connection->isInactive())
continue;
if (0 == (connect--))
break;
}
}
iter->release();
}
return (connection);
}
IOReturn IODisplayWrangler::getConnectFlagsForDisplayMode(
IODisplayConnect * connect,
IODisplayModeID mode, UInt32 * flags )
{
IOReturn err = kIOReturnUnsupported;
IODisplay * display;
display = OSDynamicCast( IODisplay, connect->getClient());
if (display)
err = display->getConnectFlagsForDisplayMode( mode, flags );
else
{
err = connect->getFramebuffer()->connectFlags(
connect->getConnection(), mode, flags );
}
return (err);
}
IOReturn IODisplayWrangler::getFlagsForDisplayMode(
IOFramebuffer * fb,
IODisplayModeID mode, UInt32 * flags )
{
IODisplayConnect * connect;
connect = gIODisplayWrangler->getDisplayConnect( fb, 0 );
if (!connect)
return (fb->connectFlags(0, mode, flags));
return (gIODisplayWrangler->
getConnectFlagsForDisplayMode(connect, mode, flags));
}
static IOPMPowerState ourPowerStates[kIODisplayWranglerNumPowerStates] = {
{ 1, 0, 0, 0, 0,0,0,0,0,0,0,0 },
{ 1, 0, 0, IOPMPowerOn, 0,0,0,0,0,0,0,0 },
{ 1, 0, 0, IOPMPowerOn, 0,0,0,0,0,0,0,0 },
{ 1, IOPMDeviceUsable | kIOPMPreventIdleSleep, 0, IOPMPowerOn, 0,0,0,0,0,0,0,0 },
{ 1, IOPMDeviceUsable | kIOPMPreventIdleSleep, 0, IOPMPowerOn, 0,0,0,0,0,0,0,0 }
};
void IODisplayWrangler::initForPM(void )
{
PMinit();
joinPMtree( this );
registerPowerDriver( this, ourPowerStates, kIODisplayWranglerNumPowerStates );
makeUsable();
registerService();
}
unsigned long IODisplayWrangler::initialPowerStateForDomainState( IOPMPowerFlags domainState )
{
if (domainState & IOPMPowerOn)
return (kIODisplayWranglerMaxPowerState);
else
return (0);
}
IOReturn IODisplayWrangler::setAggressiveness( unsigned long type, unsigned long newLevel )
{
switch (type)
{
case kIOFBCaptureAggressiveness:
if (fDimCaptured && !newLevel)
activityTickle(0,0);
fDimCaptured = (0 != newLevel);
case kPMMinutesToDim:
if (kPMMinutesToDim == type)
{
fIdleTimeoutMax = fMinutesToDim * 60 - 5;
fMinutesToDim = newLevel;
}
newLevel = fDimCaptured ? 0 : fMinutesToDim;
if (newLevel == 0)
{
if (getPowerState() < kIODisplayWranglerMaxPowerState)
{
activityTickle(0,0);
changePowerStateToPriv( kIODisplayWranglerMaxPowerState );
}
}
setIdleTimerPeriod( newLevel*60 / 2);
break;
default:
break;
}
super::setAggressiveness(type, newLevel);
return (IOPMNoErr);
}
IOReturn IODisplayWrangler::setPowerState( unsigned long powerStateOrdinal, IOService * whatDevice )
{
if (powerStateOrdinal == 0)
{
changePowerStateToPriv(0);
return (IOPMNoErr);
}
DEBG1("W", " setPowerState(%ld), sys %d\n", powerStateOrdinal, gIOGraphicsSystemPower);
if (!gIOGraphicsSystemPower)
return (IOPMNoErr);
else if (powerStateOrdinal < getPowerState())
{
idleDisplays();
}
else if (powerStateOrdinal == kIODisplayWranglerMaxPowerState)
{
makeDisplaysUsable();
}
return (IOPMNoErr);
}
void IODisplayWrangler::makeDisplaysUsable ( void )
{
OSIterator * iter;
IODisplay * display;
IOTakeLock( fMatchingLock );
iter = OSCollectionIterator::withCollection( fDisplays );
if (iter)
{
while ((display = (IODisplay *) iter->getNextObject()))
{
display->makeDisplayUsable();
}
iter->release();
}
IOUnlock( fMatchingLock );
}
void IODisplayWrangler::idleDisplays ( void )
{
OSIterator * iter;
IODisplay * display;
UInt64 current_time_ns;
UInt64 current_time_secs;
if ( kIODisplayWranglerMaxPowerState == getPowerState() )
{
AbsoluteTime current_time_absolute;
AbsoluteTime_to_scalar(¤t_time_absolute) = mach_absolute_time();
absolutetime_to_nanoseconds(current_time_absolute, ¤t_time_ns);
current_time_secs = current_time_ns / NSEC_PER_SEC;
fLastDimTime_secs = current_time_secs;
}
IOTakeLock( fMatchingLock );
iter = OSCollectionIterator::withCollection( fDisplays );
if (iter)
{
while ((display = (IODisplay *) iter->getNextObject()))
{
display->dropOneLevel();
}
iter->release();
}
IOUnlock( fMatchingLock );
}
SInt32 IODisplayWrangler::nextIdleTimeout(
AbsoluteTime currentTime,
AbsoluteTime lastActivity,
unsigned int powerState)
{
UInt64 lastActivity_ns;
UInt64 lastActivity_secs;
UInt64 current_time_ns;
UInt64 current_time_secs;
SInt32 delay_till_time_secs;
SInt32 timeout_used_for_dim;
SInt32 delay_secs;
absolutetime_to_nanoseconds(currentTime, ¤t_time_ns);
current_time_secs = current_time_ns / NSEC_PER_SEC;
absolutetime_to_nanoseconds(lastActivity, &lastActivity_ns);
lastActivity_secs = lastActivity_ns / NSEC_PER_SEC;
if (!lastActivity_secs)
{
enum { kWindowServerStartTime = 24 * 60 * 60 };
return (kWindowServerStartTime);
}
switch( getPowerState() ) {
case 4:
delay_till_time_secs =
calculate_earliest_time_idle_timeout_allowed(
current_time_secs, lastActivity_secs, powerState);
if ( delay_till_time_secs > (SInt32)current_time_secs )
{
if( (int)(delay_till_time_secs - (SInt32)lastActivity_secs) >
(int)(fMinutesToDim*60 - 5) )
{
delay_till_time_secs = (SInt32)lastActivity_secs
+ (SInt32)(fMinutesToDim*60 - 5);
}
delay_secs = (SInt32)(delay_till_time_secs - current_time_secs);
} else {
SInt32 period = calculate_idle_timer_period(powerState);
delay_secs = (SInt32)(
(UInt64)lastActivity_secs
+ (UInt64)period
- (UInt64)current_time_secs);
}
break;
case 3:
timeout_used_for_dim = (SInt32)((SInt64)fLastDimTime_secs -
(SInt64)lastActivity_secs);
delay_secs = (SInt32)fMinutesToDim*60
- timeout_used_for_dim;
break;
case 2:
case 1:
delay_secs = fMinutesToDim*30;
break;
case 0:
delay_secs = 60;
break;
default:
delay_secs = 60;
break;
}
return delay_secs;
}
UInt32 IODisplayWrangler::calculate_idle_timer_period(int powerState)
{
UInt32 idle_timer_period;
if ( 4 == powerState )
{
if ( gCOMPRESS_TIME )
{
idle_timer_period = fMinutesToDim * 60 / 12;
}
else
{
idle_timer_period = fMinutesToDim * 60 / 5;
}
if ( idle_timer_period < fIdleTimeoutMin )
{
idle_timer_period = fIdleTimeoutMin;
}
else
if ( idle_timer_period > fIdleTimeoutMax )
{
idle_timer_period = fIdleTimeoutMax;
}
}
else
{
idle_timer_period = fMinutesToDim * 30;
}
return idle_timer_period;
}
bool IODisplayWrangler::activityTickle( unsigned long x, unsigned long y )
{
AbsoluteTime current_time_absolute;
if (!fOpen)
return (true);
AbsoluteTime_to_scalar(¤t_time_absolute) = mach_absolute_time();
if (AbsoluteTime_to_scalar(&fIdleUntil))
{
if (CMP_ABSOLUTETIME(¤t_time_absolute, &fIdleUntil) < 0)
return (true);
AbsoluteTime_to_scalar(&fIdleUntil) = 0;
}
if (super::activityTickle(kIOPMSuperclassPolicy1,
kIODisplayWranglerMaxPowerState) )
{
return (true);
}
UInt64 current_time_ns;
absolutetime_to_nanoseconds(current_time_absolute, ¤t_time_ns);
UInt64 current_time_secs = current_time_ns / NSEC_PER_SEC;
fLastWakeTime_secs = current_time_secs;
record_if_annoyance();
getPMRootDomain()->wakeFromDoze();
return (false);
}
void IODisplayWrangler::record_if_annoyance() {
UInt64 delta_secs = fLastWakeTime_secs - fLastDimTime_secs;
UInt32 penalty = calculate_penalty( delta_secs );
if ( penalty > 0 )
{
enqueueAnnoyance( fLastDimTime_secs, fLastWakeTime_secs, penalty );
}
}
UInt32 IODisplayWrangler::calculate_penalty( UInt32 time_between_dim_and_wake_secs )
{
UInt32 penalty = 0;
for (int i = 0; i < fAnnoyancePenaltiesArrayLength; i++)
{
if ( time_between_dim_and_wake_secs <= fAnnoyancePenaltiesArray[ i ].time_secs )
{
penalty = fAnnoyancePenaltiesArray[ i ].penalty_points;
break;
}
}
return penalty;
}
UInt64 IODisplayWrangler::calculate_latest_veto_till_time( UInt64 current_time_secs )
{
int total = 0;
UInt64 latest_veto_till_time_secs = 0;
UInt64 rolling_wake_time_secs = 0;
int i = 0, j = 0;
while ( j < fAnnoyanceCapsArrayLength )
{
while ( ( i < fAnnoyanceEventArrayLength )
&& ( 0 != getNthAnnoyance( i )->wake_time_secs )
&& ( (current_time_secs - getNthAnnoyance(i)->wake_time_secs)
< (UInt64)fAnnoyanceCapsArray[ j ].cutoff_time_secs )
)
{
rolling_wake_time_secs = getNthAnnoyance( i )->wake_time_secs;
total += getNthAnnoyance( i )->penalty;
i ++;
}
if ( total >= fAnnoyanceCapsArray[ j ].cutoff_points )
{
UInt64 veto_till_time_secs =
(UInt64)fAnnoyanceCapsArray[ j ].cutoff_time_secs
+ rolling_wake_time_secs;
if ( veto_till_time_secs > latest_veto_till_time_secs )
{
latest_veto_till_time_secs = veto_till_time_secs;
}
}
j ++;
}
return latest_veto_till_time_secs;
}
UInt64 IODisplayWrangler::calculate_earliest_time_idle_timeout_allowed(
UInt64 current_time_secs,
UInt64 last_activity_secs,
int powerState)
{
UInt32 idle_timer_period_secs = calculate_idle_timer_period(powerState);
UInt64 idle_timer_delay_till_time_secs =
last_activity_secs
+ (UInt64) idle_timer_period_secs;
UInt64 latest_veto_till_time_secs =
calculate_latest_veto_till_time( current_time_secs );
UInt64 delay_till_time_secs;
if ( idle_timer_delay_till_time_secs > latest_veto_till_time_secs )
{
delay_till_time_secs = idle_timer_delay_till_time_secs;
}
else
{
delay_till_time_secs = latest_veto_till_time_secs;
}
return delay_till_time_secs;
}
OSObject * IODisplayWrangler::copyProperty( const char * aKey ) const
{
if (!strcmp(aKey, kIOGraphicsPrefsKey))
return (IOFramebuffer::copyPreferences());
return (super::copyProperty(aKey));
}
IOReturn IODisplayWrangler::setProperties( OSObject * properties )
{
OSDictionary * dict;
OSDictionary * prefs;
OSObject * obj;
OSNumber * num;
uint32_t idleFor = 0;
enum { kIODisplayRequestDefaultIdleFor = 1000,
kIODisplayRequestMaxIdleFor = 15000 };
if (!(dict = OSDynamicCast(OSDictionary, properties)))
return (kIOReturnBadArgument);
if ((prefs = OSDynamicCast(OSDictionary,
dict->getObject(kIOGraphicsPrefsKey))))
{
return (IOFramebuffer::setPreferences(this, prefs));
}
obj = dict->getObject(kIORequestIdleKey);
if (kOSBooleanTrue == obj)
{
idleFor = kIODisplayRequestDefaultIdleFor;
}
else if (kOSBooleanFalse == obj)
{
AbsoluteTime_to_scalar(&fIdleUntil) = 0;
activityTickle(0, 0);
}
else if ((num = OSDynamicCast(OSNumber, obj)))
{
idleFor = num->unsigned32BitValue();
if (idleFor > kIODisplayRequestMaxIdleFor)
idleFor = kIODisplayRequestMaxIdleFor;
}
if (idleFor)
{
clock_interval_to_deadline(idleFor, kMillisecondScale, &fIdleUntil);
if (getPowerState() > 3)
changePowerStateToPriv(3);
if (getPowerState() > 1)
changePowerStateToPriv(1);
return (kIOReturnSuccess);
}
OSObject * value;
value = dict->getObject( "COMPRESS_TIME" );
if ( value )
{ OSNumber * number;
number = OSDynamicCast( OSNumber, value );
if ( number )
{
gCOMPRESS_TIME = number->unsigned32BitValue();
this->setProperty( "COMPRESS_TIME", number );
}
}
value = dict->getObject( kIODisplayWrangler_AnnoyancePenalties );
if ( value )
{
int penaltiesArrayLength;
OSArray * penaltiesArray;
penaltiesArray = OSDynamicCast( OSArray, value );
if ( ! penaltiesArray )
{
goto Return;
}
penaltiesArrayLength = penaltiesArray->getCount();
if ( ! ( penaltiesArrayLength <= fAnnoyancePenaltiesArrayLength ) )
{
goto Return;
}
for (int i = 0; i < penaltiesArrayLength; i++)
{
value = penaltiesArray->getObject( i );
OSArray * penalty_time_and_points_pair;
penalty_time_and_points_pair = OSDynamicCast( OSArray, value );
if ( ! penalty_time_and_points_pair )
{
goto Return;
}
if ( 2 != penalty_time_and_points_pair->getCount() )
{
goto Return;
}
OSObject * p0, * p1;
p0 = penalty_time_and_points_pair->getObject( 0 );
p1 = penalty_time_and_points_pair->getObject( 1 );
OSNumber * n0, * n1;
n0 = OSDynamicCast( OSNumber, p0 );
if ( ! n0 )
{
goto Return;
}
n1 = OSDynamicCast( OSNumber, p1 );
if ( ! n1 )
{
goto Return;
}
int time_secs = n0->unsigned32BitValue();
int penalty_points = n1->unsigned32BitValue();
fAnnoyancePenaltiesArray[ i ].time_secs = time_secs;
fAnnoyancePenaltiesArray[ i ].penalty_points = penalty_points;
}
this->setProperty( kIODisplayWrangler_AnnoyancePenalties, penaltiesArray );
}
value = dict->getObject( kIODisplayWrangler_AnnoyanceCaps );
if ( value )
{
int capsArrayLength;
OSArray * capsArray;
capsArray = OSDynamicCast( OSArray, value );
if ( ! capsArray )
{
goto Return;
}
capsArrayLength = capsArray->getCount();
if ( ! ( capsArrayLength <= fAnnoyanceCapsArrayLength ) )
{
goto Return;
}
for (int i = 0; i < capsArrayLength; i++)
{
value = capsArray->getObject( i );
OSArray * cap_time_and_points_pair;
cap_time_and_points_pair = OSDynamicCast( OSArray, value );
if ( ! cap_time_and_points_pair )
{
goto Return;
}
if ( 2 != cap_time_and_points_pair->getCount() )
{
goto Return;
}
OSObject * p0, * p1;
p0 = cap_time_and_points_pair->getObject( 0 );
p1 = cap_time_and_points_pair->getObject( 1 );
OSNumber * n0, * n1;
n0 = OSDynamicCast( OSNumber, p0 );
if ( ! n0 )
{
goto Return;
}
n1 = OSDynamicCast( OSNumber, p1 );
if ( ! n1 )
{
goto Return;
}
int cutoff_time_secs = n0->unsigned32BitValue();
int cutoff_points = n1->unsigned32BitValue();
fAnnoyanceCapsArray[ i ].cutoff_time_secs = cutoff_time_secs;
fAnnoyanceCapsArray[ i ].cutoff_points = cutoff_points;
}
this->setProperty( kIODisplayWrangler_AnnoyanceCaps, capsArray );
}
value = dict->getObject( kIODisplayWrangler_IdleTimeoutMin );
if ( value )
{ OSNumber * number;
number = OSDynamicCast( OSNumber, value );
if ( number )
{
fIdleTimeoutMin = number->unsigned32BitValue();
this->setProperty( kIODisplayWrangler_IdleTimeoutMin, number );
}
}
value = dict->getObject( kIODisplayWrangler_IdleTimeoutMax );
if ( value )
{ OSNumber * number;
number = OSDynamicCast( OSNumber, value );
if ( number )
{
fIdleTimeoutMax = number->unsigned32BitValue();
this->setProperty( kIODisplayWrangler_IdleTimeoutMax, number );
}
}
start_PM_idle_timer();
goto Return;
Return:
return kIOReturnSuccess;
}