#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <drv_ir_def.h>
#include <drv_keypad_def.h>
#include <umf_ir.h>
#include <umf_debug.h>
#include "keypad_mapping_table.h"
#include "gl_timer.h"
#include "app_event.h"
#include "customize.h"
#include "nvm_ioctl.h"
#include "umf_ioctl.h"
#include "ir_map.h"
#include "app_data_setting.h"
#ifdef CONFIG_SMART_MODULE_SUPPORT
#include "app_smart.h"
#endif

#define IR_SAME_KEY_DELAY       100
#if defined (CONFIG_KEYPAD_SINGLE_REUSE) || defined (CONFIG_KEYPAD_THREE_KEY_REUSE)
#define POWER_TO_LONGPRESS	(500)	// 0.5 sec
#endif

#define ABSMETHOD(n) ({							\
	register int _n = n, _t = _n;					\
	_t >>= sizeof (_t) * 8 - 1;					\
	_n ^= _t;							\
	_n -= _t;							\
})

int irdev, kpdev;
static IR_MAP_t *gIRMapTable = NULL;
static UINT32 gdTableSize = 0;
static IR_CallBack_t IR_CallBack = NULL;
static UINT32 gdIrRepeat = FALSE;
static IR_RC_RepeatKey g_RepeatKey;
#ifdef SUPPORT_FACTORY_AUTO_TEST_MODE4
UINT16 gLastKPkey = 0xFFFF;
#endif
#if defined (CONFIG_KEYPAD_SINGLE_REUSE) || defined (CONFIG_KEYPAD_THREE_KEY_REUSE) || defined (CONFIG_KEYPAD_FIVE_KEY_REUSE)
static KP_CallBack_t KP_GetEvent = NULL;
#endif

#ifdef CONFIG_TESTAUTOREBOOT
static GL_Timer_t gautoreboot_timerid = 0;
static Boolean g_bautorebootStart = FALSE;
static void ir_autoreboot_cb(void *pArg)
{
    UINT32 dEvent = 0;
    UINT32 dIndex = 0;
    BOOL bfind = FALSE;
    UINT16 key = 0xFFFF;
    
    while(dIndex <gdTableSize) 
    {
    	UINT8 i = 0;
    	for (i = 0; i < CUS_CODE_COUNT; i++)
		{
			 for(key = 0; key < 0xff; key++)
			{
	            if (gIRMapTable[dIndex].pfIRGetEvent(gIRMapTable[dIndex].pCID[i], key, &dEvent) == TRUE)
	            {
					if( UI_EVENT_POWER ==  dEvent)
					{
						bfind = TRUE;
						break;
					}
				}
	        }
		}
		
        if(bfind)
        {
        	// send power key event and customer code to ap in ordrer to shutdown TV
        	IR_CallBack(dEvent, gIRMapTable[dIndex].pCID[i], key);
            break;
		}
        dIndex++;
    }
    UMFDBG(0,"%s - dIndex =%d, bfind=%d, key = 0x%02x\n", __FUNCTION__, dIndex, bfind, key);
}

static void ir_autoreboot_init(void)
{
   //int autoreboot_timerid = 0;

   GL_TimerCreate("TEST_AUTO_REBOOT", (ir_autoreboot_cb), NULL, FALSE, CONFIG_AUTOREBOOT_TIME * 1000/*CONFIG_AUTOREBOOT_TIME sec*/,0, &gautoreboot_timerid);  
}
void ir_autoreboot_disable(void)
{
    if (gautoreboot_timerid && g_bautorebootStart == TRUE)
    {
        UMFDBG(0,"disable autoreboot\n\n\n");
        GL_TimerDisable(gautoreboot_timerid);
        g_bautorebootStart = FALSE;
    }

}

void ir_autoreboot_enable(void)
{
    if(gautoreboot_timerid)
    {
        if (g_bautorebootStart == FALSE)
        {
            UMFDBG(0,"enable autoreboot after %ds\n",CONFIG_AUTOREBOOT_TIME);
            GL_TimerEnable(gautoreboot_timerid);
            g_bautorebootStart = TRUE;
        }
    }
    else //create timer
    {
        GL_TimerCreate("TEST_AUTO_REBOOT", (ir_autoreboot_cb), NULL, TRUE, CONFIG_AUTOREBOOT_TIME * 1000/*CONFIG_AUTOREBOOT_TIME sec*/,0, &gautoreboot_timerid);  
    }
}
#endif
static void IRDMON_KEY(UINT32 cid, UINT8 key, UINT8 status)
{
    do{
		if(IR_CallBack)
		{
			UINT32 dIndex = 0;
			UINT32 dEvent;
			while(dIndex < gdTableSize)
			{
				UINT8 i = 0;

				if (gIRMapTable[dIndex].pCID != NULL)
				{
					for (i = 0; i < CUS_CODE_COUNT; i++)
					{
						if (gIRMapTable[dIndex].pCID[i] == cid)
						{
							break;
						}
					}
				}
				else
				{
					i = CUS_CODE_COUNT;
				}

				if ((i < CUS_CODE_COUNT) && (gIRMapTable[dIndex].pfIRGetEvent != NULL))
				{
					if (gIRMapTable[dIndex].pfIRGetEvent(cid, key, &dEvent) == TRUE)
					{
                        if (status == ir_Press)
                        {
                            IR_CallBack(dEvent, cid ,key);
                        }
                        else if (status == ir_Repeat)
                        {
                            IR_CallBack(dEvent, (UINT32) cid | IR_EVENT_REPEAT_TYPE, key);
                        }
                        else if (status == ir_repeat_end)
                        {
                            IR_CallBack(dEvent, (UINT32) cid | IR_EVENT_REPEAT_END, key);
                        }
                        else if (status == ir_Single_end)
                        {
                            IR_CallBack(dEvent, (UINT32) cid | IR_EVENT_SINGLE_END, key);
                        }
                    }
					break;
				}
		        dIndex++;
			}
		}
    } while(0);
}

static UINT8 Ir_RC_IsRepeatKey(UINT8 IrCode)
{
	UINT8 i = 0;

	for (i = 0; i < g_RepeatKey.Size; i++)
	{
		if (g_RepeatKey.Items[i] == IrCode)
		{
			return TRUE;
		}
	}

	return FALSE;
}

static UINT8 Ir_RC_IsMatchRepeatKey(UINT32 Cid,UINT8 IrCode)
{
	UINT32 i = 0;
	UINT8 j = 0;
	UINT8 Ret = FALSE;

	while (i < gdTableSize)
	{
		for (j = 0; j < CUS_CODE_COUNT; j++)
		{
			if (gIRMapTable[i].pCID[j] == Cid)
			{
				break;
			}
		}
		if (j < CUS_CODE_COUNT)
		{
			Ret = Ir_RC_IsRepeatKey(IrCode);
			break;
		}
		i++;
	}

	return Ret;
}


