IOFireWireAVCUserClient.cpp [plain text]
#include "IOFireWireAVCUserClient.h"
#include <IOKit/IOLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOSyncer.h>
#include <IOKit/firewire/IOFireWireUnit.h>
#include <IOKit/firewire/IOFireWireController.h>
#if FIRELOG
#import <IOKit/firewire/FireLog.h>
#define FIRELOG_MSG(x) FireLog x
#else
#define FIRELOG_MSG(x) do {} while (0)
#endif
OSDefineMetaClassAndStructors(IOFireWireAVCConnection, OSObject)
OSDefineMetaClassAndStructors(IOFireWireAVCUserClientAsyncCommand, OSObject)
OSDefineMetaClassAndStructors(IOFireWireAVCUserClient, IOUserClient)
void AVCUserClientAsyncCommandCallback(void *pRefCon, IOFireWireAVCAsynchronousCommand *pCommandObject);
IOReturn IOFireWireAVCUserClient::externalMethod( uint32_t selector,
IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch,
OSObject * target,
void * reference)
{
IOReturn result = kIOReturnBadArgument;
FIRELOG_MSG(("IOFireWireAVCUserClient::externalMethod (this=0x%08X), selector=0x%08X\n",this,selector));
switch (selector)
{
case kIOFWAVCUserClientOpen:
result = open(NULL,NULL,NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientClose:
result = close(NULL,NULL,NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientGetSessionRef:
result = getSessionRef( arguments->scalarOutput,NULL,NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientAVCCommand:
result = AVCCommand((UInt8*)arguments->structureInput,
(UInt8*)arguments->structureOutput,
arguments->structureInputSize,
(UInt32*)&arguments->structureOutputSize);
break;
case kIOFWAVCUserClientOpenWithSessionRef:
result = openWithSessionRef((IOFireWireLib::UserObjectHandle) arguments->scalarInput[0],NULL,NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientAVCCommandInGen:
result = AVCCommandInGen((UInt8*) arguments->structureInput,
(UInt8*)arguments->structureOutput,
arguments->structureInputSize,
(UInt32*)&arguments->structureOutputSize);
break;
case kIOFWAVCUserClientUpdateAVCCommandTimeout:
result = updateAVCCommandTimeout(NULL,NULL,NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientMakeP2PInputConnection:
result = makeP2PInputConnection(arguments->scalarInput[0],arguments->scalarInput[1],NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientBreakP2PInputConnection:
result = breakP2PInputConnection(arguments->scalarInput[0],NULL,NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientMakeP2POutputConnection:
result = makeP2POutputConnection(arguments->scalarInput[0],arguments->scalarInput[1],(IOFWSpeed)arguments->scalarInput[2],NULL,NULL,NULL);
break;
case kIOFWAVCUserClientBreakP2POutputConnection:
result = breakP2POutputConnection(arguments->scalarInput[0],NULL,NULL,NULL,NULL,NULL);
break;
case kIOFWAVCUserClientCreateAsyncAVCCommand:
result = CreateAVCAsyncCommand((UInt8*)arguments->structureInput,
(UInt8*)arguments->structureOutput,
arguments->structureInputSize,
(UInt32*)&arguments->structureOutputSize);
break;
case kIOFWAVCUserClientSubmitAsyncAVCCommand:
result = SubmitAVCAsyncCommand(arguments->scalarInput[0]);
break;
case kIOFWAVCUserClientCancelAsyncAVCCommand:
result = CancelAVCAsyncCommand(arguments->scalarInput[0]);
break;
case kIOFWAVCUserClientReleaseAsyncAVCCommand:
result = ReleaseAVCAsyncCommand(arguments->scalarInput[0]);
break;
case kIOFWAVCUserClientReinitAsyncAVCCommand:
result = ReinitAVCAsyncCommand(arguments->scalarInput[0], (const UInt8*) arguments->structureInput, arguments->structureInputSize);
break;
case kIOFWAVCUserClientInstallAsyncAVCCommandCallback:
result = installUserLibAsyncAVCCommandCallback(arguments->asyncReference,arguments->scalarInput[0], arguments->scalarOutput);
break;
default:
break;
};
return result;
}
bool IOFireWireAVCUserClient::initWithTask(
task_t owningTask, void * securityToken, UInt32 type,
OSDictionary * properties)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::initWithTask (this=0x%08X)\n",this));
fTask = owningTask;
if (properties)
properties->setObject("IOUserClientCrossEndianCompatible", kOSBooleanTrue);
return IOUserClient::initWithTask(owningTask, securityToken, type,properties);
}
void IOFireWireAVCUserClient::free()
{
FIRELOG_MSG(("IOFireWireAVCUserClient::free (this=0x%08X)\n",this));
if(fConnections) {
UInt32 i;
if(fUnit) {
for(i=0; i<fConnections->getCount(); i++) {
IOFireWireAVCConnection *connection;
connection = (IOFireWireAVCConnection *)fConnections->getObject(i);
updateP2PCount(connection->fPlugAddr, -1, false, 0xFFFFFFFF, kFWSpeedInvalid);
}
}
fConnections->release();
}
if (fAsyncAVCCmdLock)
IOLockFree(fAsyncAVCCmdLock);
#ifdef kUseAsyncAVCCommandForBlockingAVCCommand
if (avcCmdLock)
{
if (IOLockTryLock(avcCmdLock) == false)
{
if (pCommandObject)
pCommandObject->cancel();
IOTakeLock(avcCmdLock);
}
IOLockFree(avcCmdLock);
}
#endif
IOService::free();
if (fUnit)
fUnit->release();
}
void IOFireWireAVCUserClient::stop( IOService * provider )
{
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand;
FIRELOG_MSG(("IOFireWireAVCUserClient::stop (this=0x%08X)\n",this));
fStarted = false;
IOTakeLock(fAsyncAVCCmdLock);
while (fUCAsyncCommands->getCount())
{
pUCAsyncCommand = (IOFireWireAVCUserClientAsyncCommand *)fUCAsyncCommands->getObject(0);
if (pUCAsyncCommand)
{
pUCAsyncCommand->pAsyncCommand->cancel(); pUCAsyncCommand->pAsyncCommand->release();
pUCAsyncCommand->fMem->complete();
pUCAsyncCommand->fMem->release() ;
fUCAsyncCommands->removeObject(0);
}
}
IOUnlock(fAsyncAVCCmdLock);
IOService::stop(provider);
}
bool IOFireWireAVCUserClient::start( IOService * provider )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::start (this=0x%08X)\n",this));
if( fStarted )
return false;
fUnit = OSDynamicCast(IOFireWireAVCNub, provider);
if (fUnit == NULL)
return false;
fConnections = OSArray::withCapacity(1);
fUCAsyncCommands = OSArray::withCapacity(1);
fAsyncAVCCmdLock = IOLockAlloc();
if (fAsyncAVCCmdLock == NULL)
return false;
#ifdef kUseAsyncAVCCommandForBlockingAVCCommand
pCommandObject = NULL;
avcCmdLock = IOLockAlloc();
if (avcCmdLock == NULL) {
return false;
}
#endif
if( !IOUserClient::start(provider) )
return false;
fStarted = true;
fUnit->retain();
return true;
}
IOReturn IOFireWireAVCUserClient::clientClose( void )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::clientClose (this=0x%08X)\n",this));
if( fOpened )
{
fOpened = false;
}
fStarted = false;
terminate( kIOServiceRequired );
return kIOReturnSuccess;
}
IOReturn IOFireWireAVCUserClient::clientDied( void )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::clientDied (this=0x%08X)\n",this));
return clientClose();
}
IOReturn IOFireWireAVCUserClient::open
( void *, void *, void *, void *, void *, void * )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::open (this=0x%08X)\n",this));
IOReturn status = kIOReturnSuccess;
if( fOpened )
status = kIOReturnError;
if( status == kIOReturnSuccess )
{
if( fUnit->open(this) )
{
IOFWUserObjectExporter * exporter = fUnit->getDevice()->getBus()->getSessionRefExporter();
status = exporter->addObject( this, NULL, &fSessionRef );
if( status == kIOReturnSuccess )
{
fOpened = true;
}
else
{
fUnit->close(this);
}
}
else
status = kIOReturnExclusiveAccess;
}
return status;
}
IOReturn IOFireWireAVCUserClient::openWithSessionRef( IOFireWireLib::UserObjectHandle sessionRef, void *, void *, void *, void *, void * )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::openWithSessionRef (this=0x%08X)\n",this));
IOReturn status = kIOReturnSuccess;
IOService * service = NULL;
IOService * original_service = NULL;
if( fOpened || !fUnit->isOpen() )
status = kIOReturnError;
if( status == kIOReturnSuccess )
{
IOFWUserObjectExporter * exporter = fUnit->getDevice()->getBus()->getSessionRefExporter();
original_service = (IOService*) exporter->lookupObjectForType( sessionRef, OSTypeID(IOService) );
if( original_service == NULL )
status = kIOReturnBadArgument;
}
if( status == kIOReturnSuccess )
{
service = original_service;
while( fUnit != service && service != NULL )
service = service->getProvider();
if( service == NULL )
status = kIOReturnBadArgument;
}
if( original_service )
{
original_service->release();
original_service = NULL;
}
return status;
}
IOReturn IOFireWireAVCUserClient::getSessionRef( uint64_t * sessionRef, void *, void *, void *, void *, void * )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::getSessionRef (this=0x%08X)\n",this));
IOReturn status = kIOReturnSuccess;
if( !fOpened )
status = kIOReturnError;
if( status == kIOReturnSuccess )
{
*sessionRef = (uint64_t) fSessionRef;
}
return status;
}
IOReturn IOFireWireAVCUserClient::close
( void *, void *, void *, void *, void *, void * )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::close (this=0x%08X)\n",this));
if( fOpened )
{
IOFWUserObjectExporter * exporter = fUnit->getDevice()->getBus()->getSessionRefExporter();
exporter->removeObject( fSessionRef );
fSessionRef = 0;
fUnit->close(this);
fOpened = false;
}
return kIOReturnSuccess;
}
#ifdef kUseAsyncAVCCommandForBlockingAVCCommand
void AVCAsyncCommandCallback(void *pRefCon, IOFireWireAVCAsynchronousCommand *pCommandObject)
{
IOSyncer *fSyncWakeup = (IOSyncer*) pRefCon;
FIRELOG_MSG(("IOFireWireAVCUserClient::AVCAsyncCommandCallback (cmd=0x%08X, state=%d)\n",pCommandObject,pCommandObject->cmdState));
if (!pCommandObject->isPending())
fSyncWakeup->signal(pCommandObject->cmdState);
}
#endif
IOReturn IOFireWireAVCUserClient::AVCCommand(UInt8 * cmd, UInt8 * response,
UInt32 len, UInt32 *size)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::AVCCommand (this=0x%08X)\n",this));
IOReturn res;
if(!fStarted )
return kIOReturnNoDevice;
#ifndef kUseAsyncAVCCommandForBlockingAVCCommand
res = fUnit->AVCCommand(cmd,len,response,size);
return res;
#else
IOSyncer *fSyncWakeup;
UInt32 responseLen;
IOTakeLock(avcCmdLock);
if (pCommandObject)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::AVCCommand ERROR: pCommandObject is not NULL!\n"));
return kIOReturnError;
}
fSyncWakeup = IOSyncer::create();
if(!fSyncWakeup)
{
IOUnlock(avcCmdLock);
return kIOReturnNoMemory;
}
pCommandObject = new IOFireWireAVCAsynchronousCommand;
if (pCommandObject)
{
res = pCommandObject->init(cmd,len,AVCAsyncCommandCallback,fSyncWakeup);
if (res == kIOReturnSuccess)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::AVCCommand createAVCAsynchronousCommand successful, cmd=0x%08X\n",pCommandObject));
res = pCommandObject->submit(fUnit);
if (res == kIOReturnSuccess)
{
res = fSyncWakeup->wait();
FIRELOG_MSG(("IOFireWireAVCUserClient::AVCCommand continuing after receiving async command complete notification(this=0x%08X)\n",this));
if ((pCommandObject->cmdState == kAVCAsyncCommandStateReceivedFinalResponse) &&
(pCommandObject->pFinalResponseBuf != NULL))
{
if (pCommandObject->finalResponseLen > *size)
responseLen = *size;
else
responseLen = pCommandObject->finalResponseLen;
bcopy(pCommandObject->pFinalResponseBuf, response, responseLen);
*size = responseLen;
res = kIOReturnSuccess;
}
else
{
res = kIOReturnError; }
}
}
else
{
}
pCommandObject->release();
pCommandObject = NULL;
}
IOUnlock(avcCmdLock);
return res;
#endif
}
IOReturn IOFireWireAVCUserClient::AVCCommandInGen(UInt8 * cmd, UInt8 * response,
UInt32 len, UInt32 *size)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::AVCCommandInGen (this=0x%08X)\n",this));
IOReturn res;
UInt32 generation;
generation = *(UInt32 *)cmd;
cmd += sizeof(UInt32);
len -= sizeof(UInt32);
if(!fStarted )
return kIOReturnNoDevice;
res = fUnit->AVCCommandInGeneration(generation,cmd,len,response,size);
return res;
}
IOReturn IOFireWireAVCUserClient::updateAVCCommandTimeout
( void *, void *, void *, void *, void *, void * )
{
FIRELOG_MSG(("IOFireWireAVCUserClient::updateAVCCommandTimeout (this=0x%08X)\n",this));
if(!fStarted )
return kIOReturnNoDevice;
fUnit->updateAVCCommandTimeout();
return kIOReturnSuccess;
}
IOReturn IOFireWireAVCUserClient::updateP2PCount(UInt32 addr, SInt32 inc, bool failOnBusReset, UInt32 chan, IOFWSpeed speed)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::updateP2PCount (this=0x%08X)\n",this));
if(!fStarted )
return kIOReturnNoDevice;
IOFireWireNub *device = fUnit->getDevice();
FWAddress plugAddr(kCSRRegisterSpaceBaseAddressHi, addr);
IOFWReadQuadCommand *readCmd;
IOFWCompareAndSwapCommand *lockCmd;
UInt32 plugVal, newVal;
UInt32 plugValHost, newValHost;
UInt32 curCount;
UInt32 curChan;
IOFWSpeed curSpeed;
IOReturn res;
readCmd = device->createReadQuadCommand(plugAddr, &plugVal, 1, NULL, NULL, failOnBusReset);
res = readCmd->submit();
readCmd->release();
if(res != kIOReturnSuccess)
return res;
plugValHost = OSSwapBigToHostInt32( plugVal );
for(int i=0; i<4; i++) {
bool success;
curCount = ((plugValHost & kIOFWPCRP2PCount) >> 24);
curChan = ((plugValHost & kIOFWPCRChannel) >> 16);
curSpeed = (IOFWSpeed)((plugValHost & kIOFWPCROutputDataRate) >> 14);
newValHost = plugValHost;
if (chan != 0xFFFFFFFF)
{
if ((curCount != 0) && (chan != curChan))
return kIOReturnError;
newValHost &= ~kIOFWPCRChannel;
newValHost |= ((chan & 0x3F) << 16);
}
if (speed != kFWSpeedInvalid)
{
if ((curCount != 0) && (speed != curSpeed))
return kIOReturnError;
newValHost &= ~kIOFWPCROutputDataRate;
newValHost |= ((speed & 0x03) << 14);
}
newValHost &= ~kIOFWPCRP2PCount;
if (inc > 0)
{
if (curCount == 0x3F)
return kIOReturnError;
newValHost |= ((curCount+1) << 24);
}
else
{
if (curCount == 0)
return kIOReturnError;
newValHost |= ((curCount-1) << 24);
}
newVal = OSSwapHostToBigInt32( newValHost );
lockCmd = device->createCompareAndSwapCommand(plugAddr, &plugVal, &newVal, 1);
res = lockCmd->submit();
success = lockCmd->locked(&plugVal);
plugValHost = OSSwapBigToHostInt32( plugVal );
lockCmd->release();
if(res != kIOReturnSuccess)
break;
if(success)
break;
}
return res;
}
IOReturn IOFireWireAVCUserClient::makeConnection(UInt32 addr, UInt32 chan, IOFWSpeed speed)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::makeConnection (this=0x%08X)\n",this));
IOReturn err;
IOFireWireAVCConnection *connection;
connection = new IOFireWireAVCConnection;
if(!connection)
return kIOReturnNoMemory;
err = updateP2PCount(addr, 1, false, chan, speed);
if(kIOReturnSuccess == err) {
connection->fPlugAddr = addr;
connection->fChannel = chan;
fConnections->setObject(connection);
}
connection->release();
return err;
}
void IOFireWireAVCUserClient::breakConnection(UInt32 addr)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::breakConnection (this=0x%08X)\n",this));
UInt32 i;
for(i=0; i<fConnections->getCount(); i++) {
IOFireWireAVCConnection *connection;
connection = (IOFireWireAVCConnection *)fConnections->getObject(i);
if(connection->fPlugAddr == addr) {
updateP2PCount(addr, -1, false, 0xFFFFFFFF, kFWSpeedInvalid);
fConnections->removeObject(i);
break;
}
}
}
IOReturn IOFireWireAVCUserClient::makeP2PInputConnection( UInt32 plugNo, UInt32 chan, void *, void *, void *, void *)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::makeP2PInputConnection (this=0x%08X)\n",this));
return makeConnection(kPCRBaseAddress+0x84+4*plugNo, chan, kFWSpeedInvalid);
}
IOReturn IOFireWireAVCUserClient::breakP2PInputConnection( UInt32 plugNo, void *, void *, void *, void *, void *)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::breakP2PInputConnection (this=0x%08X)\n",this));
breakConnection(kPCRBaseAddress+0x84+4*plugNo);
return kIOReturnSuccess;
}
IOReturn IOFireWireAVCUserClient::makeP2POutputConnection( UInt32 plugNo, UInt32 chan, IOFWSpeed speed, void *, void *, void *)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::makeP2POutputConnection (this=0x%08X)\n",this));
return makeConnection(kPCRBaseAddress+4+4*plugNo, chan, speed);
}
IOReturn IOFireWireAVCUserClient::breakP2POutputConnection( UInt32 plugNo, void *, void *, void *, void *, void *)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::breakP2POutputConnection (this=0x%08X)\n",this));
breakConnection(kPCRBaseAddress+4+4*plugNo);
return kIOReturnSuccess;
}
IOReturn IOFireWireAVCUserClient::message(UInt32 type, IOService *provider, void *argument)
{
if( fStarted == true && type == kIOMessageServiceIsResumed ) {
retain(); thread_t thread;
if( kernel_thread_start((thread_continue_t)remakeConnections, this, &thread ) == KERN_SUCCESS )
{
thread_deallocate(thread);
}
}
return kIOReturnSuccess;
}
void IOFireWireAVCUserClient::remakeConnections(void *arg)
{
IOFireWireAVCUserClient *me = (IOFireWireAVCUserClient *)arg;
FIRELOG_MSG(("IOFireWireAVCUserClient::remakeConnections (this=0x%08X)\n",me));
UInt32 i;
IOReturn res;
for(i=0; i<me->fConnections->getCount(); i++) {
IOFireWireAVCConnection *connection;
connection = (IOFireWireAVCConnection *)me->fConnections->getObject(i);
res = me->updateP2PCount(connection->fPlugAddr, 1, true, connection->fChannel, kFWSpeedInvalid);
if(res == kIOFireWireBusReset)
break;
}
me->release();
}
IOReturn IOFireWireAVCUserClient::installUserLibAsyncAVCCommandCallback(io_user_reference_t *asyncRef, uint64_t userRefcon, uint64_t *returnParam)
{
FIRELOG_MSG(("IOFireWireAVCUserClient::installUserLibAsyncAVCCommandCallback (this=0x%08X, userRefcon=0x%08X)\n",this,userRefcon));
bcopy(asyncRef,fAsyncAVCCmdCallbackInfo,sizeof(OSAsyncReference64));
*returnParam = 0x12345678;
return kIOReturnSuccess;
}
IOReturn IOFireWireAVCUserClient::CreateAVCAsyncCommand(UInt8 * cmd, UInt8 * asyncAVCCommandHandle, UInt32 len, UInt32 *refSize)
{
IOReturn res = kIOReturnNoMemory;
UInt32 *pReturnedCommandHandle = (UInt32*) asyncAVCCommandHandle;
UInt32 cmdLen = len - sizeof(mach_vm_address_t);
mach_vm_address_t *ppSharedBufAddress = (mach_vm_address_t*) &cmd[cmdLen];
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand;
bool memDescPrepared = false;
FIRELOG_MSG(("IOFireWireAVCUserClient::CreateAVCAsyncCommand (this=0x%08X)\n",this));
if(!fStarted )
return kIOReturnNoDevice;
do
{
pUCAsyncCommand = new IOFireWireAVCUserClientAsyncCommand;
if (!pUCAsyncCommand)
break;
pUCAsyncCommand->pUserClient = this;
pUCAsyncCommand->fMem = IOMemoryDescriptor::withAddressRange( *ppSharedBufAddress, 1024, kIODirectionInOut, fTask ) ;
if (!pUCAsyncCommand->fMem)
break;
res = pUCAsyncCommand->fMem->prepare() ;
if (res != kIOReturnSuccess)
break;
else
memDescPrepared = true;
pUCAsyncCommand->pAsyncCommand = new IOFireWireAVCAsynchronousCommand;
if (!pUCAsyncCommand->pAsyncCommand)
{
res = kIOReturnNoMemory;
break;
}
res = pUCAsyncCommand->pAsyncCommand->init(cmd,cmdLen,AVCUserClientAsyncCommandCallback,pUCAsyncCommand);
if (res != kIOReturnSuccess)
break;
}while(0);
if (res == kIOReturnSuccess)
{
IOTakeLock(fAsyncAVCCmdLock);
pUCAsyncCommand->commandIdentifierHandle = fNextAVCAsyncCommandHandle++;
fUCAsyncCommands->setObject(pUCAsyncCommand);
IOUnlock(fAsyncAVCCmdLock);
pUCAsyncCommand->release();
*pReturnedCommandHandle = pUCAsyncCommand->commandIdentifierHandle;
}
else
{
*pReturnedCommandHandle = 0xFFFFFFFF;
if (pUCAsyncCommand)
{
if (pUCAsyncCommand->fMem)
{
if (memDescPrepared == true)
pUCAsyncCommand->fMem->complete();
pUCAsyncCommand->fMem->release() ;
}
if (pUCAsyncCommand->pAsyncCommand)
pUCAsyncCommand->pAsyncCommand->release();
pUCAsyncCommand->release();
}
}
return res;
}
IOReturn IOFireWireAVCUserClient::SubmitAVCAsyncCommand(UInt32 commandHandle)
{
IOReturn res = kIOReturnBadArgument;
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand;
FIRELOG_MSG(("IOFireWireAVCUserClient::SubmitAVCAsyncCommand (this=0x%08X)\n",this));
pUCAsyncCommand = FindUCAsyncCommandWithHandle(commandHandle);
if (pUCAsyncCommand)
{
res = pUCAsyncCommand->pAsyncCommand->submit(fUnit);
}
return res;
}
IOReturn IOFireWireAVCUserClient::CancelAVCAsyncCommand(UInt32 commandHandle)
{
IOReturn res = kIOReturnBadArgument;
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand;
FIRELOG_MSG(("IOFireWireAVCUserClient::CancelAVCAsyncCommand (this=0x%08X)\n",this));
pUCAsyncCommand = FindUCAsyncCommandWithHandle(commandHandle);
if (pUCAsyncCommand)
res = pUCAsyncCommand->pAsyncCommand->cancel();
return res;
}
IOReturn IOFireWireAVCUserClient::ReleaseAVCAsyncCommand(UInt32 commandHandle)
{
IOReturn res = kIOReturnBadArgument;
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand;
bool found = false;
UInt32 i;
FIRELOG_MSG(("IOFireWireAVCUserClient::ReleaseAVCAsyncCommand (this=0x%08X)\n",this));
IOTakeLock(fAsyncAVCCmdLock);
for(i=0; i<fUCAsyncCommands->getCount(); i++)
{
pUCAsyncCommand = (IOFireWireAVCUserClientAsyncCommand *)fUCAsyncCommands->getObject(i);
if (pUCAsyncCommand->commandIdentifierHandle == commandHandle)
{
found = true;
break;
}
}
if (found == true)
{
pUCAsyncCommand->pAsyncCommand->cancel(); pUCAsyncCommand->pAsyncCommand->release();
pUCAsyncCommand->fMem->complete();
pUCAsyncCommand->fMem->release() ;
fUCAsyncCommands->removeObject(i);
res = kIOReturnSuccess;
}
IOUnlock(fAsyncAVCCmdLock);
return res;
}
IOReturn IOFireWireAVCUserClient::ReinitAVCAsyncCommand(UInt32 commandHandle, const UInt8 *pCommandBytes, UInt32 len)
{
IOReturn res = kIOReturnBadArgument;
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand;
FIRELOG_MSG(("IOFireWireAVCUserClient::CancelAVCAsyncCommand (this=0x%08X)\n",this));
pUCAsyncCommand = FindUCAsyncCommandWithHandle(commandHandle);
if (pUCAsyncCommand)
res = pUCAsyncCommand->pAsyncCommand->reinit(pCommandBytes, len);
return res;
}
IOFireWireAVCUserClientAsyncCommand *IOFireWireAVCUserClient::FindUCAsyncCommandWithHandle(UInt32 commandHandle)
{
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand;
bool found = false;
UInt32 i;
FIRELOG_MSG(("IOFireWireAVCUserClient::FindUCAsyncCommandWithHandle (this=0x%08X)\n",this));
IOTakeLock(fAsyncAVCCmdLock);
for(i=0; i<fUCAsyncCommands->getCount(); i++)
{
pUCAsyncCommand = (IOFireWireAVCUserClientAsyncCommand *)fUCAsyncCommands->getObject(i);
if (pUCAsyncCommand->commandIdentifierHandle == commandHandle)
{
found = true;
break;
}
}
IOUnlock(fAsyncAVCCmdLock);
if (found == true)
return pUCAsyncCommand;
else
return NULL;
}
void IOFireWireAVCUserClient::HandleUCAsyncCommandCallback(IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand)
{
UInt32 respLen;
io_user_reference_t args[kMaxAsyncArgs];
OSAsyncReference64 asyncRef;
FIRELOG_MSG(("IOFireWireAVCUserClient::HandleUCAsyncCommandCallback (this=0x%08X)\n",this));
bcopy(fAsyncAVCCmdCallbackInfo, asyncRef, kOSAsyncRef64Size);
switch(pUCAsyncCommand->pAsyncCommand->cmdState)
{
case kAVCAsyncCommandStateReceivedInterimResponse:
pUCAsyncCommand->fMem->writeBytes(kAsyncCmdSharedBufInterimRespOffset,
pUCAsyncCommand->pAsyncCommand->pInterimResponseBuf,
pUCAsyncCommand->pAsyncCommand->interimResponseLen);
respLen = pUCAsyncCommand->pAsyncCommand->interimResponseLen;
break;
case kAVCAsyncCommandStateReceivedFinalResponse:
pUCAsyncCommand->fMem->writeBytes(kAsyncCmdSharedBufFinalRespOffset,
pUCAsyncCommand->pAsyncCommand->pFinalResponseBuf,
pUCAsyncCommand->pAsyncCommand->finalResponseLen);
respLen = pUCAsyncCommand->pAsyncCommand->finalResponseLen;
break;
case kAVCAsyncCommandStatePendingRequest:
case kAVCAsyncCommandStateRequestSent:
case kAVCAsyncCommandStateRequestFailed:
case kAVCAsyncCommandStateWaitingForResponse:
case kAVCAsyncCommandStateTimeOutBeforeResponse:
case kAVCAsyncCommandStateBusReset:
case kAVCAsyncCommandStateOutOfMemory:
case kAVCAsyncCommandStateCanceled:
default:
respLen = 0;
break;
}
args[0] = (io_user_reference_t) pUCAsyncCommand->commandIdentifierHandle;
args[1] = (io_user_reference_t) pUCAsyncCommand->pAsyncCommand->cmdState;
args[2] = (io_user_reference_t) respLen;
sendAsyncResult64(asyncRef, kIOReturnSuccess, args, 3);
}
void AVCUserClientAsyncCommandCallback(void *pRefCon, IOFireWireAVCAsynchronousCommand *pCommandObject)
{
IOFireWireAVCUserClientAsyncCommand *pUCAsyncCommand = (IOFireWireAVCUserClientAsyncCommand*) pRefCon;
FIRELOG_MSG(("AVCUserClientAsyncCommandCallback (pCommandObject=0x%08X)\n",pCommandObject));
pUCAsyncCommand->pUserClient->HandleUCAsyncCommandCallback(pUCAsyncCommand);
}