IOUSBHubDevice.cpp [plain text]
#include <libkern/OSByteOrder.h>
#include <libkern/OSAtomic.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/usb/IOUSBLog.h>
#include <IOKit/usb/IOUSBHubDevice.h>
#ifndef IOUSBHUBDEVICE_USE_KPRINTF
#define IOUSBHUBDEVICE_USE_KPRINTF 0
#endif
#if IOUSBHUBDEVICE_USE_KPRINTF
#undef USBLog
#undef USBError
void kprintf(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#define USBLog( LEVEL, FORMAT, ARGS... ) if ((LEVEL) <= IOUSBHUBDEVICE_USE_KPRINTF) { kprintf( FORMAT "\n", ## ARGS ) ; }
#define USBError( LEVEL, FORMAT, ARGS... ) { kprintf( FORMAT "\n", ## ARGS ) ; }
#endif
#define super IOUSBDevice
#define _MAXPORTCURRENT _expansionData->_maxPortCurrent
#define _TOTALEXTRACURRENT _expansionData->_totalExtraCurrent
#define _TOTALEXTRASLEEPCURRENT _expansionData->_totalSleepCurrent
#define _CANREQUESTEXTRAPOWER _expansionData->_canRequestExtraPower
#define _EXTRAPOWERFORPORTS _expansionData->_extraPowerForPorts
#define _EXTRAPOWERALLOCATED _expansionData->_extraPowerAllocated
#define _REQUESTFROMPARENT _expansionData->_requestFromParent
#define _MAXPORTSLEEPCURRENT _expansionData->_maxPortSleepCurrent
#define _EXTRASLEEPPOWERALLOCATED _expansionData->_extraSleepPowerAllocated
#define _CANREQUESTEXTRASLEEPPOWER _expansionData->_canRequestExtraSleepPower
#define _STANDARD_PORT_POWER_IN_SLEEP _expansionData->_standardPortSleepCurrent
#define _UNCONNECTEDEXTERNALPORTS _expansionData->_unconnectedExternalPorts
#define _EXTERNAL_PORTS _expansionData->_externalPorts
#define _REVOCABLECURRENT _expansionData->_revocablePower
#define _USBPLANE_PARENT super::_expansionData->_usbPlaneParent
#define _STANDARD_PORT_POWER super::_expansionData->_standardUSBPortPower
OSDefineMetaClassAndStructors( IOUSBHubDevice, IOUSBDevice )
IOUSBHubDevice*
IOUSBHubDevice::NewHubDevice()
{
IOUSBHubDevice *me = new IOUSBHubDevice;
if (!me)
return NULL;
if (!me->init())
{
me->release();
me = NULL;
}
return me;
}
bool
IOUSBHubDevice::init()
{
if (!super::init())
return false;
if (!_expansionData)
{
_expansionData = (ExpansionData *)IOMalloc(sizeof(ExpansionData));
if (!_expansionData)
return false;
bzero(_expansionData, sizeof(ExpansionData));
}
return true;
}
bool
IOUSBHubDevice::start(IOService *provider)
{
USBLog(6, "IOUSBHubDevice[%p]::start", this );
if (!super::start(provider))
return false;
if (!InitializeCharacteristics())
return false;
return true;
}
bool
IOUSBHubDevice::InitializeCharacteristics()
{
UInt32 characteristics = 0;
SetHubCharacteristics(characteristics);
return true;
}
void
IOUSBHubDevice::stop( IOService *provider )
{
super::stop(provider);
}
void
IOUSBHubDevice::free()
{
if (_expansionData)
{
IOFree(_expansionData, sizeof(ExpansionData));
_expansionData = NULL;
}
super::free();
}
void
IOUSBHubDevice::SetHubCharacteristics(UInt32 characteristics)
{
_myCharacteristics = characteristics;
#if DEBUG_LEVEL != DEBUG_LEVEL_PRODUCTION
setProperty("characteristics", _myCharacteristics, 32);
#endif
}
UInt32
IOUSBHubDevice::GetHubCharacteristics()
{
USBLog(5, "IOUSBHubDevice[%p]::GetHubCharacteristics - returning (0x%x)", this, (int)_myCharacteristics);
return _myCharacteristics;
}
UInt32
IOUSBHubDevice::GetMaxProvidedPower()
{
return _MAXPORTCURRENT;
}
UInt32
IOUSBHubDevice::RequestProvidedPower(UInt32 requestedPower)
{
if (requestedPower <= 500)
return requestedPower;
else
return 500;
}
void
IOUSBHubDevice::SetPolicyMaker(IOUSBHubPolicyMaker *policyMaker)
{
USBLog(6, "IOUSBHubDevice[%p]::SetPolicyMaker set to %p", this, policyMaker );
_myPolicyMaker = policyMaker;
}
IOUSBHubPolicyMaker *
IOUSBHubDevice::GetPolicyMaker(void)
{
return _myPolicyMaker;
}
#pragma mark Extra Power
UInt32
IOUSBHubDevice::RequestExtraPower(UInt32 type, UInt32 requestedPower)
{
UInt32 returnValue = 0;
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower type: %d, requested %d", this, (uint32_t)type, (uint32_t) requestedPower);
if ( type == kUSBPowerDuringWake || type == kUSBPowerDuringWakeRevocable || type == kUSBPowerDuringWakeUSB3)
{
IOReturn kr = kIOReturnSuccess;
uint64_t extraAllocated = 0;
if ( IOUSBDevice::_expansionData && IOUSBDevice::_expansionData->_commandGate && IOUSBDevice::_expansionData->_workLoop)
{
IOCommandGate * gate = IOUSBDevice::_expansionData->_commandGate;
IOWorkLoop * workLoop = IOUSBDevice::_expansionData->_workLoop;
retain();
workLoop->retain();
gate->retain();
kr = gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOUSBHubDevice::RequestExtraWakePowerGated), (void *)type, (void *)requestedPower, &extraAllocated);
if ( kr != kIOReturnSuccess )
{
USBLog(2,"IOUSBHubDevice[%p]::RequestExtraPower GatedRequestExtraPower runAction() failed (0x%x)", this, kr);
}
gate->release();
workLoop->release();
release();
}
returnValue = (UInt32) extraAllocated;
}
else if ( type == kUSBPowerDuringSleep )
{
returnValue = RequestSleepPower( requestedPower );
}
else if ( type == kUSBPowerRequestWakeReallocate || type == kUSBPowerRequestSleepReallocate)
{
SendExtraPowerMessage( type, requestedPower );
}
return returnValue;
}
#pragma mark Request Extra Power (Wake)
IOReturn
IOUSBHubDevice::RequestExtraWakePowerGated(uint64_t wakeType, uint64_t requestedPower, uint64_t * powerAllocated)
{
uint64_t extraAllocated = 0;
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - type: %d, requestedPower = %d, hub has %d available, (_REQUESTFROMPARENT: %d, _CANREQUESTEXTRAPOWER: %d, _EXTRAPOWERALLOCATED: %d, _EXTRAPOWERFORPORTS: %d)",
this, (uint32_t)wakeType, (uint32_t)requestedPower, (uint32_t) _TOTALEXTRACURRENT, (uint32_t)_REQUESTFROMPARENT, (uint32_t)_CANREQUESTEXTRAPOWER, (uint32_t)_EXTRAPOWERALLOCATED, (uint32_t)_EXTRAPOWERFORPORTS);
if (requestedPower == 0)
{
*powerAllocated = 0;
return kIOReturnSuccess;
}
if ( (requestedPower + _STANDARD_PORT_POWER) > _MAXPORTCURRENT) {
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - requestedPower of %d, was greater than the maximum this port can provide (including the standard port power): %d, Requesting %d instead", this, (uint32_t)requestedPower, (uint32_t) (_MAXPORTCURRENT-500), (uint32_t) (_MAXPORTCURRENT-500));
requestedPower = _MAXPORTCURRENT - _STANDARD_PORT_POWER;
}
if (requestedPower <= _TOTALEXTRACURRENT)
{
extraAllocated = requestedPower;
_TOTALEXTRACURRENT -= extraAllocated;
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - Asked for %d, _TOTALEXTRACURRENT is %d", this, (uint32_t)requestedPower, (uint32_t) _TOTALEXTRACURRENT );
}
if (*powerAllocated == 0)
{
if ( _REQUESTFROMPARENT)
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - requesting %d from our parent", this, (uint32_t) requestedPower);
UInt32 parentPowerRequest = super::RequestExtraPower(wakeType, requestedPower);
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - requested %d from our parent and got %d ", this, (uint32_t) parentPowerRequest, (uint32_t)parentPowerRequest);
if ( parentPowerRequest == requestedPower )
{
OSNumber * currentValueProperty = NULL;
UInt32 currentValue;
extraAllocated = requestedPower;
currentValueProperty = (OSNumber *) getProperty("PortActualRequestExtraPower");
if ( currentValueProperty )
{
currentValue = currentValueProperty->unsigned32BitValue();
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - found a PortActualRequestExtraPower with value of %d", this, (uint32_t) currentValue);
currentValue += extraAllocated;
}
else
currentValue = extraAllocated;
setProperty("PortActualRequestExtraPower", currentValue, 32);
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - we didn't get the full amount we requested", this);
}
}
else
{
if ( (_CANREQUESTEXTRAPOWER != 0) and (_EXTRAPOWERALLOCATED < 2))
{
if ( requestedPower > _EXTRAPOWERFORPORTS )
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - we can request extra power from our parent but only %d and we want %d ", this, (uint32_t) _EXTRAPOWERFORPORTS, (uint32_t)requestedPower);
extraAllocated = 0;
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - requesting %d from our parent", this, (uint32_t) _CANREQUESTEXTRAPOWER);
UInt32 parentPowerRequest = super::RequestExtraPower(wakeType, _CANREQUESTEXTRAPOWER);
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - requested %d from our parent and got %d ", this, (uint32_t) _CANREQUESTEXTRAPOWER, (uint32_t)parentPowerRequest);
if ( parentPowerRequest == _CANREQUESTEXTRAPOWER )
{
extraAllocated = _EXTRAPOWERFORPORTS;
_EXTRAPOWERALLOCATED++;
setProperty("PortActualRequestExtraPower", extraAllocated, 32);
setProperty("ExtraWakePowerAllocated", _EXTRAPOWERALLOCATED, 32);
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - returning power %d because we didnt get enough", this, (uint32_t)parentPowerRequest);
super::ReturnExtraPower(wakeType, parentPowerRequest);
}
}
}
}
}
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraWakePowerGated - extraAllocated = %d", this, (uint32_t)extraAllocated);
*powerAllocated = extraAllocated;
return kIOReturnSuccess;
}
#pragma mark Return Extra Power (Wake)
IOReturn
IOUSBHubDevice::ReturnExtraPower(UInt32 type, UInt32 returnedPower)
{
IOReturn kr = kIOReturnSuccess;
USBLog(5, "IOUSBHubDevice[%p]::ReturnExtraPower type: %d, returnedPower %d", this, (uint32_t)type, (uint32_t) returnedPower);
if ( type == kUSBPowerDuringWake || type == kUSBPowerDuringWakeRevocable || type == kUSBPowerDuringWakeUSB3)
{
IOReturn kr = kIOReturnSuccess;
if ( IOUSBDevice::_expansionData && IOUSBDevice::_expansionData->_commandGate && IOUSBDevice::_expansionData->_workLoop)
{
IOCommandGate * gate = IOUSBDevice::_expansionData->_commandGate;
IOWorkLoop * workLoop = IOUSBDevice::_expansionData->_workLoop;
retain();
workLoop->retain();
gate->retain();
kr = gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOUSBHubDevice::ReturnExtraWakePowerGated), (void *)type, (void *)returnedPower);
if ( kr != kIOReturnSuccess )
{
USBLog(2,"IOUSBHubDevice[%p]::ReturnExtraPower GatedRequestExtraPower runAction() failed (0x%x)", this, kr);
}
gate->release();
workLoop->release();
release();
}
}
else if ( type == kUSBPowerDuringSleep )
{
ReturnSleepPower( returnedPower );
}
else if ( type == kUSBPowerRequestWakeRelease || type == kUSBPowerRequestSleepRelease )
{
SendExtraPowerMessage( type, returnedPower );
}
else
kr = kIOReturnBadArgument;
return kr;
}
IOReturn
IOUSBHubDevice::ReturnExtraWakePowerGated(uint64_t wakeType, uint64_t returnedPower)
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnExtraPowerGated - returning = %d", this, (uint32_t)returnedPower);
if ( returnedPower == 0 )
return kIOReturnSuccess;
if ( _EXTRAPOWERALLOCATED > 0 )
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnExtraPowerGated - we had _EXTRAPOWERALLOCATED calling our parent to return %d", this, (uint32_t)_CANREQUESTEXTRAPOWER);
super::ReturnExtraPower(wakeType, _CANREQUESTEXTRAPOWER);
_EXTRAPOWERALLOCATED--;
setProperty("ExtraWakePowerAllocated", _EXTRAPOWERALLOCATED, 32);
}
else if ( _REQUESTFROMPARENT )
{
super::ReturnExtraPower(wakeType, returnedPower);
}
else
{
if (returnedPower > 0)
_TOTALEXTRACURRENT += returnedPower;
}
return kIOReturnSuccess;
}
#pragma mark Request Extra Power (Sleep)
UInt32
IOUSBHubDevice::RequestSleepPower(UInt32 requestedPower)
{
IOReturn kr = kIOReturnSuccess;
uint64_t extraAllocated = 0;
if ( IOUSBDevice::_expansionData && IOUSBDevice::_expansionData->_commandGate && IOUSBDevice::_expansionData->_workLoop)
{
IOCommandGate * gate = IOUSBDevice::_expansionData->_commandGate;
IOWorkLoop * workLoop = IOUSBDevice::_expansionData->_workLoop;
retain();
workLoop->retain();
gate->retain();
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPower - requestedPower = %d", this, (uint32_t)requestedPower);
gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOUSBHubDevice::RequestSleepPowerGated), (void *)requestedPower, &extraAllocated);
if ( kr != kIOReturnSuccess )
{
USBLog(2,"IOUSBHubDevice[%p]::RequestSleepPower GatedRequestSleepPower runAction() failed (0x%x)", this, kr);
}
gate->release();
workLoop->release();
release();
}
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPower - returning %d", this, (uint32_t)extraAllocated);
return (UInt32) extraAllocated;
}
IOReturn
IOUSBHubDevice::RequestSleepPowerGated(uint64_t requestedPower, uint64_t *powerAllocated)
{
UInt32 extraAllocated = 0;
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - requestedPower = %d, _STANDARD_PORT_POWER_IN_SLEEP: %d, _TOTALEXTRASLEEPCURRENT: %d (_REQUESTFROMPARENT = %d)", this, (uint32_t)requestedPower, (uint32_t)_STANDARD_PORT_POWER_IN_SLEEP, (uint32_t) _TOTALEXTRASLEEPCURRENT, (uint32_t)_REQUESTFROMPARENT);
if (requestedPower == 0)
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - asked for 0, returning 0", this );
*powerAllocated = 0;
return kIOReturnSuccess;
}
if ( _STANDARD_PORT_POWER_IN_SLEEP == 0)
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - port does not have any _STANDARD_PORT_POWER_IN_SLEEP, returning 0", this );
*powerAllocated = 0;
return kIOReturnSuccess;
}
if ( requestedPower <= _STANDARD_PORT_POWER_IN_SLEEP)
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - requested <= _STANDARD_PORT_POWER_IN_SLEEP, returning %d", this, (uint32_t)requestedPower );
*powerAllocated = requestedPower;
return kIOReturnSuccess;
}
if ( _REQUESTFROMPARENT)
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - requesting %d from our parent", this, (uint32_t) requestedPower);
UInt32 parentPowerRequest = super::RequestExtraPower(kUSBPowerDuringSleep, requestedPower);
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - requested %d from our parent and got %d ", this, (uint32_t) requestedPower, (uint32_t)parentPowerRequest);
if ( parentPowerRequest == requestedPower )
{
extraAllocated = requestedPower- _STANDARD_PORT_POWER_IN_SLEEP;
setProperty("PortActualRequestExtraSleepPower", extraAllocated, 32);
}
else
{
USBLog(6, "IOUSBHubDevice[%p]::RequestSleepPowerGated - we didn't get the full amount we requested, we got only %d", this, (uint32_t)parentPowerRequest);
extraAllocated = parentPowerRequest- _STANDARD_PORT_POWER_IN_SLEEP;
setProperty("PortActualRequestExtraSleepPower", extraAllocated, 32);
}
}
else
{
if (requestedPower > _MAXPORTSLEEPCURRENT) {
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - requestedPower of %d, was greater than %d, (the maximum allowed sleep power per port). Requesting the max instead", this, (uint32_t)requestedPower, (uint32_t) (_MAXPORTSLEEPCURRENT));
requestedPower = _MAXPORTSLEEPCURRENT;
}
if ( (requestedPower - _STANDARD_PORT_POWER_IN_SLEEP) <= _TOTALEXTRASLEEPCURRENT)
{
extraAllocated = requestedPower - _STANDARD_PORT_POWER_IN_SLEEP;
_TOTALEXTRASLEEPCURRENT -= extraAllocated;
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - Asked for %d extra, _TOTALEXTRASLEEPCURRENT is now %d", this, (uint32_t)(requestedPower - _STANDARD_PORT_POWER_IN_SLEEP), (uint32_t) _TOTALEXTRASLEEPCURRENT );
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - Asked for %d extra, but only %d _TOTALEXTRASLEEPCURRENT available", this, (uint32_t)(requestedPower - _STANDARD_PORT_POWER_IN_SLEEP), (uint32_t) _TOTALEXTRASLEEPCURRENT );
}
}
#if 0 // for M84/89 (not supporting providing sleep current on those hubs, for now)
{
if ( (_CANREQUESTEXTRASLEEPPOWER != 0) (_EXTRASLEEPPOWERALLOCATED < 2) )
{
if ( requestedPower > _EXTRAPOWERFORPORTS )
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - we can request extra sleep power from our parent but only %d and we want %d ", this, (uint32_t) _EXTRAPOWERFORPORTS, (uint32_t)requestedPower);
extraAllocated = 0;
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - requesting %d from our parent", this, (uint32_t) _CANREQUESTEXTRASLEEPPOWER);
UInt32 parentPowerRequest = super::RequestExtraPower(kUSBPowerDuringSleep, _CANREQUESTEXTRASLEEPPOWER);
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - requested %d from our parent and got %d ", this, (uint32_t) _CANREQUESTEXTRASLEEPPOWER, (uint32_t)parentPowerRequest);
if ( parentPowerRequest == _CANREQUESTEXTRASLEEPPOWER )
{
extraAllocated = _EXTRAPOWERFORPORTS;
_EXTRASLEEPPOWERALLOCATED++;
setProperty("PortActualRequestExtraSleepPower", extraAllocated, 32);
setProperty("ExtraSleepPowerAllocated", _EXTRASLEEPPOWERALLOCATED, 32);
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - returning power %d because we didnt get enough", this, (uint32_t)parentPowerRequest);
super::ReturnExtraPower(kUSBPowerDuringSleep, parentPowerRequest);
}
}
}
}
#endif
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPowerGated - extraAllocated = %d, returning %d", this, (uint32_t)extraAllocated, (uint32_t)(extraAllocated + _STANDARD_PORT_POWER_IN_SLEEP));
*powerAllocated = (extraAllocated + _STANDARD_PORT_POWER_IN_SLEEP);
return kIOReturnSuccess;
}
#pragma mark Return Extra Power (Sleep)
void
IOUSBHubDevice::ReturnSleepPower(UInt32 returnedPower)
{
IOReturn kr = kIOReturnSuccess;
if ( IOUSBDevice::_expansionData && IOUSBDevice::_expansionData->_commandGate && IOUSBDevice::_expansionData->_workLoop)
{
IOCommandGate * gate = IOUSBDevice::_expansionData->_commandGate;
IOWorkLoop * workLoop = IOUSBDevice::_expansionData->_workLoop;
retain();
workLoop->retain();
gate->retain();
USBLog(5, "IOUSBHubDevice[%p]::ReturnSleepPower - returning = %d", this, (uint32_t)returnedPower);
gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOUSBHubDevice::ReturnSleepPowerGated), (void *)returnedPower);
if ( kr != kIOReturnSuccess )
{
USBLog(2,"IOUSBHubDevice[%p]::RequestExtraPower GatedRequestExtraPower runAction() failed (0x%x)", this, kr);
}
gate->release();
workLoop->release();
release();
}
}
IOReturn
IOUSBHubDevice::ReturnSleepPowerGated(uint64_t returnedPower)
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnSleepPowerGated - returning = %d", this, (uint32_t)returnedPower);
#if 0 // M84/89
if ( _EXTRASLEEPPOWERALLOCATED > 0)
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnSleepPowerGated - we had _EXTRASLEEPPOWERALLOCATED calling our parent to return %d", this, (uint32_t)_CANREQUESTEXTRASLEEPPOWER);
super::ReturnExtraPower(kUSBPowerDuringSleep, _CANREQUESTEXTRASLEEPPOWER);
_EXTRAPOWERALLOCATED--;
setProperty("ExtraWakePowerAllocated", _EXTRASLEEPPOWERALLOCATED, 32);
}
#endif
if ( returnedPower <= _STANDARD_PORT_POWER_IN_SLEEP)
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnSleepPowerGated - returned <= _STANDARD_PORT_POWER_IN_SLEEP, returning %d", this, (uint32_t)returnedPower );
return kIOReturnSuccess;
}
if ( _REQUESTFROMPARENT )
{
super::ReturnExtraPower(kUSBPowerDuringSleep, returnedPower);
}
else
{
if (returnedPower > 0)
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnSleepPowerGated - adding back %d to our extra", this, (uint32_t)(returnedPower - _STANDARD_PORT_POWER_IN_SLEEP));
_TOTALEXTRASLEEPCURRENT += (returnedPower - _STANDARD_PORT_POWER_IN_SLEEP);
}
}
return kIOReturnSuccess;
}
#pragma mark Extra Power (Other)
void
IOUSBHubDevice::InitializeExtraPower(UInt32 maxPortCurrent, UInt32 totalExtraCurrent, UInt32 maxPortCurrentInSleep, UInt32 totalExtraCurrentInSleep)
{
OSNumber * extraPowerProp = NULL;
OSObject * propertyObject = NULL;
OSBoolean * booleanObj = NULL;
UInt32 deviceInfo = 0;
bool useNewMethodToAddRequestFromParent = false;;
(void) GetDeviceInformation(&deviceInfo);
USBLog(5, "IOUSBHubDevice[%p]::InitializeExtraPower - maxPortCurrent = %d, totalExtraCurrent: %d, maxPortCurrentInSleep: %d, totalExtraCurrentInSleep: %d, deviceInfo: 0x%x", this, (uint32_t)maxPortCurrent, (uint32_t) totalExtraCurrent, (uint32_t)maxPortCurrentInSleep, (uint32_t)totalExtraCurrentInSleep, (uint32_t)deviceInfo);
_MAXPORTCURRENT = maxPortCurrent;
_TOTALEXTRACURRENT = totalExtraCurrent;
_MAXPORTSLEEPCURRENT = maxPortCurrentInSleep;
_TOTALEXTRASLEEPCURRENT = totalExtraCurrentInSleep;
if ( _controller )
{
booleanObj = OSDynamicCast(OSBoolean, _controller->getProperty("UpdatedSleepPropertiesExists"));
if (booleanObj && booleanObj->isTrue())
{
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower found UpdatedSleepPropertiesExists with true value", this);
useNewMethodToAddRequestFromParent = true;
}
}
if ( useNewMethodToAddRequestFromParent && (deviceInfo & kUSBInformationDeviceIsInternalMask) && (deviceInfo & kUSBInformationDeviceIsAttachedToRootHubMask) && (deviceInfo & kUSBInformationDeviceIsCaptiveMask) && !(deviceInfo & kUSBInformationDeviceIsOnThunderboltMask) )
{
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower found hub (0x%x, 0x%x), that is internal, attached to root hub, captive, not on Thunderbolt, and on a 'recent' machine", this, GetVendorID(), GetProductID());
_REQUESTFROMPARENT = true;
if (_USBPLANE_PARENT != NULL)
{
extraPowerProp = OSDynamicCast(OSNumber, _USBPLANE_PARENT->getProperty(kAppleMaxPortCurrent));
if ( extraPowerProp )
{
_MAXPORTCURRENT = extraPowerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower setting _MAXPORTCURRENT to %d", this, (uint32_t) _MAXPORTCURRENT );
}
}
}
else
{
propertyObject = getProperty("RequestExtraCurrentFromParent");
booleanObj = OSDynamicCast(OSBoolean, propertyObject);
if (booleanObj && booleanObj->isTrue() && DoLocationOverrideAndModelMatch())
{
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower found RequestExtraCurrentFromParent property, setting _REQUESTFROMPARENT to true", this);
_REQUESTFROMPARENT = true;
if (_USBPLANE_PARENT != NULL)
{
extraPowerProp = OSDynamicCast(OSNumber, _USBPLANE_PARENT->getProperty(kAppleMaxPortCurrent));
if ( extraPowerProp )
{
_MAXPORTCURRENT = extraPowerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower setting _MAXPORTCURRENT to %d", this, (uint32_t) _MAXPORTCURRENT );
}
}
}
}
propertyObject = copyProperty("ExtraPowerRequest");
extraPowerProp = OSDynamicCast(OSNumber, propertyObject);
if ( extraPowerProp )
{
_CANREQUESTEXTRAPOWER = extraPowerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower got ExtraPowerRequest of %d", this, (uint32_t) _CANREQUESTEXTRAPOWER );
}
if ( propertyObject)
propertyObject->release();
propertyObject = copyProperty("ExtraPowerForPorts");
extraPowerProp = OSDynamicCast(OSNumber, propertyObject);
if ( extraPowerProp )
{
_EXTRAPOWERFORPORTS = extraPowerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower got ExtraPowerForPorts of %d", this, (uint32_t) _EXTRAPOWERFORPORTS );
}
if ( propertyObject)
propertyObject->release();
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower USB Plane Parent is %p (%s)", this, _USBPLANE_PARENT, _USBPLANE_PARENT == NULL ? "" : _USBPLANE_PARENT->getName());
}
void
IOUSBHubDevice::SendExtraPowerMessage(UInt32 type, UInt32 returnedPower)
{
USBLog(7, "IOUSBHubDevice[%p]::SendExtraPowerMessage - type: %d, argument: %d (_EXTRAPOWERFORPORTS: %d, _REQUESTFROMPARENT: %d)", this, (uint32_t)type, (uint32_t) returnedPower, (uint32_t)_EXTRAPOWERFORPORTS, _REQUESTFROMPARENT);
if (_EXTRAPOWERFORPORTS || _REQUESTFROMPARENT)
{
USBLog(6, "IOUSBHubDevice[%p]::SendExtraPowerMessage - sending to our parent", this);
if ( type == kUSBPowerRequestWakeRelease )
{
super::ReturnExtraPower(type, returnedPower);
}
else
{
super::RequestExtraPower(type, returnedPower);
}
}
else
{
OSIterator * iterator = NULL;
USBLog(5, "IOUSBHubDevice[%p]::SendExtraPowerMessage - sending message to all devices attached to this hub", this);
iterator = getChildIterator(getPlane(kIOUSBPlane));
if (iterator)
{
OSObject *next;
while( (next = iterator->getNextObject()) )
{
IOUSBDevice *aDevice = OSDynamicCast(IOUSBDevice, next);
if ( aDevice )
{
if ( type == kUSBPowerRequestWakeRelease )
{
USBLog(7, "IOUSBHubDevice[%p]::SendExtraPowerMessage - sending kIOUSBMessageReleaseExtraCurrent to %s", this, aDevice->getName());
aDevice->messageClients(kIOUSBMessageReleaseExtraCurrent, &returnedPower, sizeof(UInt32));
}
else if ( type == kUSBPowerRequestWakeReallocate )
{
USBLog(7, "IOUSBHubDevice[%p]::SendExtraPowerMessage - sending kIOUSBMessageReallocateExtraCurrent to %s", this, aDevice->getName());
aDevice->messageClients(kIOUSBMessageReallocateExtraCurrent, NULL, 0);
}
}
}
iterator->release();
}
else
{
USBLog(3, "IOUSBHubDevice[%p]::SendExtraPowerMessage - could not getChildIterator", this);
}
}
}
SInt32
IOUSBHubDevice::UpdateUnconnectedExternalPorts(SInt32 count)
{
IOReturn kr = kIOReturnSuccess;
SInt32 newCount = 0;
USBLog(6, "IOUSBHubDevice[%p]::UpdateUnconnectedExternalPorts %d", this, (int32_t)count);
if ( IOUSBDevice::_expansionData && IOUSBDevice::_expansionData->_commandGate && IOUSBDevice::_expansionData->_workLoop)
{
IOCommandGate * gate = IOUSBDevice::_expansionData->_commandGate;
IOWorkLoop * workLoop = IOUSBDevice::_expansionData->_workLoop;
retain();
workLoop->retain();
gate->retain();
gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOUSBHubDevice::UpdateUnconnectedExternalPortsGated), (void*) count, (void*)&newCount);
if ( kr != kIOReturnSuccess )
{
USBLog(2,"IOUSBHubDevice[%p]::UpdateUnconnectedExternalPorts UpdateUnconnectedExternalPortsGated runAction() failed (0x%x)", this, kr);
}
gate->release();
workLoop->release();
release();
}
USBLog(6, "IOUSBHubDevice[%p]::UpdateUnconnectedExternalPorts returning %d", this, (int32_t)newCount);
return newCount;
}
IOReturn
IOUSBHubDevice::UpdateUnconnectedExternalPortsGated(SInt32 count, SInt32 * newCount)
{
OSNumber * numberObject = NULL;
UInt32 unconnectedPorts = 0;
UInt32 externalPorts = 0;
OSObject * propertyObject = NULL;
IOService * resourceService = getResourceService();
IOReturn kr = kIOReturnSuccess;
bool decreasePorts = false;
if (resourceService)
{
USBLog(6, "IOUSBHubDevice[%p]::UpdateUnconnectedExternalPortsGated %d", this, (int32_t)count);
if (count >= 2000)
{
decreasePorts = true;
count -= 1000;
}
if (count >= 1000)
{
count -= 1000;
propertyObject = resourceService->copyProperty(kAppleExternalSuperSpeedPorts);
numberObject = OSDynamicCast(OSNumber, propertyObject);
if (numberObject)
{
externalPorts = numberObject->unsigned32BitValue();
USBLog(5, "IOUSBHubDevice[%p]::UpdateUnconnectedExternalPortsGated - we have a AAPL,ExternalUSBPorts with %d", this, (uint32_t)externalPorts);
}
OSSafeReleaseNULL(propertyObject);
if (!decreasePorts)
{
externalPorts += count;
_EXTERNAL_PORTS += externalPorts;
}
else
{
externalPorts -= count;
_EXTERNAL_PORTS -= externalPorts;
}
USBLog(5, "IOUSBHubDevice[%p]::UpdateUnconnectedExternalPortsGated Total number of external SuperSpeed ports now %d", this, (uint32_t)externalPorts);
if ( count > 0 )
{
resourceService->setProperty(kAppleExternalSuperSpeedPorts, externalPorts, 32);
resourceService->setProperty(kAppleUnconnectedSuperSpeedPorts, externalPorts, 32);
}
*newCount = externalPorts;
}
else
{
propertyObject = resourceService->copyProperty(kAppleUnconnectedSuperSpeedPorts);
numberObject = OSDynamicCast(OSNumber, propertyObject);
if (numberObject)
{
unconnectedPorts = numberObject->unsigned32BitValue();
USBLog(5, "IOUSBHubDevice[%p]::UpdateUnconnectedExternalPortsGated - we have a AAPL,UnconnectedUSBPorts with %d", this, (uint32_t)unconnectedPorts);
}
OSSafeReleaseNULL(propertyObject);
unconnectedPorts += count;
_UNCONNECTEDEXTERNALPORTS = unconnectedPorts;
USBLog(5, "IOUSBHubDevice[%p]::UpdateUnconnectedExternalPortsGated unconnected external SuperSpeed ports now %d", this, (uint32_t)unconnectedPorts);
resourceService->setProperty(kAppleUnconnectedSuperSpeedPorts, unconnectedPorts, 32);
*newCount = unconnectedPorts;
}
}
else
kr = kIOReturnNoMemory;
return kr;
}
void
IOUSBHubDevice::SetTotalSleepCurrent(UInt32 sleepCurrent)
{
SetSleepCurrent(sleepCurrent);
}
UInt32
IOUSBHubDevice::GetTotalSleepCurrent()
{
return GetSleepCurrent();
}
void
IOUSBHubDevice::SetSleepCurrent(UInt32 sleepCurrent)
{
USBLog(5, "IOUSBHubDevice[%p]::SetSleepCurrent - setting _STANDARD_PORT_POWER_IN_SLEEP to %d", this, (uint32_t)sleepCurrent);
_STANDARD_PORT_POWER_IN_SLEEP = sleepCurrent;
}
UInt32
IOUSBHubDevice::GetSleepCurrent()
{
return _STANDARD_PORT_POWER_IN_SLEEP;
}
#pragma mark Extra Power (Obsolete)
void
IOUSBHubDevice::InitializeExtraPower(UInt32 maxPortCurrent, UInt32 totalExtraCurrent)
{
#pragma unused (maxPortCurrent, totalExtraCurrent)
USBLog(5, "IOUSBHubDevice[%p]::InitializeExtraPower - obsolete method called", this);
}
UInt32
IOUSBHubDevice::RequestExtraPower(UInt32 requestedPower)
{
#pragma unused (requestedPower)
USBLog(1, "IOUSBHubDevice[%p]::RequestExtraPower - OBSOLETE METHOD CALLED", this);
return 0;
}
void
IOUSBHubDevice::ReturnExtraPower(UInt32 returnedPower)
{
#pragma unused (returnedPower)
USBLog(1, "IOUSBHubDevice[%p]::ReturnExtraPower - OBSOLETE METHOD CALLED", this);
}
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 0);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 1);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 2);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 3);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 4);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 5);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 6);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 7);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 8);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 9);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 10);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 11);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 12);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 13);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 14);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 15);