HRESULT umfsleep(time_t  sec, long nsec)
{
	struct timespec req;
	struct timespec rem;
	int retval;

	req.tv_sec = sec;
	req.tv_nsec = nsec;

	while(1)
	{
		retval = nanosleep(&req, &rem);
		if (retval == 0)
		{
			//Completed the entire sleep time; all done
			return 0;
		}
		else if (retval == -1 && errno == EINTR)
		{
			//Interrupted by a signal. Try again
			req = rem;
			return -1;
		}
		else
		{
			return -1;
		}
	}
}

static UINT8 IR_GetContinueKeyStatus(UINT8 KeyStatus)
{
	UINT8 retvalue = 0;

	switch(KeyStatus)
	{
		case IR_KEY_NORMAL:
			retvalue = KEYSTATUS_NORMAL;
			//UMFDBG(0,"CONTINUE_KEY_HEAD\n");
			break;
            
		case IR_CONTINUE_KEY_START:
			retvalue  = KEYSTATUS_CONT;
			//UMFDBG(0,"CONTINUE_KEY_START\n");
			break;
            
		case IR_CONTINUE_KEY_START_END:
			//UMFDBG(0,"CONTINUE_KEY_START_END\n");
			retvalue  = KEYSTATUS_CONTEND;
			break;
            
		case IR_CONTINUE_KEY_END:
			retvalue  = KEYSTATUS_CONTEND;
			//UMFDBG(0,"CONTINUE_KEY_START_END\n");
			break;
            
		case IR_KEY_NORMAL_END:
			retvalue  = KEYSTATUS_NOREND;
			//UMFDBG(0,"CONTINUE_KEY_HEAD_END\n");
			break;

		default:
			UMFDBG(0,"Error Key Status : %d \n", KeyStatus);
			break;
	}

	return retvalue;
}

static UINT8 KP_GetContinueKeyStatus(UINT8 KeyStatus)
{
	UINT8 retvalue = 0;

	switch(KeyStatus)
	{
		case KPAD_HEAD:
			retvalue = KEYSTATUS_NORMAL;
			UMFDBG(0,"CONTINUE_KEY_HEAD\n");
			break;
            
		case CONTINUE_KPAD_HEADSTART:	//continue start
			retvalue  = KEYSTATUS_CONT;
			UMFDBG(0,"CONTINUE_KEY_START\n");
			break;
            
		case CONTINUE_KPAD_END:		//continue end
			UMFDBG(0,"CONTINUE_KEY_START_END\n");
			retvalue  = KEYSTATUS_CONTEND;
			break;
            
		case SINGLE_KPAD_END:	//single start
			retvalue  = KEYSTATUS_NOREND;
			UMFDBG(0,"CONTINUE_KEY_HEAD_END\n");
			break;

		default:
			UMFDBG(0,"Error Key Status : %d \n", KeyStatus);
			break;
	}

	return retvalue;
}

