IOUSBInterface.cpp [plain text]
#include <libkern/OSByteOrder.h>
#include <libkern/c++/OSDictionary.h>
#include <libkern/c++/OSData.h>
#include <IOKit/usb/IOUSBDevice.h>
#include <IOKit/usb/IOUSBController.h>
#include <IOKit/usb/IOUSBInterface.h>
#include <IOKit/usb/IOUSBPipe.h>
#include <IOKit/usb/IOUSBLog.h>
#include <IOKit/usb/USB.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOMessage.h>
#define super IOUSBNub
#define _gate _expansionData->_gate
#define _workLoop _expansionData->_workLoop
OSDefineMetaClassAndStructors(IOUSBInterface, IOUSBNub)
bool
IOUSBInterface::init(const IOUSBConfigurationDescriptor *cfdesc,
const IOUSBInterfaceDescriptor *ifdesc)
{
if(!ifdesc || !cfdesc)
return false;
if (!super::init()) return false;
if (!_expansionData)
{
_expansionData = (ExpansionData *)IOMalloc(sizeof(ExpansionData));
if (!_expansionData)
return false;
bzero(_expansionData, sizeof(ExpansionData));
}
_configDesc = cfdesc;
_interfaceDesc = ifdesc;
_bInterfaceNumber = _interfaceDesc->bInterfaceNumber;
_bAlternateSetting = _interfaceDesc->bAlternateSetting;
_bNumEndpoints = _interfaceDesc->bNumEndpoints;
_bInterfaceClass = _interfaceDesc->bInterfaceClass;
_bInterfaceSubClass = _interfaceDesc->bInterfaceSubClass;
_bInterfaceProtocol = _interfaceDesc->bInterfaceProtocol;
_iInterface = _interfaceDesc->iInterface;
return (true);
}
IOUSBInterface*
IOUSBInterface::withDescriptors(const IOUSBConfigurationDescriptor *cfdesc,
const IOUSBInterfaceDescriptor *ifdesc)
{
IOUSBInterface *me = new IOUSBInterface;
if (!me)
return NULL;
if (!me->init(cfdesc, ifdesc))
{
me->release();
return NULL;
}
return me;
}
void
IOUSBInterface::SetProperties(void)
{
setProperty(kUSBInterfaceNumber, (unsigned long long)_bInterfaceNumber, (sizeof(_bInterfaceNumber) * 8));
setProperty(kUSBAlternateSetting, (unsigned long long)_bAlternateSetting, (sizeof(_bAlternateSetting) * 8));
setProperty(kUSBNumEndpoints, (unsigned long long)_bNumEndpoints, (sizeof(_bNumEndpoints) * 8));
setProperty(kUSBInterfaceClass, (unsigned long long)_bInterfaceClass, (sizeof(_bInterfaceClass) * 8));
setProperty(kUSBInterfaceSubClass, (unsigned long long)_bInterfaceSubClass, (sizeof(_bInterfaceSubClass) * 8));
setProperty(kUSBInterfaceProtocol, (unsigned long long)_bInterfaceProtocol, (sizeof(_bInterfaceProtocol) * 8));
setProperty(kUSBInterfaceStringIndex, (unsigned long long)_iInterface, (sizeof(_iInterface) * 8));
setProperty(kUSBVendorID, (unsigned long long)_device->GetVendorID(), (sizeof(UInt16) * 8));
setProperty(kUSBProductID, (unsigned long long)_device->GetProductID(), (sizeof(UInt16) * 8));
setProperty(kUSBDeviceReleaseNumber, (unsigned long long)_device->GetDeviceRelease(), (sizeof(UInt16) * 8));
setProperty(kUSBConfigurationValue, (unsigned long long)_configDesc->bConfigurationValue, (sizeof(_configDesc->bConfigurationValue) * 8));
OSNumber *offset = OSNumber::withNumber(_bInterfaceNumber, 8);
if(offset)
{
UInt16 interfaceNumber;
char location[8];
interfaceNumber = offset->unsigned16BitValue();
offset->release();
sprintf( location, "%x", interfaceNumber );
setLocation(location);
}
if(_iInterface)
{
IOReturn err;
char name[128];
err = _device->GetStringDescriptor(_iInterface, name, sizeof(name));
if(err == kIOReturnSuccess)
setName(name);
}
}
bool
IOUSBInterface::start(IOService *provider)
{
if ( !super::start(provider))
return false;
_gate = IOCommandGate::commandGate(this);
if(!_gate)
{
USBError(1, "%s[%p]::start - unable to create command gate", getName(), this);
goto ErrorExit;
}
_workLoop = getWorkLoop();
if (!_workLoop)
{
USBError(1, "%s[%p]::start - unable to find my workloop", getName(), this);
goto ErrorExit;
}
_workLoop->retain();
if (_workLoop->addEventSource(_gate) != kIOReturnSuccess)
{
USBError(1, "%s[%p]::start - unable to add gate to work loop", getName(), this);
goto ErrorExit;
}
SetProperties();
if ( _device )
{
OSNumber * locationID = (OSNumber *) _device->getProperty(kUSBDevicePropertyLocationID);
if ( locationID )
setProperty(kUSBDevicePropertyLocationID,locationID->unsigned32BitValue(), 32);
}
return true;
ErrorExit:
if ( _gate != NULL )
{
_gate->release();
_gate = NULL;
}
if ( _workLoop != NULL )
{
_workLoop->release();
_workLoop = NULL;
}
return false;
}
bool
IOUSBInterface::attach(IOService *provider)
{
IOUSBDevice * device = OSDynamicCast(IOUSBDevice, provider);
if(!device)
return false;
if( !super::attach(provider))
return false;
_device = device;
return true;
}
bool
IOUSBInterface::finalize(IOOptionBits options)
{
bool ret;
USBLog(7, "+%s[%p]::finalize (options = 0x%lx)", getName(), this, (UInt32) options);
ret = super::finalize(options);
USBLog(7, "-%s[%p]::finalize (options = 0x%lx)", getName(), this, (UInt32) options);
return ret;
}
void
IOUSBInterface::free()
{
IOReturn ret = kIOReturnSuccess;
if (_expansionData)
{
if (_gate)
{
if (_workLoop)
{
ret = _workLoop->removeEventSource(_gate);
_workLoop->release();
_workLoop = NULL;
}
_gate->release();
_gate = NULL;
}
IOFree(_expansionData, sizeof(ExpansionData));
}
}
IOReturn
IOUSBInterface::CallSuperOpen(OSObject *target, void *param1, void *param2, void *param3, void *param4)
{
IOUSBInterface * me = OSDynamicCast(IOUSBInterface, target);
bool result;
IOReturn ret = kIOReturnSuccess;
IOService * forClient = (IOService *) param1;
IOOptionBits options = (IOOptionBits ) param2;
void * arg = param3;
if (!me)
{
USBLog(1, "IOUSBInterface::CallSuperOpen - invalid target");
return kIOReturnBadArgument;
}
result = me->super::open(forClient, options, arg);
if (! result )
ret = kIOReturnNoResources;
return ret;
}
IOReturn
IOUSBInterface::CallSuperClose(OSObject *target, void *param1, void *param2, void *param3, void *param4)
{
IOUSBInterface * me = OSDynamicCast(IOUSBInterface, target);
bool result;
IOReturn ret = kIOReturnSuccess;
IOService * forClient = (IOService *) param1;
IOOptionBits options = (IOOptionBits ) param2;
if (!me)
{
USBLog(1, "IOUSBInterface::CallSuperClose - invalid target");
return kIOReturnBadArgument;
}
me->super::close(forClient, options);
return kIOReturnSuccess;
}
void
IOUSBInterface::ClosePipes(void)
{
IOUSBPipe * pipe;
USBLog(7,"+%s[%p]::ClosePipes", getName(), this);
for( unsigned int i=0; i < kUSBMaxPipes; i++)
{
if( (pipe = _pipeList[i]))
{
pipe->Abort();
pipe->ClosePipe();
pipe->release();
_pipeList[i] = NULL;
}
}
USBLog(7,"-%s::ClosePipes", getName(), this);
}
IOReturn
IOUSBInterface::CreatePipes(void)
{
unsigned int i = 0;
const IOUSBDescriptorHeader *pos = NULL; bool makePipeFailed = false;
IOReturn res = kIOReturnSuccess;
while ((pos = FindNextAssociatedDescriptor(pos, kUSBEndpointDesc)))
{
if(_pipeList[i] == NULL)
_pipeList[i] = _device->MakePipe((const IOUSBEndpointDescriptor *)pos);
if(_pipeList[i] == NULL)
{
makePipeFailed = true;
}
i++;
}
if ( (i != _bNumEndpoints) && !makePipeFailed )
{
if (i < _bNumEndpoints)
USBLog(3, "%s: NOTE: Interface descriptor defines more endpoints (bNumEndpoints = %d, descriptors = %d) than endpoint descriptors", getName(), this, _bNumEndpoints, i);
else
USBLog(3, "%s: NOTE: Interface descriptor defines less endpoints (bNumEndpoints = %d, descriptors = %d) than endpoint descriptors", getName(), this, _bNumEndpoints, i);
}
if ( makePipeFailed )
{
USBLog(3,"%s[%p]: Failed to create all pipes.", getName(), this);
}
return res;
}
bool
IOUSBInterface::open( IOService *forClient, IOOptionBits options, void *arg )
{
bool res = true;
IOReturn error = kIOReturnSuccess;
bool useGate = false;
OSBoolean * boolObj = OSDynamicCast( OSBoolean, _device->getProperty(kCallInterfaceOpenWithGate) );
if ( boolObj && boolObj->isTrue() )
{
useGate = true;
}
if ( _gate && useGate )
{
USBLog(6,"%+s[%p]::open calling super::open with gate", getName(), this);
error = _gate->runAction( CallSuperOpen, (void *)forClient, (void *)options, (void *)arg );
if ( error != kIOReturnSuccess )
{
USBError(1,"%s[%p]::open super::open failed (0x%x)", getName(), this, error);
res = false;
}
}
else
{
USBLog(6,"%+s[%p]::open calling super::open with NO gate", getName(), this);
res = super::open(forClient, options, arg);
}
if (!res)
USBError(1,"%s[%p]::open super::open failed (0x%x)", getName(), this, res);
USBLog(3, "-%s[%p]::open returns %d", getName(), this, res);
return res;
}
bool
IOUSBInterface::handleOpen( IOService *forClient, IOOptionBits options, void *arg )
{
UInt16 altInterface;
IOReturn err = kIOReturnSuccess;
USBLog(3, "+%s[%p]::handleOpen (device %s)", getName(), this, _device->getName());
if(!super::handleOpen(forClient, options, arg))
{
USBError(1,"%s[%p]::handleOpen failing because super::handleOpen failed (someone already has it open)", getName(), this);
return false;
}
if (options & kIOUSBInterfaceOpenAlt)
{
altInterface = (UInt16)(UInt32)arg;
USBLog(5, "%s[%p]::handleOpen calling SetAlternateInterface(%d)", getName(), this, altInterface);
err = SetAlternateInterface(forClient, altInterface);
if ( err != kIOReturnSuccess)
USBError(1, "%s[%p]::handleOpen: SetAlternateInterface failed (0x%x)", getName(), this, err);
}
else
{
err = CreatePipes();
if ( err != kIOReturnSuccess)
USBError(1, "%s[%p]::handleOpen: CreatePipes failed (0x%x)", getName(), this, err);
}
if (err != kIOReturnSuccess)
{
close(forClient);
return false;
}
USBLog(3, "-%s[%p]::handleOpen (device %s): successful", getName(), this, _device->getName());
return true;
}
void
IOUSBInterface::close( IOService *forClient, IOOptionBits options)
{
IOReturn error = kIOReturnSuccess;
bool useGate = false;
OSBoolean * boolObj = OSDynamicCast( OSBoolean, _device->getProperty(kCallInterfaceOpenWithGate) );
if ( boolObj && boolObj->isTrue() )
{
useGate = true;
}
if ( _gate && useGate)
{
USBLog(3,"%+s[%p]::open calling super::close with gate", getName(), this);
(void) _gate->runAction( CallSuperClose, (void *)forClient, (void *)options);
}
else
{
USBLog(6,"%+s[%p]::close calling super::close with NO gate", getName(), this);
super::close(forClient, options);
}
USBLog(3, "%s[%p]::close returns", getName(), this);
}
void
IOUSBInterface::handleClose(IOService * forClient, IOOptionBits options )
{
IOUSBPipe *pipe;
unsigned int i;
USBLog(7,"+%s[%p]::handleClose", getName(), this);
for( i=0; i < kUSBMaxPipes; i++)
if( (pipe = _pipeList[i]))
pipe->Abort();
super::handleClose(forClient, options);
USBLog(7,"-%s[%p]::handleClose", getName(), this);
}
const IOUSBInterfaceDescriptor *
IOUSBInterface::FindNextAltInterface(const IOUSBInterfaceDescriptor *current,
IOUSBFindInterfaceRequest *request)
{
IOUSBInterfaceDescriptor *id = (IOUSBInterfaceDescriptor *)current;
while (_device->FindNextInterfaceDescriptor(NULL, id, request, &id) == kIOReturnSuccess)
{
if (id == NULL)
return NULL;
if (id->bInterfaceNumber != _bInterfaceNumber)
continue;
return id;
}
return NULL;
}
IOUSBPipe*
IOUSBInterface::FindNextPipe(IOUSBPipe *current,
IOUSBFindEndpointRequest *request)
{
const IOUSBController::Endpoint * endpoint;
IOUSBPipe * pipe;
int numEndpoints;
int i;
numEndpoints = _bNumEndpoints;
if (request == 0)
return NULL;
if(current != 0)
{
for(i=0;i < numEndpoints; i++)
{
if(_pipeList[i] == current)
{
i++; break;
}
}
}
else
i = 0;
for ( ;i < numEndpoints; i++) {
pipe = _pipeList[i];
if(!pipe)
continue;
endpoint = pipe->GetEndpoint();
if (request->type != kUSBAnyType &&
request->type != endpoint->transferType)
pipe = 0; else if (request->direction != kUSBAnyDirn &&
request->direction != endpoint->direction)
pipe = 0;
if (pipe == 0)
continue;
request->type = endpoint->transferType;
request->direction = endpoint->direction;
request->maxPacketSize = endpoint->maxPacketSize;
request->interval = endpoint->interval;
return(pipe);
}
return(0);
}
const IOUSBDescriptorHeader *
IOUSBInterface::FindNextAssociatedDescriptor(const void *current, UInt8 type)
{
const IOUSBDescriptorHeader *next;
if(current == NULL)
current = _interfaceDesc;
next = (const IOUSBDescriptorHeader *)current;
while (true)
{
next = _device->FindNextDescriptor(next, kUSBAnyDesc);
if(!next || next->bDescriptorType == kUSBInterfaceDesc)
return NULL;
if(next->bDescriptorType == type || type == kUSBAnyDesc)
break;
}
return next;
}
IOReturn
IOUSBInterface::SetAlternateInterface(IOService *forClient, UInt16 alternateSetting)
{
const IOUSBDescriptorHeader *next;
const IOUSBInterfaceDescriptor *ifdesc = NULL;
IOUSBDevRequest request;
IOReturn res;
USBLog(5,"%s[%p]::SetAlternateInterface to %d",getName(), this, alternateSetting);
if (!isOpen(forClient))
{
res = kIOReturnExclusiveAccess;
goto ErrorExit;
}
next = (const IOUSBDescriptorHeader *)_configDesc;
while( (next = _device->FindNextDescriptor(next, kUSBInterfaceDesc)))
{
ifdesc = (const IOUSBInterfaceDescriptor *)next;
if((ifdesc->bInterfaceNumber == _bInterfaceNumber) && (ifdesc->bAlternateSetting == alternateSetting))
break;
}
if (!ifdesc)
{
res = kIOUSBInterfaceNotFound;
goto ErrorExit;
}
ClosePipes();
_interfaceDesc = ifdesc;
_bInterfaceNumber = _interfaceDesc->bInterfaceNumber; _bAlternateSetting = _interfaceDesc->bAlternateSetting; _bNumEndpoints = _interfaceDesc->bNumEndpoints;
_bInterfaceClass = _interfaceDesc->bInterfaceClass;
_bInterfaceSubClass = _interfaceDesc->bInterfaceSubClass;
_bInterfaceProtocol = _interfaceDesc->bInterfaceProtocol;
_iInterface = _interfaceDesc->iInterface;
request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBInterface);
request.bRequest = kUSBRqSetInterface;
request.wValue = _bAlternateSetting;
request.wIndex = _bInterfaceNumber;
request.wLength = 0;
request.pData = NULL;
res = _device->DeviceRequest(&request);
if (res != kIOReturnSuccess)
{
close(forClient);
goto ErrorExit;
}
SetProperties();
res = CreatePipes();
ErrorExit:
if ( res != kIOReturnSuccess )
{
USBLog(3,"%s[%p]::SetAlternateInterface (Intfc: %d, AltSet: %d) returning error (0x%x)",getName(), this, _bInterfaceNumber, _bAlternateSetting, res);
}
return res;
}
bool
IOUSBInterface::matchPropertyTable(OSDictionary * table, SInt32 *score)
{
bool returnValue = true;
SInt32 propertyScore = *score;
OSString *userClientInitMatchKey;
char logString[256]="";
if ( table == NULL )
{
return false;
}
bool vendorPropertyExists = table->getObject(kUSBVendorID);
bool productPropertyExists = table->getObject(kUSBProductID);
bool interfaceNumberPropertyExists = table->getObject(kUSBInterfaceNumber);
bool configurationValuePropertyExists = table->getObject(kUSBConfigurationValue);
bool deviceReleasePropertyExists = table->getObject(kUSBDeviceReleaseNumber);
bool interfaceClassPropertyExists = table->getObject(kUSBInterfaceClass);
bool interfaceSubClassPropertyExists = table->getObject(kUSBInterfaceSubClass);
bool interfaceProtocolPropertyExists= table->getObject(kUSBInterfaceProtocol);
bool vendorPropertyMatches = USBCompareProperty(table, kUSBVendorID);
bool productPropertyMatches = USBCompareProperty(table, kUSBProductID);
bool interfaceNumberPropertyMatches = USBCompareProperty(table, kUSBInterfaceNumber);
bool configurationValuePropertyMatches = USBCompareProperty(table, kUSBConfigurationValue);
bool deviceReleasePropertyMatches = USBCompareProperty(table, kUSBDeviceReleaseNumber);
bool interfaceClassPropertyMatches = USBCompareProperty(table, kUSBInterfaceClass);
bool interfaceSubClassPropertyMatches = USBCompareProperty(table, kUSBInterfaceSubClass);
bool interfaceProtocolPropertyMatches= USBCompareProperty(table, kUSBInterfaceProtocol);
if (!super::matchPropertyTable(table)) return false;
userClientInitMatchKey = OSDynamicCast(OSString, table->getObject(kIOMatchCategoryKey));
if (userClientInitMatchKey && !strcmp(userClientInitMatchKey->getCStringNoCopy(), "IOUSBUserClientInit"))
{
USBLog(6, "%s[%p]: matching IOUSBUserClientInit", getName(), this);
*score = 9000;
return true;
}
if ( propertyScore >= 10000 )
propertyScore = 9000;
OSNumber * interfaceClass = (OSNumber *) getProperty(kUSBInterfaceClass);
if ( vendorPropertyMatches && productPropertyMatches && deviceReleasePropertyMatches &&
configurationValuePropertyMatches && interfaceNumberPropertyMatches &&
(!interfaceClassPropertyExists || interfaceClassPropertyMatches) &&
(!interfaceSubClassPropertyExists || interfaceSubClassPropertyMatches) &&
(!interfaceProtocolPropertyExists || interfaceProtocolPropertyMatches) )
{
*score = 100000;
}
else if ( vendorPropertyMatches && productPropertyMatches && configurationValuePropertyMatches &&
interfaceNumberPropertyMatches &&
(!deviceReleasePropertyExists || deviceReleasePropertyMatches) &&
(!interfaceClassPropertyExists || interfaceClassPropertyMatches) &&
(!interfaceSubClassPropertyExists || interfaceSubClassPropertyMatches) &&
(!interfaceProtocolPropertyExists || interfaceProtocolPropertyMatches) )
{
*score = 90000;
}
else if ( interfaceClass->unsigned32BitValue() == kUSBVendorSpecificClass )
{
if ( vendorPropertyMatches && interfaceSubClassPropertyMatches && interfaceProtocolPropertyMatches &&
(!interfaceClassPropertyExists || interfaceClassPropertyMatches) &&
!deviceReleasePropertyExists && !productPropertyExists &&
!interfaceNumberPropertyExists && !configurationValuePropertyExists )
{
*score = 80000;
}
else if ( vendorPropertyMatches && interfaceSubClassPropertyMatches &&
(!interfaceClassPropertyExists || interfaceClassPropertyMatches) &&
!interfaceProtocolPropertyExists && !deviceReleasePropertyExists &&
!productPropertyExists && !interfaceNumberPropertyExists && !configurationValuePropertyExists )
{
*score = 70000;
}
else
{
*score = 0;
returnValue = false;
}
}
else if ( interfaceClassPropertyMatches && interfaceSubClassPropertyMatches && interfaceProtocolPropertyMatches &&
!deviceReleasePropertyExists && !vendorPropertyExists && !productPropertyExists &&
!interfaceNumberPropertyExists && !configurationValuePropertyExists )
{
*score = 60000;
}
else if ( interfaceClassPropertyMatches && interfaceSubClassPropertyMatches &&
!interfaceProtocolPropertyExists && !deviceReleasePropertyExists && !vendorPropertyExists &&
!productPropertyExists && !interfaceNumberPropertyExists && !configurationValuePropertyExists )
{
*score = 50000;
}
else
{
*score = 0;
returnValue = false;
}
if ( *score != 0 )
*score += propertyScore;
OSString * identifier = OSDynamicCast(OSString, table->getObject("CFBundleIdentifier"));
OSNumber * vendor = (OSNumber *) getProperty(kUSBVendorID);
OSNumber * product = (OSNumber *) getProperty(kUSBProductID);
OSNumber * release = (OSNumber *) getProperty(kUSBDeviceReleaseNumber);
OSNumber * configuration = (OSNumber *) getProperty(kUSBConfigurationValue);
OSNumber * interfaceNumber = (OSNumber *) getProperty(kUSBInterfaceNumber);
OSNumber * interfaceSubClass = (OSNumber *) getProperty(kUSBInterfaceSubClass);
OSNumber * protocol = (OSNumber *) getProperty(kUSBInterfaceProtocol);
OSNumber * dictVendor = (OSNumber *) table->getObject(kUSBVendorID);
OSNumber * dictProduct = (OSNumber *) table->getObject(kUSBProductID);
OSNumber * dictRelease = (OSNumber *) table->getObject(kUSBDeviceReleaseNumber);
OSNumber * dictConfiguration = (OSNumber *) table->getObject(kUSBConfigurationValue);
OSNumber * dictInterfaceNumber = (OSNumber *) table->getObject(kUSBInterfaceNumber);
OSNumber * dictInterfaceClass = (OSNumber *) table->getObject(kUSBInterfaceClass);
OSNumber * dictInterfaceSubClass = (OSNumber *) table->getObject(kUSBInterfaceSubClass);
OSNumber * dictProtocol = (OSNumber *) table->getObject(kUSBInterfaceProtocol);
bool match;
if (identifier)
USBLog(5,"Finding driver for interface #%d of %s, matching personality using %s, score: %ld", _bInterfaceNumber, _device->getName(), identifier->getCStringNoCopy(), *score);
else
USBLog(6,"Finding driver for interface #%d of %s, matching user client dictionary, score: %ld", _bInterfaceNumber, _device->getName(), *score);
if ( vendor && product && release && configuration && interfaceNumber && interfaceClass && interfaceSubClass && protocol )
{
char tempString[256]="";
sprintf(logString,"\tMatched: ");
match = false;
if ( vendorPropertyMatches ) { match = true; sprintf(tempString,"idVendor (%d) ", vendor->unsigned32BitValue()); strcat(logString, tempString); }
if ( productPropertyMatches ) { match = true; sprintf(tempString,"idProduct (%d) ", product->unsigned32BitValue()); strcat(logString, tempString); }
if ( deviceReleasePropertyMatches ) { match = true; sprintf(tempString,"bcdDevice (%d) ", release->unsigned32BitValue()); strcat(logString, tempString); }
if ( configurationValuePropertyMatches ) { match = true; sprintf(tempString,"bConfigurationValue (%d) ", configuration->unsigned32BitValue());strcat(logString, tempString); }
if ( interfaceNumberPropertyMatches ) { match = true; sprintf(tempString,"bInterfaceNumber (%d) ", interfaceNumber->unsigned32BitValue());strcat(logString, tempString); }
if ( interfaceClassPropertyMatches ) { match = true; sprintf(tempString,"bInterfaceClass (%d) ", interfaceClass->unsigned32BitValue()); strcat(logString, tempString); }
if ( interfaceSubClassPropertyMatches ) { match = true; sprintf(tempString,"bInterfaceSubClass (%d) ", interfaceSubClass->unsigned32BitValue());strcat(logString, tempString); }
if ( interfaceProtocolPropertyMatches ) { match = true; sprintf(tempString,"bInterfaceProtocol (%d) ", protocol->unsigned32BitValue());strcat(logString, tempString); }
if ( !match ) strcat(logString, "no properties");
USBLog(6,logString);
sprintf(logString,"\tDidn't Match: ");
match = false;
if ( !vendorPropertyMatches && dictVendor )
{
match = true;
sprintf(tempString,"idVendor (%d,%d) ", dictVendor->unsigned32BitValue(), vendor->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !productPropertyMatches && dictProduct)
{
match = true;
sprintf(tempString,"idProduct (%d,%d) ", dictProduct->unsigned32BitValue(), product->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !deviceReleasePropertyMatches && dictRelease)
{
match = true;
sprintf(tempString,"bcdDevice (%d,%d) ", dictRelease->unsigned32BitValue(), release->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !configurationValuePropertyMatches && dictConfiguration)
{
match = true;
sprintf(tempString,"bConfigurationValue (%d,%d) ", dictConfiguration->unsigned32BitValue(), configuration->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !interfaceNumberPropertyMatches && dictInterfaceNumber)
{
match = true;
sprintf(tempString,"bInterfaceNumber (%d,%d) ", dictInterfaceNumber->unsigned32BitValue(), interfaceNumber->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !interfaceClassPropertyMatches && dictInterfaceClass)
{
match = true;
sprintf(tempString,"bInterfaceClass (%d,%d) ", dictInterfaceClass->unsigned32BitValue(), interfaceClass->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !interfaceSubClassPropertyMatches && dictInterfaceSubClass)
{
match = true;
sprintf(tempString,"bInterfaceSubClass (%d,%d) ", dictInterfaceSubClass->unsigned32BitValue(), interfaceSubClass->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !interfaceProtocolPropertyMatches && dictProtocol)
{
match = true;
sprintf(tempString,"bDeviceProtocol (%d,%d) ", dictProtocol->unsigned32BitValue(), protocol->unsigned32BitValue());
strcat(logString, tempString);
}
if ( !match ) strcat(logString,"nothing");
USBLog(6,logString);
}
return returnValue;
}
IOReturn
IOUSBInterface::message( UInt32 type, IOService * provider, void * argument )
{
IOReturn err = kIOReturnSuccess;
switch ( type )
{
case kIOUSBMessagePortHasBeenReset:
messageClients( kIOUSBMessagePortHasBeenReset, this, NULL);
break;
case kIOUSBMessagePortHasBeenResumed:
messageClients( kIOUSBMessagePortHasBeenResumed, this, NULL);
break;
case kIOMessageServiceIsTerminated:
break;
case kIOMessageServiceIsSuspended:
case kIOMessageServiceIsResumed:
case kIOMessageServiceIsRequestingClose:
case kIOMessageServiceWasClosed:
case kIOMessageServiceBusyStateChange:
err = kIOReturnUnsupported;
default:
break;
}
return err;
}
void
IOUSBInterface::stop( IOService * provider )
{
USBLog(7,"+%s[%p]::stop (provider = %p)", getName(), this, provider);
ClosePipes();
super::stop(provider);
USBLog(7,"-%s[%p]::stop (provider = %p)", getName(), this, provider);
}
IOUSBPipe *
IOUSBInterface::GetPipeObj(UInt8 index)
{
return (index < kUSBMaxPipes) ? _pipeList[index] : NULL ;
}
UInt8
IOUSBInterface::GetConfigValue()
{
return _configDesc->bConfigurationValue;
}
IOUSBDevice *
IOUSBInterface::GetDevice()
{
return _device;
}
UInt8
IOUSBInterface::GetInterfaceNumber()
{
return _bInterfaceNumber;
}
UInt8
IOUSBInterface::GetAlternateSetting()
{
return _bAlternateSetting;
}
UInt8
IOUSBInterface::GetNumEndpoints()
{
return _bNumEndpoints;
}
UInt8
IOUSBInterface::GetInterfaceClass()
{
return _bInterfaceClass;
}
UInt8
IOUSBInterface::GetInterfaceSubClass()
{
return _bInterfaceSubClass;
}
UInt8
IOUSBInterface::GetInterfaceProtocol()
{
return _bInterfaceProtocol;
}
UInt8
IOUSBInterface::GetInterfaceStringIndex()
{
return _iInterface;
}
IOReturn
IOUSBInterface::DeviceRequest(IOUSBDevRequest *request, IOUSBCompletion *completion)
{
return _device->DeviceRequest(request, completion);
}
IOReturn
IOUSBInterface::DeviceRequest(IOUSBDevRequestDesc *request, IOUSBCompletion *completion)
{
return _device->DeviceRequest(request, completion);
}
OSMetaClassDefineReservedUsed(IOUSBInterface, 0);
IOReturn
IOUSBInterface::GetEndpointProperties(UInt8 alternateSetting, UInt8 endpointNumber, UInt8 direction, UInt8 *transferType, UInt16 *maxPacketSize, UInt8 *interval)
{
const IOUSBDescriptorHeader *next, *next2;
const IOUSBInterfaceDescriptor *ifdesc = NULL;
const IOUSBEndpointDescriptor *endp = NULL;
UInt8 endpointAddress = endpointNumber | ((direction == kUSBIn) ? 0x80 : 0x00);
next = (const IOUSBDescriptorHeader *)_configDesc;
USBLog(2, "%s[%p]::GetEndpointProperties - looking for address %x in altSetting %d", getName(), this, endpointAddress, alternateSetting);
while( (next = _device->FindNextDescriptor(next, kUSBInterfaceDesc)))
{
ifdesc = (const IOUSBInterfaceDescriptor *)next;
if ((ifdesc->bInterfaceNumber == _bInterfaceNumber) && (ifdesc->bAlternateSetting == alternateSetting))
{
next2 = next;
while ( (next2 = FindNextAssociatedDescriptor(next2, kUSBEndpointDesc)))
{
endp = (const IOUSBEndpointDescriptor*)next2;
if (endp->bEndpointAddress == endpointAddress)
{
*transferType = endp->bmAttributes & 0x03;
*maxPacketSize = mungeMaxPacketSize(USBToHostWord(endp->wMaxPacketSize));
*interval = endp->bInterval;
USBLog(3, "%s[%p]::GetEndpointProperties - tt=%d, mps=%d, int=%d", getName(), this, *transferType, *maxPacketSize, *interval);
return kIOReturnSuccess;
}
}
}
}
return kIOUSBEndpointNotFound;
}
OSMetaClassDefineReservedUnused(IOUSBInterface, 1);
OSMetaClassDefineReservedUnused(IOUSBInterface, 2);
OSMetaClassDefineReservedUnused(IOUSBInterface, 3);
OSMetaClassDefineReservedUnused(IOUSBInterface, 4);
OSMetaClassDefineReservedUnused(IOUSBInterface, 5);
OSMetaClassDefineReservedUnused(IOUSBInterface, 6);
OSMetaClassDefineReservedUnused(IOUSBInterface, 7);
OSMetaClassDefineReservedUnused(IOUSBInterface, 8);
OSMetaClassDefineReservedUnused(IOUSBInterface, 9);
OSMetaClassDefineReservedUnused(IOUSBInterface, 10);
OSMetaClassDefineReservedUnused(IOUSBInterface, 11);
OSMetaClassDefineReservedUnused(IOUSBInterface, 12);
OSMetaClassDefineReservedUnused(IOUSBInterface, 13);
OSMetaClassDefineReservedUnused(IOUSBInterface, 14);
OSMetaClassDefineReservedUnused(IOUSBInterface, 15);
OSMetaClassDefineReservedUnused(IOUSBInterface, 16);
OSMetaClassDefineReservedUnused(IOUSBInterface, 17);
OSMetaClassDefineReservedUnused(IOUSBInterface, 18);
OSMetaClassDefineReservedUnused(IOUSBInterface, 19);