IOI2CInterface.cpp [plain text]
#include <IOKit/IOLib.h>
#include <IOKit/IOUserClient.h>
#include <IOKit/IOLocks.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/ndrvsupport/IONDRVFramebuffer.h>
#include <IOKit/assert.h>
#include <libkern/c++/OSContainers.h>
#include <IOKit/i2c/IOI2CInterfacePrivate.h>
#undef super
#define super IOService
OSDefineMetaClassAndAbstractStructors(IOI2CInterface, IOService)
bool IOI2CInterface::registerI2C( UInt64 id )
{
bool result = true;
fID = id;
setProperty(kIOI2CInterfaceIDKey, id, 64);
registerService();
return( result );
}
IOReturn IOI2CInterface::newUserClient( task_t owningTask,
void * security_id,
UInt32 type,
IOUserClient ** handler )
{
IOReturn err = kIOReturnSuccess;
IOUserClient * newConnect = 0;
if( type)
return( kIOReturnBadArgument );
newConnect = IOI2CInterfaceUserClient::withTask(owningTask);
if( newConnect) {
if( !newConnect->attach( this )
|| !newConnect->start( this )) {
newConnect->detach( this );
newConnect->release();
newConnect = 0;
}
}
*handler = newConnect;
return( err );
}
#undef super
#define super IOUserClient
OSDefineMetaClassAndStructors(IOI2CInterfaceUserClient, IOUserClient)
IOI2CInterfaceUserClient * IOI2CInterfaceUserClient::withTask( task_t owningTask )
{
IOI2CInterfaceUserClient * inst;
inst = new IOI2CInterfaceUserClient;
if( inst && !inst->init()) {
inst->release();
inst = 0;
}
if( inst)
inst->fTask = owningTask;
return( inst );
}
bool IOI2CInterfaceUserClient::start( IOService * provider )
{
if( !super::start( provider ))
return( false );
return( true );
}
IOReturn IOI2CInterfaceUserClient::clientClose( void )
{
terminate();
return( kIOReturnSuccess );
}
IOService * IOI2CInterfaceUserClient::getService( void )
{
return( getProvider() );
}
IOExternalMethod * IOI2CInterfaceUserClient::getTargetAndMethodForIndex(
IOService ** targetP, UInt32 index )
{
static const IOExternalMethod methodTemplate[] = {
{ NULL, (IOMethod) &IOI2CInterfaceUserClient::extAcquireBus,
kIOUCScalarIScalarO, 0, 0 },
{ NULL, (IOMethod) &IOI2CInterfaceUserClient::extReleaseBus,
kIOUCScalarIScalarO, 0, 0 },
{ NULL, (IOMethod) &IOI2CInterfaceUserClient::extIO,
kIOUCStructIStructO, 0xffffffff, 0xffffffff },
};
if( index > (sizeof(methodTemplate) / sizeof(methodTemplate[0])))
return( NULL );
*targetP = this;
return( (IOExternalMethod *)(methodTemplate + index) );
}
IOReturn IOI2CInterfaceUserClient::setProperties( OSObject * properties )
{
return( kIOReturnUnsupported );
}
IOReturn IOI2CInterfaceUserClient::extAcquireBus( void )
{
IOReturn ret = kIOReturnNotReady;
IOI2CInterface * provider;
if( (provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane))) {
ret = provider->open( this ) ? kIOReturnSuccess : kIOReturnBusy;
provider->release();
}
return( ret );
}
IOReturn IOI2CInterfaceUserClient::extReleaseBus( void )
{
IOReturn ret = kIOReturnNotReady;
IOI2CInterface * provider;
if( (provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane))) {
provider->close( this );
provider->release();
ret = kIOReturnSuccess;
}
return( ret );
}
IOReturn IOI2CInterfaceUserClient::extIO(
void * inStruct, void * outStruct,
IOByteCount inSize, IOByteCount * outSize )
{
IOReturn err = kIOReturnNotReady;
IOI2CInterface * provider;
IOI2CRequest * request;
IOI2CBuffer * buffer;
if( inSize < sizeof(IOI2CRequest))
return( kIOReturnNoSpace );
if( *outSize < inSize)
return( kIOReturnNoSpace );
if( (provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane))) do {
if( !provider->isOpen( this)) {
err = kIOReturnNotOpen;
continue;
}
buffer = (IOI2CBuffer *) inStruct;
request = &buffer->request;
if( request->sendBytes) {
if( !request->sendBuffer)
request->sendBuffer = (vm_address_t) &buffer->inlineBuffer[0];
else {
err = kIOReturnMessageTooLarge;
continue;
}
}
if( request->replyBytes) {
if( !request->replyBuffer)
request->replyBuffer = (vm_address_t) &buffer->inlineBuffer[0];
else {
err = kIOReturnMessageTooLarge;
continue;
}
}
err = provider->startIO( &buffer->request );
} while( false );
if( provider)
provider->release();
if( kIOReturnSuccess == err) {
*outSize = inSize;
bcopy(inStruct, outStruct, inSize);
} else
*outSize = 0;
return( err );
}