void * ir_Receive(void *p)
{
	IR_IOC_IOData irbuf;
	KP_IOC_IOData kpbuf;
	UINT8 i = 0, lastIRKeyStatus = 0, /*lastIRKey = 0,*/ lastKPKeyStatus = 0;
	UINT8 IRRepeat = true;
	#ifdef KEYPAD_VOL_CH_LONGKEY
	UINT8 test_keypad = false;
	#endif
	#if defined(KEYPAD_THREEKEY_LONGKEY)	//Add for mantis_0036836
	UINT8 gdthreepowerRepeatend = false;
	#elif defined(KEYPAD_SOURCE_LONGKEY) //||defined(KEYPAD_POWER_TO_SOURCE_LONGKEY)
	UINT8 gdKeypadRepeatend = false;
	#endif
	IRKey_t ir_key = {0};
	#if (defined(KEYPAD_POWER_LONGKEY)&& (KEYPAD_POWER_LONGKEY == 1))||defined(KEYPAD_THREEKEY_LONGKEY) || defined(KEYPAD_SOURCE_LONGKEY) || defined(KEYPAD_POWER_TO_SOURCE_LONGKEY) //|| defined(CONFIG_KEYPAD_SINGLE_REUSE)
	UINT32 dKeyRepeatstartTime=0;
	UINT32 dKeyRepeatendTime=0;
	#endif
	UINT32 dKeyPressedTime=0;
	UINT32 dKeySendTime=0;
	#if defined(IR_PROTOCOL_NEC) || defined(IR_PROTOCOL_NEC_SAMSUNG)
	UINT32 dKeySendTime1=0;
	#endif
	UINT32 dCurCustomID = 0;
	UINT8 dIrKey = 0xFF;
	UINT16 uKpKey = 0xFFFF;
	//UINT16 uKpRange = 0xFFFF;
	static UINT16 uPrevKyKey = 0xFFFF;
	static UINT8 dPrevIrKey = 0xFF;	//0xff is not use normally, if the customer IR use 0xff to be a IR key,modify this init value.
	#if defined (CONFIG_KEYPAD_SINGLE_REUSE) || defined (CONFIG_KEYPAD_THREE_KEY_REUSE)
	UINT32 dKeyRepeatstartTime_longpress=GL_GetTimestamp();;
	#endif
    #ifdef CONFIG_KEYPAD_FIVE_KEY_REUSE
    static UINT32 kContTime = 0;
    #endif    
	#ifdef CONFIG_SMART_MODULE_SUPPORT
	UINT16 SKeypad = 0xffff;
	#endif

	UMFDBG(0,"ir_Receive start \n");
	kpbuf.Length = 0;
	irbuf.Length = 0;

	prctl(PR_SET_NAME , "ir_Receive", NULL, NULL, NULL);
	dKeySendTime = GL_GetTimestamp();

	while(1)
	{
		ioctl(kpdev, KP_IOC_Get_Data, &kpbuf);
		ioctl(irdev, IR_IOC_Get_Data, &irbuf);
		
		if(kpbuf.Length > 0)
		{
			dKeyPressedTime = GL_GetTimestamp();
			for (i=0; i<kpbuf.Length; i++)
			{
				ir_key.IRKeyStatus = KP_GetContinueKeyStatus(kpbuf.keybuf[i].ContinueKey);
				lastIRKeyStatus = ir_key.IRKeyStatus;
				//printf("range = 0x%x, ContinueKey = 0x%x, Key = 0x%x, Source = 0x%x, dKeyPressedTime = %d, dKeySendTime : %d\n",
				//	kpbuf.keybuf[i].range, ir_key.IRKeyStatus, kpbuf.keybuf[i].Key, kpbuf.keybuf[i].Source, dKeyPressedTime, dKeySendTime);
				//lastIRKey = ir_key.IRKey;
				uKpKey = kpbuf.keybuf[i].Key;
				#ifdef CONFIG_SMART_MODULE_SUPPORT
				SKeypad = kpbuf.keybuf[i].Key;
				#endif
				#ifdef CONFIG_AC_SPECIAL_FILE_CHECK
#ifdef SUPPORT_FACTORY_AUTO_TEST_MODE4
				gLastKPkey = kpbuf.keybuf[i].range;
#endif
				//uKpRange = kpbuf.keybuf[i].range;
				//printf("keypad[%04x]=====\n",uKpRange);
				#endif	
#if defined (CONFIG_KEYPAD_SINGLE_REUSE) || defined (CONFIG_KEYPAD_THREE_KEY_REUSE)
				if (((ABSMETHOD(dKeyPressedTime - dKeyRepeatstartTime_longpress ) < POWER_TO_LONGPRESS)
					&& (uKpKey == uPrevKyKey)) && (ir_key.IRKeyStatus == KEYSTATUS_CONT))
				{
					;
				}
#else
				if ((ABSMETHOD(dKeyPressedTime - dKeySendTime ) < IR_SAME_KEY_DELAY)
					&& (uKpKey == uPrevKyKey))
				{
					;
				}
#endif
				else if (ir_key.IRKeyStatus == KEYSTATUS_NOREND)
				{
					//printf("\n--- ir press ---\n");
					dKeySendTime = GL_GetTimestamp();
#if defined (CONFIG_KEYPAD_SINGLE_REUSE) || defined (CONFIG_KEYPAD_THREE_KEY_REUSE)
					dKeyRepeatstartTime_longpress = GL_GetTimestamp();
#endif
					#if (defined(KEYPAD_POWER_LONGKEY)&& (KEYPAD_POWER_LONGKEY == 1))
					if(uKpKey == UI_EVENT_KEYPAD_POWER)
					{
						uKpKey = UI_EVENT_KEYPAD_MENU;
					}
					#elif defined(KEYPAD_POWER_TO_SOURCE_LONGKEY)
					if(uKpKey == UI_EVENT_KEYPAD_POWER)
					{
						uKpKey = UI_EVENT_KEYPAD_SOURCE;
					}
					#elif defined(KEYPAD_VOL_CH_LONGKEY)
					if(uKpKey == UI_EVENT_KEYPAD_RIGHT)
					{
						uKpKey = UI_EVENT_KEYPAD_UP;
					}
					else if(uKpKey == UI_EVENT_KEYPAD_LEFT)
					{
						uKpKey = UI_EVENT_KEYPAD_DOWN;
					}
					#elif defined(CONFIG_KEYPAD_SINGLE_REUSE)
					if(uKpKey == UI_EVENT_KEYPAD_POWER)
					{
						uKpKey = UI_EVENT_KEYPAD_SHORT_PRESS;
					}
					#elif defined(CONFIG_KEYPAD_THREE_KEY_REUSE)
					if(uKpKey == UI_EVENT_KEYPAD_POWER)
					{
						uKpKey = UI_EVENT_KEYPAD_SHORT_PRESS;
					}
					else if (uKpKey == UI_EVENT_KEYPAD_UP)
					{
						uKpKey = UI_EVENT_KEYPAD_CH_PLUS_SHORT_PRESS;
					}
					else if (uKpKey == UI_EVENT_KEYPAD_DOWN)//UI_EVENT_KEYPAD_DOWN
					{
						uKpKey = UI_EVENT_KEYPAD_CH_MINUS_SHORT_PRESS;
					}	
                    #elif defined(CONFIG_KEYPAD_FIVE_KEY_REUSE)                    
                    kContTime = 0;
                    if (KP_GetEvent)
					{
						KP_GetEvent((UINT32*)&uKpKey);
					}
					#endif 
                    
					IR_CallBack(uKpKey, 0x0, 0x0);
				}

				switch(ir_key.IRKeyStatus)
				{
					case KEYSTATUS_CONT:
						#if !defined(KEYPAD_POWER_TO_SOURCE_LONGKEY) || (!defined(CONFIG_KEYPAD_SINGLE_REUSE) && !defined(CONFIG_KEYPAD_THREE_KEY_REUSE))  
						if (uKpKey == uPrevKyKey)
						#endif	
						{
							#if (defined(KEYPAD_POWER_LONGKEY)&& (KEYPAD_POWER_LONGKEY == 1))||defined(KEYPAD_THREEKEY_LONGKEY)||defined(KEYPAD_SOURCE_LONGKEY)|| defined(KEYPAD_POWER_TO_SOURCE_LONGKEY) //|| defined(CONFIG_KEYPAD_SINGLE_REUSE)
							dKeyRepeatstartTime = GL_GetTimestamp();
							#endif
							gdIrRepeat = TRUE;
							IRRepeat = FALSE;
						}
						#if !defined(KEYPAD_POWER_TO_SOURCE_LONGKEY) || (!defined(CONFIG_KEYPAD_SINGLE_REUSE) && !defined(CONFIG_KEYPAD_THREE_KEY_REUSE))
						else
						{
							gdIrRepeat = FALSE;
						}
						#endif
						break;
                        
					case KEYSTATUS_CONTEND:
						//#if defined(KEYPAD_COM_VOL)
						//if (uKpKey == uPrevKyKey)
						//#endif	
						{
							gdIrRepeat = FALSE;
							#if (defined(KEYPAD_POWER_LONGKEY)&& (KEYPAD_POWER_LONGKEY == 1))
							dKeyRepeatendTime = GL_GetTimestamp();
							if(uKpKey == UI_EVENT_KEYPAD_POWER)
							{
								if(ABSMETHOD(dKeyRepeatstartTime - dKeyRepeatendTime) < POWER_TO_MENU)
									uKpKey = UI_EVENT_KEYPAD_MENU;
								else if(ABSMETHOD(dKeyRepeatstartTime - dKeyRepeatendTime) <POWER_TO_SOURCE)
									uKpKey = UI_EVENT_KEYPAD_SOURCE;
								else
									uKpKey = UI_EVENT_KEYPAD_POWER;
							}
							#elif defined(KEYPAD_THREEKEY_LONGKEY)
							dKeyRepeatendTime = GL_GetTimestamp();
							if(uKpKey == UI_EVENT_KEYPAD_POWER)
							{
								if(!gdthreepowerRepeatend && ABSMETHOD(dKeyRepeatstartTime - dKeyRepeatendTime) < POWER_TO_OPTION)
								{
									gdthreepowerRepeatend = FALSE;
									uKpKey = UI_EVENT_KEYPAD_POWER;
								}
								else
									break;
							}
							#elif defined(KEYPAD_SOURCE_LONGKEY)
							dKeyRepeatendTime = GL_GetTimestamp();
							if(uKpKey == UI_EVENT_KEYPAD_SOURCE)
							{
								if(!gdKeypadRepeatend && ABSMETHOD(dKeyRepeatstartTime - dKeyRepeatendTime) < SOURCE_TO_ENTER)
								{
									gdKeypadRepeatend = FALSE;
									uKpKey = UI_EVENT_KEYPAD_SOURCE;
								}
								else
									break;
							}
							#elif defined(KEYPAD_POWER_TO_SOURCE_LONGKEY)
							dKeyRepeatendTime = GL_GetTimestamp();
							if(uKpKey == UI_EVENT_KEYPAD_POWER)
							{
								if(ABSMETHOD(dKeyRepeatstartTime - dKeyRepeatendTime) <POWER_TO_SOURCE)
									uKpKey = UI_EVENT_KEYPAD_SOURCE;
								else
									uKpKey = UI_EVENT_KEYPAD_POWER;
							}
							#elif defined(KEYPAD_VOL_CH_LONGKEY)
							test_keypad=FALSE;
							/*#elif defined(CONFIG_KEYPAD_SINGLE_REUSE)
							//dKeyRepeatendTime = GL_GetTimestamp();
							if(uKpKey == UI_EVENT_KEYPAD_POWER)
							{
								//if(ABSMETHOD(dKeyRepeatstartTime - dKeyRepeatendTime) <POWER_TO_LONGPRESS)
									//uKpKey = UI_EVENT_KEYPAD_SHORT_PRESS;
								//else
									//uKpKey = UI_EVENT_KEYPAD_LONG_PRESS;
							}*/
							#endif
							#if defined (CONFIG_KEYPAD_SINGLE_REUSE)
							UINT32 dMessage = UI_EVENT_KEYPAD_MAX;
							IR_CallBack(dMessage, KEYPAD_EVENT_REPEAT_END, 0x0);
							#elif defined(CONFIG_KEYPAD_THREE_KEY_REUSE)
							{
								;
							}         
                           
                            #elif defined(CONFIG_KEYPAD_FIVE_KEY_REUSE)                           
                            if (uKpKey == UI_EVENT_KEYPAD_MENU)
                            { 
                                if (kContTime >= 30 && kContTime < 50)//3s
                                {
                                    if (KP_GetEvent)
                                    {
                                        uKpKey = UI_EVENT_KEYPAD_SOURCE;
                                        KP_GetEvent((UINT32*)&uKpKey);
                                        IR_CallBack(uKpKey, 0x0, 0x0);                                      
                                    }
                                }
                                else if (kContTime>=50)//5s
                                {
                                    if (KP_GetEvent)
                                    {
                                        uKpKey = UI_EVENT_KEYPAD_POWER;
                                        KP_GetEvent((UINT32*)&uKpKey);
                                        IR_CallBack(uKpKey, 0x0, 0x0);
                                    }                                   
                                 }
                                 kContTime = 0;
                             }
							#else
							IR_CallBack(uKpKey, KEYPAD_EVENT_REPEAT_END, 0x0);
							#endif
						}
						break;
                        
					default:
						break;
				}
				
				#ifdef CONFIG_SMART_MODULE_SUPPORT
				{
					extern int APP_GUIOBJ_Source_GetCurrSource(APP_Source_Type_t *eSourceType);
					APP_Source_Type_t eSourceType = APP_SOURCE_MAX;
					APP_GUIOBJ_Source_GetCurrSource(&eSourceType);
					if((APP_SOURCE_HDMI + CONFIG_HDMI_SMART_PORT) == eSourceType)
					{
						if(SMART_SUCCESS == APP_Smart_Set_Smart_IRKey(SKeypad))
							APP_SMART_IrPress(ir_key.IRKeyStatus);
					}
				}
				#endif
			}
		}

		if (irbuf.Length > 0)
		{
			dKeyPressedTime = GL_GetTimestamp();
			for (i=0; i<irbuf.Length; i++)
			{
				ir_key.IRKeyStatus = IR_GetContinueKeyStatus(irbuf.Databuf[i].ContinueKey);
				lastIRKeyStatus = ir_key.IRKeyStatus;
				//lastIRKey = ir_key.IRKey;
				//printf("Costomer_code_H = 0x%x, Costomer_code_L = 0x%x, HW_key = 0x%x, IR ContinueKey = 0x%x, dKeyPressedTime = %d, dKeySendTime : %d\n",
				//	irbuf.Databuf[i].Address, irbuf.Databuf[i].Address_, irbuf.Databuf[i].Command, ir_key.IRKeyStatus, dKeyPressedTime, dKeySendTime);
				dIrKey = irbuf.Databuf[i].Command;
				
				if(irbuf.Databuf[i].Protocol == Sony)	//#if defined(IR_PROTOCOL_SONY)
					dCurCustomID = (irbuf.Databuf[i].Address);
				else	//#else
					dCurCustomID = ((irbuf.Databuf[i].Address)<<8)|(irbuf.Databuf[i].Address_);
				//#endif

				if (ir_key.IRKeyStatus == KEYSTATUS_NORMAL)
				{
					//printf("\n--- ir press ---\n");
					dKeySendTime = GL_GetTimestamp();
					#if defined(IR_PROTOCOL_NEC) || defined(IR_PROTOCOL_NEC_SAMSUNG)
					if(irbuf.Databuf[i].Protocol == Nec || irbuf.Databuf[i].Protocol==NEC_SAMSUNG)
					{
							if(ABSMETHOD(dKeySendTime1 - dKeySendTime ) > 300)
							{
								dKeySendTime1 = GL_GetTimestamp();
								IRDMON_KEY(dCurCustomID, dIrKey, ir_Press);
							}
					}
					else
					#endif	
						IRDMON_KEY(dCurCustomID, dIrKey, ir_Press);
				}
				else if (ir_key.IRKeyStatus == KEYSTATUS_NOREND)
				{
					dKeySendTime = GL_GetTimestamp();
					IRDMON_KEY(dCurCustomID, dIrKey, ir_Single_end);
				}
				else if ((ABSMETHOD(dKeyPressedTime - dKeySendTime ) < IR_SAME_KEY_DELAY)
					&& (dIrKey == dPrevIrKey))
				{
					;
				}

				switch(ir_key.IRKeyStatus)
				{
					case KEYSTATUS_CONT:
						if (dIrKey == dPrevIrKey)
						{
							gdIrRepeat = TRUE;
							IRRepeat = TRUE;
						}
						else
						{
							gdIrRepeat = FALSE;
						}
						break;
                        
					case KEYSTATUS_CONTEND:
						if (dIrKey == dPrevIrKey)
						{
							gdIrRepeat = FALSE;
							IRRepeat = FALSE;
							IRDMON_KEY(dCurCustomID, dIrKey, ir_repeat_end);
						}
						break;
                        
					default:
						break;
				}
				#ifdef CONFIG_SMART_MODULE_SUPPORT
				{
					extern int APP_GUIOBJ_Source_GetCurrSource(APP_Source_Type_t *eSourceType);
					APP_Source_Type_t eSourceType = APP_SOURCE_MAX;
					APP_GUIOBJ_Source_GetCurrSource(&eSourceType);
					if((APP_SOURCE_HDMI + CONFIG_HDMI_SMART_PORT) == eSourceType)
						APP_SMART_IrPress(ir_key.IRKeyStatus);
				}
				#endif
			}
		}

		if (gdIrRepeat == TRUE)
		{
				#if defined(KEYPAD_THREEKEY_LONGKEY)	//Add for mantis_0036836
				if(uKpKey == UI_EVENT_KEYPAD_POWER &&
					((GL_GetTimestamp() < dKeySendTime) ||(GL_GetTimestamp() >= (dKeySendTime + 500))))
				{
					IR_CallBack(UI_EVENT_KEYPAD_OPTION, KEYPAD_EVENT_REPEAT_END, 0x0);
					gdIrRepeat = FALSE;
					IRRepeat = FALSE;
					gdthreepowerRepeatend = TRUE;
				}
				else
				#elif defined(KEYPAD_SOURCE_LONGKEY)
				if(uKpKey == UI_EVENT_KEYPAD_SOURCE &&
					((GL_GetTimestamp() < dKeySendTime) ||(GL_GetTimestamp() >= (dKeySendTime + 10*SOURCE_TO_ENTER))))
				{
					IR_CallBack(UI_EVENT_KEYPAD_ENTER, KEYPAD_EVENT_REPEAT_END, 0x0);
					gdIrRepeat = FALSE;
					IRRepeat = FALSE;
					gdKeypadRepeatend = TRUE;
				}
				else 
				#elif defined(KEYPAD_POWER_TO_SOURCE_LONGKEY)
				if(uKpKey == UI_EVENT_KEYPAD_POWER &&
					((GL_GetTimestamp() < dKeySendTime) ||(GL_GetTimestamp() >= (dKeySendTime + POWER_TO_SOURCE))))
				{
					IR_CallBack(UI_EVENT_KEYPAD_SOURCE, KEYPAD_EVENT_REPEAT_END, 0x0);
					gdIrRepeat = FALSE;
					IRRepeat = FALSE;
					//gdKeypadRepeatend = TRUE;
				}
				else 
				#elif defined(KEYPAD_VOL_CH_LONGKEY)
				if (test_keypad==FALSE && ((GL_GetTimestamp() < dKeySendTime) ||(GL_GetTimestamp() >= (dKeySendTime + VOL_TO_CH))))
				{
					if(uKpKey == UI_EVENT_KEYPAD_RIGHT)
					{
						uKpKey = UI_EVENT_KEYPAD_RIGHT;
					}
					if(uKpKey == UI_EVENT_KEYPAD_LEFT)
					{
						uKpKey = UI_EVENT_KEYPAD_LEFT;
					}
					IR_CallBack(uKpKey, KEYPAD_EVENT_REPEAT_TYPE, 0x0);
					test_keypad = TRUE;
				}
				else 
				#elif defined(CONFIG_KEYPAD_SINGLE_REUSE)
				if((IRRepeat == FALSE) && ((GL_GetTimestamp() < dKeyRepeatstartTime_longpress) ||(GL_GetTimestamp() >= (dKeyRepeatstartTime_longpress + POWER_TO_LONGPRESS))))				
				{
					dKeyRepeatstartTime_longpress = GL_GetTimestamp();
					if (KP_GetEvent)
					{
						UINT32 dMessage = UI_EVENT_KEYPAD_MAX;
						KP_GetEvent(&dMessage);
						if (dMessage == UI_EVENT_KEYPAD_MENU || dMessage == UI_EVENT_KEYPAD_POWER)
						{
							IR_CallBack(dMessage, KEYPAD_EVENT_REPEAT_END, 0x0);
							gdIrRepeat = FALSE;
							IRRepeat = FALSE;
						}
						else
						{
							IR_CallBack(dMessage, KEYPAD_EVENT_REPEAT_TYPE, 0x0);
						}
					}
					//gdIrRepeat = FALSE;
					//IRRepeat = FALSE;
					//gdKeypadRepeatend = TRUE;
				}
                else 
				#elif defined(CONFIG_KEYPAD_THREE_KEY_REUSE)
				if((IRRepeat == FALSE) && ((GL_GetTimestamp() < dKeyRepeatstartTime_longpress) ||(GL_GetTimestamp() >= (dKeyRepeatstartTime_longpress + POWER_TO_LONGPRESS))))				
				{
					dKeyRepeatstartTime_longpress = GL_GetTimestamp();
					if (KP_GetEvent)
					{
						UINT32 dMessage = uKpKey;
						KP_GetEvent(&dMessage);
						if (dMessage == UI_EVENT_KEYPAD_POWER_KEY_LONG_PRESS)
						{
							IR_CallBack(dMessage, KEYPAD_EVENT_REPEAT_END, 0x0);
							gdIrRepeat = FALSE;
							IRRepeat = FALSE;
						}
						else
						{
							IR_CallBack(dMessage, KEYPAD_EVENT_REPEAT_TYPE, 0x0);
						}
					}
				}
                else
                #elif defined(CONFIG_KEYPAD_FIVE_KEY_REUSE)             
				if((IRRepeat == FALSE) && ((GL_GetTimestamp() < dKeySendTime) || (GL_GetTimestamp() >= (dKeySendTime + 500))))				
                {          
    				if (KP_GetEvent)
    				{
    					UINT32 dMessage = uKpKey;		
    					if (dMessage != UI_EVENT_KEYPAD_MENU)
    					{
    					    KP_GetEvent(&dMessage);
    						IR_CallBack(dMessage, KEYPAD_EVENT_REPEAT_TYPE, 0x0);                            
    					}
    				}
                }
				else 	
				#endif
				#ifdef KEYPAD_VOL_CH_LONGKEY
				if (test_keypad == TRUE &&((GL_GetTimestamp() < dKeySendTime) ||
					(GL_GetTimestamp() >= (dKeySendTime + IR_SAME_KEY_DELAY))))
				#else
				if ((GL_GetTimestamp() < dKeySendTime) ||
					(GL_GetTimestamp() >= (dKeySendTime + IR_SAME_KEY_DELAY)))
				#endif
				{
					dKeySendTime = GL_GetTimestamp();

					if (g_RepeatKey.Size == 0) // APP has not registered Repeat data.
					{
						if (IRRepeat)
						{
							IRDMON_KEY(dCurCustomID, dIrKey, ir_Repeat);
						}
#if !defined (CONFIG_KEYPAD_SINGLE_REUSE) && !defined (CONFIG_KEYPAD_THREE_KEY_REUSE)
						else
						{
							IR_CallBack(uKpKey, KEYPAD_EVENT_REPEAT_TYPE, 0x0);
						}
#endif
					}
					else
					{
						if (IRRepeat)
						{
							if (Ir_RC_IsMatchRepeatKey(dCurCustomID,dIrKey))
							{
								IRDMON_KEY(dCurCustomID, dIrKey, ir_Repeat);
							}
						}
#if !defined (CONFIG_KEYPAD_SINGLE_REUSE) && !defined (CONFIG_KEYPAD_THREE_KEY_REUSE)
						else
						{
							IR_CallBack(uKpKey, KEYPAD_EVENT_REPEAT_TYPE, 0x0);
						}
#endif
					}
				}
			}	
			if (lastIRKeyStatus == KEYSTATUS_CONT || lastKPKeyStatus == KEYSTATUS_CONT)
			{
                #ifdef CONFIG_KEYPAD_FIVE_KEY_REUSE                
                if (uKpKey == UI_EVENT_KEYPAD_MENU)
                {
                    kContTime++;
                }
                #endif 
				umfsleep(0, IRRECEIVEWAITTIME/2);
			}
			else if (irbuf.Length == 0)
			{
				umfsleep(0, IRRECEIVEWAITTIME);
			}

			dPrevIrKey = dIrKey;
			uPrevKyKey = uKpKey;
	}
}

