IOUSBHubPolicyMaker.cpp [plain text]
#include <IOKit/IOKitKeys.h>
#include <IOKit/usb/IOUSBControllerV3.h>
#include <IOKit/usb/IOUSBHubPolicyMaker.h>
#include <IOKit/usb/IOUSBLog.h>
OSDefineMetaClass( IOUSBHubPolicyMaker, IOService )
OSDefineAbstractStructors( IOUSBHubPolicyMaker, IOService )
#define super IOService
#ifndef IOUSBHUBPOLICYMAKER_USE_KPRINTF
#define IOUSBHUBPOLICYMAKER_USE_KPRINTF 0
#endif
#if IOUSBHUBPOLICYMAKER_USE_KPRINTF
#undef USBLog
#undef USBError
void kprintf(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#define USBLog( LEVEL, FORMAT, ARGS... ) if ((LEVEL) <= IOUSBHUBPOLICYMAKER_USE_KPRINTF) { kprintf( FORMAT "\n", ## ARGS ) ; }
#define USBError( LEVEL, FORMAT, ARGS... ) { kprintf( FORMAT "\n", ## ARGS ) ; }
#endif
static IOPMPowerState ourPowerStates[kIOUSBHubNumberPowerStates] = {
{ kIOPMPowerStateVersion1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ kIOPMPowerStateVersion1, kIOPMRestartCapability, kIOPMRestart, kIOPMRestart, 0, 0, 0, 0, 0, 0, 0, 0 },
{ kIOPMPowerStateVersion1, kIOPMSleepCapability, kIOPMSleep, kIOPMSleep, 0, 0, 0, 0, 0, 0, 0, 0 },
{ kIOPMPowerStateVersion1, kIOPMLowPower, kIOPMLowPower, kIOPMLowPower, 0, 0, 0, 0, 0, 0, 0, 0 },
{ kIOPMPowerStateVersion1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
};
bool
IOUSBHubPolicyMaker::start(IOService * provider)
{
const IORegistryPlane *usbPlane = NULL;
UInt32 deviceCharacteristics;
IOReturn err;
IOUSBControllerV3 *v3Bus = NULL;
OSBoolean *boolObj = NULL;
OSNumber *numberObj = NULL;
_device = OSDynamicCast(IOUSBHubDevice, provider);
if (!_device || !super::start(provider))
return false;
_bus = OSDynamicCast(IOUSBControllerV2, _device->GetBus());
if (!_bus)
return false;
v3Bus = OSDynamicCast(IOUSBControllerV3, _bus);
if ( v3Bus )
{
boolObj = OSDynamicCast( OSBoolean, _device->getProperty(kUSBHubDontAllowLowPower) );
if ( boolObj && boolObj->isTrue() )
{
_dontAllowLowPower = true;
}
else
{
_dontAllowLowPower = false;
}
}
else
{
_dontAllowLowPower = true;
}
boolObj = OSDynamicCast( OSBoolean, _device->getProperty("kUSBNoExtraSleepCurrent") );
if ( boolObj && boolObj->isTrue() )
{
_dontAllowSleepPower = true;
}
else
{
_dontAllowSleepPower = false;
}
numberObj = OSDynamicCast( OSNumber, _device->getProperty(kUSBDeviceResumeRecoveryTime) );
if ( numberObj )
{
_hubResumeRecoveryTime = numberObj->unsigned32BitValue();
if ( _hubResumeRecoveryTime < 10 ) _hubResumeRecoveryTime = 10;
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - device %s, setting kUSBDeviceResumeRecoveryTime to %ld", this, _device->getName(), _hubResumeRecoveryTime );
}
else
{
_hubResumeRecoveryTime = kHubResumeRecoveryTime;
}
_powerStateChangingTo = kIOUSBHubPowerStateStable;
PMinit(); usbPlane = getPlane(kIOUSBPlane);
if (usbPlane)
{
deviceCharacteristics = _device->GetHubCharacteristics();
if (deviceCharacteristics & kIOUSBHubDeviceIsRootHub)
{
_isRootHub = true;
_device->attachToParent(getRegistryRoot(), usbPlane);
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - root policyMaker on bus[%p]", this, _bus);
_bus->joinPMtree(this);
}
else
{
IOUSBHubDevice *grandParentHub = OSDynamicCast(IOUSBHubDevice, _device->getParentEntry(usbPlane));
IOUSBHubPolicyMaker *policyMaker = NULL;
if (grandParentHub)
{
_parentHubDevice = grandParentHub;
UInt32 grandCharacteristics = grandParentHub->GetHubCharacteristics();
if (grandCharacteristics & kIOUSBHubDeviceIsOnHighSpeedBus)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub is on HS bus - setting characteristic", this);
_device->SetHubCharacteristics(deviceCharacteristics | kIOUSBHubDeviceIsOnHighSpeedBus);
}
else
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub is on classic speed bus - not changing characteristic", this);
}
if (grandCharacteristics & kIOUSBHubDeviceCanSleep)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub can sleep - setting characteristic", this);
_device->SetHubCharacteristics(deviceCharacteristics | kIOUSBHubDeviceCanSleep);
}
else
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub cannot sleep - not changing characteristic", this);
}
policyMaker = grandParentHub->GetPolicyMaker();
if (policyMaker)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - parent policyMaker[%p]", this, policyMaker);
policyMaker->joinPMtree(this);
}
}
}
}
AllocateExtraPower();
if (!ConfigureHubDriver())
{
USBError(1, "IOUSBHubPolicyMaker[%p]::start - ConfigureHubDriver returned false", this);
PMstop();
return false;
}
makeUsable();
err = registerPowerDriver(this, ourPowerStates, kIOUSBHubNumberPowerStates);
if (err)
{
USBError(1, "IOUSBHubPolicyMaker[%p]::start - err [%p] from registerPowerDriver", this, (void*)err);
PMstop();
return false;
}
_device->SetPolicyMaker(this);
return true;
}
#pragma mark еееее Power Manager еееее
unsigned long
IOUSBHubPolicyMaker::powerStateForDomainState ( IOPMPowerFlags domainState )
{
unsigned long ret = super::powerStateForDomainState( domainState );
USBLog(5, "IOUSBHubPolicyMaker[%p]::powerStateForDomainState - domainState(%p) - returning (%p)", this, (void*)domainState, (void*)ret);
return ret;
}
unsigned long
IOUSBHubPolicyMaker::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
{
unsigned long ret = super::maxCapabilityForDomainState( domainState );
USBLog(5, "IOUSBHubPolicyMaker[%p]::maxCapabilityForDomainState - domainState(%p) - returning (%p)", this, (void*)domainState, (void*)ret);
return ret;
}
IOReturn
IOUSBHubPolicyMaker::powerStateWillChangeTo ( IOPMPowerFlags capabilities, unsigned long stateNumber, IOService* whatDevice)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::powerStateWillChangeTo - capabilities[%p] stateNumber[%d] whatDevice[%p]", this, (void*)capabilities, (int)stateNumber, whatDevice);
_powerStateChangingTo = stateNumber;
return super::powerStateWillChangeTo( capabilities, stateNumber, whatDevice);
}
IOReturn
IOUSBHubPolicyMaker::setPowerState( unsigned long powerStateOrdinal, IOService* whatDevice )
{
IOReturn ret;
USBLog(5, "IOUSBHubPolicyMaker[%p]::setPowerState - powerStateOrdinal(%d) - whatDevice(%p) current state(%d) isInactive(%s)", this, (int)powerStateOrdinal, whatDevice, (int)_myPowerState, isInactive() ? "true" : "false");
if ( whatDevice != this )
{
USBLog(1,"IOUSBHubPolicyMaker[%p]::setPowerState - whatDevice != this", this);
return kIOPMAckImplied;
}
if ( isInactive() )
{
USBLog(3,"IOUSBHubPolicyMaker[%p]::setPowerState - I am inactive - bailing", this);
return kIOPMAckImplied;
}
if (powerStateOrdinal > kIOUSBHubPowerStateOn)
{
USBLog(1,"IOUSBHubPolicyMaker[%p]::setPowerState - bad ordinal(%d)", this, (int)powerStateOrdinal);
return kIOPMNoSuchState;
}
if (_myPowerState == powerStateOrdinal)
{
USBLog(5,"IOUSBHubPolicyMaker[%p]::setPowerState - already in correct power state (%d) - no op", this, (int)_myPowerState);
return kIOPMAckImplied;
}
ret = HubPowerChange(powerStateOrdinal);
USBLog(5, "IOUSBHubPolicyMaker[%p]::setPowerState - returning (%p)", this, (void*)ret);
return ret;
}
IOReturn
IOUSBHubPolicyMaker::powerStateDidChangeTo(IOPMPowerFlags capabilities, unsigned long stateNumber, IOService* whatDevice)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::powerStateDidChangeTo - capabilities[%p] stateNumber[%d] whatDevice[%p]", this, (void*)capabilities, (int)stateNumber, whatDevice);
_myPowerState = stateNumber;
return super::powerStateDidChangeTo(capabilities, stateNumber, whatDevice);
}
void
IOUSBHubPolicyMaker::powerChangeDone(unsigned long fromState)
{
_powerStateChangingTo = kIOUSBHubPowerStateStable;
if (_isRootHub && (_myPowerState < kIOUSBHubPowerStateSleep))
{
changePowerStateTo(kIOUSBHubPowerStateOn);
}
super::powerChangeDone(fromState);
}
IOReturn
IOUSBHubPolicyMaker::EnsureUsability(void)
{
USBLog(7, "IOUSBHubPolicyMaker[%p]::EnsureUsability - _myPowerState(%d) _dozeEnabled(%s)", this, (int)_myPowerState, _dozeEnabled ? "true" : "false");
if ((_myPowerState != kUSBPowerStateOn) || _dozeEnabled)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::EnsureUsability - _myPowerState(%d) _dozeEnabled(%s) - powering ON", this, (int)_myPowerState, _dozeEnabled ? "true" : "false");
_dozeEnabled = false;
changePowerStateToPriv(kIOUSBHubPowerStateOn);
}
return kIOReturnSuccess;
}
void
IOUSBHubPolicyMaker::AllocateExtraPower()
{
OSNumber *extraPowerProp;
UInt32 extraPowerNeeded = 0;
USBLog(2, "AppleUSBHub[%p]::AllocateExtraPower - _parentHubDevice(%p) _device(%p)", this, _parentHubDevice, _device);
if (!_parentHubDevice || !_device)
return;
extraPowerProp = (OSNumber *)_device->getProperty("ExtraPowerRequest");
if ( extraPowerProp )
extraPowerNeeded = extraPowerProp->unsigned32BitValue();
if (extraPowerNeeded)
{
_extraPower = _parentHubDevice->RequestExtraPower(extraPowerNeeded); USBLog(2, "AppleUSBHub[%p]::AllocateExtraPower - asked for extra power (%d) and received (%d)", this, (int)extraPowerNeeded, (int)_extraPower);
_extraPowerRemaining = _extraPower;
}
}
IOReturn
IOUSBHubPolicyMaker::GetExtraPortPower(UInt32 portNum, UInt32 *pExtraPower)
{
USBLog(2, "AppleUSBHub[%p]::GetExtraPortPower for port[%d] pExtraPower[%p] _extraPowerRemaining[%d]", this, (int)portNum, pExtraPower, (int)_extraPowerRemaining);
if (!_extraPowerRemaining || !pExtraPower)
return kIOReturnNoResources;
*pExtraPower = _extraPowerRemaining;
if (!_dontAllowSleepPower)
{
_device->setProperty(kAppleExtraPowerInSleep, _extraPowerRemaining, 32);
}
_extraPowerRemaining = 0;
return kIOReturnSuccess;
}
IOReturn
IOUSBHubPolicyMaker::ReturnExtraPortPower(UInt32 portNum, UInt32 extraPower)
{
USBLog(2, "AppleUSBHub[%p]::ReturnExtraPortPower for port[%d] _extraPowerRemaining[%d] extraPower[%d]", this, (int)portNum, (int)_extraPowerRemaining, (int)extraPower);
_extraPowerRemaining = extraPower;
_device->removeProperty(kAppleExtraPowerInSleep);
return kIOReturnSuccess;
}
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 0);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 1);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 2);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 3);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 4);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 5);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 6);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 7);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 8);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 9);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 10);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 11);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 12);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 13);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 14);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 15);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 16);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 17);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 18);
OSMetaClassDefineReservedUnused(IOUSBHubPolicyMaker, 19);