#include <IOKit/IOLib.h>
#include <IOKit/IODataQueue.h>
#include "KLog.h"
#include <string.h>
#define super IOUserClient
OSDefineMetaClassAndStructors( com_apple_iokit_KLogClient, IOUserClient )
#define Q_ON 1
#define Q_OFF 0
#define DEBUG_NAME "[KLogClient]"
#define kMethodObjectUserClient ((IOService*) 0 )
#define kMethodObjectDevice ((IOService*) 1 )
enum
{
kIOIgnoreCount = 0xFFFFFFFF
};
const IOExternalMethod com_apple_iokit_KLogClient::sMethods[] =
{
{
kMethodObjectUserClient, ( IOMethod ) &com_apple_iokit_KLogClient::QueueMSG, kIOUCScalarIScalarO, 1, 0 },
};
const IOItemCount com_apple_iokit_KLogClient::sMethodCount = sizeof( com_apple_iokit_KLogClient::sMethods ) /
sizeof( com_apple_iokit_KLogClient::sMethods[ 0 ] );
bool com_apple_iokit_KLogClient::init()
{
bool res;
Q_Err = 0;
ActiveFlag = false;
ClientLock = IOLockAlloc();
if(super::init() == false)
{
IOLog( DEBUG_NAME "super::init failed\n");
Q_Err++;
return(false);
}
myLogQueue = new IODataQueue;
if(myLogQueue == 0)
{
IOLog( DEBUG_NAME "[ERR] Failed to allocate memory for buffer\n");
Q_Err++;
return false;
}
res = myLogQueue->initWithEntries(MAXENTRIES, sizeof(char)*BUFSIZE);
if(res == false)
{
IOLog( DEBUG_NAME "[ERR] Could not initWithEntries\n");
Q_Err++;
return false;
}
State = 1;
return true;
}
void com_apple_iokit_KLogClient::free()
{
myLogQueue->release();
IOLockFree(ClientLock);
super::free();
}
bool com_apple_iokit_KLogClient::start(IOService *provider)
{
bool result = false;
IOLog( DEBUG_NAME "start(%p)\n", provider);
myProvider = OSDynamicCast(com_apple_iokit_KLog, provider);
if (myProvider != NULL)
result = super::start(provider);
else
result = false;
if (result == false)
{
IOLog( DEBUG_NAME "provider start failed\n");
}
return (result);
}
IOExternalMethod * com_apple_iokit_KLogClient::getTargetAndMethodForIndex(IOService **target, UInt32 index)
{
IOExternalMethod * methodPtr = NULL;
if( index <= (UInt32) sMethodCount )
{
if ( sMethods[index].object == kMethodObjectUserClient )
{
*target = this;
}
methodPtr = (IOExternalMethod *) &sMethods[0];
}
else
{
IOLog( DEBUG_NAME "[getTargetAndMethodForIndex] BAD index! Value passed was %d.\n", (int)index );
}
return( methodPtr );
}
void * com_apple_iokit_KLogClient::QueueMSG( void * inPtr,
void * outPtr,
IOByteCount inSize,
IOByteCount *outSize,
void * inUnused1,
void * inUnused2 )
{
void * result;
result = ( void * ) kIOReturnUnsupported;
if((int)inPtr == Q_ON)
{
ActiveFlag = true;
result = kIOReturnSuccess;
}
else if((int)inPtr == Q_OFF)
{
ActiveFlag = false;
result = kIOReturnSuccess;
}
return( result );
}
com_apple_iokit_KLogClient * com_apple_iokit_KLogClient::withTask(task_t owningTask)
{
com_apple_iokit_KLogClient *client;
client = new com_apple_iokit_KLogClient;
if (client != NULL)
{
if (client->init() == false)
{
client->release();
client = NULL;
}
}
if (client != NULL)
{
client->fTask = owningTask;
}
return (client);
}
IOReturn com_apple_iokit_KLogClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon)
{
myLogQueue->setNotificationPort(port);
return(kIOReturnSuccess);
}
IOReturn com_apple_iokit_KLogClient::clientMemoryForType( UInt32 type, IOOptionBits * options, IOMemoryDescriptor ** memory )
{
IOMemoryDescriptor *descriptor;
descriptor = myLogQueue->getMemoryDescriptor();
if (descriptor)
{
*memory = descriptor;
*options = 0;
}
else
{
Q_Err++;
IOLog( DEBUG_NAME "could not allocate memory for data queue");
return kIOReturnNoMemory;
}
myProvider->setErr(false);
return(kIOReturnSuccess);
}
void com_apple_iokit_KLogClient::AddEntry(void *entry, UInt32 sizeOfentry)
{
bool res = false;
if (entry == NULL)
{
IOLog( DEBUG_NAME "AddEntry - NULL entry\n");
return;
}
if(ActiveFlag == false)
{
return;
};
if((Q_Err == 0) && ((int)sizeOfentry > 0))
{
res = myLogQueue->enqueue(entry, sizeOfentry);
if(res == false)
{
if(State == 1)
{
IOLog( DEBUG_NAME "ATTN: Could not enqueue, buffer probably full, stalling....\n");
State = 0;
}
}
else
{
State = 1;
}
}
else
{
IOLog( DEBUG_NAME " Possible Q_Err, or bad log attempt: %d %d\n", Q_Err, (int)sizeOfentry);
myProvider->setErr(true);
}
}
bool com_apple_iokit_KLogClient::set_Q_Size(UInt32 capacity)
{
bool res;
if(capacity == 0)
{
return true;
}
IOLog( DEBUG_NAME "Reseting size of data queue, all data in queue is lost");
myLogQueue->release();
myLogQueue = new IODataQueue;
if(myLogQueue == 0)
{
IOLog( DEBUG_NAME "[ERR] Failed to allocate memory for buffer\n");
Q_Err++;
return false;
}
res = myLogQueue->initWithCapacity(capacity);
if(res == false)
{
IOLog( DEBUG_NAME "[ERR] Could not initWithEntries\n");
Q_Err++;
return false;
}
return true;
}
IOReturn com_apple_iokit_KLogClient::clientClose(void)
{
myProvider->setErr(false);
if (myProvider != NULL)
{
myProvider->closeChild(this);
myProvider = NULL;
}
return (kIOReturnSuccess);
}
IOReturn com_apple_iokit_KLogClient::clientDied(void)
{
return (clientClose());
}