int KP_init(void)
{
	KP_IOC_IOData KPdata;
	UINT8 i = 0;

	kpdev = open("/dev/siskeypad", O_RDWR);

	if (kpdev <= 0)
	{
		UMFDBG(0,"Unable to open /dev/siskeypad\n");
		return E_FAIL;
	}
	else
	{
		do {
			KPdata.Length = 0;
			//ioctl(kpdev, KP_IOC_Get_Data, &KPdata);
			if (KPdata.Length != 0)
			{
				UMFDBG(0, "ReInitial keypad buffer..\n");
			}
		}while(KPdata.Length != 0);
	}

	KPdata.Length = keypadNum;
	
#ifdef SUPPORT_FACTORY_AUTO_TEST
	extern int APP_Factory_GetAutoTestOnOff(void);
	if(APP_Factory_GetAutoTestOnOff() == TRUE)
	{
		for(i=0 ; i<keypadNum ; i++)
		{
			KPdata.keybuf[i].Source = KeypadMapFac_final[i].u8ADC;
			KPdata.keybuf[i].ContinueKey= KeypadMapFac_final[i].range;
			KPdata.keybuf[i].Key = KeypadMapFac_final[i].Event;
		}
	}
	else
#endif
	{
		for(i=0 ; i<keypadNum ; i++)
		{
			KPdata.keybuf[i].Source = KeypadMap_final[i].u8ADC;
			KPdata.keybuf[i].ContinueKey= KeypadMap_final[i].range;
			KPdata.keybuf[i].Key = KeypadMap_final[i].Event;
		}
	}
	//send keypad defined to KP driver
	ioctl(kpdev, KP_IOC_Set_Data, &KPdata);

	return S_OK;
}

