#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	"directfb.h"

/*
DirectFB support still image type
	jpg
	png
	gif

*/

/*	Application Action
Key		: Test Action
F1		: Display VI_logo_320_240_R90.jpg
F2		: Display VI_logo_320_240_R270.jpg
F3		: Draw Blue Box
F4		: Clear Screen
F5		: Display String..
ENTER	: Exit App

*/

#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			"밸류이노베이션" //"VI"

/*
	0: No key input or Parameter Error
	1: Key is inputed
*/
int		directfb_key_is_inputed(IDirectFBEventBuffer *pEventBuffer, uint32_t MiliSecondWaitTimeout)
{
	if ( pEventBuffer == (IDirectFBEventBuffer *)0 )
	{
		return	0;
	}
	if ( pEventBuffer->WaitForEventWithTimeout( pEventBuffer, 0, MiliSecondWaitTimeout ) == DFB_TIMEOUT )
	{
		return	0;
	}

	return	1;
}

/*
#define	DEBUG_LOW_LEVEL_KEY_INPUT_INFO
*/
/*
	0: OK
	-1: Error
*/
int		directfb_key_get_code(IDirectFBEventBuffer *pEventBuffer, uint32_t *pKeyCode, uint32_t *pIsReleased)
{
	DFBInputEvent	InputEvent;

	if ( ( pEventBuffer != (IDirectFBEventBuffer *)0 ) && ( pKeyCode != (uint32_t *)0 ) )
	{
		if ( pEventBuffer->GetEvent ( pEventBuffer, DFB_EVENT( &InputEvent ) ) == DFB_OK )
		{
#ifdef	DEBUG_LOW_LEVEL_KEY_INPUT_INFO
			printf("Input Event : Type = %d, Key ID = %d\n", InputEvent.type, InputEvent.key_id);
			printf("      clazz = %d  clazz of event\n", InputEvent.clazz);
			switch (InputEvent.clazz)
			{
			case	DFEC_NONE:
				printf("          none of these\n");
				break;
			case	DFEC_INPUT:
				printf("          raw input event\n");
				break;
			case	DFEC_WINDOW:
				printf("          windowing event\n");
				break;
			case	DFEC_USER:
				printf("          custom event for the user of this library\n");
				break;
			case	DFEC_UNIVERSAL:
				printf("          universal event for custom usage with variable size\n");
				break;
			case	DFEC_VIDEOPROVIDER:
				printf("          video provider event\n");
				break;
			case	DFEC_SURFACE:
				printf("          surface event\n");
				break;
			default:
				printf("          unknown\n");
				break;
			}
			printf("      type = %d  type of event\n", InputEvent.type);
			switch (InputEvent.type)
			{
			case	DIET_UNKNOWN:
				printf("          unknown event\n");
				break;
			case	DIET_KEYPRESS:
				printf("          a key is been pressed\n");
				break;
			case	DIET_KEYRELEASE:
				printf("          a key is been released\n");
				break;
			case	DIET_BUTTONPRESS:
				printf("          a (mouse) button is been pressed\n");
				break;
			case	DIET_BUTTONRELEASE:
				printf("          a (mouse) button is been released\n");
				break;
			case	DIET_AXISMOTION:
				printf("          mouse/joystick movement\n");
				break;
			default:
				printf("          unknown\n");
				break;
			}
			printf("      device_id = %d  source of event\n", InputEvent.device_id);
			printf("      flags = %d  which optional fields are valid\n", InputEvent.flags);
			if ( InputEvent.flags == DIEF_NONE)
			{
				printf("          no additional fields\n");
			}
			if ( (InputEvent.flags & DIEF_TIMESTAMP) == DIEF_TIMESTAMP)
			{
				printf("          timestamp is valid\n");
			}
			if ( (InputEvent.flags & DIEF_AXISABS) == DIEF_AXISABS)
			{
				printf("          axis and axisabs are valid\n");
			}
			if ( (InputEvent.flags & DIEF_AXISREL) == DIEF_AXISREL)
			{
				printf("          axis and axisrel are valid\n");
			}
			if ( (InputEvent.flags & DIEF_KEYCODE) == DIEF_KEYCODE)
			{
				printf("          DIEF_KEYCODE used internally by the input core, always set at application level\n");
			}
			if ( (InputEvent.flags & DIEF_KEYID) == DIEF_KEYID)
			{
				printf("          DIEF_KEYID used internally by the input core, always set at application level\n");
			}
			if ( (InputEvent.flags & DIEF_KEYSYMBOL) == DIEF_KEYSYMBOL)
			{
				printf("          DIEF_KEYSYMBOL used internally by the input core, always set at application level\n");
			}
			if ( (InputEvent.flags & DIEF_MODIFIERS) == DIEF_MODIFIERS)
			{
				printf("          DIEF_MODIFIERS used internally by the input core, always set at application level\n");
			}
			if ( (InputEvent.flags & DIEF_LOCKS) == DIEF_LOCKS)
			{
				printf("          DIEF_LOCKS used internally by the input core, always set at application level\n");
			}
			if ( (InputEvent.flags & DIEF_BUTTONS) == DIEF_BUTTONS)
			{
				printf("          DIEF_BUTTONS used internally by the input core, always set at application level\n");
			}
			if ( (InputEvent.flags & DIEF_GLOBAL) == DIEF_GLOBAL)
			{
				printf("          Only for event buffers creates by IDirectFB::CreateInputEventBuffer() with global events enabled\n");
				/* Indicates that the event would have been filtered if the buffer hadn't been global. */
			}
			if ( (InputEvent.flags & DIEF_REPEAT) == DIEF_REPEAT)
			{
				printf("          repeated event, e.g. key or button press\n");
			}
			if ( (InputEvent.flags & DIEF_FOLLOW) == DIEF_FOLLOW)
			{
				printf("          another event will follow immediately, e.g. x/y axis\n");
			}
			if ( (InputEvent.flags & DIEF_MIN) == DIEF_MIN)
			{
				printf("          minimum value is set, e.g. for absolute axis motion\n");
			}
			if ( (InputEvent.flags & DIEF_MAX) == DIEF_MAX)
			{
				printf("          maximum value is set, e.g. for absolute axis motion\n");
			}
			printf("   additionally (check flags)\n");
//	struct timeval                  timestamp;  /* time of event creation */
			printf("   DIET_KEYPRESS, DIET_KEYRELEASE\n");
			printf("      key_code = %d  hardware keycode, no mapping, -1 if device doesn't differentiate between several keys\n", InputEvent.key_code);
//	DFBInputDeviceKeyIdentifier     key_id;     /* basic mapping, modifier independent */
//	DFBInputDeviceKeySymbol         key_symbol; /* advanced mapping, unicode compatible, modifier dependent */
			printf("   additionally (check flags)\n");
			printf("      modifiers = 0x%X  pressed modifiers (optional)\n", InputEvent.modifiers);
#if	0
DIMM_SHIFT     = (1 << DIMKI_SHIFT),    /* Shift key is pressed */
DIMM_CONTROL   = (1 << DIMKI_CONTROL),  /* Control key is pressed */
DIMM_ALT       = (1 << DIMKI_ALT),      /* Alt key is pressed */
DIMM_ALTGR     = (1 << DIMKI_ALTGR),    /* AltGr key is pressed */
DIMM_META      = (1 << DIMKI_META),     /* Meta key is pressed */
DIMM_SUPER     = (1 << DIMKI_SUPER),    /* Super key is pressed */
DIMM_HYPER     = (1 << DIMKI_HYPER)     /* Hyper key is pressed */
#endif
//	DFBInputDeviceLockState         locks;      /* active locks (optional) */
			printf("   DIET_BUTTONPRESS, DIET_BUTTONRELEASE\n");
			printf("      button = %d  in case of a button event Left=0, Right=1, Middle=2\n", InputEvent.button);
			printf("      buttons = %d  mask of currently pressed buttons Left=1, Right=2, Middle=4\n", InputEvent.buttons);
			printf("   DIET_AXISMOTION\n");
			printf("      axis = %d  in case of an axis event X=0, Y=1, Z=2\n", InputEvent.axis);
			printf("   one of these two (check flags) : mouse/joystick\n");
			printf("      axisabs = %d  absolute mouse/joystick coordinate\n", InputEvent.axisabs);
			printf("      axisrel = %d  relative mouse/joystick movement\n", InputEvent.axisrel);
			printf("   general information\n");
			printf("      min = %d\n", InputEvent.min);
			printf("      max = %d\n", InputEvent.max);
#endif
			if ( (InputEvent.flags & DIEF_KEYCODE) == DIEF_KEYCODE )
			{
				if ( ( InputEvent.type == DIET_KEYPRESS ) || ( InputEvent.type == DIET_KEYRELEASE ) )
				{
					*pKeyCode = InputEvent.key_code;
					if ( InputEvent.type == DIET_KEYPRESS )
					{
						*pIsReleased = 0;
					}
					else /*if ( InputEvent.type == DIET_KEYRELEASE )*/
					{
						*pIsReleased = 1;
					}
					return	0;
				}
			}
		}
	}
	return	-1;
}


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 )
	{
		printf("write error(%d) : %s\n", StringLength, strerror(errno) );
		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 )
	{
		printf("failed to popen  %s - %s\n", pCommand,  strerror(errno) );
		return	-1;
	}

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

	fclose(pDeviceFile);

	return	0;
}

