/*	Application Action
Key		: Test Action
F1		: make Blue Screen
F2		: Display VI_logo.bmp
F3		: Display String..
F4		: Clear Screen
ENTER	: Exit App
*/

#include	<stdio.h>
#include	<stdint.h>
#include	<string.h>		/* for memset */
#include	<unistd.h>		/* for open/close .. */
#include	<fcntl.h>		/* for O_RDWR */
#include	<sys/ioctl.h>	/* for ioctl */
#include	<sys/mman.h>	/* for mmap */
#include	<linux/fb.h>	/* for fb_var_screeninfo, FBIOGET_VSCREENINFO */
#include	<linux/input.h>
#include	<poll.h>
#include	"SDL.h"
#include	"SDL_ttf.h"


#define	DEV_LCD_BACKLIGHT			"/sys/class/backlight/backlight/brightness"

#define	TEST_IMAGE_FILE_1			"VI_logo_320_240_R90.jpg"
#define	TEST_IMAGE_FILE_2			"VI_logo_320_240_R270.jpg"
#define	TEST_FONT_FILE				"D2Coding.ttf"
#define	TEST_DISPLAY_STRING			"밸류이노베이션"
//#define	TEST_DISPLAY_STRING			"VI"

/*
#define	DEBUG_LOW_LEVEL_KEY_INPUT_INFO
*/
int	sdl_copy_surface( SDL_Surface *pDestination, int X, int Y, SDL_Surface *pSource )
{
	int			Result;
	SDL_Rect	Offset;	/* Make a temporary rectangle to hold the offsets */

	Result = -1;
	if ( ( pDestination != (SDL_Surface *)0 )
	 &&	( pSource != (SDL_Surface *)0 ) )
	{
		/* Give the offsets to the rectangle */
		Offset.x = X;
		Offset.y = Y;
		/* Blit the surface */
		Result = SDL_BlitSurface( pSource, NULL, pDestination, &Offset );
	}
	return	Result;
}

int	sdl_clear_surface( SDL_Surface *pDestination )
{
	if ( pDestination != (SDL_Surface *)0 )
	{
		if ( SDL_FillRect(pDestination, NULL, SDL_MapRGB(pDestination->format, 0, 0, 0)) < 0)
		{
			printf("clear surface fail! : %s\n", SDL_GetError());
		}
		else
		{
			printf("clear surface OK\n");
			SDL_Flip( pDestination );
		}
	}
}

int	bright_set(const uint8_t Brightness)
{
	FILE *	pDeviceFile;
	char	pString[10] = {0};
	int		StringLength;

	pDeviceFile = fopen(DEV_LCD_BACKLIGHT, "w+");
	if ( pDeviceFile == (FILE *)0 )
	{
		printf("failed to open back light device : %s\n", DEV_LCD_BACKLIGHT);
		return	-1;
	}

	sprintf(pString, "%d", Brightness);
	StringLength = (int)strlen(pString);

	if ( fwrite(pString, StringLength, 1, pDeviceFile) < 0 )
	{
		return	-1;
	}

	fclose(pDeviceFile);

	return	0;
}

int bright_get(uint8_t *pBrightness)
{
	FILE *	pDeviceFile;
	char	pCommand[128] = {0};
	char	pString[10] = {0};

	char buf[10] = {0};
	int level = 0;

	if ( pBrightness == (uint8_t *)0 )
	{
		printf("bright_get : Input Parameter error\n");
		return	-1;
	}

	sprintf(pCommand, "cat %s", DEV_LCD_BACKLIGHT);
	pDeviceFile = popen(pCommand, "r");
	if ( pDeviceFile == (FILE *)0 )
	{
		return	-1;
	}

	while( fgets(pString, 10, pDeviceFile) );
	*pBrightness = (uint8_t)strtoul(pString, NULL, 10);

	fclose(pDeviceFile);

	return	0;
}


