#include "jtraceAPI.h"
#include <stdio.h>
#include "../colors.h"
#include <sys/ioctl.h>
#include <string.h>
#include "msm_kgsl.h"


// Sample plugin for JTrace API
// ----------------------------
//
// I made the API very simple but (hopefully) effective - q.v. the H file,
// which I've fully documented.
//
// Basically, you create a dylib, 
//
// Please direct any suggestions for improvements, or additional APIs
// you may want to me via NewAndroidBook.com
// 
//


#if 0
31233(surfaceflinger): ioctl (15 </dev/kgsl-3d0>, 0x40200946 ...);
31233(surfaceflinger): ioctl (15 </dev/kgsl-3d0>, 0xc0200948 ...);
31233(surfaceflinger): ioctl (15 </dev/kgsl-3d0>, 0xc0300947 ...);
31233(surfaceflinger): ioctl (15 </dev/kgsl-3d0>, 0xc040094a ...);
31233(surfaceflinger): ioctl (15 </dev/kgsl-3d0>, 0xc0200933 ...);
#endif




extern int config_color (void);

int gColor ;


	

int kgsl_ioctl (int Exit, int Pid)
{


   static int mine = 0;

	char *ob = getOutputBuffer();

	int pos = 0;


   if (!Exit) {

 	int fd = (int) getRegValue(REG_ARG_0);
 	uint64_t code = (uint64_t) getRegValue(REG_ARG_1);

	char *devNode = getFDName(fd);
	if (devNode && strcmp (devNode, "/dev/kgsl-3d0") == 0)
	{
		uint64_t dgAddr;
		mine++;


		pos += sprintf(ob + pos, "---->ioctl (%d<%s>,", fd, devNode);
		switch (code) {


	case IOCTL_KGSL_DEVICE_GETPROPERTY: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_DEVICE_GETPROPERTY");
		break;
	case IOCTL_KGSL_DEVICE_WAITTIMESTAMP: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_DEVICE_WAITTIMESTAMP");
		break;
	case IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID");
		break;
	case IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS");
		break;
	case IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_OLD: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_OLD");
		break;
	case IOCTL_KGSL_CMDSTREAM_READTIMESTAMP: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CMDSTREAM_READTIMESTAMP");
		break;
	case IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP");
		break;
	case IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_OLD: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_OLD");
		break;
	case IOCTL_KGSL_DRAWCTXT_CREATE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_DRAWCTXT_CREATE");
		break;
	case IOCTL_KGSL_DRAWCTXT_DESTROY: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_DRAWCTXT_DESTROY");
		break;
	case IOCTL_KGSL_MAP_USER_MEM: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_MAP_USER_MEM");
		break;
	case IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID");
		break;
	case IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID");
		break;
	case IOCTL_KGSL_SHAREDMEM_FROM_PMEM: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SHAREDMEM_FROM_PMEM");
		break;
	case IOCTL_KGSL_SHAREDMEM_FREE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SHAREDMEM_FREE");
		break;
	case IOCTL_KGSL_CFF_USER_EVENT: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CFF_USER_EVENT");
		break;
	case IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW");
		break;
	case IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC");
		break;
	case IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE");
		break;
	case IOCTL_KGSL_DRAWCTXT_SET_BIN_BASE_OFFSET: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_DRAWCTXT_SET_BIN_BASE_OFFSET");
		break;
	case IOCTL_KGSL_CMDWINDOW_WRITE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CMDWINDOW_WRITE");
		break;
	case IOCTL_KGSL_GPUMEM_ALLOC: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUMEM_ALLOC");
		break;
	case IOCTL_KGSL_CFF_SYNCMEM: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CFF_SYNCMEM");
		break;
		/*
	case IOCTL_KGSL_TIMESTAMP_EVENT_OLD: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_TIMESTAMP_EVENT_OLD");
		break;
		*/
	case IOCTL_KGSL_SETPROPERTY: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SETPROPERTY");
		break;
	case IOCTL_KGSL_TIMESTAMP_EVENT: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_TIMESTAMP_EVENT");
		break;
	case IOCTL_KGSL_GPUMEM_ALLOC_ID: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUMEM_ALLOC_ID");
		break;
	case IOCTL_KGSL_GPUMEM_FREE_ID: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUMEM_FREE_ID");
		break;
	case IOCTL_KGSL_GPUMEM_GET_INFO:
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUMEM_GET_INFO");
                break;
	case IOCTL_KGSL_GPUMEM_SYNC_CACHE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUMEM_SYNC_CACHE");
		break;
	case IOCTL_KGSL_PERFCOUNTER_GET: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_PERFCOUNTER_GET");
		break;
	case IOCTL_KGSL_PERFCOUNTER_PUT: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_PERFCOUNTER_PUT");
		break;
	case IOCTL_KGSL_PERFCOUNTER_QUERY: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_PERFCOUNTER_QUERY");
		break;
	case IOCTL_KGSL_PERFCOUNTER_READ: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_PERFCOUNTER_READ");
		break;
	case IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK");
		break;
	case IOCTL_KGSL_SUBMIT_COMMANDS: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SUBMIT_COMMANDS");
		break;
	case IOCTL_KGSL_SYNCSOURCE_CREATE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SYNCSOURCE_CREATE");
		break;
	case IOCTL_KGSL_SYNCSOURCE_DESTROY: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SYNCSOURCE_DESTROY");
		break;
	case IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE");
		break;
	case IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE");
		break;
	case IOCTL_KGSL_CFF_SYNC_GPUOBJ: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_CFF_SYNC_GPUOBJ");
		break;
	case IOCTL_KGSL_GPUOBJ_ALLOC: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUOBJ_ALLOC");
		break;
	case IOCTL_KGSL_GPUOBJ_FREE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUOBJ_FREE");
		break;
	case IOCTL_KGSL_GPUOBJ_INFO: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUOBJ_INFO");
		break;
	case IOCTL_KGSL_GPUOBJ_IMPORT: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUOBJ_IMPORT");
		break;
	case IOCTL_KGSL_GPUOBJ_SYNC: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUOBJ_SYNC");
		break;
	case IOCTL_KGSL_GPU_COMMAND: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPU_COMMAND");
		break;
	case IOCTL_KGSL_PREEMPTIONCOUNTER_QUERY: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_PREEMPTIONCOUNTER_QUERY");
		break;
	case IOCTL_KGSL_GPUOBJ_SET_INFO: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_GPUOBJ_SET_INFO");
		break;
	case IOCTL_KGSL_SPARSE_PHYS_ALLOC: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SPARSE_PHYS_ALLOC");
		break;
	case IOCTL_KGSL_SPARSE_PHYS_FREE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SPARSE_PHYS_FREE");
		break;
	case IOCTL_KGSL_SPARSE_VIRT_ALLOC: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SPARSE_VIRT_ALLOC");
		break;
	case IOCTL_KGSL_SPARSE_VIRT_FREE: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SPARSE_VIRT_FREE");
		break;
	case IOCTL_KGSL_SPARSE_BIND: 
		pos += sprintf(ob + pos, "IOCTL_KGSL_SPARSE_BIND");
		break;
	case IOCTL_KGSL_GPU_SPARSE_COMMAND: 
		sprintf(ob + pos, "IOCTL_KGSL_GPU_SPARSE_COMMAND");
		break;
		default: pos += sprintf(ob + pos, "Code 0x%lx (unknown - tell J!)", code);
		} // switch code
	}

		
	else {	// ! mine..

			return 2;

	    } // end switch

	} // end if !Exit

   	else{
		if (mine) {

				mine = 0;
 			int rc = (int) getRegValue(REG_ARG_0);
			return 2;

		}


	}
	updateOutputBufferPos(pos);
   	return 0;
} // ioctl




int init = 0;
__attribute__((constructor)) void _init(void) {
	
	if (init) return;
	init++;	
	fprintf(stderr,"LOADED kgsl plugin, hooking ioctl\n");
	gColor = config_color();

	//if (getenv("KGSL") != NULL) 
	ignoreAllSyscalls();

	int rc= registerSyscallHandler ("ioctl", // char *SyscallName, // must exist or you'll get -1 
	        kgsl_ioctl,  // syscall_handler_func Handler,     // Your callback, per above
		0, //              int Bitness,     // 32, 64 or 0 (both)
		0);	//      int Flags);      // as per flags, above


}


