IOUSBCompositeDriver.cpp [plain text]
#include <IOKit/usb/IOUSBCompositeDriver.h>
class AppleUSBComposite : public IOUSBCompositeDriver
{
OSDeclareDefaultStructors(AppleUSBComposite)
};
OSDefineMetaClassAndStructors(AppleUSBComposite, IOUSBCompositeDriver)
#define super IOService
OSDefineMetaClassAndStructors(IOUSBCompositeDriver, IOService)
#pragma mark ееееееее IOService Methods еееееееее
bool
IOUSBCompositeDriver::start(IOService * provider)
{
bool configured = false;
if( !super::start(provider))
return (false);
fDevice = OSDynamicCast(IOUSBDevice, provider);
if (!fDevice)
return false;
fDevice->retain();
retain();
fExpectingClose = false;
fNotifier = NULL;
configured = ConfigureDevice();
if ( configured )
{
fNotifier = fDevice->registerInterest( gIOGeneralInterest, &IOUSBCompositeDriver::CompositeDriverInterestHandler, this, NULL );
USBLog(3,"%s[%p]::start USB Generic Composite @ %d", getName(), this, fDevice->GetAddress());
}
USBLog(5, "%s[%p]::start returning %d", getName(), this, configured);
release();
fDevice->release();
return configured;
}
IOReturn
IOUSBCompositeDriver::message( UInt32 type, IOService * provider, void * argument )
{
IOReturn err = kIOReturnSuccess;
err = super::message (type, provider, argument);
switch ( type )
{
case kIOUSBMessagePortHasBeenReset:
USBLog(5, "%s[%p]::message - received kIOUSBMessagePortHasBeenReset",getName(), this);
err = ReConfigureDevice();
break;
case kIOUSBMessageCompositeDriverReconfigured:
USBLog(5, "%s[%p]::message - received kIOUSBMessageCompositeDriverReconfigured",getName(), this);
break;
case kIOMessageServiceIsRequestingClose:
if ( fDevice && fDevice->isOpen(this) )
{
USBLog(3, "%s[%p]::message - Received kIOMessageServiceIsRequestingClose - closing device",getName(), this);
fExpectingClose = true;
fDevice->close(this);
}
else
{
err = kIOReturnNotOpen;
}
break;
default:
break;
}
return err;
}
bool
IOUSBCompositeDriver::willTerminate( IOService * provider, IOOptionBits options )
{
USBLog(6, "%s[%p]::willTerminate isInactive = %d", getName(), this, isInactive());
if ( fNotifier )
fNotifier->remove();
return super::willTerminate(provider, options);
}
bool
IOUSBCompositeDriver::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
{
USBLog(6, "%s[%p]::didTerminate isInactive = %d", getName(), this, isInactive());
if (fDevice->isOpen(this))
fDevice->close(this);
return super::didTerminate(provider, options, defer);
}
#pragma mark ееееееее IOUSBCompositeDriver Methods еееееееее
bool
IOUSBCompositeDriver::ConfigureDevice()
{
IOReturn err = kIOReturnSuccess;
UInt8 prefConfigValue = 0;
OSNumber * prefConfig = NULL;
const IOUSBConfigurationDescriptor * cd = NULL;
const IOUSBConfigurationDescriptor * cdTemp = NULL;
UInt8 i;
SInt16 maxPower = -1;
UInt8 numberOfConfigs = 0;
OSBoolean * suspendPropertyRef;
OSBoolean * expressCardCantWakeRef;
prefConfig = (OSNumber *) getProperty(kUSBPreferredConfiguration);
if ( prefConfig )
{
prefConfigValue = prefConfig->unsigned32BitValue();
USBLog(3, "%s[%p](%s) found a preferred configuration (%d)", getName(), this, fDevice->getName(), prefConfigValue );
}
else
{
prefConfig = (OSNumber *) fDevice->getProperty(kUSBPreferredConfiguration);
if ( prefConfig )
{
prefConfigValue = prefConfig->unsigned32BitValue();
USBLog(3, "%s[%p](%s) found a preferred configuration (%d)", getName(), this, fDevice->getName(), prefConfigValue );
}
}
numberOfConfigs = fDevice->GetNumConfigurations();
if ( numberOfConfigs < 1)
{
USBError(1, "%s[%p](%s) Could not get any configurations", getName(), this, fDevice->getName() );
err = kIOUSBConfigNotFound;
goto ErrorExit;
}
if (numberOfConfigs > 1)
{
for (i = 0; i < numberOfConfigs; i++)
{
cdTemp = fDevice->GetFullConfigurationDescriptor(i);
if (!cdTemp)
{
USBLog(3,"%s[%p](%s) ConfigureDevice Config %d does not exist", getName(), this, fDevice->getName(), i);
continue;
}
if( (fDevice->GetBusPowerAvailable() >= cdTemp->MaxPower) && ( ((SInt16)cdTemp->MaxPower) > maxPower) )
{
USBLog(5,"%s[%p](%s) ConfigureDevice Config %d with MaxPower %d", getName(), this, fDevice->getName(), i, cdTemp->MaxPower );
cd = cdTemp;
maxPower = (SInt16) cdTemp->MaxPower;
}
else
{
USBLog(5,"%s[%p](%s) ConfigureDevice Config %d with MaxPower %d cannot be used (available: %ld, previous %d)", getName(), this, fDevice->getName(), i, cdTemp->MaxPower, fDevice->GetBusPowerAvailable(), maxPower );
}
}
if ( !cd )
{
USBError(1,"USB Low Power Notice: The device \"%s\" cannot be used because there is not enough power to configure it",fDevice->getName());
USBLog(3, "%s[%p](%s) ConfigureDevice failed to find configuration by power", getName(), this, fDevice->getName() );
err = kIOUSBNotEnoughPowerErr;
fDevice->DisplayUserNotification(kUSBNotEnoughPowerNotificationType);
goto ErrorExit;
}
}
else
{
cd = fDevice->GetFullConfigurationDescriptor(0);
if (!cd)
{
USBLog(1, "%s[%p](%s) GetFullConfigDescriptor(0) returned NULL, retrying", getName(), this, fDevice->getName() );
IOSleep( 300 );
cd = fDevice->GetFullConfigurationDescriptor(0);
if ( !cd )
{
USBError(1, "%s[%p](%s) GetFullConfigDescriptor(0) returned NULL", getName(), this, fDevice->getName() );
err = kIOUSBConfigNotFound;
goto ErrorExit;
}
}
}
if ( !fDevice->open(this) )
{
USBError(1, "%s[%p] Could not open device (%s)", getName(), this, fDevice->getName() );
err = kIOReturnExclusiveAccess;
goto ErrorExit;
}
fConfigValue = prefConfig ? prefConfigValue : cd->bConfigurationValue;
err = SetConfiguration(fConfigValue, true);
if (err)
{
USBError(1, "%s[%p](%s) SetConfiguration (%d) returned 0x%x", getName(), this, fDevice->getName(), (prefConfig ? prefConfigValue : cd->bConfigurationValue), err );
if ( prefConfig )
{
fConfigValue = cd->bConfigurationValue;
err = SetConfiguration(fConfigValue, true);
USBError(1, "%s[%p](%s) SetConfiguration (%d) returned 0x%x", getName(), this, fDevice->getName(), cd->bConfigurationValue, err );
}
if ( err )
{
fDevice->close(this);
goto ErrorExit;
}
}
fConfigbmAttributes = cd->bmAttributes;
if (fConfigbmAttributes & kUSBAtrRemoteWakeup)
{
USBLog(3,"%s[%p] Setting kUSBFeatureDeviceRemoteWakeup for device: %s", getName(), this, fDevice->getName());
err = fDevice->SetFeature(kUSBFeatureDeviceRemoteWakeup);
if ( err != kIOReturnSuccess )
{
IOSleep(300);
err = fDevice->SetFeature(kUSBFeatureDeviceRemoteWakeup);
}
}
expressCardCantWakeRef = OSDynamicCast( OSBoolean, fDevice->getProperty(kUSBExpressCardCantWake) );
if ( expressCardCantWakeRef && expressCardCantWakeRef->isTrue() )
{
USBLog(3, "%s[%p](%s) found an express card device which will disconnect across sleep", getName(), this, fDevice->getName() );
fDevice->GetBus()->retain();
fDevice->GetBus()->message(kIOUSBMessageExpressCardCantWake, this, fDevice);
fDevice->GetBus()->release();
}
suspendPropertyRef = OSDynamicCast( OSBoolean, fDevice->getProperty(kUSBSuspendPort) );
if ( suspendPropertyRef && suspendPropertyRef->isTrue() )
{
USBLog(3, "%s[%p](%s) Need to suspend the port", getName(), this, fDevice->getName() );
err = fDevice->SuspendDevice(true);
if ( err != kIOReturnSuccess )
{
USBLog(3, "%s[%p](%s) SuspendDevice returned 0x%x", getName(), this, fDevice->getName(), err );
}
}
fExpectingClose = true;
fDevice->close(this);
return true;
ErrorExit:
USBLog(3, "%s[%p]::start aborting startup (0x%x)", getName(), this, err );
return false;
}
IOReturn
IOUSBCompositeDriver::ReConfigureDevice()
{
const IOUSBConfigurationDescriptor * cd = NULL;
const IOUSBConfigurationDescriptor * cdTemp = NULL;
IOReturn err = kIOReturnSuccess;
IOUSBDevRequest request;
UInt8 numberOfConfigs = 0;
UInt32 i;
OSBoolean * suspendPropertyRef;
OSBoolean * expressCardCantWakeRef;
bzero( &request, sizeof(IOUSBDevRequest));
if ( fDevice && !fDevice->isOpen(this) )
{
if ( !fDevice->open(this) )
{
USBLog(3, "%s[%p]::ReConfigureDevice. Can't open it, giving up",getName(), this);
err = kIOReturnExclusiveAccess;
goto ErrorExit;
}
}
request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice);
request.bRequest = kUSBRqSetConfig;
request.wValue = fConfigValue;
request.wIndex = 0;
request.wLength = 0;
request.pData = 0;
err = fDevice->DeviceRequest(&request, 5000, 0);
if (err)
{
USBLog(3, "%s[%p]::ReConfigureDevice. SET_CONFIG returned 0x%x",getName(), this, err);
fDevice->close(this);
goto ErrorExit;
}
if (fConfigbmAttributes & kUSBAtrRemoteWakeup)
{
USBLog(3,"%s[%p]::ReConfigureDevice Setting kUSBFeatureDeviceRemoteWakeup for device: %s", getName(), this, fDevice->getName());
err = fDevice->SetFeature(kUSBFeatureDeviceRemoteWakeup);
if ( err != kIOReturnSuccess )
{
IOSleep(300);
err = fDevice->SetFeature(kUSBFeatureDeviceRemoteWakeup);
}
}
expressCardCantWakeRef = OSDynamicCast( OSBoolean, fDevice->getProperty(kUSBExpressCardCantWake) );
if ( expressCardCantWakeRef && expressCardCantWakeRef->isTrue() )
{
USBLog(3, "%s[%p](%s) found an express card device which will disconnect across sleep", getName(), this, fDevice->getName() );
fDevice->GetBus()->retain();
fDevice->GetBus()->message(kIOUSBMessageExpressCardCantWake, this, fDevice);
fDevice->GetBus()->release();
}
suspendPropertyRef = OSDynamicCast( OSBoolean, fDevice->getProperty(kUSBSuspendPort) );
if ( suspendPropertyRef && suspendPropertyRef->isTrue() )
{
USBLog(3, "%s[%p](%s) Need to suspend the port", getName(), this, fDevice->getName() );
err = fDevice->SuspendDevice(true);
if ( err != kIOReturnSuccess )
{
USBLog(3, "%s[%p](%s) SuspendDevice returned 0x%x", getName(), this, fDevice->getName(), err );
}
}
fDevice->close(this);
fDevice->retain();
(void) fDevice->messageClients(kIOUSBMessageCompositeDriverReconfigured, NULL, 0);
fDevice->release();
ErrorExit:
USBLog(6, "%s[%p]::ReConfigureDevice returned 0x%x",getName(),this, err);
return err;
}
IOReturn
IOUSBCompositeDriver::SetConfiguration(UInt8 configValue, bool startInterfaceMatching)
{
return fDevice->SetConfiguration(this, configValue, startInterfaceMatching);
}
#pragma mark ееееееее Static Methods еееееееее
IOReturn
IOUSBCompositeDriver::CompositeDriverInterestHandler( void * target, void * refCon, UInt32 messageType, IOService * provider,
void * messageArgument, vm_size_t argSize )
{
IOUSBCompositeDriver * me = (IOUSBCompositeDriver *) target;
if (!me)
{
return kIOReturnError;
}
switch ( messageType )
{
case kIOMessageServiceIsAttemptingOpen:
USBLog(5, "CompositeDriverInterestHandler received kIOMessageServiceIsAttemptingOpen with argument: %d", (int) messageArgument );
break;
case kIOMessageServiceWasClosed:
USBLog(5, "CompositeDriverInterestHandler received kIOMessageServiceWasClosed (expecting close = %d)", me->fExpectingClose);
me->fExpectingClose = false;
break;
case kIOMessageServiceIsTerminated:
case kIOUSBMessagePortHasBeenReset:
break;
default:
USBLog(5, "CompositeDriverInterestHandler message unknown: 0x%lx", messageType);
}
return kIOReturnSuccess;
}
#pragma mark ееееееее Padding Methods еееееееее
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 0);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 1);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 2);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 3);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 4);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 5);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 6);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 7);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 8);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 9);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 10);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 11);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 12);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 13);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 14);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 15);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 16);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 17);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 18);
OSMetaClassDefineReservedUnused(IOUSBCompositeDriver, 19);