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);
}