IOUSBControllerUserClient.cpp [plain text]
#include <libkern/OSByteOrder.h>
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/usb/IOUSBController.h>
#include <IOKit/usb/IOUSBControllerV2.h>
#include <IOKit/usb/IOUSBControllerV3.h>
#include <IOKit/usb/IOUSBLog.h>
#include "IOUSBControllerUserClient.h"
#include "USBTracepoints.h"
#define super IOUserClient
#ifndef kIOUserClientCrossEndianKey
#define kIOUserClientCrossEndianKey "IOUserClientCrossEndian"
#endif
#ifndef kIOUserClientCrossEndianCompatibleKey
#define kIOUserClientCrossEndianCompatibleKey "IOUserClientCrossEndianCompatible"
#endif
OSDefineMetaClassAndStructors(IOUSBControllerUserClient, IOUserClient)
enum {
kMethodObjectThis = 0,
kMethodObjectOwner
};
const IOExternalMethod
IOUSBControllerUserClient::sMethods[kNumUSBControllerMethods] =
{
{ (IOService*)kMethodObjectThis, ( IOMethod ) &IOUSBControllerUserClient::open, kIOUCScalarIScalarO, 1, 0 },
{ (IOService*)kMethodObjectThis, ( IOMethod ) &IOUSBControllerUserClient::close, kIOUCScalarIScalarO, 0, 0 },
{ (IOService*)kMethodObjectThis, ( IOMethod ) &IOUSBControllerUserClient::EnableKernelLogger, kIOUCScalarIScalarO, 1, 0 },
{ (IOService*)kMethodObjectThis, ( IOMethod ) &IOUSBControllerUserClient::SetDebuggingLevel, kIOUCScalarIScalarO, 1, 0 },
{ (IOService*)kMethodObjectThis, ( IOMethod ) &IOUSBControllerUserClient::SetDebuggingType, kIOUCScalarIScalarO, 1, 0 },
{ (IOService*)kMethodObjectThis, ( IOMethod ) &IOUSBControllerUserClient::GetDebuggingLevel, kIOUCScalarIScalarO, 0, 1 },
{ (IOService*)kMethodObjectThis, ( IOMethod ) &IOUSBControllerUserClient::GetDebuggingType, kIOUCScalarIScalarO, 0, 1 }
};
const IOItemCount
IOUSBControllerUserClient::sMethodCount = sizeof( IOUSBControllerUserClient::sMethods ) /
sizeof( IOUSBControllerUserClient::sMethods[ 0 ] );
void
IOUSBControllerUserClient::SetExternalMethodVectors()
{
fMethods = sMethods;
fNumMethods = kNumUSBControllerMethods;
}
IOExternalMethod *
IOUSBControllerUserClient::getTargetAndMethodForIndex(IOService **target, UInt32 index)
{
if (index < (UInt32)fNumMethods)
{
if ((IOService*)kMethodObjectThis == fMethods[index].object)
*target = this;
else if ((IOService*)kMethodObjectOwner == fMethods[index].object)
*target = fOwner;
else
return NULL;
return (IOExternalMethod *) &fMethods[index];
}
else
return NULL;
}
bool
IOUSBControllerUserClient::initWithTask(task_t owningTask, void *security_id, UInt32 type, OSDictionary * properties)
{
if ( properties != NULL )
{
properties->setObject( kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue);
}
if (!owningTask)
return false;
IOReturn ret = clientHasPrivilege(security_id, kIOClientPrivilegeAdministrator);
USBLog(6,"IOUSBControllerUserClient[%p]::initWithTask clientHasPrivilege returned 0x%x (%s)", this, ret, USBStringFromReturn(ret));
if ( ret == kIOReturnSuccess )
{
fIsTaskPrileged = true;
}
else
{
fIsTaskPrileged = false;
}
fTask = owningTask;
fOwner = NULL;
fGate = NULL;
fDead = false;
SetExternalMethodVectors();
return (super::initWithTask(owningTask, security_id , type, properties));
}
bool
IOUSBControllerUserClient::start( IOService * provider )
{
IOWorkLoop * workLoop = NULL;
IOCommandGate * commandGate = NULL;
fOwner = OSDynamicCast(IOUSBController, provider);
if (!fOwner)
return false;
if (!super::start(provider))
return false;
fMemMap = fOwner->getProvider()->mapDeviceMemoryWithIndex(0);
if (!fMemMap)
{
USBLog(1, "IOUSBControllerUserClient::start - unable to get a memory map");
USBTrace( kUSBTControllerUserClient, kTPControllerUCStart, (uintptr_t)this, (uintptr_t)fOwner, kIOReturnNoResources, 0 );
return kIOReturnNoResources;
}
commandGate = IOCommandGate::commandGate(this);
if (!commandGate)
{
USBError(1, "IOUSBControllerUserClient[%p]::start - unable to create command gate", this);
goto ErrorExit;
}
workLoop = fOwner->getWorkLoop();
if (!workLoop)
{
USBError(1, "IOUSBControllerUserClient[%p]::start - unable to find my workloop", this);
goto ErrorExit;
}
workLoop->retain();
if (workLoop->addEventSource(commandGate) != kIOReturnSuccess)
{
USBError(1, "IOUSBControllerUserClient[%p]::start - unable to add gate to work loop", this);
goto ErrorExit;
}
fGate = commandGate;
fWorkLoop = workLoop;
return true;
ErrorExit:
if ( commandGate != NULL )
{
commandGate->release();
commandGate = NULL;
}
if ( workLoop != NULL )
{
workLoop->release();
workLoop = NULL;
}
return false;
}
IOReturn
IOUSBControllerUserClient::open(bool seize)
{
IOOptionBits options = seize ? (IOOptionBits) kIOServiceSeize : 0;
USBLog(1, "+IOUSBControllerUserClient::open");
USBTrace( kUSBTControllerUserClient, kTPControllerUCOpen, (uintptr_t)this, (uintptr_t)fOwner, options, seize );
if (!fOwner)
return kIOReturnNotAttached;
if (!fOwner->open(this, options))
return kIOReturnExclusiveAccess;
return kIOReturnSuccess;
}
IOReturn
IOUSBControllerUserClient::close()
{
if (!fOwner)
return kIOReturnNotAttached;
if (fOwner && (fOwner->isOpen(this)))
fOwner->close(this);
return kIOReturnSuccess;
}
IOReturn
IOUSBControllerUserClient::EnableKernelLogger(bool enable)
{
if (!fOwner)
return kIOReturnNotAttached;
KernelDebugEnable(enable);
return kIOReturnSuccess;
}
IOReturn
IOUSBControllerUserClient::SetDebuggingLevel(KernelDebugLevel inLevel)
{
if (!fOwner)
return kIOReturnNotAttached;
KernelDebugSetLevel(inLevel);
return kIOReturnSuccess;
}
IOReturn
IOUSBControllerUserClient::SetDebuggingType(KernelDebuggingOutputType inType)
{
if (!fOwner)
return kIOReturnNotAttached;
KernelDebugSetOutputType(inType);
return kIOReturnSuccess;
}
IOReturn
IOUSBControllerUserClient::GetDebuggingLevel(KernelDebugLevel * inLevel)
{
if (!fOwner)
return kIOReturnNotAttached;
*inLevel = KernelDebugGetLevel();
return kIOReturnSuccess;
}
IOReturn
IOUSBControllerUserClient::GetDebuggingType(KernelDebuggingOutputType * inType)
{
if (!fOwner)
return kIOReturnNotAttached;
*inType = KernelDebugGetOutputType();
return kIOReturnSuccess;
}
void
IOUSBControllerUserClient::stop( IOService * provider )
{
USBLog(6, "IOUSBControllerUserClient[%p]::stop(%p)", this, provider);
if (fMemMap)
{
fMemMap->release();
fMemMap = NULL;
}
if (fWorkLoop && fGate)
{
fWorkLoop->removeEventSource(fGate);
if (fGate)
{
fGate->release();
fGate = NULL;
}
if (fWorkLoop)
{
fWorkLoop->release();
fWorkLoop = NULL;
}
}
super::stop(provider);
USBLog(7, "-IOUSBControllerUserClient[%p]::stop(%p)", this, provider);
super::stop( provider );
}
IOReturn
IOUSBControllerUserClient::clientClose( void )
{
if ( !isInactive())
terminate();
return( kIOReturnSuccess );
}