int	main()
{
	SDL_Surface *	pScreen;
	SDL_Event		Event;
	char *			pGetENV;

#if	1
	pGetENV = SDL_getenv("SDL_VIDEODRIVER");
	if( pGetENV == (char *)0 )
	{
		printf("No ENV!\n");
		SDL_putenv("SDL_VIDEODRIVER=directfb");
	}
//	else
//	{
		printf("SDL_VIDEODRIVER=%s\n",SDL_getenv("SDL_VIDEODRIVER"));
//	}

#endif

	if ( SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL initialized Fail! : %s\n", SDL_GetError());
		return	-1;
	}
	else
	{
		printf("SDL initialized OK!\n");
	}

	pScreen = SDL_SetVideoMode(240, 320, 32, SDL_SWSURFACE);
	if( pScreen == (SDL_Surface *)0 )
	{
		printf("Fail to SetVideoMode !\n");
	}
	else
	{
		SDL_KeyboardEvent *	pKeyEvent;
		int					IsInLoop;
		uint8_t				Brightness;

		printf("Screen SDL SetVideoMode OK\n");

		printf("SDL Surface Address = 0x%X(%d)\n", (uint32_t)pScreen, (uint32_t)pScreen);
		printf("  flags          : 0x%08X\n", pScreen->flags);
//		SDL_PixelFormat *format;		/**< Read-only */
		printf("  w              : %d\n", pScreen->w);
		printf("  h              : %d\n", pScreen->h);
		printf("  pitch          : %d\n", pScreen->pitch);
		printf("  *pixels        : 0x%X(%d)\n", (uint32_t)pScreen->pixels, (uint32_t)pScreen->pixels);
		printf("  offset         : 0x%X(%d)\n", (uint32_t)pScreen->offset, (uint32_t)pScreen->offset);
//		struct private_hwdata *hwdata;		/** Hardware-specific surface info */
		/** clipping information */
//		SDL_Rect clip_rect;			/**< Read-only */
		/** Allow recursive locks */
		printf("  locked         : 0x%X(%d)\n", (uint32_t)pScreen->locked, (uint32_t)pScreen->locked);
		Uint32 locked;				/**< Private */
		/** info for fast blit mapping to other surfaces */
//		struct SDL_BlitMap *map;		/**< Private */
		/** format version, bumped at every change to invalidate blit maps */
		printf("  format_version : 0x%X(%d)\n", (uint32_t)pScreen->format_version, (uint32_t)pScreen->format_version);
		/** Reference count -- used when freeing surface */
		printf("  refcount       : 0x%X(%d)\n", (uint32_t)pScreen->refcount, (uint32_t)pScreen->refcount);

		SDL_ShowCursor(SDL_DISABLE/* SDL_ENABLE or SDL_DISABLE */);
		/* Must be clear action before doing other actions.. */
		sdl_clear_surface( pScreen );
//		SDL_Delay(1000/*ms*/);
//		sdl_clear_surface( pScreen );

		IsInLoop = 1;
		/* Start event loop */  
		while (IsInLoop)
		{
			if ( SDL_PollEvent( &Event ) == 0)	/* While there's an event to handle */
			{
				continue;
			}

			if ( ( Event.type == SDL_KEYDOWN ) || ( Event.type == SDL_KEYUP ) )
			{	/* Keys pressed or reased */
				pKeyEvent = (SDL_KeyboardEvent *)&Event;
				switch ( pKeyEvent->keysym.sym )
				{
				case	SDLK_BACKSPACE:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - BACKSPACE\n");
					}
					else
					{
						printf("SDL Event Keys release! - BACKSPACE\n");
					}
					break;
				case	SDLK_RETURN:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - RETURN\n");
					}
					else
					{
						printf("SDL Event Keys release! - RETURN\n");
						IsInLoop = 0;
					}
					break;
				case	SDLK_0:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 0\n");
					}
					else
					{
						printf("SDL Event Keys release! - 0\n");
					}
					break;
				case	SDLK_1:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 1\n");
					}
					else
					{
						printf("SDL Event Keys release! - 1\n");
					}
					break;
				case	SDLK_2:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 2\n");
					}
					else
					{
						printf("SDL Event Keys release! - 2\n");
					}
					break;
				case	SDLK_3:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 3\n");
					}
					else
					{
						printf("SDL Event Keys release! - 3\n");
					}
					break;
				case	SDLK_4:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 4\n");
					}
					else
					{
						printf("SDL Event Keys release! - 4\n");
					}
					break;
				case	SDLK_5:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 5\n");
					}
					else
					{
						printf("SDL Event Keys release! - 5\n");
					}
					break;
				case	SDLK_6:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 6\n");
					}
					else
					{
						printf("SDL Event Keys release! - 6\n");
					}
					break;
				case	SDLK_7:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 7\n");
					}
					else
					{
						printf("SDL Event Keys release! - 7\n");
					}
					break;
				case	SDLK_8:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 8\n");
					}
					else
					{
						printf("SDL Event Keys release! - 8\n");
					}
					break;
				case	SDLK_9:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - 9\n");
					}
					else
					{
						printf("SDL Event Keys release! - 9\n");
					}
					break;
				case	SDLK_F1:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - F1\n");
					}
					else
					{
						printf("SDL Event Keys release! - F1\n");
						if ( SDL_FillRect(pScreen, NULL, SDL_MapRGB(pScreen->format, 255/*B*/, 0/*G*/, 0/*R*/)) < 0)
						{
							printf("SDL_FillRect Fail! : %s\n", SDL_GetError());
						}
						else
						{
							printf("SDL_FillRect OK\n");
							SDL_Flip( pScreen );
						}
					}
					break;
				case	SDLK_F2:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - F2\n");
					}
					else
					{
						SDL_Surface *	pBMP;
						printf("SDL Event Keys release! - F2\n");

						pBMP = SDL_LoadBMP("logo.bmp");
						if( pBMP == (SDL_Surface *)0 )
						{
							printf("Fail to SDL_LoadBMP !\n");
						}
						else
						{
							printf("BMP SDL LoadBMP OK\n");

							printf("BMP Surface Address = 0x%X(%d)\n", (uint32_t)pBMP, (uint32_t)pBMP);
							printf("  flags          : 0x%08X\n", pBMP->flags);
						//	SDL_PixelFormat *format;		/**< Read-only */
							printf("  w              : %d\n", pBMP->w);
							printf("  h              : %d\n", pBMP->h);
							printf("  pitch          : %d\n", pBMP->pitch);
							printf("  *pixels        : 0x%X(%d)\n", (uint32_t)pBMP->pixels, (uint32_t)pBMP->pixels);
							printf("  offset         : 0x%X(%d)\n", (uint32_t)pBMP->offset, (uint32_t)pBMP->offset);
						//	struct private_hwdata *hwdata;		/** Hardware-specific surface info */
							/** clipping information */
						//	SDL_Rect clip_rect;			/**< Read-only */
							/** Allow recursive locks */
							printf("  locked         : 0x%X(%d)\n", (uint32_t)pBMP->locked, (uint32_t)pBMP->locked);
							Uint32 locked;				/**< Private */
							/** info for fast blit mapping to other surfaces */
						//	struct SDL_BlitMap *map;		/**< Private */
							/** format version, bumped at every change to invalidate blit maps */
							printf("  format_version : 0x%X(%d)\n", (uint32_t)pBMP->format_version, (uint32_t)pBMP->format_version);
							/** Reference count -- used when freeing surface */
							printf("  refcount       : 0x%X(%d)\n", (uint32_t)pBMP->refcount, (uint32_t)pBMP->refcount);

						//	SDL_BlitSurface( pBMP, NULL, pScreen, NULL );
							sdl_copy_surface( pScreen, 0/*X*/, 0/*Y*/, pBMP );

						    // 화면을 갱신
							SDL_Flip( pScreen );
							SDL_FreeSurface( pBMP );
						}
					}
					break;
				case	SDLK_F3:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - F3\n");
					}
					else
					{
						SDL_Surface *	pText;
						TTF_Font *		pFont;
						SDL_Color		pTextColor = { 255, 255, 255 };	/* The color of the font */

						printf("SDL Event Keys release! - F3\n");

						if( TTF_Init() < 0 )
						{
							printf("Fail to TTF_Init !\n");
						}
						else
						{
							printf("OK to TTF_Init !\n");
							/* Open the font */
							pFont = TTF_OpenFont( TEST_FONT_FILE, 28 );
						    /* If there was an error in loading the font */
						    if( pFont == (TTF_Font *)0 )
						    {
								printf("Fail to TTF_OpenFont !\n");
						    }
							else
							{
								printf("OK to TTF_OpenFont !\n");

								/* 한글 출력을 위해 TTF_RenderUTF8_Solid 사용 */
								/* For display HanGul using TTF_RenderUTF8_Solid */
								pText = TTF_RenderUTF8_Solid( pFont, TEST_DISPLAY_STRING, pTextColor );	/* Render the text */
/*
TTF_RenderText_Solid	  	Draw LATIN1 text in solid mode
TTF_RenderUTF8_Solid	  	Draw UTF8 text in solid mode
TTF_RenderUNICODE_Solid	  	Draw UNICODE text in solid mode
TTF_RenderGlyph_Solid	  	Draw a UNICODE glyph in solid mode
*/
								/* If there was an error in rendering the text */
								if( pText == (SDL_Surface *)0 )
								{
									printf("Fail to TTF_RenderText_Solid !\n");
								}
								else
								{
									printf("OK to TTF_RenderText_Solid !\n");

									/* Apply the images to the screen */
									sdl_copy_surface( pScreen, 0/*X*/, 150/*Y*/, pText );
								    /* Update the screen */
									SDL_Flip( pScreen );

									/* Free the text surface */
									SDL_FreeSurface( pText );
								}
								/* Close the font that was used */
								TTF_CloseFont( pFont );
							}
							/* Quit SDL_ttf */
							TTF_Quit();
						}
					}
					break;
				case	SDLK_F4:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - F4\n");
					}
					else
					{
						printf("SDL Event Keys release! - F4\n");
						if ( sdl_clear_surface( pScreen ) != 0 )
						{
							printf("clar scrren fail\n");
						}
						else
						{
							printf("clar scrren OK\n");
						}
					}
					break;
				case	SDLK_F5:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - F5\n");
					}
					else
					{
						printf("SDL Event Keys release! - F5\n");
					}
					break;
				case	SDLK_F6:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - F6\n");
					}
					else
					{
						printf("SDL Event Keys release! - F6\n");
						if( Brightness != 7 )
						{
							Brightness ++;
							if( bright_set(Brightness) != 0 )
							{
								printf("Fail to bright_set\n");
							}
							printf("bright -\n");
						}
					}
					break;
				case	SDLK_F7:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - F7\n");
					}
					else
					{
						printf("SDL Event Keys release! - F7\n");
						if( Brightness != 0 )
						{
							Brightness --;
							if( bright_set(Brightness) != 0 )
							{
								printf("Fail to bright_set\n");
							}
							printf("bright +\n");
						}
					}
					break;
				default:
					if ( Event.type == SDL_KEYDOWN )
					{
						printf("SDL Event Keys pressed! - ??\n");
					}
					else
					{
						printf("SDL Event Keys release! - ??\n");
					}
					break;
				}
