AppleUSBEHCI_RootHub.cpp [plain text]
#include "AppleUSBEHCI.h"
#include <IOKit/usb/USB.h>
#include <IOKit/usb/IOUSBLog.h>
#include <libkern/OSByteOrder.h>
#define nil (0)
#define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme
#define self this
enum {
kAppleVendorID = 0x05AC,
kPrdRootHubAppleE = 0x8006
};
enum{
kMaxPorts = 16
};
static UInt32 changeBits[kMaxPorts];
IOReturn
AppleUSBEHCI::GetRootHubDeviceDescriptor(IOUSBDeviceDescriptor *desc)
{
IOUSBDeviceDescriptor newDesc =
{
sizeof(IOUSBDeviceDescriptor), kUSBDeviceDesc, HostToUSBWord(kUSBRel20), kUSBHubClass, kUSBHubSubClass, 1, 64, HostToUSBWord(kAppleVendorID), HostToUSBWord(kPrdRootHubAppleE), HostToUSBWord(0x0200), 2, 1, 0, 1 };
if (!desc)
return kIOReturnNoMemory;
bcopy(&newDesc, desc, newDesc.bLength);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::GetRootHubDescriptor(IOUSBHubDescriptor *desc)
{
IOUSBHubDescriptor hubDesc;
UInt32 HCSParams;
UInt8 pps;
int i, numBytes;
UInt8 *dstPtr;
hubDesc.length = sizeof(IOUSBHubDescriptor);
hubDesc.hubType = kUSBHubDescriptorType;
HCSParams = USBToHostLong(_pEHCICapRegisters->HCSParams);
#if (DEBUGGING_LEVEL > 2)
IOLog("UIM - EHCIGetRootDescriptor HCSParams %lx \n", HCSParams);
#endif
hubDesc.numPorts = HCSParams & kEHCINumPortsMask;
#if (DEBUGGING_LEVEL > 0)
IOLog("UIM - EHCIGetRootDescriptor numPorts %d \n", hubDesc.numPorts);
#endif
pps = (HCSParams & kEHCIPPCMask) != 0;
hubDesc.characteristics = 0;
hubDesc.characteristics |= (pps ? kPerPortSwitchingBit : 0);
hubDesc.characteristics = HostToUSBWord(hubDesc.characteristics);
hubDesc.powerOnToGood = 50; hubDesc.hubCurrent = 0;
numBytes = (hubDesc.numPorts + 1) / 8 + 1;
dstPtr = (UInt8 *)&hubDesc.removablePortFlags[0];
for (i=0; i<numBytes; i++) {
*dstPtr++ = 0;
}
for (i=0; i<numBytes; i++) {
*dstPtr++ = 0xFF;
}
hubDesc.length -= ((sizeof(hubDesc.removablePortFlags) - numBytes) +
(sizeof(hubDesc.pwrCtlPortFlags) - numBytes));
if (!desc)
return kIOReturnNoMemory;
bcopy(&hubDesc, desc, hubDesc.length);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::GetRootHubConfDescriptor(OSData *desc)
{
IOUSBConfigurationDescriptor confDesc =
{
sizeof(IOUSBConfigurationDescriptor), kUSBConfDesc, HostToUSBWord(sizeof(IOUSBConfigurationDescriptor) +
sizeof(IOUSBInterfaceDescriptor) +
sizeof(IOUSBEndpointDescriptor)), 1, 1, 0, 0x60, 0, };
IOUSBInterfaceDescriptor intfDesc =
{
sizeof(IOUSBInterfaceDescriptor), kUSBInterfaceDesc, 0, 0, 1, kUSBHubClass, kUSBHubSubClass, 1, 0 };
IOUSBEndpointDescriptor endptDesc =
{
sizeof(IOUSBEndpointDescriptor), kUSBEndpointDesc, 0x81, kUSBInterrupt, HostToUSBWord(8), 12, };
if (!desc)
return(kIOReturnNoMemory);
if (!desc->appendBytes(&confDesc, confDesc.bLength))
return(kIOReturnNoMemory);
if (!desc->appendBytes(&intfDesc, intfDesc.bLength))
return(kIOReturnNoMemory);
if (!desc->appendBytes(&endptDesc, endptDesc.bLength))
return(kIOReturnNoMemory);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::SetRootHubDescriptor(OSData * )
{
USBLog(3,"%s[%p]::SetRootHubDescriptor unimplemented", getName(), this);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::GetRootHubStatus(IOUSBHubStatus *status)
{
*(UInt32 *)status = 0;
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::SetRootHubFeature(UInt16 wValue)
{
switch(wValue)
{
case kUSBHubLocalPowerChangeFeature :
USBLog(3,"%s[%p]: unimplemented Set Power Change Feature", getName(), this);
break;
case kUSBHubOverCurrentChangeFeature :
USBLog(3,"%s[%p]: unimplemented Set Overcurrent Change Feature", getName(), this);
break;
default:
USBLog(3,"%s[%p]: Unknown hub set (%d) in root hub", getName(), this, wValue);
break;
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::ClearRootHubFeature(UInt16 wValue)
{
switch(wValue)
{
case kUSBHubLocalPowerChangeFeature :
USBLog(3,"%s[%p]: unimplemented Clear Power Change Feature", getName(), this);
break;
case kUSBHubOverCurrentChangeFeature :
USBLog(3,"%s[%p]: unimplemented Clear Overcurrent Change Feature", getName(), this);
break;
default:
USBLog(3,"%s[%p]: Unknown hub clear (%d) in root hub", getName(), this, wValue);
break;
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::GetRootHubPortStatus(IOUSBHubPortStatus *status, UInt16 port)
{
static UInt32 prevStatus[kMaxPorts];
UInt16 portFlags;
UInt32 portSC, portSCChange;
#if (DEBUGGING_LEVEL > 2)
IOLog("EHCIUIM -- GetRootHubPortStatus port %d",port);
#endif
if (port < 1 || port > 15)
return(kIOReturnBadArgument);
port--;
portSC = USBToHostLong (_pEHCIRegisters->PortSC[port]);
portFlags = 0;
if( (portSC & kEHCIPortSC_Connect) != 0)
{
portFlags |= kHubPortConnection;
}
if( (portSC & kEHCIPortSC_Enabled) != 0)
{
portFlags |= kHubPortEnabled;
}
if( (portSC & kEHCIPortSC_Suspend) != 0)
{
portFlags |= kHubPortSuspend;
}
if( (portSC & kEHCIPortSC_OverCurrent) != 0)
{
portFlags |= kHubPortOverCurrent;
}
if( (portSC & kEHCIPortSC_Reset) != 0)
{
portFlags |= kHubPortBeingReset;
}
if( (portSC & kEHCIPortSC_Power) != 0)
{
portFlags |= kHubPortPower;
}
portFlags |= kHubPortHighSpeed;
status->statusFlags = HostToUSBWord(portFlags);
portSCChange = (prevStatus[port] ^ portSC); portFlags = 0;
if( (portSC & kEHCIPortSC_ConnectChange) != 0)
{
portFlags |= kHubPortConnection;
}
if( (portSC & kEHCIPortSC_EnableChange) != 0)
{
portFlags |= kHubPortEnabled;
}
if( (portSCChange & kEHCIPortSC_Suspend) != 0)
{
changeBits[port] |= kHubPortSuspend;
}
if(changeBits[port] & kHubPortSuspend)
{
portFlags |= kHubPortSuspend;
}
if( (portSC & kEHCIPortSC_OCChange) != 0)
{
portFlags |= kHubPortOverCurrent;
}
if( (portSCChange & kEHCIPortSC_Reset) != 0)
{
changeBits[port] |= kHubPortBeingReset;
}
if(changeBits[port] & kHubPortBeingReset)
{
portFlags |= kHubPortBeingReset;
}
status->changeFlags = HostToUSBWord(portFlags);
prevStatus[port] = portSC;
#if (DEBUGGING_LEVEL > 2)
IOLog(", statusFlags %x, changeFlags %x \n",status->statusFlags, status->changeFlags);
#endif
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::SetRootHubPortFeature(UInt16 wValue, UInt16 wIndex)
{
IOReturn err;
UInt16 port = wIndex;
switch(wValue)
{
case kUSBHubPortSuspendFeature :
err = EHCIRootHubPortSuspend(port, true);
break;
case kUSBHubPortResetFeature :
err = EHCIRootHubResetPort(port);
break;
case kUSBHubPortEnableFeature :
err = EHCIRootHubPortEnable(port, true);
break;
case kUSBHubPortPowerFeature :
err = EHCIRootHubPortPower(port, true);
err = EHCIRootHubPower(true);
break;
default:
USBLog(3,"%s[%p]::SetRootHubPortFeature unknown wValue %d, wIndex %d", getName(), this, wValue, wIndex);
err = kIOReturnUnsupported;
break;
}
return err;
}
IOReturn
AppleUSBEHCI::ClearRootHubPortFeature(UInt16 wValue, UInt16 wIndex)
{
IOReturn err;
UInt16 port = wIndex;
switch(wValue)
{
case kUSBHubPortEnableFeature :
err = EHCIRootHubPortEnable(port, false);
break;
case kUSBHubPortSuspendFeature :
err = EHCIRootHubPortSuspend(port, false);
break;
case kUSBHubPortPowerFeature :
err = EHCIRootHubPortPower(port, false);
break;
case kUSBHubPortConnectionChangeFeature :
err = EHCIRootHubResetChangeConnection(port);
break;
case kUSBHubPortEnableChangeFeature :
err = EHCIRootHubResetEnableChange(port);
break;
case kUSBHubPortSuspendChangeFeature :
err = EHCIRootHubResetSuspendChange(port);
break;
case kUSBHubPortOverCurrentChangeFeature :
err = EHCIRootHubResetOverCurrentChange(port);
break;
case kUSBHubPortResetChangeFeature :
err = EHCIRootHubResetResetChange(port);
break;
default:
USBLog(3,"%s[%p]::ClearRootHubPortFeature unknown wValue %d, wIndex %d", getName(), this, wValue, wIndex);
err = kIOReturnUnsupported;
break;
}
return err;
}
IOReturn
AppleUSBEHCI::GetRootHubPortState(UInt8 *state, UInt16 port)
{
USBLog(3,"%s[%p]::GetRootHubPortState for port %d", getName(), this, port);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::SetHubAddress(UInt16 wValue)
{
_rootHubFuncAddress = wValue;
return kIOReturnSuccess;
}
static UInt32
getPortSCForWriting(EHCIRegistersPtr _pEHCIRegisters, short port)
{
return USBToHostLong(_pEHCIRegisters->PortSC[port-1]) &
~(kEHCIPortSC_ConnectChange|kEHCIPortSC_EnableChange|kEHCIPortSC_OCChange);
}
IOReturn
AppleUSBEHCI::EHCIRootHubPower(bool on)
{
on = 0;
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubResetChangeConnection(UInt16 port)
{
UInt32 value;
value = getPortSCForWriting(_pEHCIRegisters,port);
value |= kEHCIPortSC_ConnectChange;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
value = getPortSCForWriting(_pEHCIRegisters,port);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubResetResetChange(UInt16 port)
{
port--;
if(port >= kMaxPorts)
{
USBLog(3, "%s[%p]::EHCIRootHubResetResetChange Too many ports specified(%d > %d)", getName(), this, port, kMaxPorts);
return kIOReturnBadArgument;
}
changeBits[port] &= ~kHubPortBeingReset;
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubResetSuspendChange(UInt16 port)
{
port--;
if(port >= kMaxPorts)
{
USBLog(3, "%s[%p]::EHCIRootHubResetSuspendChange Too many ports specified(%d > %d)", getName(), this, port, kMaxPorts);
return kIOReturnBadArgument;
}
changeBits[port] &= ~kHubPortSuspend;
IOSync();
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubResetEnableChange(UInt16 port)
{
UInt32 value;
value = getPortSCForWriting(_pEHCIRegisters,port);
value |= kEHCIPortSC_EnableChange;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubResetOverCurrentChange(UInt16 port)
{
UInt32 value;
value = getPortSCForWriting(_pEHCIRegisters,port);
value |= kEHCIPortSC_OCChange;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
return kIOReturnSuccess;
}
void
AppleUSBEHCI::waitForSOF(EHCIRegistersPtr pEHCIRegisters)
{
IOSleep(1);
}
IOReturn
AppleUSBEHCI::EHCIRootHubResetPort (UInt16 port)
{
UInt32 value;
UInt32 count, portSC;
USBLog(5, "%s[%p]::EHCIRootHubResetPort begin", getName(), this);
value = getPortSCForWriting(_pEHCIRegisters, port);
if( (value & (kEHCIPortSC_Connect | kEHCIPortSC_Power)) != (kEHCIPortSC_Connect | kEHCIPortSC_Power) )
{
USBLog(1, "%s[%p]::EHCIRootHubResetPort - Not resetting port, beacuse device is unplugged of powered off (%x).", getName(), this, value);
return kIOReturnNotResponding;
}
if( ((value & kEHCIPortSC_LineSt) >> kEHCIPortSC_LineStPhase) == kEHCILine_Low)
{
USBLog(4, "%s[%p]::EHCIRootHubResetPort - low speed device, releasing port %d", getName(), this, port);
value |= kEHCIPortSC_Owner;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
changeBits[port-1] |= kHubPortBeingReset;
return kIOReturnNotResponding;
}
value |= kEHCIPortSC_Reset;
value &= ~kEHCIPortSC_Enabled;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
IOSleep(10);
value = getPortSCForWriting(_pEHCIRegisters, port);
value &= ~kEHCIPortSC_Reset;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
IOSleep(2);
count = 0;
do {
IOSleep(1);
portSC = USBToHostLong(_pEHCIRegisters->PortSC[port-1]);
} while( ((portSC & kEHCIPortSC_Reset) != 0) && (count++ < 2001) );
USBLog(5, "%s[%p]::EHCIRootHubResetPort reset took extra %d", getName(), this, count);
IOSleep(1);
if ( portSC != USBToHostLong(_pEHCIRegisters->PortSC[port-1]) )
{
USBLog(1, "%s[%p]::EHCIRootHubResetPort- portSC is not equal to value of register! (%p)(%p)", getName(), this, portSC, USBToHostLong(_pEHCIRegisters->PortSC[port-1]));
portSC = USBToHostLong(_pEHCIRegisters->PortSC[port-1]);
}
if( ((portSC & kEHCIPortSC_Reset) != 0) || (count >= 2000) )
{
USBLog(4, "%s[%p]::EHCIRootHubResetPort- port slow to come out of reset %d", getName(), this, count);
}
if( (portSC & (kEHCIPortSC_Connect | kEHCIPortSC_Power)) != (kEHCIPortSC_Connect | kEHCIPortSC_Power) )
{
USBLog(1, "%s[%p]::EHCIRootHubResetPort - Not resetting port 2, beacuse device is unplugged of powered off (%x).", getName(), this, portSC);
return kIOReturnNotResponding;
}
USBLog(5, "%s[%p]::EHCIRootHubResetPort - Setting port reset change bit.", getName(), this, value);
changeBits[port-1] |= kHubPortBeingReset;
if( (portSC & kEHCIPortSC_Enabled) == 0)
{
USBLog(5, "%s[%p]::EHCIRootHubResetPort- full speed device (no enable) releasing device %x", getName(), this, portSC);
value = getPortSCForWriting(_pEHCIRegisters, port);
value |= kEHCIPortSC_Owner;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
return kIOReturnNotResponding;
}
else
{
waitForSOF(_pEHCIRegisters);
IOSleep(1);
portSC = USBToHostLong(_pEHCIRegisters->PortSC[port-1]);
if( (portSC & kEHCIPortSC_Enabled) == 0)
{
USBLog(3, "%s[%p]::EHCIRootHubResetPort *********** Port disabled after 1 frame******* %x", getName(), this, portSC);
}
}
USBLog(5, "%s[%p]::EHCIRootHubResetPort done", getName(), this);
USBLog(5, "%s[%p]::EHCIRootHubResetPort - Call UIMRootHubStatusChange", getName(), this);
UIMRootHubStatusChange();
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubPortEnable(UInt16 port, bool enable)
{
UInt32 value;
USBLog(3,"%s[%p]::EHCIRootHubPortEnable port: %d, on: %d", getName(), this, port, enable);
if (enable)
{
USBLog(1,"%s[%p]::EHCIRootHubPortEnable enabling port illegal.", getName(), this);
return kIOReturnUnsupported;
}
value = getPortSCForWriting(_pEHCIRegisters, port);
value &= ~kEHCIPortSC_Enabled;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubPortSuspend(UInt16 port, bool suspend)
{
UInt32 value;
UInt32 count;
USBLog(3,"%s[%p]::EHCIRootHubPortSuspend port: %d, on: %d", getName(), this, port, suspend);
value = getPortSCForWriting(_pEHCIRegisters, port);
if (suspend)
value |= kEHCIPortSC_Suspend;
else
value |= kEHCIPortSC_Resume;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong(value);
IOSync();
if (!suspend)
{
IOSleep(20);
value = getPortSCForWriting(_pEHCIRegisters, port);
value &= ~kEHCIPortSC_Resume;
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
changeBits[port-1] |= kHubPortBeingReset;
UIMRootHubStatusChange();
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::EHCIRootHubPortPower(UInt16 port, bool on)
{
UInt32 value= 0;
value = getPortSCForWriting(_pEHCIRegisters, port);
if(on)
{
value |= kEHCIPortSC_Power; _pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
value |= kEHCIPortSC_WKCNNT_E | kEHCIPortSC_WKDSCNNT_E; }
else
{
value &= ~kEHCIPortSC_Power; }
_pEHCIRegisters->PortSC[port-1] = HostToUSBLong (value);
IOSync();
return kIOReturnSuccess;
}
void
AppleUSBEHCI::UIMRootHubStatusChange(void)
{
UIMRootHubStatusChange(false);
}
OSMetaClassDefineReservedUsed(IOUSBController, 10);
void AppleUSBEHCI::UIMRootHubStatusChange(bool abort)
{
UInt8 numPorts = 0;
UInt32 HCSParams;
UInt16 statusChangedBitmap;
IOUSBHubPortStatus portStatus;
UInt32 hubStatus, statusBit, tempStatus;
unsigned int index, port, move;
struct InterruptTransaction last;
_pEHCIRegisters->USBIntr = _pEHCIRegisters->USBIntr & ~HostToUSBLong(kEHCIPortChangeIntBit);
IOSync();
statusChangedBitmap = 0;
statusBit = 1;
if (!abort && GetRootHubStatus((IOUSBHubStatus *)&tempStatus) == kIOReturnSuccess)
{
hubStatus = USBToHostLong( tempStatus );
if ((hubStatus & (kHubLocalPowerStatus | kHubOverCurrentIndicator) ) != 0)
statusChangedBitmap |= statusBit;
HCSParams = USBToHostLong(_pEHCICapRegisters->HCSParams);
numPorts = HCSParams & kEHCINumPortsMask;
USBLog(3,"%s[%p]::UIMRootHubStatusChange numPorts %d ", getName(), this, numPorts);
for (port = 1; port <= numPorts; port++)
{
statusBit <<= 1;
GetRootHubPortStatus(&portStatus, port);
portStatus.changeFlags = USBToHostWord(portStatus.changeFlags);
if (portStatus.changeFlags & kHubPortStateChangeMask)
{
USBLog(3,"%s[%p]::UIMRootHubStatusChange port %d status 0x%x", getName(), this, port, portStatus.changeFlags);
statusChangedBitmap |= statusBit; }
}
}
if ( (abort || (statusChangedBitmap != 0)) && (_outstandingTrans[0].completion.action != NULL) )
{
last = _outstandingTrans[0];
IOTakeLock(_intLock);
for (index = 1; index < kMaxOutstandingTrans ; index++)
{
_outstandingTrans[index-1] = _outstandingTrans[index];
if (_outstandingTrans[index].completion.action == nil)
break;
}
clock_get_uptime( &_lastRootHubStatusChanged );
move = last.bufLen;
if (move > sizeof(statusChangedBitmap))
move = sizeof(statusChangedBitmap);
if (numPorts < 8)
move = 1;
statusChangedBitmap = HostToUSBWord(statusChangedBitmap);
last.buf->writeBytes(0,&statusChangedBitmap, move);
IOUnlock(_intLock);
Complete(last.completion, (abort ? kIOReturnAborted : kIOReturnSuccess), last.bufLen - move);
}
if ( !abort && ((_outstandingTrans[0].completion.action != NULL) || (statusChangedBitmap == 0)) )
{
_pEHCIRegisters->USBIntr = _pEHCIRegisters->USBIntr | HostToUSBLong(kEHCIPortChangeIntBit);
IOSync();
}
}
void
AppleUSBEHCI::SimulateRootHubInt(
UInt8 endpoint,
IOMemoryDescriptor * buf,
UInt32 bufLen,
IOUSBCompletion completion)
{
int index;
if (endpoint != 1)
{
Complete(completion, -1, bufLen);
return;
}
IOTakeLock(_intLock);
for (index = 0; index < kMaxOutstandingTrans; index++)
{
if (_outstandingTrans[index].completion.action == nil)
{
_outstandingTrans[index].buf = buf;
_outstandingTrans[index].bufLen = bufLen;
_outstandingTrans[index].completion = completion;
IOUnlock(_intLock);
_pEHCIRegisters->USBIntr = _pEHCIRegisters->USBIntr + HostToUSBLong(kEHCIPortChangeIntBit);
IOSync();
return;
}
}
IOUnlock(_intLock); Complete(completion, -1, bufLen); }
IOReturn
AppleUSBEHCI::SimulateEDDelete (short endpointNumber, short direction)
{
return SimulateEDAbort(endpointNumber, direction);
}
IOReturn
AppleUSBEHCI::SimulateEDAbort (short endpointNumber, short direction)
{
int i;
if (endpointNumber == 1)
{
if(direction != kUSBIn)
{
USBLog(1, "%s[%p]::SimulateEDAbort - Root hub wrong direction Int pipe %d", getName(), this, direction);
return(-1);
}
USBLog(1, "%s[%p]::SimulateEDAbort Root hub aborting int transactions", getName(), this);
for( i=0; i < kMaxOutstandingTrans; i++)
{
UIMRootHubStatusChange(true);
}
}
else
{
USBLog(1, "%s[%p]::SimulateEDAbort Root hub aborting control pipe", getName(), this);
UIMRootHubStatusChange(false);
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::GetRootHubStringDescriptor(UInt8 index, OSData *desc)
{
UInt8 productName[] = {
0, kUSBStringDesc, 0x45, 0x00, 0x48, 0x00, 0x43, 0x00, 0x49, 0x00, 0x20, 0x00, 0x52, 0x00, 0x6F, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x20, 0x00, 0x48, 0x00, 0x75, 0x00, 0x62, 0x00, 0x20, 0x00, 0x53, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, };
UInt8 vendorName[] = {
0, kUSBStringDesc, 0x41, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00 };
if ( index > 2 )
return kIOReturnBadArgument;
vendorName[0] = sizeof(vendorName);
productName[0] = sizeof(productName);
if ( index == 1 )
{
if (!desc)
return kIOReturnNoMemory;
if (!desc->appendBytes(&productName, productName[0]))
return kIOReturnNoMemory;
}
if ( index == 2 )
{
if (!desc)
return kIOReturnNoMemory;
if (!desc->appendBytes(&vendorName, vendorName[0]))
return kIOReturnNoMemory;
}
return kIOReturnSuccess;
}
AbsoluteTime
AppleUSBEHCI::LastRootHubPortStatusChanged( bool resetTime )
{
if ( resetTime )
clock_get_uptime(&_lastRootHubStatusChanged);
return _lastRootHubStatusChanged;
}
void
AppleUSBEHCI::GetNumberOfPorts( UInt8 * numPorts )
{
UInt32 descriptorA;
if ( _ehciBusState == kEHCIBusStateOff )
{
*numPorts = 0;
}
else
{
*numPorts = USBToHostLong(_pEHCICapRegisters->HCSParams) & kEHCINumPortsMask;
}
}
bool
AppleUSBEHCI::RootHubAreAllPortsDisconnected( )
{
UInt8 numPorts = 0;
UInt32 portStat;
int i;
GetNumberOfPorts( &numPorts );
if ( numPorts == 0 )
return false;
for (i=0; i < numPorts; i++)
{
portStat = USBToHostLong(_pEHCIRegisters->PortSC[i]);
if (portStat & kEHCIPortSC_Owner)
{
USBLog(7, "%s[%p]::RootHubAreAllPortsDisconnected - port %d owned by OHCI", getName(), this, i);
return false;
}
else if (portStat & kEHCIPortSC_Enabled)
{
USBLog(7, "%s[%p]::RootHubAreAllPortsDisconnected - port %d enabled", getName(), this, i);
return false;
}
}
return true;
}