int ir_init(IR_CallBack_t pIR_CallBackFunc)
{
	IR_IOC_IOData irbuf;
	pthread_t irthread;
    
	irdev = open("/dev/sisir", O_RDWR);

	if (irdev <= 0)
	{
		UMFDBG(0,"Unable to open /dev/sisir\n");
		return E_FAIL;
	}
	else
	{
		do {
			irbuf.Length = 0;
			ioctl(irdev, IR_IOC_Get_Data, &irbuf);
			if (irbuf.Length != 0)
			{
				UMFDBG(0, "ReInitial IR buffer..\n");
			}
		}while(irbuf.Length != 0);
	}

	if(KP_init() == E_FAIL)
	{
		return E_FAIL;
	}
	size_t stacksize = 16*1024;
	
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setstacksize(&attr, stacksize);
	if(pthread_create(&irthread, &attr, ir_Receive, NULL) != 0)
	{
		UMFDBG(0,"IR pthread_create fail \n");
	}
	pthread_attr_destroy(&attr);
	IR_CallBack = pIR_CallBackFunc;

#ifdef CONFIG_TESTAUTOREBOOT
        ir_autoreboot_init();
#endif 

	return S_OK;
}


int ir_finalize(void)
{
	if(kpdev != -1)
		close(kpdev);
	if(irdev != -1)
		close(irdev);
	return S_OK;
}

