IOUSBInterfaceUserClient.cpp [plain text]
#include <IOKit/usb/IOUSBController.h>
#include <IOKit/IOKitKeys.h>
#include "IOUSBInterfaceUserClient.h"
#if DEBUG_LEVEL != 0
#include <sys/proc.h>
#endif
#define super IOUserClient
#ifndef kIOUserClientCrossEndianKey
#define kIOUserClientCrossEndianKey "IOUserClientCrossEndian"
#endif
#ifndef kIOUserClientCrossEndianCompatibleKey
#define kIOUserClientCrossEndianCompatibleKey "IOUserClientCrossEndianCompatible"
#endif
OSDefineMetaClassAndStructors(IOUSBInterfaceUserClientV2, super)
OSDefineMetaClassAndStructors(IOUSBLowLatencyCommand, IOCommand)
const IOExternalMethodDispatch
IOUSBInterfaceUserClientV2::sMethods[kIOUSBLibInterfaceUserClientNumCommands] = {
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_open,
1, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_close,
0, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetDevice,
0, 0,
1, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_SetAlternateInterface,
1, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetFrameNumber,
0, 0,
0, sizeof(IOUSBGetFrameStruct)
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetPipeProperties,
1, 0,
5, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_ReadPipe,
5, 0,
0, 0xffffffff
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_WritePipe,
5, 0xffffffff,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetPipeStatus,
1, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_AbortPipe,
1, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_ResetPipe,
1, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_ClearPipeStall,
2, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_ControlRequestOut,
9, 0xffffffff,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_ControlRequestIn,
9, 0,
0, 0xffffffff
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_SetPipePolicy,
3, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetBandwidthAvailable,
0, 0,
1, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetEndpointProperties,
3, 0,
3, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_LowLatencyPrepareBuffer,
0, sizeof(LowLatencyUserBufferInfoV2),
1, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_LowLatencyReleaseBuffer,
0, sizeof(LowLatencyUserBufferInfoV2),
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetMicroFrameNumber,
0, 0,
0, sizeof(IOUSBGetFrameStruct)
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetFrameListTime,
0, 0,
1, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetFrameNumberWithTime,
0, 0,
0, sizeof(IOUSBGetFrameStruct)
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_SetAsyncPort,
0, 0,
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_ReadIsochPipe,
0, sizeof(IOUSBIsocStruct),
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_WriteIsochPipe,
0, sizeof(IOUSBIsocStruct),
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_LowLatencyReadIsochPipe,
0, sizeof(IOUSBLowLatencyIsocStruct),
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_LowLatencyWriteIsochPipe,
0, sizeof(IOUSBLowLatencyIsocStruct),
0, 0
},
{ (IOExternalMethodAction) &IOUSBInterfaceUserClientV2::_GetConfigDescriptor,
1, 0,
0, 0xffffffff
},
};
#pragma mark -
IOReturn IOUSBInterfaceUserClientV2::externalMethod(
uint32_t selector,
IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch,
OSObject * target,
void * reference)
{
if (selector < (uint32_t) kIOUSBLibInterfaceUserClientNumCommands)
{
dispatch = (IOExternalMethodDispatch *) &sMethods[selector];
if (!target)
target = this;
}
return super::externalMethod(selector, arguments, dispatch, target, reference);
}
#pragma mark Async Support
IOReturn
IOUSBInterfaceUserClientV2::_SetAsyncPort(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_SetAsyncPort", target->getName(), target);
return target->SetAsyncPort(arguments->asyncWakePort);
}
IOReturn IOUSBInterfaceUserClientV2::SetAsyncPort(mach_port_t port)
{
USBLog(7,"+IOUSBInterfaceUserClientV2::SetAsyncPort");
if (!fOwner)
return kIOReturnNotAttached;
fWakePort = port;
return kIOReturnSuccess;
}
void
IOUSBInterfaceUserClientV2::ReqComplete(void *obj, void *param, IOReturn res, UInt32 remaining)
{
io_user_reference_t args[1];
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock *)param;
IOUSBInterfaceUserClientV2 *me = OSDynamicCast(IOUSBInterfaceUserClientV2, (OSObject*)obj);
if (!me)
return;
USBLog(7, "%s[%p]::ReqComplete, res = 0x%x, req = %08x, remaining = %08x", me->getName(), me, res, (int)pb->fMax, (int)remaining);
if(res == kIOReturnSuccess)
{
args[0] = (io_user_reference_t)(pb->fMax - remaining);
}
else
{
args[0] = 0;
}
if (pb->fMem)
{
pb->fMem->complete();
pb->fMem->release();
}
if (!me->fDead)
sendAsyncResult64(pb->fAsyncRef, res, args, 1);
IOFree(pb, sizeof(*pb));
me->DecrementOutstandingIO();
me->release();
}
void
IOUSBInterfaceUserClientV2::IsoReqComplete(void *obj, void *param, IOReturn res, IOUSBIsocFrame *pFrames)
{
io_user_reference_t args[1];
IOUSBInterfaceUserClientISOAsyncParamBlock * pb = (IOUSBInterfaceUserClientISOAsyncParamBlock *)param;
IOUSBInterfaceUserClientV2 * me = OSDynamicCast(IOUSBInterfaceUserClientV2, (OSObject*)obj);
UInt32 i;
if (!me)
return;
USBLog(7, "%s[%p]::IsoReqComplete, result = 0x%x, dataMem: %p", me->getName(), me, res, pb->dataMem);
args[0] = (io_user_reference_t) pb->frameBase;
pb->countMem->writeBytes(0, pb->frames, pb->frameLen);
pb->dataMem->complete();
pb->dataMem->release();
pb->dataMem = NULL;
pb->countMem->complete();
pb->countMem->release();
pb->countMem = NULL;
if (!me->fDead)
sendAsyncResult64(pb->fAsyncRef, res, args, 1);
IOFree(pb, sizeof(*pb)+pb->frameLen);
me->DecrementOutstandingIO();
me->release();
}
void
IOUSBInterfaceUserClientV2::LowLatencyIsoReqComplete(void *obj, void *param, IOReturn res, IOUSBLowLatencyIsocFrame *pFrames)
{
io_user_reference_t args[1];
IOUSBLowLatencyCommand * command = (IOUSBLowLatencyCommand *) param;
IOMemoryDescriptor * dataBufferDescriptor;
OSAsyncReference64 asyncRef;
IOUSBInterfaceUserClientV2 * me = OSDynamicCast(IOUSBInterfaceUserClientV2, (OSObject*)obj);
if (!me)
return;
args[0] = (io_user_reference_t) command->GetFrameBase();
command->GetAsyncReference(&asyncRef);
if (!me->fDead)
sendAsyncResult64( asyncRef, res, args, 1);
dataBufferDescriptor = command->GetDataBuffer();
dataBufferDescriptor->complete();
dataBufferDescriptor->release();
dataBufferDescriptor = NULL;
me->fFreeUSBLowLatencyCommandPool->returnCommand(command);
me->DecrementOutstandingIO();
me->release();
}
#pragma mark User Client Start/Close
bool
IOUSBInterfaceUserClientV2::initWithTask(task_t owningTask,void *security_id , UInt32 type, OSDictionary * properties )
{
if ( properties != NULL )
{
properties->setObject( kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue);
}
if (!super::initWithTask(owningTask, security_id , type, properties))
return false;
if (!owningTask)
return false;
if (!fIOUSBInterfaceUserClientExpansionData)
{
fIOUSBInterfaceUserClientExpansionData = (IOUSBInterfaceUserClientExpansionData *)IOMalloc(sizeof(IOUSBInterfaceUserClientExpansionData));
if (!fIOUSBInterfaceUserClientExpansionData)
return false;
bzero(fIOUSBInterfaceUserClientExpansionData, sizeof(IOUSBInterfaceUserClientExpansionData));
}
fTask = owningTask;
fDead = false;
#if DEBUG_LEVEL != 0
char nbuf[256];
proc_t p = proc_self();
int owningPID = proc_pid(p);
proc_name(owningPID,nbuf,256);
OSNumber* pidProp = OSNumber::withNumber( proc_pid(p), sizeof(proc_pid(p)) * 8 );
if ( pidProp )
{
setProperty( "Owning PID", pidProp ) ;
pidProp->release() ; }
OSSymbol* processNameProp = (OSSymbol *)OSSymbol::withCString(nbuf);
if ( processNameProp)
{
setProperty( "Process Name", processNameProp ) ;
processNameProp->release() ; }
USBLog(5,"IOUSBInterfaceUserClientV2[%p]::initWithTask Owning PID is %d, name is %s", this, owningPID, nbuf);
proc_rele(p);
#endif
fClientRunningUnderRosetta = ( type & 0x80000000 );
return true;
}
bool
IOUSBInterfaceUserClientV2::start( IOService * provider )
{
IOWorkLoop * workLoop = NULL;
IOCommandGate * commandGate = NULL;
OSObject * propertyObj = NULL;
OSBoolean * boolObj = NULL;
USBLog(7, "+%s[%p]::start(%p)", getName(), this, provider);
IncrementOutstandingIO();
fOwner = OSDynamicCast(IOUSBInterface, provider);
if (!fOwner)
{
USBError(1, "%s[%p]::start - provider is NULL!", getName(), this);
goto ErrorExit;
}
if(!super::start(provider))
{
USBError(1, "%s[%p]::start - super::start returned false!", getName(), this);
goto ErrorExit;
}
commandGate = IOCommandGate::commandGate(this);
if (!commandGate)
{
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(commandGate) != kIOReturnSuccess)
{
USBError(1, "%s[%p]::start - unable to add gate to work loop", getName(), this);
goto ErrorExit;
}
fFreeUSBLowLatencyCommandPool = IOCommandPool::withWorkLoop(workLoop);
if (!fFreeUSBLowLatencyCommandPool)
{
USBError(1,"%s[%p]::start - unable to create free command pool", getName(), this);
workLoop->removeEventSource(commandGate);
goto ErrorExit;
}
propertyObj = fOwner->GetDevice()->copyProperty(kUSBControllerNeedsContiguousMemoryForIsoch);
boolObj = OSDynamicCast( OSBoolean, propertyObj);
if ( boolObj )
{
if ( boolObj->isTrue() )
fNeedContiguousMemoryForLowLatencyIsoch = true;
else
fNeedContiguousMemoryForLowLatencyIsoch = false;
}
if (propertyObj)
propertyObj->release();
fGate = commandGate;
fWorkLoop = workLoop;
USBLog(7, "-%s[%p]::start", getName(), this);
DecrementOutstandingIO();
return true;
ErrorExit:
if ( commandGate != NULL )
{
commandGate->release();
commandGate = NULL;
}
if ( workLoop != NULL )
{
workLoop->release();
workLoop = NULL;
}
DecrementOutstandingIO();
return false;
}
IOReturn IOUSBInterfaceUserClientV2::_open(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_open", target->getName(), target);
return target->open((bool)arguments->scalarInput[0]);
}
IOReturn
IOUSBInterfaceUserClientV2::open(bool seize)
{
IOOptionBits options = seize ? (IOOptionBits)kIOServiceSeize : 0;
USBLog(7, "+%s[%p]::open", getName(), this);
if (!fOwner)
return kIOReturnNotAttached;
if (!fOwner->open(this, options))
{
USBLog(3, "+%s[%p]::open failed", getName(), this);
return kIOReturnExclusiveAccess;
}
if ( fClientRunningUnderRosetta )
{
USBLog(5, "%s[%p]::open setting kIOUserClientCrossEndianCompatibleKey TRUE on %p", getName(), this, fOwner);
fOwner->setProperty(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue);
}
else
{
USBLog(5, "%s[%p]::open setting kIOUserClientCrossEndianCompatibleKey FALSE on %p", getName(), this, fOwner);
fOwner->setProperty(kIOUserClientCrossEndianCompatibleKey, kOSBooleanFalse);
}
fNeedToClose = false;
return kIOReturnSuccess;
}
IOReturn
IOUSBInterfaceUserClientV2::_close(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_close", target->getName(), target);
return target->close();
}
IOReturn
IOUSBInterfaceUserClientV2::close()
{
IOReturn ret = kIOReturnSuccess;
USBLog(7, "+%s[%p]::close", getName(), this);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
if (fOwner->isOpen(this))
{
fNeedToClose = true; if (GetOutstandingIO() > 1) {
int i;
USBLog(6, "%s[%p]::close - outstanding IO, aborting pipes", getName(), this);
for (i=1; i <= kUSBMaxPipes; i++)
AbortPipe(i);
}
}
else
ret = kIOReturnNotOpen;
}
else
ret = kIOReturnNotAttached;
USBLog(7, "-%s[%p]::close - returning %x", getName(), this, ret);
DecrementOutstandingIO();
return ret;
}
#pragma mark Miscellaneous InterfaceUserClient
IOReturn IOUSBInterfaceUserClientV2::_SetAlternateInterface(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_SetAlternateInterface", target->getName(), target);
return target->SetAlternateInterface((UInt8)arguments->scalarInput[0]);
}
IOReturn
IOUSBInterfaceUserClientV2::SetAlternateInterface(UInt8 altSetting)
{
IOReturn ret;
USBLog(7, "+%s[%p]::SetAlternateInterface to %d", getName(), this, altSetting);
IncrementOutstandingIO();
if (fOwner && !isInactive())
ret = fOwner->SetAlternateInterface(this, altSetting);
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::SetAlternateInterface - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetDevice(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret;
USBLog(7, "+%s[%p]::_GetDevice", target->getName(), target);
return target->GetDevice(&(arguments->scalarOutput[0]));
}
IOReturn
IOUSBInterfaceUserClientV2::GetDevice(uint64_t *device)
{
IOReturn ret;
io_object_t service;
USBLog(7, "+%s[%p]::GetDevice (%p, 0x%qx)", getName(), this, device, *device);
IncrementOutstandingIO();
*device = NULL;
if (fOwner && !isInactive())
{
fOwner->GetDevice()->retain();
ret = exportObjectToClient(fTask, fOwner->GetDevice(), &service);
USBLog(7, "+%s[%p]::GetDevice exportObjectToClient of (%p) returning err 0x%x", getName(), this, fOwner->GetDevice(), ret);
*device = (uint64_t) service;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::GetDevice - returning %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetFrameNumber(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetFrameNumber", target->getName(), target);
return target->GetFrameNumber((IOUSBGetFrameStruct *)arguments->structureOutput, (UInt32 *)&(arguments->structureOutputSize));
}
IOReturn
IOUSBInterfaceUserClientV2::GetFrameNumber(IOUSBGetFrameStruct *data, UInt32 *size)
{
IOReturn ret = kIOReturnSuccess;
USBLog(7, "+%s[%p]::GetFrameNumber", getName(), this);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
clock_get_uptime(&data->timeStamp);
data->frame = fOwner->GetDevice()->GetBus()->GetFrameNumber();
USBLog(7,"IOUSBInterfaceUserClientV2::GetFrameNumber frame: 0x%qx, timeStamp.hi: 0x%lx, timeStamp.lo: 0x%lx", data->frame, (data->timeStamp).hi, (data->timeStamp).lo);
*size = sizeof(IOUSBGetFrameStruct);
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::GetFrameNumber - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
USBLog(7, "-%s[%p]::GetFrameNumber FrameNumber: %qd", getName(), this,data->frame);
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetMicroFrameNumber(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetMicroFrameNumber", target->getName(), target);
return target->GetMicroFrameNumber((IOUSBGetFrameStruct *)arguments->structureOutput, (UInt32 *)&(arguments->structureOutputSize));
}
IOReturn
IOUSBInterfaceUserClientV2::GetMicroFrameNumber(IOUSBGetFrameStruct *data, UInt32 *size)
{
IOUSBControllerV2 *v2 = NULL;
IOReturn ret = kIOReturnSuccess;
if (fOwner)
v2 = OSDynamicCast(IOUSBControllerV2, fOwner->GetDevice()->GetBus());
if (!v2)
{
USBLog(3, "%s[%p]::GetMicroFrameNumber - Not a USB 2.0 controller! Returning 0x%x", getName(), this, kIOReturnNotAttached);
return kIOReturnNotAttached;
}
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
UInt64 microFrame;
clock_get_uptime(&data->timeStamp);
microFrame = v2->GetMicroFrameNumber();
if ( microFrame != 0)
{
data->frame = microFrame;
USBLog(7,"IOUSBInterfaceUserClientV2::GetMicroFrameNumber frame: 0x%qx, timeStamp.hi: 0x%lx, timeStamp.lo: 0x%lx", data->frame, (data->timeStamp).hi, (data->timeStamp).lo);
*size = sizeof(IOUSBGetFrameStruct);
}
else
{
ret = kIOReturnUnsupported;
*size = 0;
}
}
else
{
USBLog(3, "%s[%p]::GetMicroFrameNumber - no fOwner(%p) or isInactive", getName(), this, fOwner);
ret = kIOReturnNotAttached;
}
if (ret)
{
USBLog(3, "%s[%p]::GetFrameNumber - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetFrameNumberWithTime(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetFrameNumberWithTime", target->getName(), target);
return target->GetFrameNumberWithTime( (IOUSBGetFrameStruct*) arguments->structureOutput, (UInt32 *)&(arguments->structureOutputSize));
}
IOReturn
IOUSBInterfaceUserClientV2::GetFrameNumberWithTime(IOUSBGetFrameStruct *data, UInt32 *size)
{
IOReturn ret = kIOReturnSuccess;
USBLog(7, "+%s[%p]::GetFrameNumberWithTime", getName(), this);
if(*size != sizeof(IOUSBGetFrameStruct))
return kIOReturnBadArgument;
if (fOwner && !isInactive())
{
IOUSBControllerV2 *busV2 = OSDynamicCast(IOUSBControllerV2, fOwner->GetDevice()->GetBus());
if (busV2)
{
ret = busV2->GetFrameNumberWithTime(&data->frame, &data->timeStamp);
USBLog(7,"IOUSBInterfaceUserClientV2::GetFrameNumberWithTime frame: 0x%qx, timeStamp.hi: 0x%lx, timeStamp.lo: 0x%lx", data->frame, (data->timeStamp).hi, (data->timeStamp).lo);
*size = sizeof(IOUSBGetFrameStruct);
}
else
{
ret = kIOReturnUnsupported;
}
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::GetFrameNumberWithTime - returning err %x", getName(), this, ret);
}
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetBandwidthAvailable(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetBandwidthAvailable", target->getName(), target);
return target->GetBandwidthAvailable(&(arguments->scalarOutput[0]));
}
IOReturn
IOUSBInterfaceUserClientV2::GetBandwidthAvailable(uint64_t *bandwidth)
{
IOReturn ret = kIOReturnSuccess;
USBLog(7, "+%s[%p]::GetBandwidthAvailable", getName(), this);
if (fOwner && !isInactive())
{
*bandwidth = fOwner->GetDevice()->GetBus()->GetBandwidthAvailable();
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::GetBandwidthAvailable - returning err %x", getName(), this, ret);
}
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetFrameListTime(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetFrameListTime", target->getName(), target);
return target->GetFrameListTime(&(arguments->scalarOutput[0]));
}
IOReturn
IOUSBInterfaceUserClientV2::GetFrameListTime(uint64_t *microsecondsInFrame)
{
IOReturn ret = kIOReturnSuccess;
USBLog(7, "+%s[%p]::GetFrameListTime", getName(), this);
if (fOwner && !isInactive())
{
UInt8 speed;
speed = fOwner->GetDevice()->GetSpeed();
if ( speed == kUSBDeviceSpeedHigh )
{
*microsecondsInFrame = kUSBHighSpeedMicrosecondsInFrame;
}
else
{
*microsecondsInFrame = kUSBFullSpeedMicrosecondsInFrame;
}
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::GetFrameListTime - returning err %x", getName(), this, ret);
}
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetEndpointProperties(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetEndpointProperties", target->getName(), target);
return target->GetEndpointProperties((UInt8)arguments->scalarInput[0], (UInt8)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2],
&(arguments->scalarOutput[0]), &(arguments->scalarOutput[1]), &(arguments->scalarOutput[2]));
}
IOReturn
IOUSBInterfaceUserClientV2::GetEndpointProperties(UInt8 alternateSetting, UInt8 endpointNumber, UInt8 direction, uint64_t *transferType, uint64_t *maxPacketSize, uint64_t *interval)
{
IOReturn ret = kIOReturnSuccess;
UInt8 myTT;
UInt16 myMPS;
UInt8 myIV;
USBLog(7, "+%s[%p]::GetEndpointProperties for altSetting %d, endpoint: %d, direction %d", getName(), this, alternateSetting, endpointNumber, direction);
if (fOwner && !isInactive())
ret = fOwner->GetEndpointProperties(alternateSetting, endpointNumber, direction, &myTT, &myMPS, &myIV);
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::GetEndpointProperties - returning err %x", getName(), this, ret);
}
else
{
*transferType = myTT;
*maxPacketSize = myMPS;
*interval = myIV;
}
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::_GetConfigDescriptor(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetConfigDescriptor", target->getName(), target);
if ( arguments->structureOutputDescriptor )
return target->GetConfigDescriptor((UInt8)arguments->scalarInput[0], arguments->structureOutputDescriptor, &(arguments->structureOutputDescriptorSize));
else
return target->GetConfigDescriptor((UInt8)arguments->scalarInput[0], (IOUSBConfigurationDescriptorPtr) arguments->structureOutput, (UInt32 *)&(arguments->structureOutputSize));
}
IOReturn
IOUSBInterfaceUserClientV2::GetConfigDescriptor(UInt8 configIndex, IOUSBConfigurationDescriptorPtr desc, UInt32 *size)
{
UInt16 length;
const IOUSBConfigurationDescriptor *cached;
IOReturn ret;
USBLog(7,"+%s[%p]::GetConfigDescriptor (Config %d), with size %ld, struct: %p", getName(), this, configIndex, *size, desc);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
cached = fOwner->GetDevice()->GetFullConfigurationDescriptor(configIndex);
if ( cached == NULL )
{
USBLog(5,"+%s[%p]::GetConfigDescriptor GetFullConfigurationDescriptor returned NULL", getName(), this);
desc = NULL;
ret = kIOReturnNotFound;
}
else
{
USBLog(7,"+%s[%p]::GetConfigDescriptor got descriptor %p, length: %d", getName(), this, cached, USBToHostWord(cached->wTotalLength));
length = USBToHostWord(cached->wTotalLength);
if(length < *size)
*size = length;
bcopy(cached, desc, *size);
ret = kIOReturnSuccess;
}
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(5, "%s[%p]::GetConfigDescriptor - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::GetConfigDescriptor(UInt8 configIndex, IOMemoryDescriptor * mem, uint32_t *size)
{
UInt16 length;
const IOUSBConfigurationDescriptor *cached;
IOReturn ret;
USBLog(7,"+%s[%p]::GetConfigDescriptor > 4K (Config %d), with size %d, mem: %p", getName(), this, configIndex, *size, mem);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
cached = fOwner->GetDevice()->GetFullConfigurationDescriptor(configIndex);
if ( cached == NULL )
{
USBLog(5,"+%s[%p]::GetConfigDescriptor > 4K GetFullConfigurationDescriptor returned NULL", getName(), this);
ret = kIOReturnNotFound;
}
else
{
USBLog(7,"+%s[%p]::GetConfigDescriptor > 4K got descriptor %p, length: %d", getName(), this, cached, USBToHostWord(cached->wTotalLength));
length = USBToHostWord(cached->wTotalLength);
if(length < *size)
{
*size = length;
}
mem->prepare();
mem->writeBytes(0, cached, *size);
mem->complete();
ret = kIOReturnSuccess;
}
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(5, "%s[%p]::GetConfigDescriptor - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
#pragma mark Pipe Methods
IOReturn IOUSBInterfaceUserClientV2::_ReadPipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret;
USBLog(7, "+%s[%p]::_ReadPipe", target->getName(), target);
if ( arguments->asyncWakePort )
{
IOUSBCompletion tap;
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock*) IOMalloc(sizeof(IOUSBUserClientAsyncParamBlock));
if (!pb)
return kIOReturnNoMemory;
target->retain();
target->IncrementOutstandingIO();
bcopy(arguments->asyncReference, pb->fAsyncRef, sizeof(OSAsyncReference64));
pb->fAsyncCount = arguments->asyncReferenceCount;
tap.target = target;
tap.action = &IOUSBInterfaceUserClientV2::ReqComplete;
tap.parameter = pb;
ret = target->ReadPipe( (UInt8) arguments->scalarInput[0], (UInt32) arguments->scalarInput[1], (UInt32) arguments->scalarInput[2], (mach_vm_address_t) arguments->scalarInput[3], (mach_vm_size_t) arguments->scalarInput[4], &tap);
if ( ret )
{
if ( pb )
IOFree(pb, sizeof(*pb));
target->DecrementOutstandingIO();
target->release();
}
}
else if ( arguments->structureOutputDescriptor )
ret = target->ReadPipe( (UInt8)arguments->scalarInput[0], (UInt32)arguments->scalarInput[1], (UInt32)arguments->scalarInput[2],
arguments->structureOutputDescriptor, (UInt32 *)&(arguments->structureOutputDescriptorSize));
else
ret = target->ReadPipe((UInt8)arguments->scalarInput[0], (UInt32)arguments->scalarInput[1], (UInt32)arguments->scalarInput[2],
arguments->structureOutput, (UInt32 *)&(arguments->structureOutputSize));
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ReadPipe(UInt8 pipeRef, UInt32 noDataTimeout, UInt32 completionTimeout, mach_vm_address_t buffer, mach_vm_size_t size, IOUSBCompletion * completion)
{
IOReturn ret = kIOReturnNotAttached;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj = NULL;
USBLog(7, "+%s(%p)::ReadPipe (Async) (pipeRef: %d, %ld, %ld, buffer: 0x%qx, size: %qd, completion: %p)", getName(), this, pipeRef, noDataTimeout, completionTimeout, buffer, size, completion);
if (fOwner && !isInactive())
{
if (completion == NULL)
{
USBLog(1,"%s[%p]::ReadPipe (async) bad arguments (%qd, %qx, %p)", getName(), this, size, buffer, completion);
ret = kIOReturnBadArgument;
goto Exit;
}
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock *)completion->parameter;
USBLog(7,"%s[%p]::ReadPipe (async) creating IOMD", getName(), this);
mem = IOMemoryDescriptor::withAddressRange( buffer, size, kIODirectionIn, fTask);
if (!mem)
{
USBLog(1,"%s[%p]::ReadPipe (async ) IOMemoryDescriptor::withAddressRange returned NULL", getName(), this);
ret = kIOReturnNoMemory;
goto Exit;
}
ret = mem->prepare();
if ( ret != kIOReturnSuccess)
{
USBLog(3,"%s[%p]::ReadPipe (async) mem->prepare() returned 0x%x", getName(), this, ret);
mem->release();
goto Exit;
}
pb->fMax = size;
pb->fMem = mem;
ret = pipeObj->Read(mem, noDataTimeout, completionTimeout, completion, NULL);
if ( ret != kIOReturnSuccess)
{
USBLog(5,"%s[%p]::ReadPipe (async) returned 0x%x", getName(), this, ret);
mem->complete();
mem->release();
}
}
else
{
USBLog(5,"%s[%p]::ReadPipe (async) can't find pipeRef, returning kIOUSBUnknownPipeErr", getName(), this);
ret = kIOUSBUnknownPipeErr;
}
}
Exit:
if (pipeObj)
pipeObj->release();
if (ret)
{
USBLog(3, "%s[%p]::ReadPipe (async - returning err %x", getName(), this, ret);
}
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ReadPipe(UInt8 pipeRef, UInt32 noDataTimeout, UInt32 completionTimeout, void *buf, UInt32 *size)
{
IOReturn ret = kIOReturnSuccess;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj;
USBLog(7, "+%s(%p)::ReadPipe < 4K (pipeRef: %d, data timeout: %ld, completionTimeout: %ld, buf: %p, size: %ld)", getName(), this, pipeRef, noDataTimeout, completionTimeout, buf, *size);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
mem = IOMemoryDescriptor::withAddress( (void *)buf, *size, kIODirectionIn);
if(mem)
{
*size = 0;
ret = mem->prepare();
if ( ret == kIOReturnSuccess)
{
ret = pipeObj->Read(mem, noDataTimeout, completionTimeout, 0, size);
mem->complete();
}
else
{
USBLog(3,"%s[%p]::ReadPipe (sync < 4K) mem->prepare() returned 0x%x", getName(), this, ret);
}
mem->release();
mem = NULL;
}
else
ret = kIOReturnNoMemory;
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ReadPipe - returning err %x, size read: %ld", getName(), this, ret, *size);
}
DecrementOutstandingIO();
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ReadPipe(UInt8 pipeRef, UInt32 noDataTimeout, UInt32 completionTimeout, IOMemoryDescriptor *mem, IOByteCount *bytesRead)
{
IOReturn ret = kIOReturnSuccess;
IOUSBPipe * pipeObj;
USBLog(7, "+%s(%p)::ReadPipe > 4K (pipeRef: %d, %ld, %ld, IOMD: %p)", getName(), this, pipeRef, noDataTimeout, completionTimeout, mem);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
if(mem)
{
ret = mem->prepare();
if (ret == kIOReturnSuccess)
{
ret = pipeObj->Read(mem, noDataTimeout, completionTimeout, 0, bytesRead );
mem->complete();
}
else
{
USBLog(3,"%s[%p]::ReadPipe (sync > 4K) mem->prepare() returned 0x%x", getName(), this, ret);
}
}
else
{
ret = kIOReturnNoMemory;
}
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ReadPipe > 4K - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_WritePipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret;
USBLog(7, "+%s[%p]::_WritePipe", target->getName(), target);
if ( arguments->asyncWakePort )
{
IOUSBCompletion tap;
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock*) IOMalloc(sizeof(IOUSBUserClientAsyncParamBlock));
if (!pb)
return kIOReturnNoMemory;
target->retain();
target->IncrementOutstandingIO();
bcopy(arguments->asyncReference, pb->fAsyncRef, sizeof(OSAsyncReference64));
pb->fAsyncCount = arguments->asyncReferenceCount;
tap.target = target;
tap.action = &IOUSBInterfaceUserClientV2::ReqComplete;
tap.parameter = pb;
ret = target->WritePipe( (UInt8) arguments->scalarInput[0], (UInt32) arguments->scalarInput[1], (UInt32) arguments->scalarInput[2], (mach_vm_address_t) arguments->scalarInput[3], (mach_vm_size_t) arguments->scalarInput[4], &tap);
if ( ret )
{
if ( pb )
IOFree(pb, sizeof(*pb));
target->DecrementOutstandingIO();
target->release();
}
}
else if ( arguments->structureInputDescriptor )
ret = target->WritePipe( (UInt8)arguments->scalarInput[0], (UInt32)arguments->scalarInput[1], (UInt32)arguments->scalarInput[2],
arguments->structureInputDescriptor);
else
ret = target->WritePipe((UInt16)arguments->scalarInput[0], (UInt32)arguments->scalarInput[1], (UInt32)arguments->scalarInput[2],
arguments->structureInput, arguments->structureInputSize);
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::WritePipe(UInt8 pipeRef, UInt32 noDataTimeout, UInt32 completionTimeout, mach_vm_address_t buffer, mach_vm_size_t size, IOUSBCompletion * completion)
{
IOReturn ret = kIOReturnNotAttached;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj = NULL;
USBLog(7, "+%s(%p)::WritePipe (Async) (pipeRef: %d, %ld, %ld, buffer: 0x%qx, size: %qd, completion: %p)", getName(), this, pipeRef, noDataTimeout, completionTimeout, buffer, size, completion);
if (fOwner && !isInactive())
{
if (completion == NULL )
{
USBLog(1,"%s[%p]::WritePipe (async) bad arguments (%qd, %qx, %p)", getName(), this, size, buffer, completion);
ret = kIOReturnBadArgument;
goto Exit;
}
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock *)completion->parameter;
USBLog(7,"%s[%p]::WritePipe (async) creating IOMD", getName(), this);
mem = IOMemoryDescriptor::withAddressRange( buffer, size, kIODirectionOut, fTask);
if (!mem)
{
USBLog(1,"%s[%p]::WritePipe (async ) IOMemoryDescriptor::withAddressRange returned NULL", getName(), this);
ret = kIOReturnNoMemory;
goto Exit;
}
ret = mem->prepare();
if ( ret != kIOReturnSuccess)
{
USBLog(3,"%s[%p]::WritePipe (async) mem->prepare() returned 0x%x", getName(), this, ret);
mem->release();
goto Exit;
}
pb->fMax = size;
pb->fMem = mem;
ret = pipeObj->Write(mem, noDataTimeout, completionTimeout, completion);
if ( ret != kIOReturnSuccess)
{
USBLog(5,"%s[%p]::WritePipe (async) returned 0x%x", getName(), this, ret);
mem->complete();
mem->release();
}
}
else
{
USBLog(5,"%s[%p]::WritePipe (async) can't find pipeRef, returning kIOUSBUnknownPipeErr", getName(), this);
ret = kIOUSBUnknownPipeErr;
}
}
Exit:
if (pipeObj)
pipeObj->release();
if (ret)
{
USBLog(3, "%s[%p]::WritePipe (async - returning err %x", getName(), this, ret);
}
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::WritePipe(UInt8 pipeRef, UInt32 noDataTimeout, UInt32 completionTimeout, const void *buf, UInt32 size)
{
IOReturn ret = kIOReturnSuccess;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj;
USBLog(7, "+%s(%p)::WritePipe < 4K (pipeRef: %d, %ld, %ld, buf: %p, size: %ld)", getName(), this, pipeRef, noDataTimeout, completionTimeout, buf, size);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
mem = IOMemoryDescriptor::withAddress( (void *) buf, size, kIODirectionOut);
if(mem)
{
ret = mem->prepare();
if ( ret == kIOReturnSuccess)
{
ret = pipeObj->Write(mem, noDataTimeout, completionTimeout);
if ( ret != kIOReturnSuccess)
{
USBLog(5,"%s[%p]::WritePipe (sync < 4K) returned 0x%x", getName(), this, ret);
}
mem->complete();
}
else
{
USBLog(3,"%s[%p]::WritePipe (sync < 4K) mem->prepare() returned 0x%x", getName(), this, ret);
}
mem->release();
mem = NULL;
}
else
ret = kIOReturnNoMemory;
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::WritePipe < 4K - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::WritePipe(UInt8 pipeRef, UInt32 noDataTimeout, UInt32 completionTimeout, IOMemoryDescriptor *mem)
{
IOReturn ret;
IOUSBPipe * pipeObj;
USBLog(7, "+%s(%p)::WritePipe > 4K (pipeRef: %d, %ld, %ld, IOMD: %p)", getName(), this, pipeRef, noDataTimeout, completionTimeout, mem);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
if(mem)
{
ret = mem->prepare();
if (ret == kIOReturnSuccess)
{
ret = pipeObj->Write(mem, noDataTimeout, completionTimeout );
mem->complete();
}
else
{
USBLog(1,"%s[%p]::WritePipe > (sync > 4K) mem->prepare() returned 0x%x", getName(), this, ret);
}
}
else
{
ret = kIOReturnNoMemory;
}
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::WritePipe > 4K - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetPipeProperties(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetPipeProperties", target->getName(), target);
return target->GetPipeProperties((UInt8)arguments->scalarInput[0], &(arguments->scalarOutput[0]),&(arguments->scalarOutput[1]),
&(arguments->scalarOutput[2]), &(arguments->scalarOutput[3]), &(arguments->scalarOutput[4]));
}
IOReturn
IOUSBInterfaceUserClientV2::GetPipeProperties(UInt8 pipeRef, uint64_t *direction, uint64_t *number, uint64_t *transferType, uint64_t *maxPacketSize, uint64_t *interval)
{
IOUSBPipe *pipeObj;
IOReturn ret = kIOReturnSuccess;
USBLog(7, "+%s[%p]::GetPipeProperties for pipe %d", getName(), this, pipeRef);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
if (direction)
*direction = pipeObj->GetDirection();
if (number)
*number = pipeObj->GetEndpointNumber();
if (transferType)
*transferType = pipeObj->GetType();
if (maxPacketSize)
*maxPacketSize = pipeObj->GetMaxPacketSize();
if (interval)
*interval = pipeObj->GetInterval();
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::GetPipeProperties - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_GetPipeStatus(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_GetPipeStatus", target->getName(), target);
return target->GetPipeStatus((UInt8)arguments->scalarInput[0]);
}
IOReturn
IOUSBInterfaceUserClientV2::GetPipeStatus(UInt8 pipeRef)
{
IOUSBPipe *pipeObj;
IOReturn ret;
USBLog(7, "+%s[%p]::GetPipeStatus", getName(), this);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
ret = pipeObj->GetPipeStatus();
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_AbortPipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_AbortPipe", target->getName(), target);
return target->AbortPipe((UInt8)arguments->scalarInput[0]);
}
IOReturn
IOUSBInterfaceUserClientV2::AbortPipe(UInt8 pipeRef)
{
IOUSBPipe *pipeObj;
IOReturn ret;
USBLog(7, "+%s[%p]::AbortPipe", getName(), this);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
ret = pipeObj->Abort();
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
if ( ret == kIOUSBUnknownPipeErr )
{
USBLog(6, "%s[%p]::AbortPipe - returning err %x", getName(), this, ret);
}
else
{
USBLog(3, "%s[%p]::AbortPipe - returning err %x", getName(), this, ret);
}
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_ResetPipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_ResetPipe", target->getName(), target);
return target->ResetPipe((UInt8)arguments->scalarInput[0]);
}
IOReturn
IOUSBInterfaceUserClientV2::ResetPipe(UInt8 pipeRef)
{
IOUSBPipe *pipeObj;
IOReturn ret;
USBLog(7, "+%s[%p]::ResetPipe", getName(), this);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
ret = pipeObj->Reset();
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ResetPipe - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_ClearPipeStall(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_ClearPipeStall", target->getName(), target);
return target->ClearPipeStall((UInt8)arguments->scalarInput[0], (bool)arguments->scalarInput[1]);
}
IOReturn
IOUSBInterfaceUserClientV2::ClearPipeStall(UInt8 pipeRef, bool bothEnds)
{
IOUSBPipe *pipeObj;
IOReturn ret;
USBLog(7, "+%s[%p]::ClearPipeStall (pipe: %d, bothEnds: %d)", getName(), this, pipeRef, bothEnds);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
USBLog(6, "%s[%p]::ClearPipeStall = bothEnds = %d", getName(), this, bothEnds);
ret = pipeObj->ClearPipeStall(bothEnds);
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ClearPipeStall - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_SetPipePolicy(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_SetPipePolicy", target->getName(), target);
return target->SetPipePolicy((UInt8)arguments->scalarInput[0], (UInt16)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2]);
}
IOReturn
IOUSBInterfaceUserClientV2::SetPipePolicy(UInt8 pipeRef, UInt16 maxPacketSize, UInt8 maxInterval)
{
IOUSBPipe *pipeObj;
IOReturn ret;
USBLog(7, "+%s[%p]::SetPipePolicy", getName(), this);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
USBLog(7, "%s[%p]::SetPipePolicy(%d, %d)", getName(), this, maxPacketSize, maxInterval);
ret = pipeObj->SetPipePolicy(maxPacketSize, maxInterval);
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::SetPipePolicy - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
#pragma mark Control Request Out
IOReturn
IOUSBInterfaceUserClientV2::_ControlRequestOut(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret;
USBLog(7, "+%s[%p]::_ControlRequestOut", target->getName(), target);
if ( arguments->asyncWakePort )
{
IOUSBCompletion tap;
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock*) IOMalloc(sizeof(IOUSBUserClientAsyncParamBlock));
if (!pb)
return kIOReturnNoMemory;
target->retain();
target->IncrementOutstandingIO();
bcopy(arguments->asyncReference, pb->fAsyncRef, sizeof(OSAsyncReference64));
pb->fAsyncCount = arguments->asyncReferenceCount;
tap.target = target;
tap.action = &IOUSBInterfaceUserClientV2::ReqComplete;
tap.parameter = pb;
ret = target->ControlRequestOut( (UInt8)arguments->scalarInput[0], (UInt8)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2], (UInt16)arguments->scalarInput[3], (UInt16)arguments->scalarInput[4], (mach_vm_size_t)arguments->scalarInput[5], (mach_vm_address_t)arguments->scalarInput[6], (UInt32)arguments->scalarInput[7], (UInt32)arguments->scalarInput[8], &tap);
if ( ret )
{
if ( pb )
IOFree(pb, sizeof(*pb));
target->DecrementOutstandingIO();
target->release();
}
}
else if ( arguments->structureInputDescriptor )
{
ret = target->ControlRequestOut( (UInt8)arguments->scalarInput[0], (UInt8)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2], (UInt16)arguments->scalarInput[3], (UInt16)arguments->scalarInput[4], (UInt32)arguments->scalarInput[7], (UInt32)arguments->scalarInput[8], arguments->structureInputDescriptor); }
else
{
ret = target->ControlRequestOut( (UInt8)arguments->scalarInput[0], (UInt8)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2], (UInt16)arguments->scalarInput[3], (UInt16)arguments->scalarInput[4], (UInt32)arguments->scalarInput[7], (UInt32)arguments->scalarInput[8], arguments->structureInput, arguments->structureInputSize); }
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ControlRequestOut(UInt8 pipeRef, UInt8 bmRequestType, UInt8 bRequest, UInt16 wValue, UInt16 wIndex, mach_vm_size_t size, mach_vm_address_t buffer, UInt32 noDataTimeout, UInt32 completionTimeout, IOUSBCompletion * completion)
{
IOReturn ret = kIOReturnSuccess;
IOUSBDevRequest req;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj = NULL;;
USBLog(7, "IOUSBInterfaceUserClientV2::ControlRequestOut (Async) : bmRequestType = 0x%2.2x bRequest = 0x%2.2x wValue = 0x%4.4x wIndex = 0x%4.4x, noDataTimeout = %ld completionTimeout = %ld",
bmRequestType,
bRequest,
wValue,
wIndex,
noDataTimeout,
completionTimeout);
if (fOwner && !isInactive())
{
if (completion == NULL)
{
USBLog(1,"%s[%p]::ControlRequestOut (async) completion is NULL!", getName(), this);
ret = kIOReturnBadArgument;
goto Exit;
}
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock *)completion->parameter;
if (size != 0 )
{
USBLog(7,"%s[%p]::ControlRequestOut (async) creating IOMD", getName(), this);
mem = IOMemoryDescriptor::withAddressRange( buffer, size, kIODirectionOut, fTask);
if (!mem)
{
USBLog(1,"%s[%p]::ControlRequestOut (async ) IOMemoryDescriptor::withAddressRange returned NULL", getName(), this);
ret = kIOReturnNoMemory;
goto Exit;
}
ret = mem->prepare();
if ( ret != kIOReturnSuccess)
{
USBLog(3,"%s[%p]::ControlRequestOut (async) mem->prepare() returned 0x%x", getName(), this, ret);
mem->release();
goto Exit;
}
}
pb->req.bmRequestType = bmRequestType;
pb->req.bRequest = bRequest;
pb->req.wValue = wValue;
pb->req.wIndex = wIndex;
pb->req.wLength = size;
pb->req.pData = mem;
pb->fMax = size;
pb->fMem = mem;
ret = pipeObj->ControlRequest(&pb->req, noDataTimeout, completionTimeout, completion);
if ( ret != kIOReturnSuccess)
{
USBLog(5,"%s[%p]::ControlRequestOut (async) returned 0x%x", getName(), this, ret);
mem->complete();
mem->release();
}
}
else
{
USBLog(5,"%s[%p]::ControlRequestOut (async) can't find pipeRef, returning kIOUSBUnknownPipeErr", getName(), this);
ret = kIOUSBUnknownPipeErr;
}
}
Exit:
if (pipeObj)
pipeObj->release();
if (ret)
{
USBLog(3, "%s[%p]::ControlRequestOut (async) - returning err %x", getName(), this, ret);
}
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ControlRequestOut(UInt8 pipeRef, UInt8 bmRequestType, UInt8 bRequest, UInt16 wValue, UInt16 wIndex, UInt32 noDataTimeout, UInt32 completionTimeout, const void *requestBuffer, uint32_t size)
{
IOReturn ret = kIOReturnSuccess;
IOUSBDevRequest req;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj = NULL;
USBLog(7, "IOUSBInterfaceUserClientV2::ControlRequestOut < 4K : bmRequestType = 0x%2.2x bRequest = 0x%2.2x wValue = 0x%4.4x wIndex = 0x%4.4x wLength = 0x%4.4x noDataTimeout = %ld completionTimeout = %ld",
bmRequestType,
bRequest,
wValue,
wIndex,
size,
noDataTimeout,
completionTimeout);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if (pipeObj)
{
req.bmRequestType = bmRequestType;
req.bRequest = bRequest;
req.wValue = wValue;
req.wIndex = wIndex;
req.wLength = size;
req.pData = (void *)requestBuffer;
req.wLenDone = 0;
ret = pipeObj->ControlRequest(&req, noDataTimeout, completionTimeout);
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ControlRequest - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ControlRequestOut(UInt8 pipeRef, UInt8 bmRequestType, UInt8 bRequest, UInt16 wValue, UInt16 wIndex, UInt32 noDataTimeout, UInt32 completionTimeout, IOMemoryDescriptor *mem)
{
IOUSBDevRequestDesc req;
IOReturn ret;
IOUSBPipe * pipeObj = NULL;
USBLog(7, "IOUSBInterfaceUserClientV2::ControlRequestOut > 4K: bmRequestType = 0x%2.2x bRequest = 0x%2.2x wValue = 0x%4.4x wIndex = 0x%4.4x wLength = 0x%4.4lx noDataTimeout = %ld completionTimeout = %ld",
bmRequestType,
bRequest,
wValue,
wIndex,
mem->getLength(),
noDataTimeout,
completionTimeout);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
ret = mem->prepare();
if (ret == kIOReturnSuccess)
{
req.bmRequestType = bmRequestType;
req.bRequest = bRequest;
req.wValue = wValue;
req.wIndex = wIndex;
req.wLength = mem->getLength();
req.pData = mem;
req.wLenDone = 0;
ret = pipeObj->ControlRequest(&req, noDataTimeout, completionTimeout);
mem->complete();
}
else
{
USBLog(4,"%s[%p]::ControlRequestOut > 4K mem->prepare() returned 0x%x", getName(), this, ret);
}
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ControlRequestOut (sync OOL) - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
#pragma mark Control Request In
IOReturn IOUSBInterfaceUserClientV2::_ControlRequestIn(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret;
USBLog(7, "+%s[%p]::_ControlRequestIn", target->getName(), target);
if ( arguments->asyncWakePort )
{
IOUSBCompletion tap;
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock*) IOMalloc(sizeof(IOUSBUserClientAsyncParamBlock));
if (!pb)
return kIOReturnNoMemory;
target->retain();
target->IncrementOutstandingIO();
bcopy(arguments->asyncReference, pb->fAsyncRef, sizeof(OSAsyncReference64));
pb->fAsyncCount = arguments->asyncReferenceCount;
tap.target = target;
tap.action = &IOUSBInterfaceUserClientV2::ReqComplete;
tap.parameter = pb;
ret = target->ControlRequestIn( (UInt8)arguments->scalarInput[0], (UInt8)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2], (UInt16)arguments->scalarInput[3], (UInt16)arguments->scalarInput[4], (mach_vm_size_t)arguments->scalarInput[5], (mach_vm_address_t)arguments->scalarInput[6], (UInt32)arguments->scalarInput[7], (UInt32)arguments->scalarInput[8], &tap);
if ( ret )
{
if ( pb )
IOFree(pb, sizeof(*pb));
target->DecrementOutstandingIO();
target->release();
}
}
else if ( arguments->structureOutputDescriptor )
{
ret = target->ControlRequestIn( (UInt8)arguments->scalarInput[0], (UInt8)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2], (UInt16)arguments->scalarInput[3], (UInt16)arguments->scalarInput[4], (UInt32)arguments->scalarInput[7], (UInt32)arguments->scalarInput[8], arguments->structureOutputDescriptor, &(arguments->structureOutputDescriptorSize)); }
else
{
ret = target->ControlRequestIn( (UInt8)arguments->scalarInput[0], (UInt8)arguments->scalarInput[1], (UInt8)arguments->scalarInput[2], (UInt16)arguments->scalarInput[3], (UInt16)arguments->scalarInput[4], (UInt32)arguments->scalarInput[7], (UInt32)arguments->scalarInput[8], arguments->structureOutput, &(arguments->structureOutputSize)); }
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ControlRequestIn(UInt8 pipeRef, UInt8 bmRequestType, UInt8 bRequest, UInt16 wValue, UInt16 wIndex, mach_vm_size_t size, mach_vm_address_t buffer, UInt32 noDataTimeout, UInt32 completionTimeout, IOUSBCompletion * completion)
{
IOReturn ret = kIOReturnSuccess;
IOUSBDevRequest req;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj = NULL;;
USBLog(7, "IOUSBInterfaceUserClientV2::ControlRequestIn (Async) : bmRequestType = 0x%2.2x bRequest = 0x%2.2x wValue = 0x%4.4x wIndex = 0x%4.4x, noDataTimeout = %ld completionTimeout = %ld",
bmRequestType,
bRequest,
wValue,
wIndex,
noDataTimeout,
completionTimeout);
if (fOwner && !isInactive())
{
if (completion == NULL)
{
USBLog(1,"%s[%p]::ControlRequestIn (async) bad arguments (%qd, %qx, %p)", getName(), this, size, buffer, completion);
ret = kIOReturnBadArgument;
goto Exit;
}
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
IOUSBUserClientAsyncParamBlock * pb = (IOUSBUserClientAsyncParamBlock *)completion->parameter;
if ( size != 0)
{
USBLog(7,"%s[%p]::ControlRequestIn (async) creating IOMD", getName(), this);
mem = IOMemoryDescriptor::withAddressRange( buffer, size, kIODirectionIn, fTask);
if (!mem)
{
USBLog(1,"%s[%p]::ControlRequestIn (async ) IOMemoryDescriptor::withAddressRange returned NULL", getName(), this);
ret = kIOReturnNoMemory;
goto Exit;
}
ret = mem->prepare();
if ( ret != kIOReturnSuccess)
{
USBLog(3,"%s[%p]::ControlRequestIn (async) mem->prepare() returned 0x%x", getName(), this, ret);
mem->release();
goto Exit;
}
}
pb->req.bmRequestType = bmRequestType;
pb->req.bRequest = bRequest;
pb->req.wValue = wValue;
pb->req.wIndex = wIndex;
pb->req.wLength = size;
pb->req.pData = mem;
pb->fMax = size;
pb->fMem = mem;
ret = pipeObj->ControlRequest(&pb->req, noDataTimeout, completionTimeout, completion);
if ( ret != kIOReturnSuccess)
{
USBLog(5,"%s[%p]::ControlRequestIn (async) returned 0x%x", getName(), this, ret);
mem->complete();
mem->release();
}
}
else
{
USBLog(5,"%s[%p]::ControlRequestIn (async) can't find pipeRef, returning kIOUSBUnknownPipeErr", getName(), this);
ret = kIOUSBUnknownPipeErr;
}
}
Exit:
if (pipeObj)
pipeObj->release();
if (ret)
{
USBLog(3, "%s[%p]::ControlRequestIn (async) - returning err %x", getName(), this, ret);
}
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ControlRequestIn(UInt8 pipeRef, UInt8 bmRequestType, UInt8 bRequest, UInt16 wValue, UInt16 wIndex, UInt32 noDataTimeout, UInt32 completionTimeout, void *requestBuffer, uint32_t *size)
{
IOReturn ret = kIOReturnSuccess;
IOUSBDevRequest req;
IOMemoryDescriptor * mem = NULL;
IOUSBPipe * pipeObj = NULL;;
USBLog(7, "IOUSBInterfaceUserClientV2::ControlRequestIn < 4K : bmRequestType = 0x%2.2x bRequest = 0x%2.2x wValue = 0x%4.4x wIndex = 0x%4.4x wLength = 0x%4.4x noDataTimeout = %ld completionTimeout = %ld",
bmRequestType,
bRequest,
wValue,
wIndex,
*size,
noDataTimeout,
completionTimeout);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if (pipeObj)
{
req.bmRequestType = bmRequestType;
req.bRequest = bRequest;
req.wValue = wValue;
req.wIndex = wIndex;
req.wLength = *size;
req.pData = requestBuffer;
req.wLenDone = 0;
ret = pipeObj->ControlRequest(&req, noDataTimeout, completionTimeout);
USBLog(7, "%s[%p]::ControlRequestIn (sync < 4k) err:0x%x, wLenDone = %ld", getName(), this, ret, req.wLenDone);
if (ret == kIOReturnSuccess)
{
*size = req.wLenDone;
}
else
{
USBLog(3, "%s[%p]::ControlRequestIn (sync < 4k) err:0x%x", getName(), this, ret);
*size = 0;
}
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ControlRequestIn < 4K - returning err %x, size: %d", getName(), this, ret, *size);
}
DecrementOutstandingIO();
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::ControlRequestIn(UInt8 pipeRef, UInt8 bmRequestType, UInt8 bRequest, UInt16 wValue, UInt16 wIndex, UInt32 noDataTimeout, UInt32 completionTimeout, IOMemoryDescriptor *mem, uint32_t *pOutSize)
{
IOUSBDevRequestTO reqIn;
IOUSBDevRequestDesc req;
IOReturn ret;
IOUSBPipe * pipeObj = NULL;
USBLog(7, "+%s[%p]::ControlRequestIn > 4K ", getName(), this);
reqIn.bmRequestType = bmRequestType;
reqIn.bRequest = bRequest;
reqIn.wValue = wValue;
reqIn.wIndex = wIndex;
reqIn.wLength = *pOutSize;
reqIn.noDataTimeout = noDataTimeout;
reqIn.completionTimeout = completionTimeout;
USBLog(7, "IOUSBInterfaceUserClientV2::ControlRequestIn > 4K: bmRequestType = 0x%2.2x bRequest = 0x%2.2x wValue = 0x%4.4x wIndex = 0x%4.4x wLength = 0x%4.4x noDataTimeout = %ld completionTimeout = %ld",
reqIn.bmRequestType,
reqIn.bRequest,
reqIn.wValue,
reqIn.wIndex,
reqIn.wLength,
reqIn.noDataTimeout,
reqIn.completionTimeout);
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(pipeRef);
if(pipeObj)
{
ret = mem->prepare();
if (ret == kIOReturnSuccess)
{
req.bmRequestType = reqIn.bmRequestType;
req.bRequest = reqIn.bRequest;
req.wValue = reqIn.wValue;
req.wIndex = reqIn.wIndex;
req.wLength = reqIn.wLength;
req.pData = mem;
req.wLenDone = 0;
ret = pipeObj->ControlRequest(&req, reqIn.noDataTimeout, reqIn.completionTimeout);
if (ret == kIOReturnSuccess)
*pOutSize = req.wLenDone;
else
*pOutSize = 0;
mem->complete();
}
else
{
USBLog(4,"%s[%p]::ControlRequestIn > 4K mem->prepare() returned 0x%x", getName(), this, ret);
}
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if (ret)
{
USBLog(3, "%s[%p]::ControlRequestIn > 4K - returning err %x, outSize: %d", getName(), this, ret, *pOutSize);
}
DecrementOutstandingIO();
return ret;
}
#pragma mark Isoch Methods
IOReturn IOUSBInterfaceUserClientV2::_ReadIsochPipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret = kIOReturnUnsupported;
USBLog(7, "+%s[%p]::_ReadIsochPipe", target->getName(), target);
if ( arguments->asyncWakePort )
{
target->retain();
target->IncrementOutstandingIO();
if ( arguments->structureInputDescriptor )
{
USBLog(3, "+%s[%p]::__ReadIsochPipe We got an unexpected structureOutputDescriptor. Returning bad argument ", target->getName(), target);
ret = kIOReturnBadArgument;
}
else
ret = target->DoIsochPipeAsync( (IOUSBIsocStruct *) arguments->structureInput, arguments->asyncReference, arguments->asyncReferenceCount, kIODirectionIn);
if ( ret )
{
target->DecrementOutstandingIO();
target->release();
}
}
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_WriteIsochPipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret = kIOReturnUnsupported;
USBLog(7, "+%s[%p]::_WriteIsochPipe", target->getName(), target);
if ( arguments->asyncWakePort )
{
target->retain();
target->IncrementOutstandingIO();
if ( arguments->structureInputDescriptor )
{
USBLog(3, "+%s[%p]::_WriteIsochPipe We got an unexpected structureInputDescriptor. Returning unsupported ", target->getName(), target);
ret = kIOReturnUnsupported;
}
else
ret = target->DoIsochPipeAsync( (IOUSBIsocStruct *) arguments->structureInput, arguments->asyncReference, arguments->asyncReferenceCount, kIODirectionOut);
if ( ret )
{
target->DecrementOutstandingIO();
target->release();
}
}
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::DoIsochPipeAsync(IOUSBIsocStruct *stuff, io_user_reference_t * asyncReference, uint32_t asyncCount, IODirection direction)
{
IOReturn ret;
IOUSBPipe * pipeObj = NULL;
IOMemoryDescriptor * dataMem = NULL;
IOMemoryDescriptor * countMem = NULL;
uint32_t frameLen = 0; bool countMemPrepared = false;
bool dataMemPrepared = false;
IOUSBIsocCompletion tap;
IOUSBInterfaceUserClientISOAsyncParamBlock * pb = NULL;
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(stuff->fPipe);
if(pipeObj)
{
frameLen = stuff->fNumFrames * sizeof(IOUSBIsocFrame);
do {
dataMem = IOMemoryDescriptor::withAddress( (vm_address_t)stuff->fBuffer, stuff->fBufSize, direction, fTask);
if(!dataMem)
{
USBLog(1, "%s[%p]::DoIsochPipeAsync could not create dataMem descriptor", getName(), this);
ret = kIOReturnNoMemory;
break;
}
ret = dataMem->prepare();
if (ret != kIOReturnSuccess)
{
USBLog(1, "%s[%p]::DoIsochPipeAsync could not prepare dataMem descriptor (0x%x)", getName(), this, ret);
break;
}
dataMemPrepared = true;
countMem = IOMemoryDescriptor::withAddress( (vm_address_t)stuff->fFrameCounts, frameLen, kIODirectionOutIn, fTask);
if(!countMem)
{
USBLog(1, "%s[%p]::DoIsochPipeAsync could not create countMem descriptor", getName(), this);
ret = kIOReturnNoMemory;
break;
}
ret = countMem->prepare();
if (ret != kIOReturnSuccess)
{
USBLog(1, "%s[%p]::DoIsochPipeAsync could not prepare dataMem descriptor (0x%x)", getName(), this, ret);
break;
}
countMemPrepared = true;
pb = (IOUSBInterfaceUserClientISOAsyncParamBlock*) IOMalloc(sizeof(IOUSBInterfaceUserClientISOAsyncParamBlock) + frameLen);
if (!pb)
{
ret = kIOReturnNoMemory;
break;
}
bcopy(asyncReference, pb->fAsyncRef, sizeof(OSAsyncReference64));
pb->fAsyncCount = asyncCount;
pb->frameLen = frameLen;
pb->frameBase = stuff->fFrameCounts;
pb->numFrames = stuff->fNumFrames;
pb->dataMem = dataMem;
pb->countMem = countMem;
countMem->readBytes(0, pb->frames, frameLen);
tap.target = this;
tap.action = &IOUSBInterfaceUserClientV2::IsoReqComplete;
tap.parameter = pb;
USBLog(7,"+%s[%p]::DoIsochPipeAsync fPipe: %ld, dataMem: %p, fBufSize = 0x%lx, fStartFrame: %qd", getName(), this,
stuff->fPipe,dataMem, stuff->fBufSize, stuff->fStartFrame);
if(direction == kIODirectionOut)
ret = pipeObj->Write(dataMem, stuff->fStartFrame, stuff->fNumFrames, pb->frames, &tap);
else
ret = pipeObj->Read(dataMem, stuff->fStartFrame, stuff->fNumFrames, pb->frames, &tap);
} while (false);
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if(kIOReturnSuccess != ret)
{
USBLog(3, "%s[%p]::DoIsochPipeAsync err 0x%x", getName(), this, ret);
if(dataMem)
{
if ( dataMemPrepared )
dataMem->complete();
dataMem->release();
dataMem = NULL;
}
if(countMem)
{
if ( countMemPrepared )
countMem->complete();
countMem->release();
countMem = NULL;
}
}
if ( ret != kIOReturnSuccess )
{
USBLog(3, "%s[%p]::-DoIsochPipeAsync err 0x%x", getName(), this, ret);
}
return ret;
}
#pragma mark Low Latency Isoch Methods
IOReturn IOUSBInterfaceUserClientV2::_LowLatencyReadIsochPipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret = kIOReturnUnsupported;
USBLog(7, "+%s[%p]::_LowLatencyReadIsochPipe", target->getName(), target);
if ( arguments->asyncWakePort )
{
IOUSBLowLatencyIsocCompletion tap;
IOUSBLowLatencyCommand * command = NULL;
command = (IOUSBLowLatencyCommand *) target->fFreeUSBLowLatencyCommandPool->getCommand(false);
if ( command == NULL )
{
target->IncreaseCommandPool();
command = (IOUSBLowLatencyCommand *) target->fFreeUSBLowLatencyCommandPool->getCommand(false);
if ( command == NULL )
{
USBLog(3,"%s[%p]::DoLowLatencyIsochPipeAsync Could not get a IOUSBLowLatencyIsocCommand", target->getName(),target);
ret = kIOReturnNoResources;
goto ErrorExit;
}
}
target->retain();
target->IncrementOutstandingIO();
command->SetAsyncReference( arguments->asyncReference );
command->SetAsyncCount(arguments->asyncReferenceCount);
tap.target = target;
tap.action = &IOUSBInterfaceUserClientV2::LowLatencyIsoReqComplete;
tap.parameter = command;
if ( arguments->structureInputDescriptor )
{
USBLog(3, "+%s[%p]::_LowLatencyReadIsochPipe We got an unexpected structureOutputDescriptor. Returning unsupported ", target->getName(), target);
ret = kIOReturnUnsupported;
}
else
ret = target->DoLowLatencyIsochPipeAsync( (IOUSBLowLatencyIsocStruct *) arguments->structureInput, &tap, kIODirectionIn);
if(kIOReturnSuccess != ret)
{
USBLog(3, "%s[%p]::_LowLatencyReadIsochPipe err 0x%x", target->getName(), target, ret);
if ( command )
target->fFreeUSBLowLatencyCommandPool->returnCommand(command);
target->DecrementOutstandingIO();
target->release();
}
}
ErrorExit:
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_LowLatencyWriteIsochPipe(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
IOReturn ret = kIOReturnUnsupported;
USBLog(7, "+%s[%p]::_LowLatencyWriteIsochPipe", target->getName(), target);
if ( arguments->asyncWakePort )
{
IOUSBLowLatencyIsocCompletion tap;
IOUSBLowLatencyCommand * command = NULL;
command = (IOUSBLowLatencyCommand *) target->fFreeUSBLowLatencyCommandPool->getCommand(false);
if ( command == NULL )
{
target->IncreaseCommandPool();
command = (IOUSBLowLatencyCommand *) target->fFreeUSBLowLatencyCommandPool->getCommand(false);
if ( command == NULL )
{
USBLog(3,"%s[%p]::DoLowLatencyIsochPipeAsync Could not get a IOUSBLowLatencyIsocCommand",target->getName(),target);
ret = kIOReturnNoResources;
goto ErrorExit;
}
}
target->retain();
target->IncrementOutstandingIO();
command->SetAsyncReference( arguments->asyncReference );
command->SetAsyncCount(arguments->asyncReferenceCount);
tap.target = target;
tap.action = &IOUSBInterfaceUserClientV2::LowLatencyIsoReqComplete;
tap.parameter = command;
if ( arguments->structureInputDescriptor )
{
USBLog(3, "+%s[%p]::_LowLatencyWriteIsochPipe We got an unexpected structureInputDescriptor. Returning unsupported ", target->getName(), target);
ret = kIOReturnUnsupported;
}
else
ret = target->DoLowLatencyIsochPipeAsync( (IOUSBLowLatencyIsocStruct *) arguments->structureInput, &tap, kIODirectionOut);
if(kIOReturnSuccess != ret)
{
USBLog(3, "%s[%p]::_LowLatencyReadIsochPipe err 0x%x", target->getName(), target, ret);
if ( command )
target->fFreeUSBLowLatencyCommandPool->returnCommand(command);
target->DecrementOutstandingIO();
target->release();
}
}
ErrorExit:
return ret;
}
IOReturn
IOUSBInterfaceUserClientV2::DoLowLatencyIsochPipeAsync(IOUSBLowLatencyIsocStruct *isocInfo, IOUSBLowLatencyIsocCompletion *completion, IODirection direction)
{
IOReturn ret;
IOUSBPipe * pipeObj = NULL;
IOUSBLowLatencyIsocCompletion tap;
IOMemoryDescriptor * aDescriptor = NULL;
IOUSBLowLatencyCommand * command = NULL;
IOUSBLowLatencyIsocFrame * pFrameList = NULL;
IOUSBLowLatencyUserClientBufferInfo * dataBuffer = NULL;
IOUSBLowLatencyUserClientBufferInfo * frameListDataBuffer = NULL;
USBLog(7, "+%s[%p]::DoLowLatencyIsochPipeAsync", getName(), this);
if (fOwner && !isInactive())
{
pipeObj = GetPipeObj(isocInfo->fPipe);
if(pipeObj)
{
do {
USBLog(6,"%s[%p]::DoLowLatencyIsochPipeAsync: dataBuffer cookie: %ld, offset: %ld, frameList cookie: %ld, offset : %ld", getName(),this, isocInfo->fDataBufferCookie, isocInfo->fDataBufferOffset, isocInfo->fFrameListBufferCookie, isocInfo->fFrameListBufferOffset );
IOUSBLowLatencyCommand * command = (IOUSBLowLatencyCommand *)completion->parameter;
dataBuffer = FindBufferCookieInList(isocInfo->fDataBufferCookie);
if ( dataBuffer == NULL )
{
USBLog(3,"%s[%p]::DoLowLatencyIsochPipeAsync: Could not find our buffer (cookie %ld) in the list", getName(),this, isocInfo->fDataBufferCookie );
ret = kIOReturnNoMemory;
break;
}
USBLog(6,"%s[%p]::DoLowLatencyIsochPipeAsync: Found data buffer for cookie: %ld, descriptor: %p, uhciDescriptor: %p, offset : %ld", getName(),this, isocInfo->fDataBufferCookie,
dataBuffer->bufferDescriptor, dataBuffer->writeDescritporForUHCI,isocInfo->fDataBufferOffset );
aDescriptor = IOMemoryDescriptor::withSubRange( dataBuffer->bufferDescriptor == NULL ? dataBuffer->writeDescritporForUHCI : dataBuffer->bufferDescriptor, isocInfo->fDataBufferOffset, isocInfo->fBufSize, direction );
if ( aDescriptor == NULL )
{
USBLog(3,"%s[%p]::DoLowLatencyIsochPipeAsync: Could not create an IOMD:withSubRange", getName(),this );
ret = kIOReturnNoMemory;
break;
}
ret = aDescriptor->prepare();
if (ret != kIOReturnSuccess)
{
USBLog(3,"%s[%p]::DoLowLatencyIsochPipeAsync: Preparing the descriptor returned 0x%x", getName(),this, ret );
break;
}
frameListDataBuffer = FindBufferCookieInList(isocInfo->fFrameListBufferCookie);
if ( frameListDataBuffer == NULL )
{
USBLog(3,"%s[%p]::DoLowLatencyIsochPipeAsync: Could not find our buffer (cookie %ld) in the list, returning kIOReturnNoMemory", getName(),this, isocInfo->fFrameListBufferCookie );
ret = kIOReturnNoMemory;
break;
}
USBLog(7,"%s[%p]::DoLowLatencyIsochPipeAsync: Found frameList buffer for cookie: %ld, descriptor: %p, offset : %ld", getName(),this, isocInfo->fFrameListBufferCookie,
(void *) frameListDataBuffer->frameListKernelAddress,isocInfo->fFrameListBufferOffset );
pFrameList = (IOUSBLowLatencyIsocFrame *) ( (UInt32) frameListDataBuffer->frameListKernelAddress + isocInfo->fFrameListBufferOffset);
command->SetFrameBase( (void *) ((UInt32) frameListDataBuffer->bufferAddress + isocInfo->fFrameListBufferOffset));
command->SetDataBuffer( aDescriptor );
if ( direction == kIODirectionOut )
ret = pipeObj->Write(aDescriptor, isocInfo->fStartFrame, isocInfo->fNumFrames, pFrameList, completion, isocInfo->fUpdateFrequency);
else
ret = pipeObj->Read(aDescriptor, isocInfo->fStartFrame, isocInfo->fNumFrames,pFrameList, completion, isocInfo->fUpdateFrequency);
} while (false);
pipeObj->release();
}
else
ret = kIOUSBUnknownPipeErr;
}
else
ret = kIOReturnNotAttached;
if(kIOReturnSuccess != ret)
{
USBLog(3, "%s[%p]::DoLowLatencyIsochPipeAsync err 0x%x", getName(), this, ret);
if ( aDescriptor )
{
aDescriptor->release();
aDescriptor = NULL;
}
}
USBLog(7, "-%s[%p]::DoLowLatencyIsochPipeAsync", getName(), this);
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_LowLatencyPrepareBuffer(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_LowLatencyPrepareBuffer", target->getName(), target);
return target->LowLatencyPrepareBuffer( (LowLatencyUserBufferInfoV2 *) arguments->structureInput, &(arguments->scalarOutput[0]));
}
IOReturn
IOUSBInterfaceUserClientV2::LowLatencyPrepareBuffer(LowLatencyUserBufferInfoV2 *bufferData, uint64_t * addrOut)
{
IOReturn ret = kIOReturnSuccess;
IOMemoryDescriptor * aDescriptor = NULL;
IOUSBLowLatencyUserClientBufferInfo * kernelDataBuffer = NULL;
IOMemoryMap * frameListMap = NULL;
IODirection direction;
IOBufferMemoryDescriptor * uhciDescriptor = NULL;
IOMemoryMap * uhciMap = NULL;
void * uhciMappedData = NULL;
bool preparedUHCIDescriptor = false;
IncrementOutstandingIO();
if (fOwner && !isInactive())
{
USBLog(3, "%s[%p]::LowLatencyPrepareBuffer cookie: %ld, buffer: %p, size: %ld, type %ld, isPrepared: %d, next: %p", getName(), this,
bufferData->cookie,
bufferData->bufferAddress,
bufferData->bufferSize,
bufferData->bufferType,
bufferData->isPrepared,
bufferData->nextBuffer);
*addrOut = 0;
kernelDataBuffer = ( IOUSBLowLatencyUserClientBufferInfo *) IOMalloc( sizeof(IOUSBLowLatencyUserClientBufferInfo) );
if (kernelDataBuffer == NULL )
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not malloc buffer info (size = %ld)!", getName(), this, sizeof(IOUSBLowLatencyUserClientBufferInfo) );
return kIOReturnNoMemory;
}
bzero(kernelDataBuffer, sizeof(IOUSBLowLatencyUserClientBufferInfo));
kernelDataBuffer->cookie = bufferData->cookie;
kernelDataBuffer->bufferType = bufferData->bufferType;
if ( fNeedContiguousMemoryForLowLatencyIsoch and ((bufferData->bufferType == kUSBLowLatencyWriteBuffer) or (bufferData->bufferType == kUSBLowLatencyReadBuffer)) )
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer About to call to get a contiguous bufferMemoryDescriptor( %ld)!", getName(), this, bufferData->bufferSize );
direction = ( bufferData->bufferType == kUSBLowLatencyWriteBuffer ? kIODirectionOut : kIODirectionIn );
uhciDescriptor = IOBufferMemoryDescriptor::withOptions( direction | kIOMemoryPhysicallyContiguous | kIOMemoryKernelUserShared, bufferData->bufferSize, PAGE_SIZE);
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Returned %p", getName(), this, uhciDescriptor );
if ( uhciDescriptor == NULL)
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not create a physically contiguous IOBMD (size %ld)!", getName(), this, bufferData->bufferSize );
ret = kIOReturnNoMemory;
goto ErrorExit;
}
ret = uhciDescriptor->prepare();
if (ret != kIOReturnSuccess)
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not prepare the data buffer memory descriptor 0x%x", getName(), this, ret );
goto ErrorExit;
}
preparedUHCIDescriptor = true;
uhciMap = uhciDescriptor->map(fTask, NULL, kIOMapAnywhere, 0, 0 );
if ( uhciMap == NULL )
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not map the data buffer memory descriptor", getName(), this );
goto ErrorExit;
}
uhciMappedData = (void *) uhciMap->getVirtualAddress();
if ( uhciMappedData == NULL )
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not get the virtual address of the map", getName(), this );
goto ErrorExit;
}
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer mapped virtual address = %p", getName(), this, uhciMappedData );
UInt32 * theAddr = (UInt32 *) uhciMappedData;
kernelDataBuffer->bufferSize = bufferData->bufferSize;
kernelDataBuffer->writeDescritporForUHCI = uhciDescriptor;
kernelDataBuffer->writeMapForUHCI= uhciMap;
*addrOut = (UInt32)uhciMappedData;
}
else if ( (bufferData->bufferType == kUSBLowLatencyWriteBuffer) or ( bufferData->bufferType == kUSBLowLatencyReadBuffer) )
{
direction = ( bufferData->bufferType == kUSBLowLatencyWriteBuffer ? kIODirectionOut : kIODirectionIn );
aDescriptor = IOMemoryDescriptor::withAddress((vm_address_t)bufferData->bufferAddress, bufferData->bufferSize, direction, fTask);
if(!aDescriptor)
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not create a data buffer memory descriptor (addr: %p, size %ld)!", getName(), this, bufferData->bufferAddress, bufferData->bufferSize );
ret = kIOReturnNoMemory;
goto ErrorExit;
}
ret = aDescriptor->prepare();
if (ret != kIOReturnSuccess)
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not prepare the data buffer memory descriptor (0x%x)!", getName(), this, ret );
goto ErrorExit;
}
kernelDataBuffer->bufferAddress = bufferData->bufferAddress;
kernelDataBuffer->bufferSize = bufferData->bufferSize;
kernelDataBuffer->bufferDescriptor = aDescriptor;
USBLog(3, "%s[%p]::LowLatencyPrepareBuffer finished preparing data buffer: %p, size %ld, desc: %p, cookie: %ld", getName(), this,
kernelDataBuffer->bufferAddress, kernelDataBuffer->bufferSize, kernelDataBuffer->bufferDescriptor, kernelDataBuffer->cookie);
}
else if ( bufferData->bufferType == kUSBLowLatencyFrameListBuffer )
{
aDescriptor = IOMemoryDescriptor::withAddress((vm_address_t)bufferData->bufferAddress, bufferData->bufferSize, kIODirectionOutIn, fTask);
if(!aDescriptor)
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not create a frame list memory descriptor (addr: %p, size %ld)!", getName(), this, bufferData->bufferAddress, bufferData->bufferSize );
ret = kIOReturnNoMemory;
goto ErrorExit;
}
ret = aDescriptor->prepare();
if (ret != kIOReturnSuccess)
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not prepare the frame list memory descriptor (0x%x)", getName(), this, ret );
goto ErrorExit;
}
frameListMap = aDescriptor->map();
if (!frameListMap)
{
USBLog(1,"%s[%p]::LowLatencyPrepareBuffer Could not map the frame list memory descriptor!", getName(), this );
ret = kIOReturnNoMemory;
aDescriptor->complete();
goto ErrorExit;
}
kernelDataBuffer->frameListKernelAddress = frameListMap->getVirtualAddress();
kernelDataBuffer->bufferAddress = bufferData->bufferAddress;
kernelDataBuffer->bufferSize = bufferData->bufferSize;
kernelDataBuffer->frameListDescriptor = aDescriptor;
kernelDataBuffer->frameListMap = frameListMap;
USBLog(3, "%s[%p]::LowLatencyPrepareBuffer finished preparing frame list buffer: %p, size %ld, desc: %p, map %p, kernel address: 0x%x, cookie: %ld", getName(), this,
kernelDataBuffer->bufferAddress, kernelDataBuffer->bufferSize, kernelDataBuffer->bufferDescriptor, kernelDataBuffer->frameListMap,
kernelDataBuffer->frameListKernelAddress, kernelDataBuffer->cookie);
}
AddDataBufferToList( kernelDataBuffer );
}
else
ret = kIOReturnNotAttached;
ErrorExit:
if (ret)
{
USBLog(3, "%s[%p]::LowLatencyPrepareBuffer - returning err %x", getName(), this, ret);
if ( uhciDescriptor )
{
if (preparedUHCIDescriptor)
uhciDescriptor->complete();
uhciDescriptor->release();
}
if ( uhciMap != NULL )
uhciMap->release();
}
DecrementOutstandingIO();
return ret;
}
IOReturn IOUSBInterfaceUserClientV2::_LowLatencyReleaseBuffer(IOUSBInterfaceUserClientV2 * target, void * reference, IOExternalMethodArguments * arguments)
{
USBLog(7, "+%s[%p]::_LowLatencyReleaseBuffer", target->getName(), target);
return target->LowLatencyReleaseBuffer( (LowLatencyUserBufferInfoV2 *) arguments->structureInput);
}
IOReturn
IOUSBInterfaceUserClientV2::LowLatencyReleaseBuffer(LowLatencyUserBufferInfoV2 *dataBuffer)
{
IOUSBLowLatencyUserClientBufferInfo * kernelDataBuffer = NULL;
IOReturn ret = kIOReturnSuccess;
bool found = false;
IncrementOutstandingIO();
USBLog(3, "+%s[%p]::LowLatencyReleaseBuffer for cookie: %ld", getName(), this, dataBuffer->cookie);
if (fOwner && !isInactive())
{
kernelDataBuffer = FindBufferCookieInList( dataBuffer->cookie );
if ( kernelDataBuffer == NULL )
{
USBLog(3, "+%s[%p]::LowLatencyReleaseBuffer cookie: %ld, could not find buffer in list", getName(), this, dataBuffer->cookie);
ret = kIOReturnBadArgument;
goto ErrorExit;
}
found = RemoveDataBufferFromList( kernelDataBuffer );
if ( !found )
{
USBLog(3, "+%s[%p]::LowLatencyReleaseBuffer cookie: %ld, could not remove buffer (%p) from list", getName(), this, dataBuffer->cookie, kernelDataBuffer);
ret = kIOReturnBadArgument;
goto ErrorExit;
}
if ( kernelDataBuffer->frameListMap )
{
USBLog(6, "+IOUSBInterfaceUserClientV2[%p]::LowLatencyReleaseBuffer releasing frameListMap (0x%x)", this, kernelDataBuffer->frameListKernelAddress);
kernelDataBuffer->frameListMap->release();
kernelDataBuffer->frameListMap = NULL;
kernelDataBuffer->frameListKernelAddress = NULL;
}
if ( kernelDataBuffer->frameListDescriptor )
{
kernelDataBuffer->frameListDescriptor->complete();
kernelDataBuffer->frameListDescriptor->release();
kernelDataBuffer->frameListDescriptor = NULL;
}
if ( kernelDataBuffer->bufferDescriptor )
{
kernelDataBuffer->bufferDescriptor->complete();
kernelDataBuffer->bufferDescriptor->release();
kernelDataBuffer->bufferDescriptor = NULL;
}
if ( kernelDataBuffer->writeDescritporForUHCI )
{
kernelDataBuffer->writeDescritporForUHCI->complete();
kernelDataBuffer->writeDescritporForUHCI->release();
kernelDataBuffer->writeDescritporForUHCI = NULL;
}
if ( kernelDataBuffer->writeMapForUHCI )
{
USBLog(3, "+IOUSBInterfaceUserClientV2[%p]::LowLatencyReleaseBuffer releasing uhciMap (%p)", this, kernelDataBuffer->writeMapForUHCI);
kernelDataBuffer->writeMapForUHCI->release();
kernelDataBuffer->writeMapForUHCI = NULL;
}
IOFree(kernelDataBuffer, sizeof(IOUSBLowLatencyUserClientBufferInfo));
}
else
ret = kIOReturnNotAttached;
ErrorExit:
if (ret)
{
USBLog(3, "%s[%p]::LowLatencyReleaseBuffer - returning err %x", getName(), this, ret);
}
DecrementOutstandingIO();
return ret;
}
void
IOUSBInterfaceUserClientV2::AddDataBufferToList( IOUSBLowLatencyUserClientBufferInfo * insertBuffer )
{
IOUSBLowLatencyUserClientBufferInfo * buffer;
if ( fUserClientBufferInfoListHead == NULL )
{
fUserClientBufferInfoListHead = insertBuffer;
return;
}
buffer = fUserClientBufferInfoListHead;
while ( buffer->nextBuffer != NULL )
{
buffer = buffer->nextBuffer;
}
buffer->nextBuffer = insertBuffer;
}
IOUSBLowLatencyUserClientBufferInfo *
IOUSBInterfaceUserClientV2::FindBufferCookieInList( UInt32 cookie)
{
IOUSBLowLatencyUserClientBufferInfo * buffer;
bool foundIt = true;
if ( fUserClientBufferInfoListHead == NULL )
{
USBLog(3, "%s[%p]::FindBufferCookieInList - fUserClientBufferInfoListHead was NULL", getName(), this);
return NULL;
}
buffer = fUserClientBufferInfoListHead;
while ( buffer->cookie != cookie )
{
buffer = buffer->nextBuffer;
if ( buffer == NULL )
{
foundIt = false;
break;
}
}
if ( foundIt )
return buffer;
else
{
USBLog(3, "%s[%p]::FindBufferCookieInList - Could no find buffer for cookie (%ld), returning NULL", getName(), this, cookie);
return NULL;
}
}
bool
IOUSBInterfaceUserClientV2::RemoveDataBufferFromList( IOUSBLowLatencyUserClientBufferInfo *removeBuffer)
{
IOUSBLowLatencyUserClientBufferInfo * buffer;
IOUSBLowLatencyUserClientBufferInfo * previousBuffer;
if ( fUserClientBufferInfoListHead == NULL )
{
return false;
}
buffer = fUserClientBufferInfoListHead;
if ( buffer == removeBuffer )
{
fUserClientBufferInfoListHead = buffer->nextBuffer;
}
else
{
previousBuffer = buffer;
while ( buffer->nextBuffer != removeBuffer )
{
previousBuffer = buffer;
buffer = previousBuffer->nextBuffer;
}
buffer->nextBuffer = removeBuffer->nextBuffer;
}
return true;
}
#pragma mark Bookkeeping Methods
void
IOUSBInterfaceUserClientV2::DecrementOutstandingIO(void)
{
if (!fGate)
{
if (!--fOutstandingIO && fNeedToClose)
{
USBLog(3, "%s[%p]::DecrementOutstandingIO isInactive = %d, outstandingIO = %d - closing device", getName(), this, isInactive(), fOutstandingIO);
if (fOwner && fOwner->isOpen(this) )
{
fOwner->close(this);
fNeedToClose = false;
if ( isInactive() )
fOwner = NULL;
}
if ( fDead)
{
fDead = false;
release();
}
}
return;
}
fGate->runAction(ChangeOutstandingIO, (void*)-1);
}
void
IOUSBInterfaceUserClientV2::IncrementOutstandingIO(void)
{
if (!fGate)
{
fOutstandingIO++;
return;
}
fGate->runAction(ChangeOutstandingIO, (void*)1);
}
IOReturn
IOUSBInterfaceUserClientV2::ChangeOutstandingIO(OSObject *target, void *param1, void *param2, void *param3, void *param4)
{
IOUSBInterfaceUserClientV2 *me = OSDynamicCast(IOUSBInterfaceUserClientV2, target);
UInt32 direction = (UInt32)param1;
if (!me)
{
USBLog(1, "IOUSBInterfaceUserClientV2::ChangeOutstandingIO - invalid target");
return kIOReturnSuccess;
}
switch (direction)
{
case 1:
me->fOutstandingIO++;
break;
case -1:
if (!--me->fOutstandingIO && me->fNeedToClose)
{
USBLog(6, "%s[%p]::ChangeOutstandingIO isInactive = %d, outstandingIO = %d - closing device", me->getName(), me, me->isInactive(), me->fOutstandingIO);
if (me->fOwner && me->fOwner->isOpen(me))
{
me->fOwner->close(me);
me->fNeedToClose = false;
if ( me->isInactive() )
me->fOwner = NULL;
}
if ( me->fDead)
{
me->fDead = false;
me->release();
}
}
break;
default:
USBLog(1, "%s[%p]::ChangeOutstandingIO - invalid direction", me->getName(), me);
}
return kIOReturnSuccess;
}
UInt32
IOUSBInterfaceUserClientV2::GetOutstandingIO()
{
UInt32 count = 0;
if (!fGate)
{
return fOutstandingIO;
}
fGate->runAction(GetGatedOutstandingIO, (void*)&count);
return count;
}
IOReturn
IOUSBInterfaceUserClientV2::GetGatedOutstandingIO(OSObject *target, void *param1, void *param2, void *param3, void *param4)
{
IOUSBInterfaceUserClientV2 *me = OSDynamicCast(IOUSBInterfaceUserClientV2, target);
if (!me)
{
USBLog(1, "IOUSBInterfaceUserClientV2::GetGatedOutstandingIO - invalid target");
return kIOReturnSuccess;
}
*(UInt32 *) param1 = me->fOutstandingIO;
return kIOReturnSuccess;
}
void
IOUSBInterfaceUserClientV2::IncreaseCommandPool(void)
{
int i;
USBLog(3,"%s[%p] Adding (%d) to Command Pool", getName(), this, kSizeToIncrementLowLatencyCommandPool);
for (i = 0; i < kSizeToIncrementLowLatencyCommandPool; i++)
{
IOUSBLowLatencyCommand *command = IOUSBLowLatencyCommand::NewCommand();
if (command)
fFreeUSBLowLatencyCommandPool->returnCommand(command);
}
fCurrentSizeOfCommandPool += kSizeToIncrementLowLatencyCommandPool;
}
void
IOUSBInterfaceUserClientV2::ReleasePreparedDescriptors(void)
{
IOUSBLowLatencyUserClientBufferInfo * kernelDataBuffer;
IOUSBLowLatencyUserClientBufferInfo * nextBuffer;
if ( fOutstandingIO != 0 )
{
USBLog(7, "+IOUSBInterfaceUserClientV2[%p]::ReleasePreparedDescriptors: OutstandingIO is NOT 0 (%d) ", this, fOutstandingIO);
return;
}
if (fUserClientBufferInfoListHead != NULL)
{
nextBuffer = fUserClientBufferInfoListHead;
kernelDataBuffer = fUserClientBufferInfoListHead;
while ( nextBuffer != NULL )
{
nextBuffer = kernelDataBuffer->nextBuffer;
if ( kernelDataBuffer->frameListMap )
{
USBLog(3, "+IOUSBInterfaceUserClientV2[%p]::ReleasePreparedDescriptors releasing frameListMap (@ 0x%x)", this, kernelDataBuffer->frameListKernelAddress);
kernelDataBuffer->frameListMap->release();
kernelDataBuffer->frameListMap = NULL;
kernelDataBuffer->frameListKernelAddress = NULL;
}
if ( kernelDataBuffer->frameListDescriptor )
{
kernelDataBuffer->frameListDescriptor->complete();
kernelDataBuffer->frameListDescriptor->release();
kernelDataBuffer->frameListDescriptor = NULL;
}
if ( kernelDataBuffer->bufferDescriptor )
{
kernelDataBuffer->bufferDescriptor->complete();
kernelDataBuffer->bufferDescriptor->release();
kernelDataBuffer->bufferDescriptor = NULL;
}
if ( kernelDataBuffer->writeDescritporForUHCI )
{
kernelDataBuffer->writeDescritporForUHCI->complete();
kernelDataBuffer->writeDescritporForUHCI->release();
kernelDataBuffer->writeDescritporForUHCI = NULL;
}
if ( kernelDataBuffer->writeMapForUHCI )
{
USBLog(3, "+IOUSBInterfaceUserClientV2[%p]::ReleasePreparedDescriptors releasing uhciMap (%p)", this, kernelDataBuffer->writeMapForUHCI);
kernelDataBuffer->writeMapForUHCI->release();
kernelDataBuffer->writeMapForUHCI = NULL;
}
IOFree(kernelDataBuffer, sizeof(IOUSBLowLatencyUserClientBufferInfo));
kernelDataBuffer = nextBuffer;
}
fUserClientBufferInfoListHead = NULL;
}
}
#pragma mark Helper Methods
IOUSBPipe*
IOUSBInterfaceUserClientV2::GetPipeObj(UInt8 pipeNo)
{
IOUSBPipe *pipe = NULL;
if (fOwner && !isInactive())
{
if (pipeNo == 0)
pipe = fOwner->GetDevice()->GetPipeZero();
if ((pipeNo > 0) && (pipeNo <= kUSBMaxPipes))
pipe = fOwner->GetPipeObj(pipeNo-1);
}
if (pipe)
pipe->retain();
return pipe;
}
#pragma mark IOKit Methods
IOReturn
IOUSBInterfaceUserClientV2::clientClose( void )
{
USBLog(7, "+%s[%p]::clientClose(%p), IO: %d", getName(), this, fUserClientBufferInfoListHead, fOutstandingIO);
IOSleep(1);
if ( fDead && fOwner && !isInactive() && fOwner->isOpen(this) )
{
UInt8 altSetting = fOwner->GetAlternateSetting();
if ( altSetting != 0 )
{
USBLog(6, "+%s[%p]::clientClose setting Alternate Interface to 0 before closing pipes", getName(), this);
fOwner->SetAlternateInterface(this, 0);
}
fOwner->ClosePipes();
}
if ( !isInactive() )
{
if ( fOutstandingIO == 0 )
{
USBLog(6, "+%s[%p]::clientClose closing provider", getName(), this);
if ( fOwner && fOwner->isOpen(this))
{
fOwner->close(this);
fNeedToClose = false;
}
if ( fDead)
{
fDead = false;
release();
}
}
else
{
USBLog(5, "+%s[%p]::clientClose will close provider later", getName(), this);
fNeedToClose = true;
}
fTask = NULL;
terminate();
}
USBLog(7, "-%s[%p]::clientClose(%p)", getName(), this, fUserClientBufferInfoListHead);
return kIOReturnSuccess; }
IOReturn
IOUSBInterfaceUserClientV2::clientDied( void )
{
IOReturn ret;
USBLog(6, "+%s[%p]::clientDied() IO: %d", getName(), this, fOutstandingIO);
retain();
fDead = true; ret = super::clientDied();
USBLog(6, "-%s[%p]::clientDied()", getName(), this);
return ret;
}
void
IOUSBInterfaceUserClientV2::stop(IOService * provider)
{
USBLog(7, "+%s[%p]::stop(%p), IO: %d", getName(), this, provider, fOutstandingIO);
if (fUserClientBufferInfoListHead != NULL)
{
ReleasePreparedDescriptors();
}
if (fWorkLoop && fGate)
fWorkLoop->removeEventSource(fGate);
super::stop(provider);
USBLog(7, "-%s[%p]::stop(%p)", getName(), this, provider);
}
void
IOUSBInterfaceUserClientV2::free()
{
IOReturn ret;
USBLog(7, "IOUSBInterfaceUserClientV2[%p]::free", this);
if (fUserClientBufferInfoListHead != NULL)
{
ReleasePreparedDescriptors();
}
if ( fFreeUSBLowLatencyCommandPool )
{
fFreeUSBLowLatencyCommandPool->release();
fFreeUSBLowLatencyCommandPool = NULL;
}
if (fGate)
{
fGate->release();
fGate = NULL;
}
if (fWorkLoop)
{
fWorkLoop->release();
fWorkLoop = NULL;
}
if (fIOUSBInterfaceUserClientExpansionData)
{
IOFree(fIOUSBInterfaceUserClientExpansionData, sizeof(IOUSBInterfaceUserClientExpansionData));
fIOUSBInterfaceUserClientExpansionData = NULL;
}
super::free();
}
bool
IOUSBInterfaceUserClientV2::finalize( IOOptionBits options )
{
bool ret;
USBLog(7, "+%s[%p]::finalize(%08x)", getName(), this, (int)options);
ret = super::finalize(options);
USBLog(7, "-%s[%p]::finalize(%08x) - returning %s", getName(), this, (int)options, ret ? "true" : "false");
return ret;
}
bool
IOUSBInterfaceUserClientV2::willTerminate( IOService * provider, IOOptionBits options )
{
IOUSBPipe *pipe = NULL;
IOReturn ret;
UInt32 ioPending = 0;
USBLog(3, "%s[%p]::willTerminate isInactive = %d", getName(), this, isInactive());
if ( fOwner )
{
IncrementOutstandingIO();
ioPending = GetOutstandingIO();
if ( (ioPending > 1) && fOwner )
{
int i;
USBLog(7, "%s[%p]::willTerminate - outstanding IO(%ld), aborting pipes", getName(), this, ioPending);
for (i=1; i <= kUSBMaxPipes; i++)
{
pipe = fOwner->GetPipeObj(i-1);
if(pipe)
{
pipe->retain();
ret = pipe->Abort();
pipe->release();
}
}
}
DecrementOutstandingIO();
}
return super::willTerminate(provider, options);
}
bool
IOUSBInterfaceUserClientV2::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
{
USBLog(3, "%s[%p]::didTerminate isInactive = %d, outstandingIO = %d", getName(), this, isInactive(), fOutstandingIO);
if ( fOwner && fOwner->isOpen(this))
{
if ( fOutstandingIO == 0 )
{
fOwner->close(this);
fNeedToClose = false;
if ( isInactive() )
fOwner = NULL;
}
else
fNeedToClose = true;
}
return super::didTerminate(provider, options, defer);
}
IOReturn
IOUSBInterfaceUserClientV2::message( UInt32 type, IOService * provider, void * argument )
{
IOReturn err = kIOReturnSuccess;
switch ( type )
{
case kIOUSBMessagePortHasBeenSuspended:
USBLog(6, "%s[%p]::message - received kIOUSBMessagePortHasBeenSuspended", getName(), this);
break;
case kIOUSBMessagePortHasBeenReset:
USBLog(6, "%s[%p]::message - received kIOUSBMessagePortHasBeenReset", getName(), this);
break;
case kIOUSBMessagePortHasBeenResumed:
USBLog(6, "%s[%p]::message - received kIOUSBMessagePortHasBeenResumed", getName(), this);
break;
case kIOMessageServiceIsTerminated:
USBLog(6, "%s[%p]::message - received kIOMessageServiceIsTerminated", getName(), this);
break;
default:
break;
}
return err;
}
#pragma mark Debugging
void
IOUSBInterfaceUserClientV2::PrintExternalMethodArgs( IOExternalMethodArguments * arguments, UInt32 level )
{
USBLog(level,"ExternalMethodArguments\n\tversion:\t0x%x\n\tselector:\t0x%x\n\tasyncWakePort:\t%p\n\tasyncReference:\t%p\n\tasyncReferenceCount:0x%x\n\tscalarInput:\t%p\n\tscalarInputCount:\t0x%x\n\tstructureInput:\t%p\n\tstructureInputSize:\t0x%x\n\tstructureInputMemoryDesc:\t%p\n\tscalarOutput:\t%p\n\tscalarOutputSize:\t0x%x\n\tstructureOutput:\t%p\n\tstructureOutputSize:\t0x%x\n\tstructureOutputDescriptor:\t%p\n\tstructureOutputDescriptorSize:\t0x%x\n",
arguments->version,
arguments->selector,
arguments->asyncWakePort,
arguments->asyncReference,
arguments->asyncReferenceCount,
arguments->scalarInput,
arguments->scalarInputCount,
arguments->structureInput,
arguments->structureInputSize,
arguments->structureInputDescriptor,
arguments->scalarOutput,
arguments->scalarOutputCount,
arguments->structureOutput,
arguments->structureOutputSize,
arguments->structureOutputDescriptor,
arguments->structureOutputDescriptorSize
);
for ( uint32_t i = 0; i < arguments->scalarInputCount; i++ )
{
USBLog(level,"\targuments->scalarInput[%d]: 0x%qx", i, arguments->scalarInput[i]);
}
}
#pragma mark Padding Methods
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 0);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 1);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 2);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 3);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 4);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 5);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 6);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 7);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 8);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 9);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 10);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 11);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 12);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 13);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 14);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 15);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 16);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 17);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 18);
OSMetaClassDefineReservedUnused(IOUSBInterfaceUserClientV2, 19);
#pragma mark Low Latency Commands
IOUSBLowLatencyCommand *
IOUSBLowLatencyCommand::NewCommand()
{
IOUSBLowLatencyCommand *me = new IOUSBLowLatencyCommand;
return me;
}
void
IOUSBLowLatencyCommand::SetAsyncReference(OSAsyncReference64 ref)
{
bcopy(ref, fAsyncRef, sizeof(OSAsyncReference64));
}
void
IOUSBLowLatencyCommand::SetAsyncCount(uint32_t count)
{
fAsyncReferenceCount = count;
}
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 0);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 1);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 2);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 3);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 4);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 5);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 6);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 7);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 8);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 9);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 10);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 11);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 12);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 13);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 14);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 15);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 16);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 17);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 18);
OSMetaClassDefineReservedUnused(IOUSBLowLatencyCommand, 19);