int		main()
{
	IDirectFB *				pDirectFb;
	IDirectFBInputDevice *	pInputDevice;
	IDirectFBEventBuffer *	pEventBuffer;
	IDirectFBSurface *		pPrimarySurface;	/* primary surface - Base Screen */
	IDirectFBFont *			pFont;
	DFBSurfaceDescription	SurfaceDescription;
    DFBResult				Result;

	int						nScreenWidth = 0;
	int						nScreenHeight = 0;
	int						IsInLoop;

	uint32_t				KeyCode;
	uint32_t				IsReleased;

	uint8_t					Brightness;


	Result = DirectFBInit(0,0);
	if ( Result != DFB_OK )
	{
		printf( "DirectFBInit Fail!\n");
		return	-1;
	}
	printf( "DirectFBInit OK\n");

	/*	create super interface. */
	Result = DirectFBCreate(&pDirectFb);
	if ( Result != DFB_OK )
	{
		printf( "DirectFBCreate Fail!\n");
		return	-1;
	}
	printf( "DirectFBCreate OK\n");

	Result = pDirectFb->GetInputDevice( pDirectFb, DIDID_KEYBOARD, &pInputDevice );
	if ( Result != DFB_OK )
	{
		printf( "GetInputDevice Fail!\n");
		pDirectFb->Release( pDirectFb );
		return	-1;
	}
	printf( "GetInputDevice OK\n");

	Result = pInputDevice->CreateEventBuffer( pInputDevice, &pEventBuffer );
	if ( Result != DFB_OK )
	{
		printf( "GetInputDevice Fail!\n");
		pDirectFb->Release( pDirectFb );
		pInputDevice->Release( pInputDevice );
		return	-1;
	}
	printf( "GetInputDevice OK\n");

	Result = pDirectFb->SetCooperativeLevel(pDirectFb, DFSCL_FULLSCREEN);
	if ( Result != DFB_OK )
	{
		printf( "SetCooperativeLevel Fail!\n");
		pEventBuffer->Release( pEventBuffer );
		pInputDevice->Release( pInputDevice );
		pDirectFb->Release( pDirectFb );
		return	-1;
	}
	printf( "SetCooperativeLevel OK\n");

	/* set flags */
	SurfaceDescription.flags = DSDESC_CAPS;
	SurfaceDescription.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;
	/* create surface */
	Result = pDirectFb->CreateSurface(pDirectFb, &SurfaceDescription, &pPrimarySurface);
	if ( Result != DFB_OK )
	{
		printf( "CreateSurface Fail!\n");
		pEventBuffer->Release( pEventBuffer );
		pInputDevice->Release( pInputDevice );
		pDirectFb->Release( pDirectFb );
		return	-1;
	}
	printf( "CreateSurface OK\n");

	/* get surface size */
	Result = pPrimarySurface->GetSize(pPrimarySurface, &nScreenWidth, &nScreenHeight);
	if ( Result != DFB_OK )
	{
		printf( "Get Screen Size Fail!\n");
		pEventBuffer->Release( pEventBuffer );
		pInputDevice->Release( pInputDevice );
		pPrimarySurface->Release( pPrimarySurface );
		pDirectFb->Release( pDirectFb );
		return	-1;
	}
	printf("Width: %d, Height: %d\n", nScreenWidth, nScreenHeight);

	/* clear surface */
	Result = pPrimarySurface->FillRectangle (pPrimarySurface, 0, 0, nScreenWidth, nScreenHeight);
	if ( Result != DFB_OK )
	{
		printf( "FillRectangle to clear surface Fail!\n");
		pEventBuffer->Release( pEventBuffer );
		pInputDevice->Release( pInputDevice );
		pPrimarySurface->Release( pPrimarySurface );
		pDirectFb->Release( pDirectFb );
		return	-1;
	}
	printf( "FillRectangle to clear surface OK!\n");

	if ( bright_get(&Brightness) != 0 )
	{
		printf("Fail to bright_get()\n");
	}
	else
	{
		printf("Brightness == %d\n", Brightness);
	}
	Brightness = 7;	/* */
	if( bright_set(Brightness) != 0 )
	{
		printf("Fail to bright_set(0)\n");
	}

	IsInLoop = 1;
	/* Start event loop */  
	while (IsInLoop)
	{
		if ( directfb_key_is_inputed( pEventBuffer, 100/*100ms MiliSecondWaitTimeout*/) == 0 )
		{
			continue;
		}

		while ( directfb_key_get_code(pEventBuffer, &KeyCode, &IsReleased) == 0 )
		{
			switch (KeyCode)
			{
			case	KEY_ESC:
				printf("Key Code : KEY_ESC (0x%X)\n", KeyCode);
				break;
			case	KEY_1:
				printf("Key code : KEY_1 (0x%X)\n", KeyCode);
				break;
			case	KEY_2:
				printf("Key code : KEY_2 (0x%X)\n", KeyCode);
				break;
			case	KEY_3:
				printf("Key code : KEY_3 (0x%X)\n", KeyCode);
				break;
			case	KEY_4:
				printf("Key code : KEY_4 (0x%X)\n", KeyCode);
				break;
			case	KEY_5:
				printf("Key code : KEY_5 (0x%X)\n", KeyCode);
				break;
			case	KEY_6:
				printf("Key code : KEY_6 (0x%X)\n", KeyCode);
				break;
			case	KEY_7:
				printf("Key code : KEY_7 (0x%X)\n", KeyCode);
				break;
			case	KEY_8:
				printf("Key code : KEY_8 (0x%X)\n", KeyCode);
				break;
			case	KEY_9:
				printf("Key code : KEY_9 (0x%X)\n", KeyCode);
				break;
			case	KEY_0:
				printf("Key code : KEY_0 (0x%X)\n", KeyCode);
				break;
			case	KEY_BACKSPACE:
				printf("Key code : KEY_BACKSPACE (0x%X)\n", KeyCode);
				break;
			case	KEY_ENTER:
				printf("Key code : KEY_ENTER (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{	/* Key Released */
					IsInLoop = 0;	/* Exit */
				}
				break;
			case	KEY_F1:
				printf("Key code : KEY_F1 (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{
					IDirectFBSurface *		pImageSurface;	/* Image surface */
					IDirectFBImageProvider *pImageProvider;	/* */
			       /* Create image provider */
					if ( pDirectFb->CreateImageProvider( pDirectFb, TEST_IMAGE_FILE_1, &pImageProvider ) == DFB_OK )
					{
						printf("CreateImageProvider : open %s\n", TEST_IMAGE_FILE_1);
						pImageProvider->GetSurfaceDescription(pImageProvider, &SurfaceDescription);
						if ( pDirectFb->CreateSurface(pDirectFb, &SurfaceDescription, &pImageSurface) == DFB_OK )
						{
							printf("CreateSurface : OK to creat Image Surface\n");
							if ( pImageProvider->RenderTo(pImageProvider, pImageSurface, NULL) == DFB_OK )
							{
								printf("RenderTo : OK to rander Pmage provider to Image Surface\n");
								if ( pPrimarySurface->Blit(pPrimarySurface, pImageSurface, NULL, 0, 0) == DFB_OK )
								{
									printf("Blit : OK to copy Image Surface to Screen Surface\n");
									if ( pPrimarySurface->Flip(pPrimarySurface, NULL, 0) == DFB_OK )
									{
										printf("Update Surface OK\n");
									}
									else
									{
										printf("Update(Flip) Fail!\n");
									}
								}
								else
								{
									printf("Blit : fail to copy Image Surface to Screen Surface\n");
								}
							}
							else
							{
								printf("RenderTo : fail to rander Pmage provider to Image Surface\n");
							}
							pImageSurface->Release( pImageSurface );
						}
						else
						{
							printf("CreateSurface : fail to creat Image Surface\n");
						}
						pImageProvider->Release( pImageProvider );
					}
					else
					{
						printf("CreateImageProvider : Faile to open %s\n", TEST_IMAGE_FILE_1);
					}
				}
				break;
			case	KEY_F2:
				printf("Key code : KEY_F2 (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{
					IDirectFBSurface *		pImageSurface;	/* Image surface */
					IDirectFBImageProvider *pImageProvider;	/* */
			       /* Create image provider */
					if ( pDirectFb->CreateImageProvider( pDirectFb, TEST_IMAGE_FILE_2, &pImageProvider ) == DFB_OK )
					{
						printf("CreateImageProvider : open %s\n", TEST_IMAGE_FILE_2);
						pImageProvider->GetSurfaceDescription(pImageProvider, &SurfaceDescription);
						if ( pDirectFb->CreateSurface(pDirectFb, &SurfaceDescription, &pImageSurface) == DFB_OK )
						{
							printf("CreateSurface : OK to creat Image Surface\n");
							if ( pImageProvider->RenderTo(pImageProvider, pImageSurface, NULL) == DFB_OK )
							{
								printf("RenderTo : OK to rander Pmage provider to Image Surface\n");
								if ( pPrimarySurface->Blit(pPrimarySurface, pImageSurface, NULL, 0, 0) == DFB_OK )
								{
									printf("Blit : OK to copy Image Surface to Screen Surface\n");
									if ( pPrimarySurface->Flip(pPrimarySurface, NULL, 0) == DFB_OK )
									{
										printf("Update Surface OK\n");
									}
									else
									{
										printf("Update(Flip) Fail!\n");
									}
								}
								else
								{
									printf("Blit : fail to copy Image Surface to Screen Surface\n");
								}
							}
							else
							{
								printf("RenderTo : fail to rander Pmage provider to Image Surface\n");
							}
							pImageSurface->Release( pImageSurface );
						}
						else
						{
							printf("CreateSurface : fail to creat Image Surface\n");
						}
						pImageProvider->Release( pImageProvider );
					}
					else
					{
						printf("CreateImageProvider : Faile to open %s\n", TEST_IMAGE_FILE_2);
					}
				}
				break;
			case	KEY_F3:
				printf("Key code : KEY_F3 (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{	/* Key Released */
					if ( pPrimarySurface->SetColor(pPrimarySurface, 0xFF/*B*/, 0x00/*G*/, 0x00/*R*/, 0xFF/*A*/) == DFB_OK )
					{	/* set surface color -> Blue */
						printf( "SetColor OK!\n");
						/* draw rectangle */
						printf("Draw Rectangle\n");
						if ( pPrimarySurface->FillRectangle (pPrimarySurface, 100/*x*/, 100/*y*/, 40/*w*/, 80/*h*/) == DFB_OK )
						{
							printf( "FillRectangle OK!\n");
							/* update surface */
							printf("Update Surface\n");
							if ( pPrimarySurface->Flip(pPrimarySurface, NULL, 0) == DFB_OK )
							{
								printf("Update Surface OK\n");
							}
							else
							{
								printf("Update(Flip) Fail!\n");
							}
						}
						else
						{
							printf( "FillRectangle Fail!\n");
						}
					}
					else
					{
						printf( "SetColor Fail!\n");
					}
				}
				break;
			case	KEY_F4:
				printf("Key code : KEY_F4 (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{	/* Key Released */
					/* clear surface */
					if ( pPrimarySurface->SetColor(pPrimarySurface, 0x00/*B*/, 0x00/*G*/, 0x00/*R*/, 0xFF/*A*/) == DFB_OK )
					{	/* set surface color -> Blue */
						printf( "SetColor to clear surface OK!\n");
						/* draw rectangle */
						printf("Draw Rectangle to clear surface \n");
						if ( pPrimarySurface->FillRectangle (pPrimarySurface, 0, 0, nScreenWidth, nScreenHeight) == DFB_OK )
						{
							printf( "FillRectangle to clear surface OK!\n");
							/* update surface */
							printf("Update Surface to clear surface \n");
							if ( pPrimarySurface->Flip(pPrimarySurface, NULL, 0) == DFB_OK )
							{
								printf("Update Surface to clear surface OK\n");
							}
							else
							{
								printf("Update(Flip) to clear surface Fail!\n");
							}
						}
						else
						{
							printf("FillRectangle to clear surface Fail!\n");
						}
					}
					else
					{
						printf("SetColor to clear surface Fail!\n");
					}
				}
				break;
			case	KEY_F5:
				printf("Key code : KEY_F5 (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{
					DFBFontDescription	FontDescription;
					int					FongHeight;

					FontDescription.flags      = DFDESC_HEIGHT | DFDESC_ATTRIBUTES;
					FontDescription.height     = 22;
					FontDescription.attributes = DFFA_MONOCHROME;	//	DFFA_NONE
					if ( pDirectFb->CreateFont( pDirectFb, TEST_FONT_FILE, &FontDescription, &pFont ) == DFB_OK )
					{
						printf("CreateFont : OK -  %s\n", TEST_FONT_FILE);
						pFont->GetHeight( pFont, &FongHeight );
						if ( pPrimarySurface->SetFont( pPrimarySurface, pFont ) == DFB_OK )
						{
							printf("SetFont OK\n");
							if ( pPrimarySurface->SetColor( pPrimarySurface, 0xA0, 0xA0, 0xA0, 0xFF ) == DFB_OK )
							{
								printf("SetColor(Font Color) OK\n");
								if ( pPrimarySurface->DrawString( pPrimarySurface, TEST_DISPLAY_STRING, -1/*Bytes*/, 100/*X*/, 100/*Y*/, DSTF_CENTER/*Flasg*/ ) == DFB_OK )
								/*	Flasg
								DSTF_NONE
							 	DSTF_LEFT
							 	DSTF_CENTER
							 	DSTF_RIGHT
							 	DSTF_TOP
							 	DSTF_BOTTOM
							 	DSTF_OUTLINE
							 	DSTF_BLEND_FUNCS
							 	DSTF_TOPLEFT
							 	DSTF_TOPCENTER
							 	DSTF_TOPRIGHT
							 	DSTF_BOTTOMLEFT
							 	DSTF_BOTTOMCENTER
							 	DSTF_BOTTOMRIGHT
							 	*/
								{
									printf("DrawString OK\n");
									/* update surface */
									printf("Update Surface to show string \n");
									if ( pPrimarySurface->Flip(pPrimarySurface, NULL, 0) == DFB_OK )
									{
										printf("Update Surface to show string OK\n");
									}
									else
									{
										printf("Update(Flip) to show string Fail!\n");
									}
								}
								else
								{
									printf("DrawString Fail\n");
								}
							}
							else
							{
								printf("SetColor(Font Color) Fail\n");
							}
						}
						else
						{
							printf("SetFont Fail\n");
						}

						pFont->Release( pFont );
					}
					else
					{
						printf("CreateFont Fail!\n");
					}
				}
				break;
			case	KEY_F6:
				printf("Key code : KEY_F6 (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{	/* Key Released */
					if( Brightness != 7 )
					{
						Brightness ++;
						if( bright_set(Brightness) != 0 )
						{
							printf("Fail to bright_set\n");
						}
						printf("bright -\n");
					}
				}
				break;
			case	KEY_F7:
				printf("Key code : KEY_F7 (0x%X)\n", KeyCode);
				if ( IsReleased == 1 )
				{	/* Key Released */
					if( Brightness != 0 )
					{
						Brightness --;
						if( bright_set(Brightness) != 0 )
						{
							printf("Fail to bright_set\n");
						}
						printf("bright +\n");
					}
				}
				break;
			default:
				break;
			}
		}
	} /* while (IsInLoop)*/

	/* clean up */
	pEventBuffer->Release( pEventBuffer );
	pInputDevice->Release( pInputDevice );
	pPrimarySurface->Release( pPrimarySurface );
	pDirectFb->Release( pDirectFb );

	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

*/

