IOFireWireSBP2LibLUN.cpp [plain text]
#include <Carbon/Carbon.h> // for printf
#include "FWDebugging.h"
#include "IOFireWireSBP2LibLUN.h"
#include "IOFireWireSBP2LibLogin.h"
#include "IOFireWireSBP2LibMgmtORB.h"
#include "IOFireWireSBP2UserClientCommon.h"
__BEGIN_DECLS
#include <IOKit/iokitmig.h>
__END_DECLS
IOCFPlugInInterface IOFireWireSBP2LibLUN::sIOCFPlugInInterface =
{
0,
&IOFireWireSBP2LibLUN::staticQueryInterface,
&IOFireWireSBP2LibLUN::staticAddRef,
&IOFireWireSBP2LibLUN::staticRelease,
1, 0, &IOFireWireSBP2LibLUN::staticProbe,
&IOFireWireSBP2LibLUN::staticStart,
&IOFireWireSBP2LibLUN::staticStop
};
IOFireWireSBP2LibLUNInterface IOFireWireSBP2LibLUN::sIOFireWireSBP2LibLUNInterface =
{
0,
&IOFireWireSBP2LibLUN::staticQueryInterface,
&IOFireWireSBP2LibLUN::staticAddRef,
&IOFireWireSBP2LibLUN::staticRelease,
1, 0, &IOFireWireSBP2LibLUN::staticOpen,
&IOFireWireSBP2LibLUN::staticOpenWithSessionRef,
&IOFireWireSBP2LibLUN::staticGetSessionRef,
&IOFireWireSBP2LibLUN::staticClose,
&IOFireWireSBP2LibLUN::staticAddIODispatcherToRunLoop,
&IOFireWireSBP2LibLUN::staticRemoveIODispatcherFromRunLoop,
&IOFireWireSBP2LibLUN::staticSetMessageCallback,
&IOFireWireSBP2LibLUN::staticSetRefCon,
&IOFireWireSBP2LibLUN::staticGetRefCon,
&IOFireWireSBP2LibLUN::staticCreateLogin,
&IOFireWireSBP2LibLUN::staticCreateMgmtORB,
};
void *IOFireWireSBP2LibFactory( CFAllocatorRef allocator, CFUUIDRef typeID )
{
FWLOG(( "IOFireWireSBP2LibFactory called\n" ));
if( CFEqual(typeID, kIOFireWireSBP2LibTypeID) )
return (void *) IOFireWireSBP2LibLUN::alloc();
else
return NULL;
}
IOCFPlugInInterface ** IOFireWireSBP2LibLUN::alloc()
{
IOFireWireSBP2LibLUN * me;
IOCFPlugInInterface ** interface = NULL;
me = new IOFireWireSBP2LibLUN;
if( me )
{
me->addRef();
interface = (IOCFPlugInInterface **) &me->fIOCFPlugInInterface.pseudoVTable;
}
return interface;
}
IOFireWireSBP2LibLUN::IOFireWireSBP2LibLUN( void )
{
fRefCount = 0;
fConnection = MACH_PORT_NULL;
fService = MACH_PORT_NULL;
fAsyncPort = MACH_PORT_NULL;
fMessageCallbackRoutine = NULL;
fMessageCallbackRefCon = NULL;
fIOCFPlugInInterface.pseudoVTable = (IUnknownVTbl *) &sIOCFPlugInInterface;
fIOCFPlugInInterface.obj = this;
fIOFireWireSBP2LibLUNInterface.pseudoVTable
= (IUnknownVTbl *) &sIOFireWireSBP2LibLUNInterface;
fIOFireWireSBP2LibLUNInterface.obj = this;
fFactoryId = kIOFireWireSBP2LibFactoryID;
CFRetain( fFactoryId );
CFPlugInAddInstanceForFactory( fFactoryId );
}
IOFireWireSBP2LibLUN::~IOFireWireSBP2LibLUN()
{
CFPlugInRemoveInstanceForFactory( fFactoryId );
CFRelease( fFactoryId );
}
HRESULT IOFireWireSBP2LibLUN::staticQueryInterface( void * self, REFIID iid, void **ppv )
{
return getThis(self)->queryInterface( iid, ppv );
}
HRESULT IOFireWireSBP2LibLUN::queryInterface( REFIID iid, void **ppv )
{
CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid);
HRESULT result = S_OK;
if( CFEqual(uuid, IUnknownUUID) || CFEqual(uuid, kIOCFPlugInInterfaceID) )
{
*ppv = &fIOCFPlugInInterface;
addRef();
}
else if( CFEqual(uuid, kIOFireWireSBP2LibLUNInterfaceID) )
{
*ppv = &fIOFireWireSBP2LibLUNInterface;
addRef();
}
else
*ppv = 0;
if( !*ppv )
result = E_NOINTERFACE;
CFRelease( uuid );
return result;
}
UInt32 IOFireWireSBP2LibLUN::staticAddRef( void * self )
{
return getThis(self)->addRef();
}
UInt32 IOFireWireSBP2LibLUN::addRef()
{
fRefCount += 1;
return fRefCount;
}
UInt32 IOFireWireSBP2LibLUN::staticRelease( void * self )
{
return getThis(self)->release();
}
UInt32 IOFireWireSBP2LibLUN::release( void )
{
UInt32 retVal = fRefCount;
if( 1 == fRefCount-- )
{
delete this;
}
else if( fRefCount < 0 )
{
fRefCount = 0;
}
return retVal;
}
IOReturn IOFireWireSBP2LibLUN::staticProbe( void * self, CFDictionaryRef propertyTable,
io_service_t service, SInt32 *order )
{
return getThis(self)->probe( propertyTable, service, order );
}
IOReturn IOFireWireSBP2LibLUN::probe( CFDictionaryRef propertyTable,
io_service_t service, SInt32 *order )
{
if( !service || !IOObjectConformsTo(service, "IOFireWireSBP2LUN") )
return kIOReturnBadArgument;
return kIOReturnSuccess;
}
IOReturn IOFireWireSBP2LibLUN::staticStart( void * self, CFDictionaryRef propertyTable,
io_service_t service )
{
return getThis(self)->start( propertyTable, service );
}
IOReturn IOFireWireSBP2LibLUN::start( CFDictionaryRef propertyTable, io_service_t service )
{
IOReturn status = kIOReturnSuccess;
FWLOG(( "IOFireWireSBP2LibLUN : start\n" ));
fService = service;
status = IOServiceOpen( fService, mach_task_self(),
kIOFireWireSBP2LibConnection, &fConnection );
if( !fConnection )
status = kIOReturnNoDevice;
if( status == kIOReturnSuccess )
{
status = IOCreateReceivePort( kOSAsyncCompleteMessageID, &fAsyncPort );
}
FWLOG(( "IOFireWireSBP2LibLUN : IOServiceOpen status = 0x%08lx, connection = %d\n", (UInt32) status, fConnection ));
return status;
}
IOReturn IOFireWireSBP2LibLUN::staticStop( void * self )
{
return getThis(self)->stop();
}
IOReturn IOFireWireSBP2LibLUN::stop( void )
{
FWLOG(( "IOFireWireSBP2LibLUN : stop\n" ));
if( fConnection )
{
FWLOG(( "IOFireWireSBP2LibLUN : IOServiceClose connection = %d\n", fConnection ));
IOServiceClose( fConnection );
fConnection = MACH_PORT_NULL;
}
if( fAsyncPort != MACH_PORT_NULL )
{
FWLOG(( "IOFireWireSBP2LibLUN : release asyncPort\n" ));
IOObjectRelease( fAsyncPort );
fAsyncPort = MACH_PORT_NULL;
}
return kIOReturnSuccess;
}
IOReturn IOFireWireSBP2LibLUN::staticOpen( void * self )
{
return getThis(self)->open();
}
IOReturn IOFireWireSBP2LibLUN::open( void )
{
IOReturn status = kIOReturnSuccess;
if( !fConnection )
return kIOReturnNoDevice;
FWLOG(( "IOFireWireSBP2LUN : open\n" ));
mach_msg_type_number_t len = 0;
status = io_connect_method_scalarI_scalarO( fConnection, kIOFWSBP2UserClientOpen,
NULL, 0, NULL, &len );
return status;
}
IOReturn IOFireWireSBP2LibLUN::staticOpenWithSessionRef( void * self, IOFireWireSessionRef sessionRef )
{
return getThis(self)->openWithSessionRef( sessionRef );
}
IOReturn IOFireWireSBP2LibLUN::openWithSessionRef( IOFireWireSessionRef sessionRef )
{
IOReturn status = kIOReturnSuccess;
if( !fConnection )
return kIOReturnNoDevice;
FWLOG(( "IOFireWireSBP2LUN : openWithSessionRef\n" ));
mach_msg_type_number_t len = 0;
status = io_connect_method_scalarI_scalarO( fConnection, kIOFWSBP2UserClientOpenWithSessionRef,
(int*)&sessionRef, 1, NULL, &len );
return status;
}
IOFireWireSessionRef IOFireWireSBP2LibLUN::staticGetSessionRef(void * self)
{
return getThis(self)->getSessionRef();
}
IOFireWireSessionRef IOFireWireSBP2LibLUN::getSessionRef( void )
{
IOReturn status = kIOReturnSuccess;
IOFireWireSessionRef sessionRef = 0;
if( !fConnection )
return sessionRef;
FWLOG(( "IOFireWireSBP2LUN : getSessionRef\n" ));
mach_msg_type_number_t len = 1;
status = io_connect_method_scalarI_scalarO( fConnection, kIOFWSBP2UserClientGetSessionRef,
NULL, 0, (int*)&sessionRef, &len );
if( status != kIOReturnSuccess )
sessionRef = 0;
return sessionRef;
}
void IOFireWireSBP2LibLUN::staticClose( void * self )
{
getThis(self)->close();
}
void IOFireWireSBP2LibLUN::close( void )
{
if( !fConnection )
return;
FWLOG(( "IOFireWireSBP2LUN : close\n" ));
mach_msg_type_number_t len = 0;
io_connect_method_scalarI_scalarO( fConnection, kIOFWSBP2UserClientClose,
NULL, 0, NULL, &len );
}
IOReturn IOFireWireSBP2LibLUN::staticAddIODispatcherToRunLoop( void *self,
CFRunLoopRef cfRunLoopRef )
{
return getThis(self)->addIODispatcherToRunLoop( cfRunLoopRef );
}
IOReturn IOFireWireSBP2LibLUN::addIODispatcherToRunLoop( CFRunLoopRef cfRunLoopRef )
{
IOReturn status = kIOReturnSuccess;
CFMachPortRef cfPort = NULL;
FWLOG(( "IOFireWireSBP2LibLUN : addIODispatcherToRunLoop\n" ));
if( !fConnection )
return kIOReturnNoDevice;
if( status == kIOReturnSuccess )
{
CFMachPortContext context;
Boolean shouldFreeInfo;
context.version = 1;
context.info = this;
context.retain = NULL;
context.release = NULL;
context.copyDescription = NULL;
cfPort = CFMachPortCreateWithPort( kCFAllocatorDefault, fAsyncPort,
(CFMachPortCallBack) IODispatchCalloutFromMessage,
&context, &shouldFreeInfo );
if( !cfPort )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fCFRunLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, cfPort, 0 );
if( !fCFRunLoopSource )
status = kIOReturnNoMemory;
}
if( cfPort != NULL )
CFRelease( cfPort );
if( status == kIOReturnSuccess )
{
fCFRunLoop = cfRunLoopRef;
CFRunLoopAddSource( fCFRunLoop, fCFRunLoopSource, kCFRunLoopDefaultMode );
}
if( fCFRunLoopSource != NULL )
CFRelease( fCFRunLoopSource );
if( status == kIOReturnSuccess )
{
io_async_ref_t asyncRef;
mach_msg_type_number_t size = 0;
io_scalar_inband_t params;
asyncRef[0] = 0;
params[0] = (UInt32)this;
params[1] = (UInt32)(IOAsyncCallback1)&IOFireWireSBP2LibLUN::staticMessageCallback;
status = io_async_method_scalarI_scalarO( fConnection, fAsyncPort,
asyncRef, 1,
kIOFWSBP2UserClientSetMessageCallback,
params, 2,
NULL, &size );
}
return status;
}
void IOFireWireSBP2LibLUN::staticRemoveIODispatcherFromRunLoop( void * self )
{
return getThis(self)->removeIODispatcherFromRunLoop();
}
void IOFireWireSBP2LibLUN::removeIODispatcherFromRunLoop( void )
{
if( fCFRunLoopSource )
{
CFRunLoopRemoveSource( fCFRunLoop, fCFRunLoopSource, kCFRunLoopDefaultMode );
fCFRunLoopSource = NULL;
}
}
void IOFireWireSBP2LibLUN::staticSetMessageCallback( void * self, void * refCon,
IOFWSBP2MessageCallback callback )
{
getThis(self)->setMessageCallback( refCon, callback );
}
void IOFireWireSBP2LibLUN::setMessageCallback( void * refCon,
IOFWSBP2MessageCallback callback )
{
fMessageCallbackRoutine = callback;
fMessageCallbackRefCon = refCon;
}
IUnknownVTbl ** IOFireWireSBP2LibLUN::staticCreateLogin( void * self, REFIID iid )
{
return getThis(self)->createLogin( iid );
}
IUnknownVTbl ** IOFireWireSBP2LibLUN::createLogin( REFIID iid )
{
IOReturn status = kIOReturnSuccess;
IUnknownVTbl ** iunknown = NULL;
if( !fConnection )
status = kIOReturnError;
if( fAsyncPort == MACH_PORT_NULL )
status = kIOReturnError;
if( status == kIOReturnSuccess )
{
iunknown = IOFireWireSBP2LibLogin::alloc( fConnection, fAsyncPort );
if( iunknown == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
HRESULT res;
res = (*iunknown)->QueryInterface( iunknown, iid,
(void **) &fLoginInterface );
if( res != S_OK )
status = kIOReturnError;
}
if( iunknown != NULL )
{
(*iunknown)->Release(iunknown);
}
if( status == kIOReturnSuccess )
return fLoginInterface;
else
return NULL;
}
void IOFireWireSBP2LibLUN::staticSetRefCon( void * self, UInt32 refCon )
{
getThis(self)->setRefCon( refCon );
}
void IOFireWireSBP2LibLUN::setRefCon( UInt32 refCon )
{
fRefCon = refCon;
}
UInt32 IOFireWireSBP2LibLUN::staticGetRefCon( void * self )
{
return getThis(self)->getRefCon();
}
UInt32 IOFireWireSBP2LibLUN::getRefCon( void )
{
return fRefCon;
}
IUnknownVTbl ** IOFireWireSBP2LibLUN::staticCreateMgmtORB( void * self, REFIID iid )
{
return getThis(self)->createMgmtORB( iid );
}
IUnknownVTbl ** IOFireWireSBP2LibLUN::createMgmtORB( REFIID iid )
{
IOReturn status = kIOReturnSuccess;
IUnknownVTbl ** iunknown = NULL;
IUnknownVTbl ** mgmtORB = NULL;
if( !fConnection )
status = kIOReturnError;
if( fAsyncPort == MACH_PORT_NULL )
status = kIOReturnError;
if( status == kIOReturnSuccess )
{
iunknown = IOFireWireSBP2LibMgmtORB::alloc( fConnection, fAsyncPort );
if( iunknown == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
HRESULT res;
res = (*iunknown)->QueryInterface( iunknown, iid,
(void **) &mgmtORB );
if( res != S_OK )
status = kIOReturnError;
}
if( iunknown != NULL )
{
(*iunknown)->Release(iunknown);
}
if( status == kIOReturnSuccess )
return mgmtORB;
else
return NULL;
}
void IOFireWireSBP2LibLUN::staticMessageCallback( void *refcon, IOReturn result,
void **args, int numArgs )
{
((IOFireWireSBP2LibLUN*)refcon)->messageCallback( result, args, numArgs );
}
void IOFireWireSBP2LibLUN::messageCallback( IOReturn result, void **args, int numArgs )
{
FWLOG(( "IOFireWireSBP2LibLUN : messageCallback numArgs = %d\n", numArgs ));
FWSBP2ReconnectParams params;
void * outArgs = NULL;
UInt32 type = (UInt32)args[11];
if( type == kIOMessageFWSBP2ReconnectComplete ||
type == kIOMessageFWSBP2ReconnectFailed )
{
UInt32 statusBlock[8];
bcopy( &args[3], statusBlock, 8 * sizeof(UInt32) );
params.refCon = (void*)fRefCon;
params.generation = (UInt32)args[0];
params.status = (IOReturn)args[1];
params.reconnectStatusBlock = (FWSBP2StatusBlock*)&statusBlock;
params.reconnectStatusBlockLength = (UInt32)args[2];
outArgs = ¶ms;
}
if( fMessageCallbackRoutine != NULL )
(fMessageCallbackRoutine)( fMessageCallbackRefCon, type, outArgs );
}