IONetworkUserClient.cpp [plain text]
#include <IOKit/assert.h>
#include <IOKit/network/IONetworkInterface.h>
#include "IONetworkUserClient.h"
#include <IOKit/network/IONetworkData.h>
#define super IOUserClient
OSDefineMetaClassAndStructors( IONetworkUserClient, IOUserClient )
#ifdef DEBUG
#define DLOG(fmt, args...) IOLog(fmt, ## args)
#else
#define DLOG(fmt, args...)
#endif
IONetworkUserClient * IONetworkUserClient::withTask(task_t owningTask)
{
IONetworkUserClient * me;
me = new IONetworkUserClient;
if (me)
{
if (!me->init())
{
me->release();
return 0;
}
me->_task = owningTask;
}
return me;
}
bool IONetworkUserClient::start(IOService * provider)
{
_owner = OSDynamicCast(IONetworkInterface, provider);
assert(_owner);
_handleArray = OSArray::withCapacity(4);
if (!_handleArray)
return false;
_handleLock = IOLockAlloc();
if (!_handleLock)
return false;
if (!super::start(_owner))
return false;
if (!_owner->open(this))
return false;
return true;
}
void IONetworkUserClient::free(void)
{
if (_handleArray)
{
_handleArray->release();
_handleArray = 0;
}
if (_handleLock)
{
IOLockFree(_handleLock);
_handleLock = 0;
}
super::free();
}
IOReturn IONetworkUserClient::clientClose(void)
{
if (_owner) {
_owner->close(this);
detach(_owner);
}
return kIOReturnSuccess;
}
IOReturn IONetworkUserClient::clientDied(void)
{
return clientClose();
}
IOReturn IONetworkUserClient::externalMethod(
uint32_t selector, IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch, OSObject * target,
void * reference )
{
IOReturn ret = kIOReturnBadArgument;
if (!arguments)
return kIOReturnBadArgument;
switch (selector)
{
case kIONUCResetNetworkDataIndex:
if (arguments->scalarInputCount == 1)
ret = resetNetworkData(
(uint32_t) arguments->scalarInput[0]);
break;
case kIONUCWriteNetworkDataIndex:
if ((arguments->scalarInputCount == 1) &&
(arguments->structureInputSize > 0))
ret = writeNetworkData(
(uint32_t) arguments->scalarInput[0],
(void *) arguments->structureInput,
arguments->structureInputSize);
break;
case kIONUCReadNetworkDataIndex:
if ((arguments->scalarInputCount == 1) &&
(arguments->structureOutputSize > 0))
ret = readNetworkData(
(uint32_t) arguments->scalarInput[0],
arguments->structureOutput,
&arguments->structureOutputSize);
break;
case kIONUCGetNetworkDataCapacityIndex:
if ((arguments->scalarInputCount == 1) &&
(arguments->scalarOutputCount == 1))
ret = getNetworkDataCapacity(
(uint32_t) arguments->scalarInput[0],
&arguments->scalarOutput[0]);
break;
case kIONUCGetNetworkDataHandleIndex:
ret = getNetworkDataHandle(
(const char *) arguments->structureInput,
(uint32_t *) arguments->structureOutput,
arguments->structureInputSize,
&arguments->structureOutputSize);
break;
}
return ret;
}
IOReturn IONetworkUserClient::resetNetworkData(uint32_t dataHandle)
{
IONetworkData * data;
const OSSymbol * key;
IOReturn ret;
IOLockLock(_handleLock);
key = (const OSSymbol *) _handleArray->getObject(dataHandle);
IOLockUnlock(_handleLock);
if (!key)
return kIOReturnBadArgument;
data = _owner->getNetworkData(key);
ret = data ? data->reset() : kIOReturnBadArgument;
return ret;
}
IOReturn
IONetworkUserClient::writeNetworkData(uint32_t dataHandle,
void * srcBuffer,
uint32_t srcBufferSize)
{
IONetworkData * data;
const OSSymbol * key;
IOReturn ret;
IOLockLock(_handleLock);
key = (const OSSymbol *) _handleArray->getObject(dataHandle);
IOLockUnlock(_handleLock);
if (!key || !srcBuffer || !srcBufferSize)
return kIOReturnBadArgument;
data = _owner->getNetworkData(key);
ret = data ? data->write(srcBuffer, srcBufferSize) : kIOReturnBadArgument;
return ret;
}
IOReturn
IONetworkUserClient::readNetworkData(uint32_t dataHandle,
void * dstBuffer,
uint32_t * dstBufferSize)
{
IONetworkData * data;
const OSSymbol * key;
IOReturn ret;
IOLockLock(_handleLock);
key = (const OSSymbol *) _handleArray->getObject(dataHandle);
IOLockUnlock(_handleLock);
if (!key || !dstBuffer || !dstBufferSize)
return kIOReturnBadArgument;
data = _owner->getNetworkData(key);
ret = data ? data->read(dstBuffer, (UInt32 *) dstBufferSize) :
kIOReturnBadArgument;
return ret;
}
IOReturn
IONetworkUserClient::getNetworkDataCapacity(uint32_t dataHandle,
uint64_t * capacity)
{
const OSSymbol * key;
IONetworkData * data;
IOReturn ret = kIOReturnBadArgument;
IOLockLock(_handleLock);
key = (const OSSymbol *) _handleArray->getObject(dataHandle);
IOLockUnlock(_handleLock);
if (key)
{
data = _owner->getNetworkData(key);
if (data) {
*capacity = (uint64_t) data->getSize();
ret = kIOReturnSuccess;
}
}
return ret;
}
IOReturn
IONetworkUserClient::getNetworkDataHandle(const char * name,
uint32_t * handle,
uint32_t nameSize,
uint32_t * handleSizeP)
{
IOReturn ret = kIOReturnBadArgument;
const OSSymbol * key;
int index;
if (!name || !nameSize || (name[nameSize - 1] != '\0') ||
(*handleSizeP != sizeof(*handle)))
return kIOReturnBadArgument;
key = OSSymbol::withCStringNoCopy(name);
if (!key)
return kIOReturnNoMemory;
if (_owner->getNetworkData(key))
{
IOLockLock(_handleLock);
index = _handleArray->getNextIndexOfObject(key, 0);
if (index < 0)
{
_handleArray->setObject(key);
index = _handleArray->getNextIndexOfObject(key, 0);
}
IOLockUnlock(_handleLock);
if (index >= 0)
{
*handle = index;
ret = kIOReturnSuccess;
}
}
if (key)
key->release();
return ret;
}
IOReturn
IONetworkUserClient::setProperties(OSObject * properties)
{
return _owner->setProperties(properties);
}
IOService * IONetworkUserClient::getService()
{
return _owner;
}