#ifndef _IOKIT_APPLEUSBHUB_H
#define _IOKIT_APPLEUSBHUB_H
#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/usb/USB.h>
#include <IOKit/usb/USBHub.h>
#include <IOKit/usb/IOUSBLog.h>
#include <IOKit/usb/IOUSBHubPolicyMaker.h>
#include <kern/thread_call.h>
#ifndef APPLEUSBHUB_USE_KPRINTF
#define APPLEUSBHUB_USE_KPRINTF 0
#endif
#if APPLEUSBHUB_USE_KPRINTF
#undef USBLog
#undef USBError
void kprintf(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#define USBLog( LEVEL, FORMAT, ARGS... ) if ((LEVEL) <= APPLEUSBHUB_USE_KPRINTF) { kprintf( FORMAT "\n", ## ARGS ) ; }
#define USBError( LEVEL, FORMAT, ARGS... ) { kprintf( FORMAT "\n", ## ARGS ) ; }
#endif
enum
{
kHubPortPowerOff = 0,
kHubPortPowerOn = 1
};
enum
{
kErrataCaptiveOKBit = 1,
kStartupDelayBit = 2,
kDisplayOverCurrentTimeout = 30 };
class IOUSBController;
class IOUSBDevice;
class IOUSBInterface;
class IOUSBPipe;
class AppleUSBHubPort;
class AppleUSBHub : public IOUSBHubPolicyMaker
{
OSDeclareDefaultStructors(AppleUSBHub)
friend class AppleUSBHubPort;
friend class AppleUSBHSHubUserClient;
IOUSBInterface * _hubInterface;
IOUSBConfigurationDescriptor *_configDescriptor;
IOUSBHubDescriptor _hubDescriptor;
USBDeviceAddress _address;
IOUSBHubPortStatus _hubStatus;
IOUSBPipe * _interruptPipe;
IOBufferMemoryDescriptor * _buffer;
IOCommandGate * _gate;
IOWorkLoop * _workLoop;
UInt32 _locationID;
UInt32 _inStartMethod;
UInt32 _devZeroLockedTimeoutCounter; bool _portSuspended;
bool _hubHasBeenDisconnected;
bool _hubIsDead;
bool _abortExpected;
UInt32 _retryCount;
IOUSBHubDevice * _hubParent;
bool _busPowered;
bool _selfPowered;
bool _busPowerGood;
bool _selfPowerGood;
bool _needToClose;
bool _okToCloseWhileOff;
bool _needInterruptRead; bool _needToCallResetDevice;
UInt32 _interruptReadPending;
UInt32 _powerForCaptive;
thread_call_t _workThread;
thread_call_t _resetPortZeroThread;
thread_call_t _hubDeadCheckThread;
thread_call_t _clearFeatureEndpointHaltThread;
thread_call_t _checkForActivePortsThread;
thread_call_t _waitForPortResumesThread;
thread_call_t _ensureUsabilityThread;
thread_call_t _initialDelayThread;
thread_call_t _hubResetPortThread;
UInt8 _readBytes;
UInt8 _numCaptive;
AppleUSBHubPort ** _ports; bool _multiTTs; bool _hsHub; bool _needToAckSetPowerState;
bool _checkPortsThreadActive;
bool _abandonCheckPorts; bool _doPortActionLock; bool _waitingForPowerOn; IOTimerEventSource * _timerSource;
UInt32 _timeoutFlag;
UInt32 _portTimeStamp[32];
UInt32 _portWithDevZeroLock;
UInt32 _outstandingIO;
UInt32 _raisedPowerStateCount; UInt32 _outstandingResumes;
UInt32 _hubGetConfigResetRetries;
UInt32 _errataBits;
UInt32 _startupDelay;
AbsoluteTime _wakeupTime;
bool _ignoreDisconnectOnWakeup;
bool _retryBogusPortStatus;
bool _overCurrentNoticeDisplayed;
AbsoluteTime _overCurrentNoticeTimeStamp;
bool _hubWithExpressCardPort; int _expressCardPort; bool _hasExtraPowerRequest;
volatile UInt32 _hubDeadCheckLock;
static void InterruptReadHandlerEntry(OSObject *target, void *param, IOReturn status, UInt32 bufferSizeRemaining);
void InterruptReadHandler(IOReturn status, UInt32 bufferSizeRemaining);
static void ProcessStatusChangedEntry(OSObject *target);
void ProcessStatusChanged(void);
static void ResetPortZeroEntry(OSObject *target);
void ResetPortZero();
static void CheckForDeadHubEntry(OSObject *target);
void CheckForDeadHub();
static void ClearFeatureEndpointHaltEntry(OSObject *target);
void ClearFeatureEndpointHalt(void);
static void CheckForActivePortsEntry(OSObject *target);
void CheckForActivePorts(void);
static void WaitForPortResumesEntry(OSObject *target);
void WaitForPortResumes(void);
static void TimeoutOccurred(OSObject *owner, IOTimerEventSource *sender);
IOReturn DoDeviceRequest(IOUSBDevRequest *request);
IOReturn DoDeviceRequestWithRetries(IOUSBDevRequest *request, bool retrySTALLs = false);
UInt32 GetHubErrataBits(void);
void DecrementOutstandingIO(void);
void IncrementOutstandingIO(void);
static IOReturn ChangeOutstandingIO(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);
void LowerPowerState(void);
void RaisePowerState(void);
static IOReturn ChangeRaisedPowerState(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);
void IncrementOutstandingResumes(void);
void DecrementOutstandingResumes(void);
static IOReturn ChangeOutstandingResumes(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);
IOReturn TakeDoPortActionLock(void);
IOReturn ReleaseDoPortActionLock(void);
static IOReturn ChangeDoPortActionLock(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);
void UnpackPortFlags(void);
void CountCaptivePorts(void);
IOReturn CheckPortPowerRequirements(void);
IOReturn AllocatePortMemory(void);
IOReturn StartPorts(void);
IOReturn SuspendPorts(void);
IOReturn StopPorts(void);
IOReturn ConfigureHub(void);
bool HubStatusChanged(void);
IOReturn GetHubDescriptor(IOUSBHubDescriptor *desc);
IOReturn GetHubStatus(IOUSBHubStatus *status);
IOReturn ClearHubFeature(UInt16 feature);
IOReturn GetPortStatus(IOUSBHubPortStatus *status, UInt16 port);
IOReturn GetPortState(UInt8 *state, UInt16 port);
IOReturn SetPortFeature(UInt16 feature, UInt16 port);
IOReturn ClearPortFeature(UInt16 feature, UInt16 port);
IOReturn GetDeviceStatus(USBStatus *status);
void PrintHubDescriptor(IOUSBHubDescriptor *desc);
void FatalError(IOReturn err, const char *str);
IOReturn DoPortAction(UInt32 type, UInt32 portNumber, UInt32 options );
void StartWatchdogTimer();
void StopWatchdogTimer();
IOReturn RearmInterruptRead();
void ResetMyPort();
void CallCheckForDeadHub(void);
IOUSBHubDescriptor GetCachedHubDescriptor() { return _hubDescriptor; }
bool HubAreAllPortsDisconnectedOrSuspended();
bool IsPortInitThreadActiveForAnyPort();
bool IsStatusChangedThreadActiveForAnyPort();
bool IsHSRootHub();
bool HasExpressCardPort();
void InitialDelay(void);
void HubResetPortAfterPowerChangeDone(void);
IOReturn WaitForPowerOn( uint64_t timeout );
void WakeOnPowerOn( );
static const char * HubMessageToString(UInt32 message);
bool ValidateHubDevice();
bool HasInternalDevice(UInt32 portnum);
public:
virtual bool init(OSDictionary * propTable );
virtual bool start(IOService * provider);
virtual void stop(IOService * provider);
virtual bool finalize(IOOptionBits options);
virtual IOReturn message( UInt32 type, IOService * provider, void * argument = 0 );
virtual IOReturn powerStateWillChangeTo ( IOPMPowerFlags capabilities, unsigned long stateNumber, IOService* whatDevice);
virtual IOReturn setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice );
virtual IOReturn powerStateDidChangeTo ( IOPMPowerFlags capabilities, unsigned long stateNumber, IOService* whatDevice);
virtual void powerChangeDone ( unsigned long fromState);
virtual bool willTerminate( IOService * provider, IOOptionBits options );
virtual bool didTerminate( IOService * provider, IOOptionBits options, bool * defer );
virtual bool requestTerminate( IOService * provider, IOOptionBits options );
virtual bool terminate( IOOptionBits options = 0 );
virtual void free( void );
virtual bool terminateClient( IOService * client, IOOptionBits options );
virtual bool ConfigureHubDriver(void);
virtual IOReturn HubPowerChange(unsigned long powerStateOrdinal);
virtual IOReturn EnsureUsability(void);
virtual IOReturn GetPortInformation(UInt32 portNum, UInt32 *info);
virtual IOReturn ResetPort(UInt32 portNum);
virtual IOReturn SuspendPort(UInt32 portNum, bool suspend);
virtual IOReturn ReEnumeratePort(UInt32 portNum, UInt32 options);
static void EnsureUsabilityEntry(OSObject *target);
static void InitialDelayEntry(OSObject *target);
static void HubResetPortAfterPowerChangeDoneEntry(OSObject *target);
IOUSBDevice * GetDevice(void) { return _device; }
};
#endif _IOKIT_APPLEUSBHUB_H