IOI2CUserClient.cpp [plain text]
#include "IOI2CUserClient.h"
#include "IOI2CDevice.h"
#ifdef DLOG
#undef DLOG
#endif
#ifdef I2CUSERCLIENT_DEBUG
#define DLOG(fmt, args...) kprintf(fmt, ## args)
#else
#define DLOG(fmt, args...)
#endif
#define I2C_ERRLOG 1
#if (defined(I2C_ERRLOG) && I2C_ERRLOG)
#define ERRLOG(fmt, args...) kprintf(fmt, ## args)
#else
#define ERRLOG(fmt, args...)
#endif
#define super IOUserClient
OSDefineMetaClassAndStructors(IOI2CUserClient, IOUserClient)
bool IOI2CUserClient::initWithTask(
task_t owningTask,
void *security_id,
UInt32 type)
{
DLOG("+IOI2CUserClient::initWithTask\n");
if (kIOReturnSuccess != clientHasPrivilege(security_id, kIOClientPrivilegeAdministrator))
{
ERRLOG("-IOI2CUserClient::initWithTask client is not root!\n");
return false;
}
if (!owningTask || !super::initWithTask(owningTask, security_id, type))
{
ERRLOG("-IOI2CUserClient::initWithTask failed to init\n");
return false;
}
fOwningTask = owningTask;
return true;
}
bool
IOI2CUserClient::start(
IOService *provider)
{
DLOG("+IOI2CUserClient::start provider=%08lx\n", (UInt32)provider);
if ( ! super::start(provider) )
return false;
symLockI2CBus = OSSymbol::withCStringNoCopy(kLockI2Cbus);
symUnlockI2CBus = OSSymbol::withCStringNoCopy(kUnlockI2Cbus);
symWriteI2CBus = OSSymbol::withCStringNoCopy(kWriteI2Cbus);
symReadI2CBus = OSSymbol::withCStringNoCopy(kReadI2Cbus);
fProvider = provider;
return true;
}
void IOI2CUserClient::free(void)
{
DLOG("+IOI2CUserClient::free\n");
if (symLockI2CBus) { symLockI2CBus->release(); symLockI2CBus = 0; }
if (symUnlockI2CBus) { symUnlockI2CBus->release(); symUnlockI2CBus = 0; }
if (symWriteI2CBus) { symWriteI2CBus->release(); symWriteI2CBus = 0; }
if (symReadI2CBus) { symReadI2CBus->release(); symReadI2CBus = 0; }
super::free();
}
IOReturn IOI2CUserClient::clientClose(void)
{
DLOG("+IOI2CUserClient::clientClose\n");
if (fClientKey)
unlockI2CBus(fClientKey);
fClientKey = 0;
terminate();
return(kIOReturnSuccess);
}
IOExternalMethod *
IOI2CUserClient::getTargetAndMethodForIndex(
IOService **target,
UInt32 index)
{
DLOG("IOI2CUserClient::getTargetAndMethodForIndex (index=%lu/%d)\n", index, kI2CUCNumMethods);
static const IOExternalMethod sMethods[kI2CUCNumMethods] =
{
{ NULL, (IOMethod) &IOI2CUserClient::lockI2CBus,
kIOUCScalarIScalarO,
1, 1 },
{ NULL, (IOMethod) &IOI2CUserClient::unlockI2CBus,
kIOUCScalarIScalarO,
1, 0 },
{ NULL, (IOMethod) &IOI2CUserClient::readI2CBus,
kIOUCStructIStructO,
sizeof(I2CUserReadInput),
sizeof(I2CUserReadOutput)
},
{ NULL, (IOMethod) &IOI2CUserClient::writeI2CBus,
kIOUCStructIStructO,
sizeof(I2CUserWriteInput),
sizeof(I2CUserWriteOutput)
},
{ NULL, (IOMethod) &IOI2CUserClient::readModifyWriteI2CBus,
kIOUCStructIStructO,
sizeof(I2CRMWInput),
0
}
};
if (index < (UInt32)kI2CUCNumMethods)
{
*target = this;
return ((IOExternalMethod *) &sMethods[index]);
}
ERRLOG("IOI2CUserClient::getTargetAndMethodForIndex (index=%lu) Not Found\n", index);
*target = NULL;
return NULL;
}
IOReturn
IOI2CUserClient::lockI2CBus(
UInt32 bus,
UInt32 *clientKeyRef)
{
IOReturn status;
DLOG("+IOI2CUserClient::lockI2CBus\n");
if (fClientKey != 0)
{
ERRLOG("-IOI2CUserClient::lockI2CBus already locked!\n");
*clientKeyRef = kIOI2C_CLIENT_KEY_INVALID;
return kIOReturnExclusiveAccess;
}
if (kIOReturnSuccess == (status = fProvider->callPlatformFunction(symLockI2CBus, false,
(void *)bus, (void *)&fClientKey, (void *)0, (void *)0)))
*clientKeyRef = fClientKey;
else
*clientKeyRef = kIOI2C_CLIENT_KEY_INVALID;
return status;
}
IOReturn
IOI2CUserClient::unlockI2CBus(UInt32 clientKey)
{
DLOG("+IOI2CUserClient::unlockI2CBus\n");
if (clientKey != fClientKey)
{
ERRLOG("IOI2CUserClient::unlockI2CBus with wrong key: %lx != %lx\n", clientKey, fClientKey);
}
fClientKey = 0;
return fProvider->callPlatformFunction(symUnlockI2CBus, false,
(void *)0, (void *)clientKey, (void *)0, (void *)0);
}
IOReturn
IOI2CUserClient::readI2CBus(
I2CUserReadInput *input,
I2CUserReadOutput *output,
IOByteCount inputSize,
IOByteCount *outputSizeP,
void *p5,
void *p6)
{
IOReturn status = kIOReturnSuccess;
DLOG("+IOI2CUserClient::readI2CBus\n");
if (!(fProvider
&& input
&& output
&& outputSizeP
&& (inputSize == sizeof(I2CUserReadInput))
&& (*outputSizeP == sizeof(I2CUserReadOutput))
&& (input->count <= kI2CUCBufSize)) )
{
ERRLOG("-IOI2CUserClient::readI2CBus got invalid arguments\n");
return kIOReturnBadArgument;
}
{
IOI2CCommand cmd = {0};
cmd.subAddress = input->subAddr;
cmd.buffer = output->buf;
cmd.count = input->count;
cmd.mode = input->mode;
cmd.bus = input->busNo;
cmd.address = input->addr;
cmd.options = input->options;
DLOG("IOI2CUserClient::readI2CBus cmd key:%lx, B:%lx, A:%lx S:%lx, L:%lx, M:%lx\n",
input->key, cmd.bus, cmd.address, cmd.subAddress, cmd.count, cmd.mode);
status = fProvider->callPlatformFunction(symReadI2CBus, false,
(void *)&cmd, (void *)input->key, (void *)0, (void *)0);
if (status != kIOReturnSuccess)
output->realCount = 0;
else
output->realCount = input->count;
}
return status;
}
IOReturn
IOI2CUserClient::writeI2CBus(
I2CUserWriteInput *input,
I2CUserWriteOutput *output,
IOByteCount inputSize,
IOByteCount *outputSizeP,
void *p5,
void *p6)
{
IOReturn status = kIOReturnSuccess;
DLOG("+IOI2CUserClient::writeI2CBus\n");
if (!(fProvider
&& input
&& output
&& outputSizeP
&& (inputSize == sizeof(I2CUserWriteInput))
&& (*outputSizeP == sizeof(I2CUserWriteOutput)) ) )
{
ERRLOG("-IOI2CUserClient::writeI2CBus got invalid arguments\n");
return kIOReturnBadArgument;
}
{
IOI2CCommand cmd = {0};
cmd.subAddress = input->subAddr;
cmd.buffer = input->buf;
cmd.count = input->count;
cmd.mode = input->mode;
cmd.bus = input->busNo;
cmd.address = input->addr;
cmd.options = input->options;
status = fProvider->callPlatformFunction(symWriteI2CBus, false,
(void *)&cmd, (void *)input->key, (void *)0, (void *)0);
if (status != kIOReturnSuccess)
output->realCount = 0;
else
output->realCount = input->count;
}
DLOG("-IOI2CUserClient::writeI2CBus\n");
return status;
}
IOReturn IOI2CUserClient::readModifyWriteI2CBus(
I2CRMWInput *input,
IOByteCount inputSize,
void *p3, void *p4, void *p5, void *p6)
{
DLOG("IOI2CUserClient::readModifyWriteI2CBus\n");
ERRLOG("IOI2CUserClient::readModifyWriteI2CBus --- WARNING: method not supported\n");
return kIOReturnUnsupported;
}
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 0 );
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 1 );
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 2 );
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 3 );
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 4 );
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 5 );
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 6 );
OSMetaClassDefineReservedUnused ( IOI2CUserClient, 7 );