IOFireWireAVCLibProtocol.c [plain text]
#include <stdlib.h>
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/avc/IOFireWireAVCLib.h>
#include "IOFireWireAVCUserClientCommon.h"
#include <IOKit/avc/IOFireWireAVCConsts.h>
#include <mach/mach_port.h>
#import <System/libkern/OSCrossEndian.h>
#include <syslog.h> // Debug messages
__BEGIN_DECLS
#include <IOKit/iokitmig.h>
__END_DECLS
#define FWLOG printf
struct _AVCProtocol;
typedef struct _InterfaceMap
{
IUnknownVTbl *pseudoVTable;
struct _AVCProtocol *obj;
} InterfaceMap;
typedef struct _AVCProtocol
{
InterfaceMap fIOCFPlugInInterface;
InterfaceMap fIOFireWireAVCLibProtocolInterface;
CFUUIDRef fFactoryId;
UInt32 fRefCount;
io_service_t fService;
io_connect_t fConnection;
mach_port_t fAsyncPort;
CFRunLoopRef fCFRunLoop;
CFRunLoopSourceRef fCFRunLoopSource;
CFMachPortRef fCFAsyncPort;
IONotificationPortRef fNotifyPort;
io_object_t fNotification;
IOFWAVCMessageCallback fMessageCallbackRoutine;
void * fMessageCallbackRefCon;
IOFWAVCRequestCallback fAVCRequestCallbackRoutine;
void * fAVCRequestCallbackRefCon;
UInt32 fCmdLen;
UInt32 fCmdGeneration;
UInt32 fCmdSource;
UInt8 fCommand[512];
IOFWAVCCommandHandlerCallback userCallBack;
void *userRefCon;
IOFWSpeed speed;
UInt32 handlerSearchIndex;
} AVCProtocol;
#define getThis( self ) \
(((InterfaceMap *) self)->obj)
static IOReturn stop( void * self );
static void removeIODispatcherFromRunLoop( void * self );
static IOReturn sendAVCResponse(void *self,
UInt32 generation,
UInt16 nodeID,
const char *response,
UInt32 responseLen);
IOReturn setSubunitPlugSignalFormat(void *self,
UInt32 subunitTypeAndID,
IOFWAVCPlugTypes plugType,
UInt32 plugNum,
UInt32 signalFormat);
static void messageCallback(void * refcon, io_service_t service,
natural_t messageType, void *messageArgument)
{
AVCProtocol *me = (AVCProtocol *)refcon;
if( me->fMessageCallbackRoutine != NULL )
(me->fMessageCallbackRoutine)( me->fMessageCallbackRefCon, messageType, messageArgument );
}
static void avcCommandHandlerCallback( void *refcon, IOReturn result, io_user_reference_t *args, int numArgs)
{
AVCProtocol *me = (AVCProtocol *)refcon;
UInt32 pos;
UInt32 len;
const UInt8* src;
UInt32 fixedArgs[kMaxAsyncArgs];
UInt32 i;
uint64_t inArg[4];
uint32_t outputScalarCnt = 0;
size_t outputStructSize = 0;
IF_ROSETTA()
{
for (i=0;i<numArgs;i++)
fixedArgs[i] = (OSSwapInt32(args[i]) & 0xFFFFFFFF);
}
else
{
for (i=0;i<numArgs;i++)
fixedArgs[i] = (args[i] & 0xFFFFFFFF);
}
pos = args[0] & 0xFFFFFFFF;
len = args[1] & 0xFFFFFFFF;
src = (const UInt8*)(fixedArgs+2);
if(pos == 0)
{
me->fCmdGeneration = args[2] & 0xFFFFFFFF;
me->fCmdSource = args[3] & 0xFFFFFFFF;;
me->fCmdLen = args[4] & 0xFFFFFFFF;
me->userCallBack = (IOFWAVCCommandHandlerCallback) ((unsigned long)args[5]);
me->userRefCon = (void*) ((unsigned long)args[6]);
me->speed = (IOFWSpeed) args[7] & 0xFFFFFFFF;
me->handlerSearchIndex = args[8] & 0xFFFFFFFF;
src = (const UInt8*)(fixedArgs+9);
}
bcopy(src, me->fCommand+pos, len);
if(pos+len == me->fCmdLen)
{
IOReturn status;
status = me->userCallBack(me->userRefCon, me->fCmdGeneration, me->fCmdSource, me->speed, me->fCommand , me->fCmdLen);
if (status != kIOReturnSuccess)
{
inArg[0] = me->fCmdGeneration;
inArg[1] = me->fCmdSource;
inArg[2] = me->speed;
inArg[3] = me->handlerSearchIndex;
IOConnectCallMethod(me->fConnection,
kIOFWAVCProtocolUserClientAVCRequestNotHandled,
inArg,
4,
me->fCommand,
me->fCmdLen,
NULL,
&outputScalarCnt,
NULL,
&outputStructSize);
}
}
}
static void subunitPlugHandlerCallback( void *refcon, IOReturn result, io_user_reference_t *args, int numArgs)
{
AVCProtocol *me = (AVCProtocol *)refcon;
IOFWAVCSubunitPlugHandlerCallback userCallBack;
void *userRefCon;
IOReturn status;
IOFWAVCSubunitPlugMessages plugMessage = (IOFWAVCSubunitPlugMessages)args[3];
UInt32 generation = args[7] & 0xFFFFFFFF;
UInt32 nodeID = args[8] & 0xFFFFFFFF;
UInt8 response[8];
IOFWAVCPlugTypes plugType = (IOFWAVCPlugTypes) args[1] & 0xFFFFFFFF;
UInt32 plugNum = args[2] & 0xFFFFFFFF;
UInt32 msgParams = args[4] & 0xFFFFFFFF;
UInt32 subunitTypeAndID = args[0] & 0xFFFFFFFF;
userCallBack = (IOFWAVCSubunitPlugHandlerCallback) ((unsigned long)args[5]);
userRefCon = (void*) ((unsigned long)args[6]);
status = userCallBack(userRefCon,subunitTypeAndID,plugType,plugNum,plugMessage,msgParams);
if (plugMessage == kIOFWAVCSubunitPlugMsgSignalFormatModified)
{
response[kAVCCommandResponse] = (status == kIOReturnSuccess) ? kAVCAcceptedStatus : kAVCRejectedStatus;
response[kAVCAddress] = kAVCUnitAddress;
response[kAVCOpcode] = (plugType == IOFWAVCPlugSubunitSourceType) ? kAVCOutputPlugSignalFormatOpcode : kAVCInputPlugSignalFormatOpcode;
response[kAVCOperand0] = plugNum;
response[kAVCOperand1] = ((msgParams & 0xFF000000) >> 24);
response[kAVCOperand2] = ((msgParams & 0x00FF0000) >> 16);
response[kAVCOperand3] = ((msgParams & 0x0000FF00) >> 8);
response[kAVCOperand4] = (msgParams & 0x000000FF);
sendAVCResponse(me,generation,(UInt16) nodeID,(const char *)response,8);
if (status == kIOReturnSuccess)
setSubunitPlugSignalFormat(me,subunitTypeAndID,plugType,plugNum,msgParams);
}
return;
}
static void pcrWriteCallback( void *refcon, IOReturn result, io_user_reference_t *args, int numArgs)
{
IOFWAVCPCRCallback func;
func = (IOFWAVCPCRCallback) ((unsigned long)args[0]);
func(refcon, (UInt32)args[1], (UInt16)args[2], (UInt32)args[3], (UInt32)args[4], (UInt32)args[5]);
}
static UInt32 addRef( void * self )
{
AVCProtocol *me = getThis(self);
me->fRefCount++;
return me->fRefCount;
}
static UInt32 release( void * self )
{
AVCProtocol *me = getThis(self);
UInt32 retVal = me->fRefCount;
if( 1 == me->fRefCount-- )
{
removeIODispatcherFromRunLoop(self);
stop(self);
CFPlugInRemoveInstanceForFactory( me->fFactoryId );
CFRelease( me->fFactoryId );
free(me);
}
else if( me->fRefCount < 0 )
{
me->fRefCount = 0;
}
return retVal;
}
static HRESULT queryInterface( void * self, REFIID iid, void **ppv )
{
CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid);
HRESULT result = S_OK;
AVCProtocol *me = getThis(self);
if( CFEqual(uuid, IUnknownUUID) || CFEqual(uuid, kIOCFPlugInInterfaceID) )
{
*ppv = &me->fIOCFPlugInInterface;
addRef(self);
}
else if( CFEqual(uuid, kIOFireWireAVCLibProtocolInterfaceID) )
{
*ppv = &me->fIOFireWireAVCLibProtocolInterface;
addRef(self);
}
else
*ppv = 0;
if( !*ppv )
result = E_NOINTERFACE;
CFRelease( uuid );
return result;
}
static IOReturn probe( void * self, CFDictionaryRef propertyTable,
io_service_t service, SInt32 *order )
{
if( !service || !IOObjectConformsTo(service, "IOFireWireLocalNode") )
return kIOReturnBadArgument;
return kIOReturnSuccess;
}
static IOReturn start( void * self, CFDictionaryRef propertyTable,
io_service_t service )
{
IOReturn status = kIOReturnSuccess;
CFNumberRef guidDesc = 0;
io_iterator_t enumerator = 0;
io_object_t device = 0;
mach_port_t masterDevicePort;
AVCProtocol *me = getThis(self);
CFMutableDictionaryRef dict;
CFMutableDictionaryRef dict2;
me->fService = service;
do {
dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if(!dict)
continue;
dict2 = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if(!dict2)
continue;
CFDictionarySetValue( dict2, CFSTR("IODesiredChild"), CFSTR("IOFireWireAVCProtocolUserClient") );
CFDictionarySetValue( dict, CFSTR("SummonNub"), dict2 );
status = IORegistryEntrySetCFProperties(service, dict );
CFRelease( dict );
CFRelease( dict2 );
guidDesc = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("GUID"), kCFAllocatorDefault, 0);
dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if(!dict)
break;
CFDictionarySetValue( dict, CFSTR(kIOProviderClassKey), CFSTR("IOFireWireAVCProtocolUserClient"));
status = IOMasterPort(bootstrap_port, & masterDevicePort) ;
if ( status != kIOReturnSuccess ) {
break;
}
status = IOServiceGetMatchingServices(
masterDevicePort,
dict,
& enumerator );
if( kIOReturnSuccess != status ) {
break;
}
while(device = IOIteratorNext(enumerator)) {
status = IOServiceOpen( device, mach_task_self(),
kIOFireWireAVCLibConnection, &me->fConnection );
IOObjectRelease(device);
if(kIOReturnSuccess == status)
break;
}
} while(0);
if(guidDesc)
CFRelease(guidDesc);
if (enumerator)
IOObjectRelease(enumerator) ;
if( !me->fConnection )
status = kIOReturnNoDevice;
if( status == kIOReturnSuccess )
{
status = IOCreateReceivePort( kOSAsyncCompleteMessageID, &me->fAsyncPort );
}
return status;
}
static IOReturn stop( void * self )
{
AVCProtocol *me = getThis(self);
if( me->fConnection )
{
IOServiceClose( me->fConnection );
me->fConnection = MACH_PORT_NULL;
}
if( me->fAsyncPort != MACH_PORT_NULL )
{
mach_port_destroy( mach_task_self(), me->fAsyncPort);
me->fAsyncPort = MACH_PORT_NULL;
}
return kIOReturnSuccess;
}
static IOReturn addIODispatcherToRunLoop( void *self, CFRunLoopRef cfRunLoopRef )
{
AVCProtocol *me = getThis(self);
IOReturn status = kIOReturnSuccess;
mach_port_t masterDevicePort;
IONotificationPortRef notifyPort;
CFRunLoopSourceRef cfSource;
if( !me->fConnection )
return kIOReturnNoDevice;
status = IOMasterPort(bootstrap_port, &masterDevicePort) ;
notifyPort = IONotificationPortCreate(masterDevicePort);
cfSource = IONotificationPortGetRunLoopSource(notifyPort);
CFRunLoopAddSource(cfRunLoopRef, cfSource, kCFRunLoopDefaultMode);
status = IOServiceAddInterestNotification(notifyPort, me->fService,
kIOGeneralInterest, messageCallback, me,
&me->fNotification);
me->fCFRunLoop = cfRunLoopRef;
me->fNotifyPort = notifyPort;
if( status == kIOReturnSuccess )
{
CFMachPortContext context;
Boolean shouldFreeInfo;
context.version = 1;
context.info = me;
context.retain = NULL;
context.release = NULL;
context.copyDescription = NULL;
me->fCFAsyncPort = CFMachPortCreateWithPort( kCFAllocatorDefault, me->fAsyncPort,
(CFMachPortCallBack) IODispatchCalloutFromMessage,
&context, &shouldFreeInfo );
if( !me->fCFAsyncPort )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
me->fCFRunLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, me->fCFAsyncPort, 0 );
if( !me->fCFRunLoopSource )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
CFRunLoopAddSource(cfRunLoopRef, me->fCFRunLoopSource, kCFRunLoopDefaultMode );
}
return status;
}
static void removeIODispatcherFromRunLoop( void * self )
{
AVCProtocol *me = getThis(self);
if( me->fNotification )
{
IOObjectRelease(me->fNotification);
me->fNotification = (io_object_t)0;
}
if( me->fNotifyPort )
{
CFRunLoopRemoveSource( me->fCFRunLoop,
IONotificationPortGetRunLoopSource(me->fNotifyPort), kCFRunLoopDefaultMode );
IONotificationPortDestroy(me->fNotifyPort);
me->fNotifyPort = NULL;
}
if(me->fCFRunLoopSource) {
CFRunLoopRemoveSource( me->fCFRunLoop,
me->fCFRunLoopSource, kCFRunLoopDefaultMode );
CFRelease(me->fCFRunLoopSource);
me->fCFRunLoopSource = NULL;
}
if( me->fCFAsyncPort != NULL ) {
CFMachPortInvalidate(me->fCFAsyncPort);
CFRelease( me->fCFAsyncPort );
me->fCFAsyncPort = NULL;
}
}
static void setMessageCallback( void * self, void * refCon,
IOFWAVCMessageCallback callback )
{
AVCProtocol *me = getThis(self);
me->fMessageCallbackRoutine = callback;
me->fMessageCallbackRefCon = refCon;
}
static IOReturn setAVCRequestCallback( void *self, UInt32 subUnitType, UInt32 subUnitID,
void *refCon, IOFWAVCRequestCallback callback)
{
return kIOReturnUnsupported;
}
static IOReturn allocateInputPlug( void *self, void *refcon, IOFWAVCPCRCallback func, UInt32 *plug)
{
AVCProtocol *me = getThis(self);
uint64_t params;
IOReturn status;
uint64_t refrncData[kOSAsyncRef64Count];
uint32_t outputCnt = 1;
uint64_t returnVal;
refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)&pcrWriteCallback;
refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)refcon;
params = (unsigned long)func;
const uint64_t inputs[1]={(const uint64_t)params};
status = IOConnectCallAsyncScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientAllocateInputPlug,
me->fAsyncPort,
refrncData,kOSAsyncRef64Count,
inputs, 1,
&returnVal,&outputCnt);
*plug = returnVal & 0xFFFFFFFF;
return status;
}
static void freeInputPlug( void *self, UInt32 plug)
{
AVCProtocol *me = getThis(self);
uint32_t outputCnt = 0;
const uint64_t inArg = plug;
const uint64_t inputs[1]={(const uint64_t)inArg};
IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientFreeInputPlug,
inputs,
1,
NULL,
&outputCnt);
}
static UInt32 readInputPlug( void *self, UInt32 plug)
{
AVCProtocol *me = getThis(self);
UInt32 val;
const uint64_t inArg = plug;
uint32_t outputCnt = 1;
uint64_t outputVal = 0;
const uint64_t inputs[1]={(const uint64_t)inArg};
IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientReadInputPlug,
inputs,
1,
&outputVal,
&outputCnt);
val = outputVal & 0xFFFFFFFF;
return val;
}
static IOReturn updateInputPlug( void *self, UInt32 plug, UInt32 oldVal, UInt32 newVal)
{
AVCProtocol *me = getThis(self);
uint64_t inArg[3];
uint32_t outputCnt = 0;
inArg[0] = plug;
inArg[1] = oldVal;
inArg[2] = newVal;
return IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientUpdateInputPlug,
inArg,
3,
NULL,
&outputCnt);
}
static IOReturn allocateOutputPlug( void *self, void *refcon, IOFWAVCPCRCallback func, UInt32 *plug)
{
AVCProtocol *me = getThis(self);
uint64_t params;
IOReturn status;
uint64_t refrncData[kOSAsyncRef64Count];
uint32_t outputCnt = 1;
uint64_t returnVal;
refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)pcrWriteCallback;
refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)refcon;
params = (unsigned long)func;
const uint64_t inputs[1]={(const uint64_t)params};
status = IOConnectCallAsyncScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientAllocateOutputPlug,
me->fAsyncPort,
refrncData,kOSAsyncRef64Count,
inputs, 1,
&returnVal,&outputCnt);
*plug = returnVal & 0xFFFFFFFF;
return status;
}
static void freeOutputPlug( void *self, UInt32 plug)
{
AVCProtocol *me = getThis(self);
uint32_t outputCnt = 0;
const uint64_t inArg = plug;
const uint64_t inputs[1]={(const uint64_t)inArg};
IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientFreeOutputPlug,
inputs,
1,
NULL,
&outputCnt);
}
static UInt32 readOutputPlug( void *self, UInt32 plug)
{
AVCProtocol *me = getThis(self);
UInt32 val;
const uint64_t inArg = plug;
uint32_t outputCnt = 1;
uint64_t outputVal = 0;
const uint64_t inputs[1]={(const uint64_t)inArg};
IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientReadOutputPlug,
inputs,
1,
&outputVal,
&outputCnt);
val = outputVal & 0xFFFFFFFF;
return val;
}
static IOReturn updateOutputPlug( void *self, UInt32 plug, UInt32 oldVal, UInt32 newVal)
{
AVCProtocol *me = getThis(self);
uint64_t inArg[3];
uint32_t outputCnt = 0;
inArg[0] = plug;
inArg[1] = oldVal;
inArg[2] = newVal;
return IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientUpdateOutputPlug,
inArg,
3,
NULL,
&outputCnt);
}
static UInt32 readOutputMasterPlug( void *self)
{
AVCProtocol *me = getThis(self);
UInt32 val;
uint32_t outputCnt = 1;
uint64_t outputVal = 0;
IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientReadOutputMasterPlug,
NULL,
0,
&outputVal,
&outputCnt);
val = outputVal & 0xFFFFFFFF;
return val;
}
static IOReturn updateOutputMasterPlug( void *self, UInt32 oldVal, UInt32 newVal)
{
AVCProtocol *me = getThis(self);
uint64_t inArg[2];
uint32_t outputCnt = 0;
inArg[0] = oldVal;
inArg[1] = newVal;
return IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientUpdateOutputMasterPlug,
inArg,
2,
NULL,
&outputCnt);
}
static UInt32 readInputMasterPlug( void *self)
{
AVCProtocol *me = getThis(self);
UInt32 val;
uint32_t outputCnt = 1;
uint64_t outputVal = 0;
IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientReadInputMasterPlug,
NULL,
0,
&outputVal,
&outputCnt);
val = outputVal & 0xFFFFFFFF;
return val;
}
static IOReturn updateInputMasterPlug( void *self, UInt32 oldVal, UInt32 newVal)
{
AVCProtocol *me = getThis(self);
uint64_t inArg[2];
uint32_t outputCnt = 0;
inArg[0] = oldVal;
inArg[1] = newVal;
return IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientUpdateInputMasterPlug,
inArg,
2,
NULL,
&outputCnt);
}
static IOReturn publishAVCUnitDirectory(void *self)
{
AVCProtocol *me = getThis(self);
uint32_t outputCnt = 0;
IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientPublishAVCUnitDirectory,
NULL,
0,
NULL,
&outputCnt);
return kIOReturnSuccess;
}
static IOReturn installAVCCommandHandler(void *self,
UInt32 subUnitTypeAndID,
UInt32 opCode,
void *refCon,
IOFWAVCCommandHandlerCallback callback)
{
AVCProtocol *me = getThis(self);
IOReturn status = kIOReturnSuccess;
uint64_t params[4];
uint64_t refrncData[kOSAsyncRef64Count];
uint32_t outputCnt = 0;
refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)avcCommandHandlerCallback;
refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)me;
params[0] = subUnitTypeAndID;
params[1] = opCode;
params[2] = (unsigned long)callback;
params[3] = (unsigned long)refCon;
status = IOConnectCallAsyncScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientInstallAVCCommandHandler,
me->fAsyncPort,
refrncData,kOSAsyncRef64Count,
params, 4,
NULL,&outputCnt);
return status;
}
static IOReturn sendAVCResponse(void *self,
UInt32 generation,
UInt16 nodeID,
const char *response,
UInt32 responseLen)
{
AVCProtocol *me = getThis(self);
uint64_t inArg[2];
uint32_t outputScalarCnt = 0;
size_t outputStructSize = 0;
inArg[0] = generation;
inArg[1] = nodeID;
return IOConnectCallMethod(me->fConnection,
kIOFWAVCProtocolUserClientSendAVCResponse,
inArg,
2,
response,
responseLen,
NULL,
&outputScalarCnt,
NULL,
&outputStructSize);
}
IOReturn addSubunit(void *self,
UInt32 subunitType,
UInt32 numSourcePlugs,
UInt32 numDestPlugs,
void *refCon,
IOFWAVCSubunitPlugHandlerCallback callback,
UInt32 *pSubunitTypeAndID)
{
AVCProtocol *me = getThis(self);
IOReturn status = kIOReturnSuccess;
uint64_t params[5];
uint64_t refrncData[kOSAsyncRef64Count];
uint32_t outputCnt = 1;
uint64_t returnVal;
refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)subunitPlugHandlerCallback;
refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)me;
params[0] = subunitType;
params[1] = numSourcePlugs;
params[2] = numDestPlugs;
params[3] = (unsigned long)callback;
params[4] = (unsigned long)refCon;
status = IOConnectCallAsyncScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientAddSubunit,
me->fAsyncPort,
refrncData,kOSAsyncRef64Count,
params, 5,
&returnVal,&outputCnt);
*pSubunitTypeAndID = returnVal & 0xFFFFFFFF;
return status;
}
IOReturn setSubunitPlugSignalFormat(void *self,
UInt32 subunitTypeAndID,
IOFWAVCPlugTypes plugType,
UInt32 plugNum,
UInt32 signalFormat)
{
AVCProtocol *me = getThis(self);
uint64_t inArg[4];
uint32_t outputCnt = 0;
inArg[0] = subunitTypeAndID;
inArg[1] = plugType;
inArg[2] = plugNum;
inArg[3] = signalFormat;
return IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientSetSubunitPlugSignalFormat,
inArg,
4,
NULL,
&outputCnt);
}
IOReturn getSubunitPlugSignalFormat(void *self,
UInt32 subunitTypeAndID,
IOFWAVCPlugTypes plugType,
UInt32 plugNum,
UInt32 *pSignalFormat)
{
AVCProtocol *me = getThis(self);
IOReturn status = kIOReturnSuccess;
uint32_t outputCnt = 1;
uint64_t outputVal = 0;
uint64_t inArg[3];
inArg[0] = subunitTypeAndID;
inArg[1] = plugType;
inArg[2] = plugNum;
status = IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientGetSubunitPlugSignalFormat,
inArg,
3,
&outputVal,
&outputCnt);
*pSignalFormat = outputVal & 0xFFFFFFFF;
return status;
}
IOReturn connectTargetPlugs(void *self,
UInt32 sourceSubunitTypeAndID,
IOFWAVCPlugTypes sourcePlugType,
UInt32 *pSourcePlugNum,
UInt32 destSubunitTypeAndID,
IOFWAVCPlugTypes destPlugType,
UInt32 *pDestPlugNum,
bool lockConnection,
bool permConnection)
{
AVCProtocol *me = getThis(self);
IOReturn status = kIOReturnSuccess;
AVCConnectTargetPlugsInParams inParams;
AVCConnectTargetPlugsOutParams outParams;
size_t outputCnt = sizeof(AVCConnectTargetPlugsOutParams);
inParams.sourceSubunitTypeAndID = sourceSubunitTypeAndID;
inParams.sourcePlugType = sourcePlugType;
inParams.sourcePlugNum = *pSourcePlugNum;
inParams.destSubunitTypeAndID = destSubunitTypeAndID;
inParams.destPlugType = destPlugType;
inParams.destPlugNum = *pDestPlugNum;
inParams.lockConnection = lockConnection;
inParams.permConnection = permConnection;
ROSETTA_ONLY(
{
inParams.sourceSubunitTypeAndID = OSSwapInt32(inParams.sourceSubunitTypeAndID);
inParams.sourcePlugType = OSSwapInt32(inParams.sourcePlugType);
inParams.sourcePlugNum = OSSwapInt32(inParams.sourcePlugNum);
inParams.destSubunitTypeAndID = OSSwapInt32(inParams.destSubunitTypeAndID);
inParams.destPlugType = OSSwapInt32(inParams.destPlugType);
inParams.destPlugNum = OSSwapInt32(inParams.destPlugNum);
}
);
status = IOConnectCallStructMethod(me->fConnection,
kIOFWAVCProtocolUserClientConnectTargetPlugs,
&inParams,
sizeof(AVCConnectTargetPlugsInParams),
&outParams,
&outputCnt);
ROSETTA_ONLY(
{
outParams.sourcePlugNum = OSSwapInt32(outParams.sourcePlugNum);
outParams.destPlugNum = OSSwapInt32(outParams.destPlugNum);
}
);
*pSourcePlugNum = outParams.sourcePlugNum;
*pDestPlugNum = outParams.destPlugNum;
return status;
}
IOReturn disconnectTargetPlugs(void *self,
UInt32 sourceSubunitTypeAndID,
IOFWAVCPlugTypes sourcePlugType,
UInt32 sourcePlugNum,
UInt32 destSubunitTypeAndID,
IOFWAVCPlugTypes destPlugType,
UInt32 destPlugNum)
{
AVCProtocol *me = getThis(self);
uint32_t outputCnt = 0;
uint64_t inArg[6];
inArg[0] = sourceSubunitTypeAndID;
inArg[1] = sourcePlugType;
inArg[2] = sourcePlugNum;
inArg[3] = destSubunitTypeAndID;
inArg[4] = destPlugType;
inArg[5] = destPlugNum;
return IOConnectCallScalarMethod(me->fConnection,
kIOFWAVCProtocolUserClientDisconnectTargetPlugs,
inArg,
6,
NULL,
&outputCnt);
}
IOReturn getTargetPlugConnection(void *self,
UInt32 subunitTypeAndID,
IOFWAVCPlugTypes plugType,
UInt32 plugNum,
UInt32 *pConnectedSubunitTypeAndID,
IOFWAVCPlugTypes *pConnectedPlugType,
UInt32 *pConnectedPlugNum,
bool *pLockConnection,
bool *pPermConnection)
{
AVCProtocol *me = getThis(self);
IOReturn status = kIOReturnSuccess;
AVCGetTargetPlugConnectionInParams inParams;
AVCGetTargetPlugConnectionOutParams outParams;
size_t outputCnt = sizeof(AVCGetTargetPlugConnectionInParams);
inParams.subunitTypeAndID = subunitTypeAndID;
inParams.plugType = plugType;
inParams.plugNum = plugNum;
ROSETTA_ONLY(
{
inParams.subunitTypeAndID = OSSwapInt32(inParams.subunitTypeAndID);
inParams.plugType = OSSwapInt32(inParams.plugType);
inParams.plugNum = OSSwapInt32(inParams.plugNum);
}
);
status = IOConnectCallStructMethod(me->fConnection,
kIOFWAVCProtocolUserClientGetTargetPlugConnection,
&inParams,
sizeof(AVCConnectTargetPlugsInParams),
&outParams,
&outputCnt);
ROSETTA_ONLY(
{
outParams.connectedSubunitTypeAndID = OSSwapInt32(outParams.connectedSubunitTypeAndID);
outParams.connectedPlugType = OSSwapInt32(outParams.connectedPlugType);
outParams.connectedPlugNum = OSSwapInt32(outParams.connectedPlugNum);
}
);
*pConnectedSubunitTypeAndID = outParams.connectedSubunitTypeAndID;
*pConnectedPlugType = outParams.connectedPlugType;
*pConnectedPlugNum = outParams.connectedPlugNum;
*pLockConnection = outParams.lockConnection;
*pPermConnection = outParams.permConnection;
return status;
}
static IOCFPlugInInterface sIOCFPlugInInterface =
{
0,
&queryInterface,
&addRef,
&release,
1, 0, &probe,
&start,
&stop
};
static IOFireWireAVCLibProtocolInterface sProtocolInterface =
{
0,
&queryInterface,
&addRef,
&release,
2, 0, &addIODispatcherToRunLoop,
&removeIODispatcherFromRunLoop,
&setMessageCallback,
&setAVCRequestCallback,
&allocateInputPlug,
&freeInputPlug,
&readInputPlug,
&updateInputPlug,
&allocateOutputPlug,
&freeOutputPlug,
&readOutputPlug,
&updateOutputPlug,
&readOutputMasterPlug,
&updateOutputMasterPlug,
&readInputMasterPlug,
&updateInputMasterPlug,
&publishAVCUnitDirectory,
&installAVCCommandHandler,
&sendAVCResponse,
&addSubunit,
&setSubunitPlugSignalFormat,
&getSubunitPlugSignalFormat,
&connectTargetPlugs,
&disconnectTargetPlugs,
&getTargetPlugConnection
};
static IOCFPlugInInterface ** alloc()
{
IOCFPlugInInterface ** interface = NULL;
AVCProtocol * me;
me = (AVCProtocol *)malloc(sizeof(AVCProtocol));
if( me )
{
bzero(me, sizeof(AVCProtocol));
me->fRefCount = 1;
me->fConnection = MACH_PORT_NULL;
me->fService = MACH_PORT_NULL;
me->fIOCFPlugInInterface.pseudoVTable = (IUnknownVTbl *) &sIOCFPlugInInterface;
me->fIOCFPlugInInterface.obj = me;
me->fIOFireWireAVCLibProtocolInterface.pseudoVTable
= (IUnknownVTbl *) &sProtocolInterface;
me->fIOFireWireAVCLibProtocolInterface.obj = me;
me->fFactoryId = kIOFireWireAVCLibProtocolFactoryID;
CFRetain( me->fFactoryId );
CFPlugInAddInstanceForFactory( me->fFactoryId );
interface = (IOCFPlugInInterface **) &me->fIOCFPlugInInterface.pseudoVTable;
}
return interface;
}
void *IOFireWireAVCLibProtocolFactory( CFAllocatorRef allocator, CFUUIDRef typeID )
{
if( CFEqual(typeID, kIOFireWireAVCLibProtocolTypeID) )
return (void *) alloc();
else
return NULL;
}