#include <sys/systm.h>
#include <IOKit/usb/IOUSBLog.h>
#ifdef __cplusplus
extern "C" {
#endif
KernelDebugLevel gKernelDebugLevel = 1;
KernelDebuggingOutputType gKernelDebugOutputType = kKernelDebugOutputIOLogType;
com_apple_iokit_KLog * gKernelLogger = NULL;
#define DEBUG_NAME "[KernelDebugging] "
const char LOWEST = 0x20;
char *armor(void *buffer, int bytecount);
void KernelDebugEnable( bool enable )
{
IOLog( DEBUG_NAME"KernelDebugEnable (%d)\n",enable);
if ( enable )
{
KernelDebugFindKernelLogger();
}
}
void KernelDebugSetLevel( KernelDebugLevel inLevel )
{
gKernelDebugLevel = inLevel;
IOLog( DEBUG_NAME "Debugging level changed to: %d\n", (int) gKernelDebugLevel );
}
KernelDebugLevel KernelDebugGetLevel()
{
IOLog( DEBUG_NAME "KernelDebugGetLevel called (%d)\n", (int) gKernelDebugLevel );
return( gKernelDebugLevel );
}
KernelDebugLevel KernelDebugGetOutputType()
{
IOLog( DEBUG_NAME "KernelDebugGetOutputType called (%d)\n", (int) gKernelDebugOutputType );
return( gKernelDebugOutputType );
}
void KernelDebugSetOutputType( KernelDebuggingOutputType inType )
{
gKernelDebugOutputType = inType;
if( inType & kKernelDebugOutputKextLoggerType )
{
if( !gKernelLogger )
{
IOLog( DEBUG_NAME "SetOutputType failed: could not find kernel logger. It probably needs to be loaded?\n" );
}
}
IOLog( DEBUG_NAME "Debugging type changed to: %d\n", (int) gKernelDebugOutputType );
}
void KernelDebugLogInternal( UInt32 inLevel, UInt32 inTag, char const *inFormatString, ... )
{
AbsoluteTime currentTime;
UInt64 elapsedTime;
UInt32 secs, milliSecs;
if( inLevel > gKernelDebugLevel )
{
return;
}
else
{
if( gKernelDebugOutputType & kKernelDebugOutputIOLogType )
{
va_list ap;
extern void conslog_putc(char);
clock_get_uptime(¤tTime);
absolutetime_to_nanoseconds(currentTime, &elapsedTime);
elapsedTime = elapsedTime/(1000000);
secs = elapsedTime / 1000;
milliSecs = elapsedTime % 1000;
IOLog("%c%c%c%c:\t%ld.%3.3ld\t",(char)(inTag>>24), (char)(inTag>>16), (char)(inTag>>8), (char)inTag, secs, milliSecs);
va_start( ap, inFormatString );
_doprnt( inFormatString, &ap, conslog_putc, 16 );
va_end( ap );
if ( inTag == 'USBF')
IOLog("\n");
}
if( (gKernelDebugOutputType & kKernelDebugOutputKextLoggerType) && gKernelLogger )
{
va_list ap;
va_start( ap, inFormatString );
gKernelLogger->vLog( inLevel, inTag, inFormatString, ap );
va_end( ap );
}
}
}
void KernelDebugLogDataInternal( UInt32 inLevel, UInt32 inTag, void *buffer, UInt32 byteCount, bool preBuffer)
{
if(preBuffer)
KernelDebugLogInternal(inLevel, inTag, "%s", armor(buffer, byteCount));
else
KernelDebugLogInternal(inLevel, inTag, "%s\n", armor(buffer, byteCount));
}
#ifdef __cplusplus
}
#endif
IOReturn KernelDebugFindKernelLogger()
{
OSIterator * iterator = NULL;
OSDictionary * matchingDictionary = NULL;
IOReturn error = 0;
matchingDictionary = IOService::serviceMatching( kLogKextName );
if( !matchingDictionary )
{
error = kIOReturnError;
IOLog( DEBUG_NAME "[FindKernelLogger] Couldn't create a matching dictionary.\n" );
goto exit;
}
iterator = IOService::getMatchingServices( matchingDictionary );
if( !iterator )
{
error = kIOReturnError;
IOLog( DEBUG_NAME "[FindKernelLogger] No %s found.\n", kLogKextName );
goto exit;
}
gKernelLogger = (com_apple_iokit_KLog*) iterator->getNextObject();
if( gKernelLogger )
{
IOLog( DEBUG_NAME "[FindKernelLogger] Found a logger at %p.\n", gKernelLogger );
}
exit:
if( error == kIOReturnSuccess )
{
IOLog( DEBUG_NAME "[FindKernelLogger] Found a logger instance.\n" );
}
else
{
gKernelLogger = NULL;
IOLog( DEBUG_NAME "[FindKernelLogger] Could not find a logger instance. Error = %X.\n", error );
}
if( matchingDictionary ) matchingDictionary->release();
if( iterator ) iterator->release();
return( error );
}
char *armor(void *buffer, int bytecount)
{
int asc_i, bin_i;
UInt16 asc_length;
char *asciiBuffer;
char *binaryBuffer = (char*)buffer;
asc_length = bytecount * 4 / 3 + 1;
asciiBuffer = (char*)IOMalloc(asc_length);
for(asc_i=0, bin_i=0; bin_i < bytecount; bin_i+=3) {
asciiBuffer[asc_i] = (binaryBuffer[bin_i] >> 2) & 0x3f;
asciiBuffer[asc_i++] += LOWEST;
asciiBuffer[asc_i] = (binaryBuffer[bin_i] << 4) & 0x30;
if (bin_i+1 < bytecount) {
asciiBuffer[asc_i] |= (binaryBuffer[bin_i+1] >> 4) & 0xf;
asciiBuffer[asc_i++] += LOWEST;
} else {
asciiBuffer[asc_i++] += LOWEST;
break;
}
asciiBuffer[asc_i] = (binaryBuffer[bin_i+1] << 2) & 0x3c;
if (bin_i+2 < bytecount) {
asciiBuffer[asc_i] |= (binaryBuffer[bin_i+2] >> 6) & 0x3;
asciiBuffer[asc_i++] += LOWEST;
} else {
asciiBuffer[asc_i++] += LOWEST;
break;
}
asciiBuffer[asc_i] = binaryBuffer[bin_i+2] & 0x3f;
asciiBuffer[asc_i++] += LOWEST;
}
asciiBuffer[asc_i] = '\0';
return asciiBuffer;
}
#define super IOService
OSDefineMetaClassAndStructors( IOUSBLog, IOService )
bool IOUSBLog::init( OSDictionary * dictionary )
{
if (!super::init(dictionary))
return false;
return true;
}
IOUSBLog *
IOUSBLog::usblog()
{
IOUSBLog *me = new IOUSBLog;
if (me && !me->init()) {
me->release();
return false;
}
return me;
}
void IOUSBLog::USBLogPrintf(UInt32 level, char *format,...)
{
va_list ap;
char msgBuf[255];
va_start( ap, format );
vsprintf(msgBuf, format, ap);
va_end( ap );
USBLog(level,msgBuf);
}
void IOUSBLog::AddStatusLevel (UInt32 level, UInt32 ref, char *status, UInt32 value)
{
}
void IOUSBLog::AddStatus(char *message)
{
}
void IOUSBLog::AddStatus(UInt32 level, char *message)
{
}