#include <unistd.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <spawn.h>
#include <mach/clock_types.h>
#include <mach/mach_time.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <libutil.h> // for reexec_to_match_kernel()
#include <mach/mach_host.h> // for host_info()
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/usb/USB.h>
#include <IOKit/usb/USBTracepoints.h>
#ifndef KERNEL_PRIVATE
#define KERNEL_PRIVATE
#include <sys/kdebug.h>
#undef KERNEL_PRIVATE
#else
#include <sys/kdebug.h>
#endif // KERNEL_PRIVATE
#include "IOUSBFamilyInfoPlist.pch"
#define DEBUG 0
#ifndef USBTRACE_VERSION
#define USBTRACE_VERSION "100.4.0"
#endif
#define log(a,b,c,d,x,...) if ( PrintHeader(a,b,c,d) ) { if (x){fprintf(stdout,x, ##__VA_ARGS__);} fprintf(stdout, "\n"); }
#define logs(a,b,c,x...) log(a,b,c,0,x...)
#define vlog(x...) if ( gVerbose ) { fprintf(stdout,x); }
#define elog(x...) fprintf(stderr, x)
#define kTraceBufferSampleSize 65500
#define kMicrosecondsPerSecond 1000000
#define kMicrosecondsPerMillisecond 1000
#define kPrintMaskAllTracepoints 0x80000000
#define kTimeStringSize 17
#define kTimeStampKernel 0x1
#define kTimeStampLocalTime 0x2
#define kPrintStartToken "->"
#define kPrintEndToken "<-"
#define kPrintMedialToken " "
#define kFilePathMaxSize 256
#define kMicrosecondsPerCollectionDelay 20
#define gTimeStampDivisorString "TimeStampDivisor="
#define kInvalid 0xdeadbeef
#define kDivisorEntry 0xfeedface
#define kKernelTraceCodes "/usr/local/share/misc/trace.codes"
typedef struct {
uint64_t timestamp;
uintptr_t thread;
uint32_t debugid;
uint32_t cpuid;
} trace_info;
typedef struct {
uint64_t timestamp;
uintptr_t arg1;
uintptr_t arg2;
uintptr_t arg3;
uintptr_t arg4;
uintptr_t arg5;
uint32_t debugid;
uint64_t delta; uint32_t cpuid;
} raw_data_t;
#define kTPAllUSB USB_TRACE ( 0, 0, 0 )
#pragma mark Prototypes
static void EnableUSBTracing ( void );
static void EnableTraceBuffer ( int val );
static void SignalHandler ( int signal );
static void GetDivisor ( void );
static void RegisterSignalHandlers ( void );
static void AllocateTraceBuffer ( void );
static void RemoveTraceBuffer ( void );
static void SetTraceBufferSize ( int nbufs );
static void GetTraceBufferInfo ( kbufinfo_t * val );
static void Quit ( const char * s );
static void ResetDebugFlags ( void );
static void InitializeTraceBuffer ( void );
static void Reinitialize ( void );
static void SetInterest ( unsigned int type );
static void ParseArguments ( int argc, const char * argv[] );
static void PrintUsage ( void );
static void CollectTrace ( void );
static void CollectWithAlloc( void );
static void ProcessTracepoint( kd_buf tracepoint );
static void CollectTraceController( kd_buf tracepoint );
static void CollectTraceControllerUserClient( kd_buf tracepoint );
static void CollectTraceDevice ( kd_buf tracepoint ); static void CollectTraceDeviceUserClient ( kd_buf tracepoint ); static void CollectTraceHub ( kd_buf tracepoint ); static void CollectTraceHubPort ( kd_buf tracepoint ); static void CollectTraceHSHubUserClient ( kd_buf tracepoint ); static void CollectTraceHID ( kd_buf tracepoint ); static void CollectTracePipe ( kd_buf tracepoint ); static void CollectTraceInterfaceUserClient ( kd_buf tracepoint );
static void CollectTraceEnumeration( kd_buf tracepoint ); static void CollectTraceUHCI ( kd_buf tracepoint ); static void CollectTraceUHCIUIM ( kd_buf tracepoint );
static void CollectTraceUHCIInterrupts ( kd_buf tracepoint ); static void CollectTraceOHCI ( kd_buf tracepoint ); static void CollectTraceOHCIInterrupts ( kd_buf tracepoint ); static void CollectTraceEHCI ( kd_buf tracepoint ); static void CollectTraceEHCIUIM ( kd_buf tracepoint ); static void CollectTraceEHCIHubInfo ( kd_buf tracepoint ); static void CollectTraceEHCIInterrupts ( kd_buf tracepoint ); static void CollectTraceHubPolicyMaker ( kd_buf tracepoint ); static void CollectTraceCompositeDriver ( kd_buf tracepoint ); static void CollectTraceOutstandingIO ( kd_buf tracepoint );
static void CollectTraceAudioDriver ( kd_buf tracepoint );
static void CollectTraceUnknown ( kd_buf tracepoint );
static void CollectCodeFile ( void );
static void ReadRawFile( const char * filepath );
static void CollectToRawFile ( FILE * file );
static void PrependDivisorEntry ( FILE * file );
static void CollectTraceUnknown ( kd_buf tracepoint );
static char * DecodeID ( uint32_t id, char * string, const int max );
static void CollectTraceBasic ( kd_buf tracepoint );
static char * ConvertTimestamp ( uint64_t timestamp, char * timestring );
static bool PrintHeader ( trace_info info, const char * group, const char * method, uintptr_t theThis );
static void TabIndent ( int numOfTabs );
static void Indent ( int numOfTabs );
static void IndentIn ( int numOfTabs );
static void IndentOut ( int numOfTabs );
const char * DecodeUSBTransferType( uint32_t type );