static int load_ir_data_fromflash(UINT8 * ir_name, PIRKeymap_t * pOutIRKeymap_t, 
	UINT8 * EventTableSize, UINT16 ** pCusCode)
{
    UINT8 *pBuf = NULL;
    UINT32 flashSize = 0;
    UINT32 irCount = 0;
    UINT32 i = 0;
    PIRKeymap_t pTempMap_t = NULL;
    PIRKeyInfo_t pIRKeyInfo = NULL;
	char arName[13];

	memset(arName, 0, sizeof(arName));
	snprintf(arName, 13, "%s", ir_name);
    flashSize = Cmd_LookupFlashtableSize((UINT8* )arName);

    if (flashSize)
    {
        pBuf = (UINT8 *) malloc(sizeof(UINT8) * flashSize);
        if (pBuf == NULL)
        {
            return FALSE;
        }
        memset(pBuf, 0, flashSize);

		if (Cmd_LookupFlashtableAddr((UINT8* )arName, (UINT32) pBuf, flashSize) == 0)
		{
			pIRKeyInfo = (PIRKeyInfo_t) pBuf;
		
			if (pOutIRKeymap_t != NULL)
			{
				*pOutIRKeymap_t = pIRKeyInfo->irUMFMapping;
			}
		
			if (pCusCode != NULL)
			{
				*pCusCode = pIRKeyInfo->irCstCode;
			}
		
			pTempMap_t = pIRKeyInfo->irUMFMapping;
		
			for (i = 0; i < IR_KEY_NUMBER_MAX; i++, pTempMap_t++)
			{
				if (pTempMap_t->CusCode != 0 || pTempMap_t->Keycode != 0 || pTempMap_t->Event != 0)
				{
					irCount++;
				}
		
			}
		
			if (EventTableSize != NULL)
			{
				*EventTableSize = irCount;
			}

			return TRUE;
		}
    }

	free(pBuf);
	pBuf = NULL;
    return FALSE;
}

static int load_kp_data_fromflash(UINT8 table_index)
{
    UINT32 flashSize = 0;
    UINT8 *pBuf = NULL;
    UINT32 keysize = 0;
	KEYPAD_Info_t KeypadInfoTbl[TableNum];

	memset(KeypadInfoTbl, 0, sizeof(KEYPAD_Info_t)*TableNum);
    flashSize = Cmd_LookupFlashtableSize((UINT8 *) "KeyPad");

    if (flashSize)
    {
        pBuf = (UINT8 *) malloc(sizeof(UINT8) * flashSize);
        if (pBuf == NULL)
        {
            return FALSE;
        }
    }
    if (pBuf != NULL)
    {
    	memset(pBuf, 0, flashSize);
        if (Cmd_LookupFlashtableAddr((UINT8 *) "KeyPad", (UINT32) pBuf, flashSize) == 0)
        {
            flashSize = flashSize - sizeof(UINT32);
            keysize = sizeof(KeypadInfoTbl);
            if (flashSize < keysize)
            {
                keysize = flashSize;
            }
			memcpy(KeypadInfoTbl, pBuf, keysize);
            memcpy(KeypadMap_final, KeypadInfoTbl[table_index].KeypadMap, sizeof(KeypadMap_final));
            //tv_SetKeypadPowerKey(KeypadInfoTbl[table_index].KPPowerKey);
            free(pBuf);
            return TRUE;
        }
		free(pBuf);
    }

    return FALSE;
}