#ifdef	DEBUG_LOW_LEVEL_KEY_INPUT_INFO
				printf(" The keyboard device index = %d\n", pKeyEvent->which);
				printf(" The SDL_PRESSED or SDL_RELEASED = %d\n", pKeyEvent->state);
				printf(" hardware specific scancode = %d\n", pKeyEvent->keysym.scancode);
				printf(" SDL virtual keysym = %d\n", pKeyEvent->keysym.sym);
				printf(" current key modifiers = %d\n", pKeyEvent->keysym.mod);
				printf(" translated character = %d\n", pKeyEvent->keysym.unicode);
#endif
			}
			else
			{
				switch (Event.type)
				{
				case	SDL_ACTIVEEVENT:	/**< Application loses/gains visibility */
					printf("SDL Event Application loses/gains visibility!\n");
					break;
				case	SDL_KEYDOWN:		/**< Keys pressed */
					printf("SDL Event Keys pressed!\n");
					break;
				case	SDL_KEYUP:			/**< Keys released */
					printf("SDL Event Keys released!\n");
					break;
				case	SDL_MOUSEMOTION:	/**< Mouse moved */
					printf("SDL Event Mouse moved!\n");
					break;
				case	SDL_MOUSEBUTTONDOWN:/**< Mouse button pressed */
					printf("SDL Event Mouse button pressed!\n");
					break;
				case	SDL_MOUSEBUTTONUP:	/**< Mouse button released */
					printf("SDL Event Mouse button released!\n");
					break;
				case	SDL_JOYAXISMOTION:	/**< Joystick axis motion */
					printf("SDL Event Joystick axis motion!\n");
					break;
				case	SDL_JOYBALLMOTION:	/**< Joystick trackball motion */
					printf("SDL Event Joystick trackball motion!\n");
					break;
				case	SDL_JOYHATMOTION:	/**< Joystick hat position change */
					printf("SDL Event Joystick hat position change!\n");
					break;
				case	SDL_JOYBUTTONDOWN:	/**< Joystick button pressed */
					printf("SDL Event Joystick button pressed!\n");
					break;
				case	SDL_JOYBUTTONUP:	/**< Joystick button released */
					printf("SDL Event Joystick button released!\n");
					break;
				case	SDL_QUIT:			/**< User-requested quit */
					printf("SDL Event User-requested quit!\n");
					break;
				case	SDL_SYSWMEVENT:		/**< System specific event */
					printf("SDL Event System specific!\n");
					break;
				case	SDL_EVENT_RESERVEDA:/**< Reserved for future use.. */
					printf("SDL Event reserved!\n");
					break;
				case	SDL_EVENT_RESERVEDB:/**< Reserved for future use.. */
					printf("SDL Event reserved!\n");
					break;
				case	SDL_VIDEORESIZE:	/**< User resized video mode */
					printf("SDL Event User resized video mode!\n");
					break;
				case	SDL_VIDEOEXPOSE:	/**< Screen needs to be redrawn */
					printf("SDL Event Screen needs to be redrawn!\n");
					break;
				case	SDL_EVENT_RESERVED2:/**< Reserved for future use.. */
				case	SDL_EVENT_RESERVED3:/**< Reserved for future use.. */
				case	SDL_EVENT_RESERVED4:/**< Reserved for future use.. */
				case	SDL_EVENT_RESERVED5:/**< Reserved for future use.. */
				case	SDL_EVENT_RESERVED6:/**< Reserved for future use.. */
				case	SDL_EVENT_RESERVED7:/**< Reserved for future use.. */
					printf("SDL Event reserved!\n");
					break;
				case	SDL_USEREVENT:
					printf("SDL Event user!\n");
					break;
				default:
					printf("SDL Event unknown!\n");
					break;
				}
			}
		}

		SDL_FreeSurface( pScreen );
	}

	SDL_Quit();
	return	0;
}
/*
# modetest
trying to open device 'i915'...failed
trying to open device 'amdgpu'...failed
trying to open device 'radeon'...failed
trying to open device 'nouveau'...failed
trying to open device 'vmwgfx'...failed
trying to open device 'omapdrm'...failed
trying to open device 'exynos'...failed
trying to open device 'tilcdc'...failed
trying to open device 'msm'...failed
trying to open device 'sti'...failed
trying to open device 'tegra'...failed
trying to open device 'imx-drm'...failed
trying to open device 'rockchip'...failed
trying to open device 'atmel-hlcdc'...done
Encoders:
id      crtc    type    possible crtcs  possible clones
23      31      none    0x00000001      0x00000000

Connectors:
id      encoder status          name            size (mm)       modes   encoders
24      23      connected       unknown-1       49x65           1       23
  modes:
        name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
  240x320 70 240 250 270 280 320 322 326 328 6549 flags: phsync, pvsync; type: preferred, driver
  props:
        1 EDID:
                flags: immutable blob
                blobs:

                value:
        2 DPMS:
                flags: enum
                enums: On=0 Standby=1 Suspend=2 Off=3
                value: 0

CRTCs:
id      fb      pos     size
31      34      (0,0)   (240x320)
  240x320 70 240 250 270 280 320 322 326 328 6549 flags: phsync, pvsync; type: preferred, driver
  props:

Planes:
id      crtc    fb      CRTC x,y        x,y     gamma size      possible crtcs
27      31      34      0,0             0,0     0               0x00000001
  formats: XR12 AR12 RA12 AR15 RG16 RG24 XR24 AR24 RA24
  props:
        5 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 1
        26 rotation:
                flags: bitmask
                values: rotate-0=0x1 rotate-90=0x2 rotate-180=0x4 rotate-270=0x8
                value: 1
28      0       0       0,0             0,0     0               0x00000001
  formats: XR12 AR12 RA12 AR15 RG16 RG24 XR24 AR24 RA24
  props:
        5 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 0
        25 alpha:
                flags: range
                values: 0 255
                value: 255
        26 rotation:
                flags: bitmask
                values: rotate-0=0x1 rotate-90=0x2 rotate-180=0x4 rotate-270=0x8
                value: 1
29      0       0       0,0             0,0     0               0x00000001
  formats: XR12 AR12 RA12 AR15 RG16 RG24 XR24 AR24 RA24
  props:
        5 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 0
        25 alpha:
                flags: range
                values: 0 255
                value: 255
        26 rotation:
                flags: bitmask
                values: rotate-0=0x1 rotate-90=0x2 rotate-180=0x4 rotate-270=0x8
                value: 1
30      0       0       0,0             0,0     0               0x00000001
  formats: XR12 AR12 RA12 AR15 RG16 RG24 XR24 AR24 RA24 AYUV YUYV UYVY YVYU VYUY NV21 NV61 YU16 YU12
  props:
        5 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 0
        25 alpha:
                flags: range
                values: 0 255
                value: 255
        26 rotation:
                flags: bitmask
                values: rotate-0=0x1 rotate-90=0x2 rotate-180=0x4 rotate-270=0x8
                value: 1

Frame buffers:
id      size    pitch

*/

