IOUSBHubPolicyMaker.cpp [plain text]
#include <IOKit/IOKitKeys.h>
#include <IOKit/usb/IOUSBControllerV3.h>
#include <IOKit/usb/IOUSBHubPolicyMaker.h>
#include <IOKit/usb/IOUSBLog.h>
#include "USBTracepoints.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
{
if( (gUSBStackDebugFlags & kUSBDontAllowHubLowPowerMask) != 0)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - boot arg not allowing low power: %x", this, (uint32_t)gUSBStackDebugFlags);
_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 %d", this, _device->getName(), (uint32_t)_hubResumeRecoveryTime );
}
else
{
_hubResumeRecoveryTime = kHubResumeRecoveryTime;
}
_powerStateChangingTo = kIOUSBHubPowerStateStable;
PMinit(); makeUsable();
usbPlane = getPlane(kIOUSBPlane);
if (usbPlane)
{
deviceCharacteristics = _device->GetHubCharacteristics();
if (deviceCharacteristics & kIOUSBHubDeviceIsRootHub)
{
_isRootHub = true;
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)
{
UInt32 newCharacteristics = deviceCharacteristics;
_parentHubDevice = grandParentHub;
UInt32 grandCharacteristics = grandParentHub->GetHubCharacteristics();
if (grandCharacteristics & kIOUSBHubDeviceIsOnHighSpeedBus)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub is on HS bus - setting characteristic", this);
newCharacteristics |= kIOUSBHubDeviceIsOnHighSpeedBus;
}
else if (grandCharacteristics & kIOUSBHubDeviceIsOnSuperSpeedBus)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub is on SS bus - setting characteristic", this);
newCharacteristics |= kIOUSBHubDeviceIsOnSuperSpeedBus;
}
else
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - grand hub is on classic speed bus (0x%x) - not changing characteristic", this, (int)grandCharacteristics);
}
if (grandCharacteristics & kIOUSBHubDeviceCanSleep)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub can sleep - setting characteristic", this);
newCharacteristics |= kIOUSBHubDeviceCanSleep;
}
else
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - hub cannot sleep - not changing characteristic", this);
}
if (newCharacteristics != deviceCharacteristics)
_device->SetHubCharacteristics(newCharacteristics);
policyMaker = grandParentHub->GetPolicyMaker();
if (policyMaker)
{
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - parent policyMaker[%p]", this, policyMaker);
policyMaker->joinPMtree(this);
}
}
}
}
if ( !_isRootHub)
AllocateExtraPower();
if (!ConfigureHubDriver())
{
USBLog(1, "IOUSBHubPolicyMaker[%p]::start - ConfigureHubDriver returned false", this);
PMstop();
return false;
}
numberObj = OSDynamicCast(OSNumber, _device->getProperty(kAppleStandardPortCurrentInSleep));
if ( numberObj )
{
UInt32 perPortPowerInSleep = 0;
perPortPowerInSleep = numberObj->unsigned32BitValue();
USBLog(5, "IOUSBHubPolicyMaker[%p]::start - setting per port power in sleep to %d", this, (uint32_t) perPortPowerInSleep);
_device->SetSleepCurrent( perPortPowerInSleep);
}
USBLog(7, "IOUSBHubPolicyMaker[%p]::start - calling registerPowerDriver", this);
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);
USBTrace( kUSBTHubPolicyMaker, kTPSetPowerState , (uintptr_t)this, (int)powerStateOrdinal, (uintptr_t)whatDevice, (int)_myPowerState);
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);
USBTrace( kUSBTHubPolicyMaker, kTPSetPowerState , (uintptr_t)this, (int)powerStateOrdinal, (int)_myPowerState, kIOPMNoSuchState);
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)
{
if (isInactive())
{
unsigned long curState = getPowerState();
if (_myPowerState != curState)
{
USBLog(2, "IOUSBHubPolicyMaker[%p]::powerChangeDone - we must have skipped powerStateDidChangeTo _myPowerState(%d) curState(%d)", this, (int)_myPowerState, (int)curState);
_myPowerState = curState;
}
}
_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;
}
#pragma mark Extra Power APIs
void
IOUSBHubPolicyMaker::AllocateExtraPower()
{
OSNumber *powerProp = NULL;
UInt32 maxPortCurrent = 0;
UInt32 totalExtraCurrent = 0;
UInt32 maxPortCurrentInSleep = 0;
UInt32 totalExtraCurrentInSleep = 0;
USBLog(2, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower - _parentHubDevice(%p - %s) _device(%p - %s)", this, _parentHubDevice, _parentHubDevice != NULL ? _parentHubDevice->getName() : "", _device, _device != NULL ? _device->getName() : "");
if (!_device)
return;
maxPortCurrent = _device->GetSpeed() == kUSBDeviceSpeedSuper ? kUSB3MaxPowerPerPort: kUSB2MaxPowerPerPort;; totalExtraCurrent = 0;
powerProp = OSDynamicCast(OSNumber, _device->getProperty(kAppleMaxPortCurrent));
if ( powerProp )
{
maxPortCurrent = powerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower Setting Maximum Port Current = %d", this, (uint32_t)maxPortCurrent);
}
else
{
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower no kAppleMaxPortCurrent property", this);
}
powerProp = OSDynamicCast(OSNumber, _device->getProperty(kAppleCurrentExtra));
if ( powerProp )
{
totalExtraCurrent = powerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower Setting Total Extra Current = %d", this, (uint32_t)totalExtraCurrent);
}
else
{
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower no kAppleCurrentExtra property", this);
}
powerProp = OSDynamicCast(OSNumber, _device->getProperty(kAppleMaxPortCurrentInSleep));
if ( powerProp )
{
maxPortCurrentInSleep = powerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower Setting Maximum Port Current in sleep = %d", this, (uint32_t)maxPortCurrentInSleep);
}
else
{
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower no kAppleMaxPortCurrentInSleep property", this);
}
powerProp = OSDynamicCast(OSNumber, _device->getProperty(kAppleCurrentExtraInSleep));
if ( powerProp )
{
totalExtraCurrentInSleep = powerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower Setting Total Extra Current in Sleep = %d", this, (uint32_t)totalExtraCurrentInSleep);
}
else
{
USBLog(6, "IOUSBHubPolicyMaker[%p]::AllocateExtraPower no kAppleCurrentExtraInSleep property", this);
}
_device->InitializeExtraPower(maxPortCurrent, totalExtraCurrent, maxPortCurrentInSleep, totalExtraCurrentInSleep);
}
UInt32
IOUSBHubPolicyMaker::RequestExtraPower(UInt32 portNum, UInt32 type, UInt32 requestedPower)
{
#pragma unused (portNum)
UInt32 returnValue = 0;
USBLog(5, "IOUSBHubPolicyMaker[%p]::RequestExtraPower for port %d, type: %d, requested %d", this, (uint32_t)portNum,(uint32_t)type, (uint32_t) requestedPower);
returnValue = _device->RequestExtraPower(type, requestedPower);
return returnValue;
}
IOReturn
IOUSBHubPolicyMaker::ReturnExtraPower(UInt32 portNum, UInt32 type, UInt32 returnedPower)
{
#pragma unused (portNum)
IOReturn kr = kIOReturnSuccess;
USBLog(5, "IOUSBHubPolicyMaker[%p]::ReturnExtraPower for port %d, type %d, returnedPower %d", this, (uint32_t)portNum, (uint32_t)type, (uint32_t) returnedPower);
kr = _device->ReturnExtraPower( type, returnedPower );
return kr;
}
#pragma mark Obsolete
IOReturn
IOUSBHubPolicyMaker::GetExtraPortPower(UInt32 portNum, UInt32 *pExtraPower)
{
#pragma unused (portNum, pExtraPower)
USBLog(1, "IOUSBHubPolicyMaker[%p]::GetExtraPortPower UNSUPPORTED", this);
return kIOReturnUnsupported;
}
IOReturn
IOUSBHubPolicyMaker::ReturnExtraPortPower(UInt32 portNum, UInt32 extraPower)
{
#pragma unused (portNum, extraPower)
USBLog(1, "IOUSBHubPolicyMaker[%p]::ReturnExtraPortPower UNSUPPORTED", this);
return kIOReturnUnsupported;
}
IOReturn
IOUSBHubPolicyMaker::GetPortInformation(UInt32 portNum, UInt32 *info)
{
#pragma unused (portNum, info)
USBLog(5, "IOUSBHubPolicyMaker[%p]::GetPortInformation UNSUPPORTED", this);
return kIOReturnUnsupported;
}
IOReturn
IOUSBHubPolicyMaker::ResetPort(UInt32 portNum)
{
#pragma unused (portNum)
USBLog(5, "IOUSBHubPolicyMaker[%p]::ResetPort UNSUPPORTED", this);
return kIOReturnUnsupported;
}
IOReturn
IOUSBHubPolicyMaker::SuspendPort(UInt32 portNum, bool suspend )
{
#pragma unused (portNum, suspend)
USBLog(5, "IOUSBHubPolicyMaker[%p]::SuspendPort UNSUPPORTED", this);
return kIOReturnUnsupported;
}
IOReturn
IOUSBHubPolicyMaker::ReEnumeratePort(UInt32 portNum, UInt32 options)
{
#pragma unused (portNum, options)
USBLog(5, "IOUSBHubPolicyMaker[%p]::ReEnumeratePort UNSUPPORTED", this);
return kIOReturnUnsupported;
}
#pragma mark MetaClass
OSMetaClassDefineReservedUsed(IOUSBHubPolicyMaker, 0);
OSMetaClassDefineReservedUsed(IOUSBHubPolicyMaker, 1);
OSMetaClassDefineReservedUsed(IOUSBHubPolicyMaker, 2);
OSMetaClassDefineReservedUsed(IOUSBHubPolicyMaker, 3);
OSMetaClassDefineReservedUsed(IOUSBHubPolicyMaker, 4);
OSMetaClassDefineReservedUsed(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);