#ifdef SUPPORT_FACTORY_AUTO_TEST
static int load_kpFac_data_fromflash(void)
{
    UINT32 flashSize = 0;
    UINT8 *pBuf = NULL;
    UINT32 keysize = 0;

    flashSize = Cmd_LookupFlashtableSize((UINT8 *) "KeyPadFac");

    if (flashSize)
    {
        pBuf = (UINT8 *) malloc(sizeof(UINT8) * flashSize);
        if (pBuf == NULL)
        {
            return FALSE;
        }
    }
    if (pBuf != NULL)
    {
        if (Cmd_LookupFlashtableAddr((UINT8 *) "KeyPadFac", (UINT32) pBuf, flashSize) == 0)
        {
            flashSize = flashSize - sizeof(UINT32);
            keysize = sizeof(KeypadMapFac_final);
            if (flashSize < keysize)
            {
                keysize = flashSize;
            }
            memcpy(KeypadMapFac_final, pBuf, keysize);
            return TRUE;
        }
    }

    return FALSE;
}
#endif

int ir_LoadEventCode(UINT8 table_index)
{
    UINT32 iIrCount = 0;

    for (iIrCount = 0; iIrCount < gdTableSize; iIrCount++)
    {
        if (gIRMapTable)
        {
            load_ir_data_fromflash((UINT8 *) (gIRMapTable[iIrCount].IRName),
                                   (PIRKeymap_t *) (&(gIRMapTable[iIrCount].pdIR_Map)),
                                   (UINT8 *) (&(gIRMapTable[iIrCount].IR_Count)), &(gIRMapTable[iIrCount].pCID));
        }
    }

    load_kp_data_fromflash(table_index);

#ifdef SUPPORT_FACTORY_AUTO_TEST
	load_kpFac_data_fromflash();
#endif
    return 0;

}


int ir_SetMappingTable(IR_MAP_t* pIRTable, UINT32 dTableSize)
{
	if(pIRTable == NULL || dTableSize == 0)
	{
	    return -1;
    }
	gIRMapTable = pIRTable;
	gdTableSize = dTableSize;
    
	return 0;
}

void Ir_RC_SetRepeatKey(UINT8* DefaultRepeatKeys, UINT8 DefaultRepeatKeySize, UINT8 RepeatKeyBufferSize)
{
	UINT8 i;

	if (DefaultRepeatKeySize > RepeatKeyBufferSize)
	{
		UMFDBG(0,"[%s] ERROR: Repeat key buffer size of RC must be larger than default repeat key size of RC!\n", __FUNCTION__);
		return;
	}

	g_RepeatKey.Items = (UINT8 *)malloc(sizeof(UINT8) * RepeatKeyBufferSize);
	if (g_RepeatKey.Items == NULL)
	{
		UMFDBG(0,"[%s] ERROR: Memory allocation for RC repeat keys fails!\n", __FUNCTION__);
		return;
	}

	g_RepeatKey.Size = RepeatKeyBufferSize;
	for (i = 0; i < DefaultRepeatKeySize; i++)
	{
		g_RepeatKey.Items[i] = DefaultRepeatKeys[i];
	}
	for (i = DefaultRepeatKeySize; i < g_RepeatKey.Size; i++)
	{
		//0xff is not use normally, if the customer IR use 0xff to be a IR key,modify this init value.
		g_RepeatKey.Items[i] = 0xff; //  TODO: must match with APP_VIRTUAL_EVENT
	}
}

void KP_Set_MapTable(UINT8 table_index)
{
	UINT8 i = 0;
	KP_IOC_IOData KPdata;

	memset(&KPdata, 0, sizeof(KP_IOC_IOData));

#ifdef SUPPORT_FACTORY_AUTO_TEST
	extern int APP_Factory_GetAutoTestOnOff(void);
	if(APP_Factory_GetAutoTestOnOff() == TRUE)
	{
		return;
	}
#endif

	load_kp_data_fromflash(table_index);
	
	if (kpdev > 0)
	{
		//Clear keypad driver buffer.
		do {
			KPdata.Length = 0;			
			//ioctl(kpdev, KP_IOC_Get_Data, &KPdata);
			if (KPdata.Length != 0) 
			{
				UMFDBG(0, "ReInitial keypad buffer..\n");
			}
		}while(KPdata.Length != 0);

		//Send keypad mapping table to keypad driver
		for(i=0 ; i<keypadNum ; i++)
		{
			KPdata.keybuf[i].Source = KeypadMap_final[i].u8ADC;
			KPdata.keybuf[i].ContinueKey= KeypadMap_final[i].range;
			KPdata.keybuf[i].Key = KeypadMap_final[i].Event;
		}
		KPdata.Length = keypadNum;
		ioctl(kpdev, KP_IOC_Set_Data, &KPdata);
	}

}


