IOUSBHubDevice.cpp [plain text]
#include <libkern/OSByteOrder.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/usb/IOUSBLog.h>
#include "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 _TOTALSLEEPCURRENT _expansionData->_totalSleepCurrent
#define _CANREQUESTEXTRAPOWER _expansionData->_canRequestExtraPower
#define _EXTRAPOWERFORPORTS _expansionData->_extraPowerForPorts
#define _EXTRAPOWERALLOCATED _expansionData->_extraPowerAllocated
#define _REQUESTFROMPARENT _expansionData->_requestFromParent
#define _USBPLANE_PARENT super::_expansionData->_usbPlaneParent
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;
}
UInt32
IOUSBHubDevice::GetHubCharacteristics()
{
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;
}
UInt32
IOUSBHubDevice::RequestExtraPower(UInt32 requestedPower)
{
UInt32 extraAllocated = 0;
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - requestedPower = %d, hub has %d available", this, (uint32_t)requestedPower, (uint32_t) _TOTALEXTRACURRENT);
if (requestedPower == 0)
return 0;
if (requestedPower > (_MAXPORTCURRENT-500)) {
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - requestedPower of %d, was greater than %d, (the maximum power per port - 500mA). Requesting %d instead", this, (uint32_t)requestedPower, (uint32_t) (_MAXPORTCURRENT-500), (uint32_t) (_MAXPORTCURRENT-500));
requestedPower = _MAXPORTCURRENT-500;
}
if (requestedPower <= _TOTALEXTRACURRENT)
{
extraAllocated = requestedPower;
_TOTALEXTRACURRENT -= extraAllocated;
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - Asked for %d, _TOTALEXTRACURRENT is %d", this, (uint32_t)requestedPower, (uint32_t) _TOTALEXTRACURRENT );
}
if ( _REQUESTFROMPARENT)
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - requesting %d from our parent", this, (uint32_t) requestedPower);
UInt32 parentPowerRequest = super::RequestExtraPower(kUSBPowerDuringWake, requestedPower);
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - requested %d from our parent and got %d ", this, (uint32_t) parentPowerRequest, (uint32_t)parentPowerRequest);
if ( parentPowerRequest == requestedPower )
{
extraAllocated = requestedPower;
setProperty("PortActualRequestExtraPower", extraAllocated, 32);
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - returning power %d because we didnt get enough", this, (uint32_t)parentPowerRequest);
super::ReturnExtraPower(kUSBPowerDuringWake, parentPowerRequest);
}
}
else
{
if ( (_CANREQUESTEXTRAPOWER != 0) and not _EXTRAPOWERALLOCATED)
{
if ( requestedPower > _EXTRAPOWERFORPORTS )
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - 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]::RequestExtraPower - requesting %d from our parent", this, (uint32_t) _CANREQUESTEXTRAPOWER);
UInt32 parentPowerRequest = super::RequestExtraPower(kUSBPowerDuringWake, _CANREQUESTEXTRAPOWER);
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - requested %d from our parent and got %d ", this, (uint32_t) _CANREQUESTEXTRAPOWER, (uint32_t)parentPowerRequest);
if ( parentPowerRequest == _CANREQUESTEXTRAPOWER )
{
extraAllocated = _EXTRAPOWERFORPORTS;
_EXTRAPOWERALLOCATED = true;
setProperty("PortActualRequestExtraPower", extraAllocated, 32);
}
else
{
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - returning power %d because we didnt get enough", this, (uint32_t)parentPowerRequest);
super::ReturnExtraPower(kUSBPowerDuringWake, parentPowerRequest);
}
}
}
}
USBLog(5, "IOUSBHubDevice[%p]::RequestExtraPower - extraAllocated = %d", this, (uint32_t)extraAllocated);
return extraAllocated;
}
void
IOUSBHubDevice::ReturnExtraPower(UInt32 returnedPower)
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnExtraPower - returning = %d", this, (uint32_t)returnedPower);
if ( returnedPower == 0 )
return;
if ( _EXTRAPOWERALLOCATED )
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnExtraPower - we had _EXTRAPOWERALLOCATED calling our parent to return %d", this, (uint32_t)_CANREQUESTEXTRAPOWER);
super::ReturnExtraPower(kUSBPowerDuringWake, _CANREQUESTEXTRAPOWER);
_EXTRAPOWERALLOCATED = false;
}
else if ( _REQUESTFROMPARENT )
{
super::ReturnExtraPower(kUSBPowerDuringWake, returnedPower);
}
else
{
if (returnedPower > 0)
_TOTALEXTRACURRENT += returnedPower;
}
}
void
IOUSBHubDevice::SetTotalSleepCurrent(UInt32 sleepCurrent)
{
SetSleepCurrent(sleepCurrent);
}
UInt32
IOUSBHubDevice::GetTotalSleepCurrent()
{
return GetSleepCurrent();
}
void
IOUSBHubDevice::SetSleepCurrent(UInt32 sleepCurrent)
{
USBLog(5, "IOUSBHubDevice[%p]::SetSleepCurrent - %d", this, (uint32_t)sleepCurrent);
_TOTALSLEEPCURRENT = sleepCurrent;
}
UInt32
IOUSBHubDevice::GetSleepCurrent()
{
return _TOTALSLEEPCURRENT;
}
void
IOUSBHubDevice::InitializeExtraPower(UInt32 maxPortCurrent, UInt32 totalExtraCurrent)
{
OSNumber * extraPowerProp = NULL;
OSObject * propertyObject = NULL;
OSBoolean * booleanObj = NULL;
USBLog(5, "IOUSBHubDevice[%p]::InitializeExtraPower - maxPortCurrent = %d, totalExtraCurrent: %d", this, (uint32_t)maxPortCurrent, (uint32_t) totalExtraCurrent);
_MAXPORTCURRENT = maxPortCurrent;
_TOTALEXTRACURRENT = totalExtraCurrent;
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(kAppleCurrentAvailable));
if ( extraPowerProp )
{
_MAXPORTCURRENT = extraPowerProp->unsigned32BitValue();
USBLog(6, "IOUSBHubDevice[%p]::InitializeExtraPower setting _MAXPORTCURRENT to %d", this, (uint32_t) _MAXPORTCURRENT );
}
}
}
else
{
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());
}
UInt32
IOUSBHubDevice::RequestSleepPower(UInt32 requestedPower)
{
UInt32 extraAllocated = 0;
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPower - requestedPower = %d, available: %d", this, (uint32_t)requestedPower, (uint32_t) _TOTALSLEEPCURRENT);
if (requestedPower <= _TOTALSLEEPCURRENT)
{
extraAllocated = requestedPower;
_TOTALSLEEPCURRENT -= extraAllocated;
}
USBLog(5, "IOUSBHubDevice[%p]::RequestSleepPower - extraAllocated = %d", this, (uint32_t)extraAllocated);
return extraAllocated;
}
void
IOUSBHubDevice::ReturnSleepPower(UInt32 returnedPower)
{
USBLog(5, "IOUSBHubDevice[%p]::ReturnSleepPower - returning = %d", this, (uint32_t)returnedPower);
if (returnedPower > 0)
_TOTALSLEEPCURRENT += returnedPower;
}
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 0);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 1);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 2);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 3);
OSMetaClassDefineReservedUsed(IOUSBHubDevice, 4);
OSMetaClassDefineReservedUnused(IOUSBHubDevice, 5);
OSMetaClassDefineReservedUnused(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);