//For IR message,	Only Include all IR501 IR keys temprary below
const char *Ir_GetKeyString(UINT32 IrKey)
{
	switch (IrKey)
	{
		case UI_EVENT_KEYPAD_MENU:
			return "UI_EVENT_KEYPAD_MENU";
            
		case UI_EVENT_KEYPAD_DOWN:
			return "UI_EVENT_KEYPAD_DOWN";
            
		case UI_EVENT_KEYPAD_UP:
			return "UI_EVENT_KEYPAD_UP";
            
		case UI_EVENT_KEYPAD_SOURCE:
			return "UI_EVENT_KEYPAD_SOURCE";
            
		case UI_EVENT_KEYPAD_LEFT:
			return "UI_EVENT_KEYPAD_LEFT";
            
		case UI_EVENT_KEYPAD_RIGHT:
			return "UI_EVENT_KEYPAD_RIGHT";
            
		case UI_EVENT_KEYPAD_POWER:
			return "UI_EVENT_KEYPAD_POWER";
            
		case UI_EVENT_KEYPAD_EXIT:
			return "UI_EVENT_KEYPAD_EXIT";
            
		case UI_EVENT_KEYPAD_EJECT:
			return "UI_EVENT_KEYPAD_EJECT";
            
		case UI_EVENT_KEYPAD_PLAY:
			return "UI_EVENT_KEYPAD_PLAY";
            
		case UI_EVENT_KEYPAD_STOP:
			return "UI_EVENT_KEYPAD_STOP";
    
		case UI_EVENT_0:
			return "UI_EVENT_0";
            
		case UI_EVENT_1:
			return "UI_EVENT_1";
            
		case UI_EVENT_2:
			return "UI_EVENT_2";
            
		case UI_EVENT_3:
			return "UI_EVENT_3";
            
		case UI_EVENT_4:
			return "UI_EVENT_4";
            
		case UI_EVENT_5:
			return "UI_EVENT_5";
            
		case UI_EVENT_6:
			return "UI_EVENT_6";
            
		case UI_EVENT_7:
			return "UI_EVENT_7";
            
		case UI_EVENT_8:
			return "UI_EVENT_8";
            
		case UI_EVENT_9:
			return "UI_EVENT_9";
            
		case UI_EVENT_10:
			return "UI_EVENT_-/--";
            
		case UI_EVENT_POWER:
			return "UI_EVENT_POWER";
            
		case UI_EVENT_UP:
			return "UI_EVENT_UP";
            
		case UI_EVENT_DOWN:
			return "UI_EVENT_DOWN";
            
		case UI_EVENT_LEFT:
			return "UI_EVENT_LEFT";
            
		case UI_EVENT_RIGHT:
			return "UI_EVENT_RIGHT";
            
		case UI_EVENT_ENTER:
			return "UI_EVENT_ENTER";
            
		case UI_EVENT_DISPLAY:
			return "UI_EVENT_DISPLAY";
            
		case UI_EVENT_MUTE:
			return "UI_EVENT_MUTE";
            
		case UI_EVENT_VOL_UP:
			return "UI_EVENT_VOL_UP";
            
		case UI_EVENT_VOL_DN:
			return "UI_EVENT_VOL_DN";
            
		case UI_EVENT_MENU:
			return "UI_EVENT_MENU";
            
		case UI_EVENT_GOTO:
			return "UI_EVENT_GOTO";
            
		case UI_EVENT_AB:
			return "UI_EVENT_AB";
            
		case UI_EVENT_STOP:
			return "UI_EVENT_STOP";
            
		case UI_EVENT_PLAY:
			return "UI_EVENT_PLAY";
            
		case UI_EVENT_PAUSE:
			return "UI_EVENT_PAUSE";
            
		case UI_EVENT_SLOW:
			return "UI_EVENT_SLOW";
            
		case UI_EVENT_FF:
			return "UI_EVENT_FF";
            
		case UI_EVENT_FR:
			return "UI_EVENT_FR";
            
		case UI_EVENT_NEXT:
			return "UI_EVENT_NEXT";
            
		case UI_EVENT_PREV:
			return "UI_EVENT_PREV";
            
		case UI_EVENT_RED:
			return "UI_EVENT_RED";
            
		case UI_EVENT_GREEN:
			return "UI_EVENT_GREEN";
            
		case UI_EVENT_YELLOW:
			return "UI_EVENT_YELLOW";
            
		case UI_EVENT_BLUE:
			return "UI_EVENT_BLUE";
            
		case UI_EVENT_TV_DVD:
			return "UI_EVENT_TV_DVD";
            
		case UI_EVENT_RETURN:
			return "UI_EVENT_RETURN";
            
		case UI_EVENT_PLAY_PAUSE:
			return "UI_EVENT_PLAY_PAUSE";
            
		case UI_EVENT_FAV_UP:
			return "UI_EVENT_FAV_UP";
            
		case UI_EVENT_FAV_DN:
			return "UI_EVENT_FAV_DN";
            
		case UI_EVENT_TTX_MIX:
			return "UI_EVENT_TTX_MIX";
            
		case UI_EVENT_TTX_LANGUAGE:
			return "UI_EVENT_TTX_LANGUAGE";
            
		case UI_EVENT_REC_FILE:
			return "UI_EVENT_REC_FILE";
            
		case UI_EVENT_CH_UP:
			return "UI_EVENT_CH_UP";
            
		case UI_EVENT_CH_DN:
			return "UI_EVENT_CH_DN";
            
		case UI_EVENT_FAV:
			return "UI_EVENT_FAV";
            
		case UI_EVENT_AUDIO:
			return "UI_EVENT_AUDIO";
            
		case UI_EVENT_TVRADIO:
			return "UI_EVENT_TVRADIO";
            
		case UI_EVENT_ATVDTV:
			return "UI_EVENT_ATVDTV";
			
#ifdef SUPPORT_SOURCE_DVBTCS
		case UI_EVENT_DVBC:
			return "UI_EVENT_DVBC";
            
		case UI_EVENT_DVBS:
			return "UI_EVENT_DVBS";
#endif
		case UI_EVENT_PAGE_UP:
			return "UI_EVENT_PAGE_UP";
            
		case UI_EVENT_PAGE_DN:
			return "UI_EVENT_PAGE_DN";
            
		case UI_EVENT_RECALL:
			return "UI_EVENT_RECALL";
            
		case UI_EVENT_EXIT:
			return "UI_EVENT_EXIT";
            
		case UI_EVENT_TEXT:
			return "UI_EVENT_TEXT";
            
		case UI_EVENT_EPG:
			return "UI_EVENT_EPG";
            
		case UI_EVENT_SUBTITLE:
			return "UI_EVENT_SUBTITLE";
            
		case UI_EVENT_SOURCE:
			return "UI_EVENT_SOURCE";
            
		case UI_EVENT_REC:
			return "UI_EVENT_REC";
            
		case UI_EVENT_ASPECT:
			return "UI_EVENT_ASPECT";
            
		case UI_EVENT_TIMESHIFT:
			return "UI_EVENT_TIMESHIFT";
            
		case UI_EVENT_PIC_MOD:
			return "UI_EVENT_PIC_MOD";
            
		case UI_EVENT_SND_MOD:
			return "UI_EVENT_SND_MOD";
            
		case UI_EVENT_FREEZE:
			return "UI_EVENT_FREEZE";
            
		case UI_EVENT_SLEEP:
			return "UI_EVENT_SLEEP";
            
		case UI_EVENT_FACTORY:
			return "UI_EVENT_FACTORY";
            
		case UI_EVENT_TTX_INDEX:
			return "UI_EVENT_TTX_INDEX";
            
		case UI_EVENT_TTX_SIZE:
			return "UI_EVENT_TTX_SIZE";
            
		case UI_EVENT_TTX_REVEAL:
			return "UI_EVENT_TTX_REVEAL";
            
		case UI_EVENT_TTX_HOLD:
			return "UI_EVENT_TTX_HOLD";
            
		case UI_EVENT_TTX_SUBPAGE:
			return "UI_EVENT_TTX_SUBPAGE";
            
		case UI_EVENT_TTX_CANCEL:
			return "UI_EVENT_TTX_CANCEL";
            
		case UI_EVENT_DEVLIST:
			return "UI_EVENT_DEVLIST";
            
		case UI_EVENT_CHLIST:
			return "UI_EVENT_CHLIST";
            
		case UI_EVENT_SRC_USB:
			return "UI_EVENT_SRC_USB";
            
		case UI_EVENT_PIP_MENU:
			return "UI_EVENT_PIP_MENU";
            
		case UI_EVENT_AD:
			return "UI_EVENT_AD";
            
		default:
			return "Unknown";
	}  
}
#ifdef SUPPORT_FACTORY_AUTO_TEST_MODE4
UINT16 ir_GetLastKPKey(void)
{
	switch(gLastKPkey)
	{
		case 0x1:
			return 31;
		case 0x2:
			return 51;
		case 0x4:
			return 71;
		case 0x8:
			return 91;
		case 0x10:
			return 111;
		case 0x20:
			return 131;
		case 0x40:
			return 151;
		case 0x80:
			return 171;
		case 0x100:
			return 191;
		default:
			break;
	}
	return gLastKPkey;
}
#endif

#if defined (CONFIG_KEYPAD_SINGLE_REUSE) || defined (CONFIG_KEYPAD_THREE_KEY_REUSE) || defined (CONFIG_KEYPAD_FIVE_KEY_REUSE)
void ir_RegisterKpCallback(KP_CallBack_t pKP_CallBackFunc)
{
	KP_GetEvent = pKP_CallBackFunc;
}
#endif

