#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/prctl.h>
#include <linux/joystick.h>  
#include <unistd.h>
#include "js_info.h"
#include "js_map_table.h"
#include "nes_game.h"
#include "umf_js.h"
#include "umf_debug.h"
#include "umf_ir.h"
#include "gl_mempool.h"
#include "gl_sema.h"
#include "app_data_setting.h"
#include "app_event.h"

#define JOYSTICK_DEVNAME0 "/dev/input/js0"
#define JOYSTICK_DEVNAME1 "/dev/input/js1"

#define HAL_DCACHE_LINE_SIZE 32

#define ZERO_MALLOC_FUNC(func_malloc, x) \
({ \
	UINT32 x_align = (x + (HAL_DCACHE_LINE_SIZE-1)) & (~(HAL_DCACHE_LINE_SIZE-1));	\
	UINT8 *ret = (UINT8 *)func_malloc(x_align);	\
	if(ret) memset(ret, 0, x_align); \
	ret; \
})

#define SAFR_FREE_FUNC(func_free, p)		{if(p){ func_free(p); p = NULL;}}

//#define JS_DEBUG
#ifdef JS_DEBUG
#define js_printf(fmt, arg...) UMFDBG(0,"[umf_js]"fmt, ##arg)
#else
#define js_printf(fmt, arg...) ((void) 0)
#endif


// malloc cached DRAM-A or DRAM-B when A not enough
#define zero_malloc(x) 			ZERO_MALLOC_FUNC(GL_MemAlloc, x)
// free
#define SAFE_FREE(p)				SAFR_FREE_FUNC(GL_MemFree, p)

typedef struct {
	js_key_t *p_js_key;
	UINT8 key_number;
	UINT32 event;
}js_ramdom_map_t;

typedef struct{
	js_ramdom_map_t *p_js_event;
	UINT8 event_number;
	char *p_js_name;
}js_number_t;

typedef struct {
    int js_fd;
    UINT8 preAnixEventX_A;
    UINT8 preAnixEventX_B;
    UINT8 preAnixEventY_A;
    UINT8 preAnixEventY_B;
}js_anix_event_t;

js_anix_event_t *pJsAnixEvent1= NULL;
js_anix_event_t *pJsAnixEvent2= NULL;

static int joystick_fd0 = -1;
static int joystick_fd1 = -1;
static pthread_t joythread = 0;
static JOY_CallBack_t Joy_CallBack = NULL;
static js_number_t *p_js_number = NULL;
static char js_name[MAX_JS_NUMBER][MAX_JSNAME_LEN];
static pthread_t add_event_thread = 0;
static UINT8 AddEventFinish = TRUE;
static UINT8 joypad_number = JOYPAD_MAX;
static Control_Key js_Event = EVENT_JOYPAD_MIN;
static GL_Semaphore_t pSemaphore = NULL;
static UINT8 AddEventOk = FALSE;
static INT32 gConvertUIEventFlag = FALSE;

static int joystick_memory_alloc(void)
{
	UINT8 i = 0, j = 0;

	if (p_js_number != NULL)
	{
		return 0;
	}
	p_js_number = (js_number_t *)zero_malloc((sizeof(js_number_t))*MAX_JS_NUMBER);

	if (p_js_number == NULL)
	{
		UMFDBG(0, "[%s:%d] malloc fail \n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	for (i = 0; i < MAX_JS_NUMBER; i++)
	{
		p_js_number[i].p_js_event = (js_ramdom_map_t *)zero_malloc(sizeof(js_ramdom_map_t)*MAX_EVENT_SIZE);
		if (p_js_number[i].p_js_event == NULL)
		{
			UMFDBG(0, "[%s:%d] malloc fail \n",__FUNCTION__,__LINE__);
			goto init_fail;
		}

		p_js_number[i].p_js_name = (char *)zero_malloc(MAX_JSNAME_LEN);
		if (p_js_number[i].p_js_name == NULL)
		{
			UMFDBG(0, "[%s:%d] malloc fail \n",__FUNCTION__,__LINE__);
			goto init_fail;
		}

		for (j = 0; j < MAX_EVENT_SIZE; j++)
		{
			p_js_number[i].p_js_event[j].p_js_key = (js_key_t *)zero_malloc(sizeof(js_key_t)*MAX_KEY_SIZE);
			if (p_js_number[i].p_js_event[j].p_js_key == NULL)
			{
				UMFDBG(0, "[%s:%d] malloc fail \n",__FUNCTION__,__LINE__);
				goto init_fail;
			}
			p_js_number[i].p_js_event[j].key_number = 0;
		}
		p_js_number[i].event_number = 0;
	} 

	return 0;
	
	init_fail:
		if (p_js_number)
		{
			for (i = 0; i < MAX_JS_NUMBER; i++)
			{
				if (p_js_number[i].p_js_event)
				{
					for (j = 0; j < MAX_EVENT_SIZE; j++)
					{
						if (p_js_number[i].p_js_event[j].p_js_key)
						{
							SAFE_FREE(p_js_number[i].p_js_event[j].p_js_key);
						}
					}
					SAFE_FREE(p_js_number[i].p_js_event);
				}

				if (p_js_number[i].p_js_name)
				{
					SAFE_FREE(p_js_number[i].p_js_name);
				}
			}
			SAFE_FREE(p_js_number);
		}
	return -1;	
}

static void  joystick_memory_free(void)
{
	UINT8 i = 0, j = 0;

	if (p_js_number)
	{
		for (i = 0; i < MAX_JS_NUMBER; i++)
		{
			if (p_js_number[i].p_js_event)
			{
				for (j = 0; j < MAX_EVENT_SIZE; j++)
				{
					if (p_js_number[i].p_js_event[j].p_js_key)
					{
						SAFE_FREE(p_js_number[i].p_js_event[j].p_js_key);
					}
				}
				SAFE_FREE(p_js_number[i].p_js_event);
			}

			if (p_js_number[i].p_js_name)
			{
				SAFE_FREE(p_js_number[i].p_js_name);
			}
		}
		SAFE_FREE(p_js_number);
	}
}

static int joystick_get_info_index(int js_fd)
{
	int iCount = 0;

	for (iCount = 0; iCount < js_info_table_size; iCount++)
	{
		if ((js_fd == joystick_fd0) && (joystick_fd0 > 0))
		{
			if (strcmp(js_name[0], js_info[iCount].js_name) == 0)
			{
				break;
			}
		}
		else if ((js_fd == joystick_fd1) && (joystick_fd1 > 0))
		{
			if (strcmp(js_name[1], js_info[iCount].js_name) == 0)
			{
				break;
			}
		}
	}

	if (iCount < js_info_table_size)
	{
		return iCount;
	}
	else
	{
		return 0;
	}
}
static int joystick_get_btn_event(int js_fd, int js_info_index, js_event_t js_event, UINT32 *p_event, JoyPadNum *joypadNum)
{
	UINT8 iCount = 0;
	UINT8 iTotal = 0;

	iTotal = js_get_table_size(TRUE, js_info[js_info_index].js_name);
	if (p_event == NULL || js_fd < 0 || js_info_index < 0 || iTotal == 0)
	{
		return FALSE;
	}
			
	*p_event = EVENT_JOYPAD_MIN;
	
	for (iCount = 0; iCount < iTotal; iCount++)
	{
		if (js_event.value == js_info[js_info_index].p_js_button_map[iCount].js_key.value 
			&& js_event.type == js_info[js_info_index].p_js_button_map[iCount].js_key.type
			&& js_event.number == js_info[js_info_index].p_js_button_map[iCount].js_key.number)
		{
			*p_event = js_info[js_info_index].p_js_button_map[iCount].event;
			if (joypadNum != NULL)
			{
				*joypadNum = js_info[js_info_index].p_js_button_map[iCount].js_number;
			}
			break;
		}
	}

	if (iCount < iTotal)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

static int joystick_get_axis_event(int js_fd, int js_info_index, js_event_t js_event, UINT32 *p_event, JoyPadNum *joypadNum)
{
	int ret_value = FALSE;
	UINT8 iCount = 0;
	UINT8 iTotal = 0;
    UINT8 js_number = 0;
    js_anix_event_t *pTmpAnixEvent = NULL;
    
	iTotal = js_get_table_size(TRUE, js_info[js_info_index].js_name);
	
	if (p_event == NULL || js_fd < 0 || js_info_index < 0)
	{
		return FALSE;
	}

	*p_event = EVENT_JOYPAD_MIN;

	for (iCount = 0; iCount < iTotal; iCount++)
	{
		if (js_event.value == js_info[js_info_index].p_js_axis_map[iCount].js_key.value 
			&& js_event.type == js_info[js_info_index].p_js_axis_map[iCount].js_key.type
			&& js_event.number == js_info[js_info_index].p_js_axis_map[iCount].js_key.number)
		{
			*p_event = js_info[js_info_index].p_js_axis_map[iCount].event;
            
			if (joypadNum != NULL)
			{
				*joypadNum = js_info[js_info_index].p_js_axis_map[iCount].js_number;
			}

            
            if (pJsAnixEvent1->js_fd == js_fd)
            {
                pTmpAnixEvent = pJsAnixEvent1;
                js_number = js_info[js_info_index].p_js_axis_map[iCount].js_number;
            }
            else
            {
                pTmpAnixEvent = pJsAnixEvent2;
                js_number = JOYPAD_B;
            }

            if (pTmpAnixEvent == NULL)
            {
                printf("[jsong][%s:%d] error!!!\n", __FUNCTION__, __LINE__);
                return FALSE;
            }
            
			switch (*p_event)
			{
				case ADD_EVENT_JOYPAD_UP:
				case ADD_EVENT_JOYPAD_DOWN:
					if (js_number == JOYPAD_A)
					{
						if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_UP)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_UP, js_number);
						}
						else if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_DOWN)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_DOWN, js_number);
						}
						pTmpAnixEvent->preAnixEventY_A = *p_event;
					}
					else
					{
						if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_UP)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_UP, js_number);
						}
						else if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_DOWN)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_DOWN, js_number);
						}
						pTmpAnixEvent->preAnixEventY_B = *p_event;
					}
					ret_value = TRUE;
					break;
					
				case ADD_EVENT_JOYPAD_LEFT:
				case ADD_EVENT_JOYPAD_RIGHT:
					if (js_number == JOYPAD_A)
					{
						if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_LEFT)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_LEFT, js_number);
						}
						else if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_RIGHT)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_RIGHT, js_number);
						}
						pTmpAnixEvent->preAnixEventX_A = *p_event;
					}
					else
					{
						if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_LEFT)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_LEFT, js_number);
						}
						else if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_RIGHT)
						{
							Joy_CallBack(REMOVE_EVENT_JOYPAD_RIGHT, js_number);
						}
						pTmpAnixEvent->preAnixEventX_B = *p_event;
					}
					ret_value = TRUE;
					break;

				case REMOVE_EVENT_JOYPAD_UP:
				case REMOVE_EVENT_JOYPAD_DOWN:
					if (js_number == JOYPAD_A)
					{
						if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_UP)
						{
							*p_event = REMOVE_EVENT_JOYPAD_UP;
							ret_value = TRUE;
						}
						else if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_DOWN)
						{
							*p_event = REMOVE_EVENT_JOYPAD_DOWN;
							ret_value = TRUE;
						}
						pTmpAnixEvent->preAnixEventY_A = EVENT_JOYPAD_MIN;
					}
					else
					{
						if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_UP)
						{
							*p_event = REMOVE_EVENT_JOYPAD_UP;
							ret_value = TRUE;
						}
						else if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_DOWN)
						{
							*p_event = REMOVE_EVENT_JOYPAD_DOWN;
							ret_value = TRUE;
						}
						pTmpAnixEvent->preAnixEventY_B = EVENT_JOYPAD_MIN;
					}
					break;
				case REMOVE_EVENT_JOYPAD_LEFT:
				case REMOVE_EVENT_JOYPAD_RIGHT:
					if (js_number == JOYPAD_A)
					{
						if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_LEFT)
						{
							*p_event = REMOVE_EVENT_JOYPAD_LEFT;
							ret_value = TRUE;
						}
						else if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_RIGHT)
						{
							*p_event = REMOVE_EVENT_JOYPAD_RIGHT;
							ret_value = TRUE;
						}
						pTmpAnixEvent->preAnixEventX_A = EVENT_JOYPAD_MIN;
					}
					else
					{
						if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_LEFT)
						{
							*p_event = REMOVE_EVENT_JOYPAD_LEFT;
							ret_value = TRUE;
						}
						else if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_RIGHT)
						{
							*p_event = REMOVE_EVENT_JOYPAD_RIGHT;
							ret_value = TRUE;
						}
						pTmpAnixEvent->preAnixEventX_B = EVENT_JOYPAD_MIN;
					}
					break;
				default:
					break;
			}
			
			
			break;
		}
	}

	return ret_value;
}

static int joystick_key_check(int js_fd, int number, JoyPadNum joypadNum, js_event_t js_event, UINT32 *p_event)
{
	UINT16 i = 0;
	int ret_value = FALSE;
    js_anix_event_t *pTmpAnixEvent = NULL;

	if (p_event == NULL)
	{
		return FALSE;
	}

	AL_Setting_Read(APP_Data_UserSetting_Handle(), SYS_SET_ID_GAME, 0,
		sizeof(APP_SETTING_GameInfo_t), &(g_stGameData));
	*p_event = EVENT_JOYPAD_MIN;
	js_printf("[%s:%d]number =============== %d\n",__FUNCTION__,__LINE__,number);
	for (i = 0; i < g_stGameData.js_data[number].event_number; i++)
	{
		js_printf("[%s:%d]joypadNum: %d, event: %d.	   value: %d, %d; type: %d, %d; number: %d, %d\n",__FUNCTION__,__LINE__, joypadNum,i, 
			g_stGameData.js_data[number].js_event[i].js_key.value, js_event.value,
			g_stGameData.js_data[number].js_event[i].js_key.type, js_event.type,
			g_stGameData.js_data[number].js_event[i].js_key.number, js_event.number);
		
		if (g_stGameData.js_data[number].js_event[i].js_key.value == js_event.value
			&& g_stGameData.js_data[number].js_event[i].js_key.type == js_event.type
			&& g_stGameData.js_data[number].js_event[i].js_key.number == js_event.number)
		{
			break;
		}
	}

	if (i >= g_stGameData.js_data[number].event_number)
	{
		return FALSE;
	}

	*p_event = g_stGameData.js_data[number].js_event[i].event;
    
    if (pJsAnixEvent1->js_fd == js_fd)
    {
        pTmpAnixEvent = pJsAnixEvent1;
    }
    else
    {
        pTmpAnixEvent = pJsAnixEvent2;
    }
    
    if (pTmpAnixEvent == NULL)
    {
        printf("[jsong][%s:%d] error!!!\n", __FUNCTION__, __LINE__);
        return FALSE;
    }

	switch (*p_event)
	{
		case ADD_EVENT_JOYPAD_UP:
		case ADD_EVENT_JOYPAD_DOWN:
			if (joypadNum == JOYPAD_A)
			{
				if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_UP)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_UP, joypadNum);
				}
				else if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_DOWN)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_DOWN, joypadNum);
				}
				pTmpAnixEvent->preAnixEventY_A = *p_event;
			}
			else
			{
				if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_UP)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_UP, joypadNum);
				}
				else if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_DOWN)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_DOWN, joypadNum);
				}
				pTmpAnixEvent->preAnixEventY_B = *p_event;
			}
			ret_value = TRUE;
			break;
			
		case ADD_EVENT_JOYPAD_LEFT:
		case ADD_EVENT_JOYPAD_RIGHT:
			if (joypadNum == JOYPAD_A)
			{
				if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_LEFT)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_LEFT, joypadNum);
				}
				else if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_RIGHT)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_RIGHT, joypadNum);
				}
				pTmpAnixEvent->preAnixEventX_A = *p_event;
			}
			else
			{
				if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_LEFT)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_LEFT, joypadNum);
				}
				else if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_RIGHT)
				{
					Joy_CallBack(REMOVE_EVENT_JOYPAD_RIGHT, joypadNum);
				}
				pTmpAnixEvent->preAnixEventX_B = *p_event;
			}
			ret_value = TRUE;
			break;

		case REMOVE_EVENT_JOYPAD_UP:
		case REMOVE_EVENT_JOYPAD_DOWN:
			if (joypadNum == JOYPAD_A)
			{
				if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_UP)
				{
					*p_event = REMOVE_EVENT_JOYPAD_UP;
					ret_value = TRUE;
				}
				else if (pTmpAnixEvent->preAnixEventY_A == ADD_EVENT_JOYPAD_DOWN)
				{
					*p_event = REMOVE_EVENT_JOYPAD_DOWN;
					ret_value = TRUE;
				}
				pTmpAnixEvent->preAnixEventY_A = EVENT_JOYPAD_MIN;
			}
			else
			{
				if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_UP)
				{
					*p_event = REMOVE_EVENT_JOYPAD_UP;
					ret_value = TRUE;
				}
				else if (pTmpAnixEvent->preAnixEventY_B == ADD_EVENT_JOYPAD_DOWN)
				{
					*p_event = REMOVE_EVENT_JOYPAD_DOWN;
					ret_value = TRUE;
				}
				pTmpAnixEvent->preAnixEventY_B = EVENT_JOYPAD_MIN;
			}
			break;
		case REMOVE_EVENT_JOYPAD_LEFT:
		case REMOVE_EVENT_JOYPAD_RIGHT:
			if (joypadNum == JOYPAD_A)
			{
				if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_LEFT)
				{
					*p_event = REMOVE_EVENT_JOYPAD_LEFT;
					ret_value = TRUE;
				}
				else if (pTmpAnixEvent->preAnixEventX_A == ADD_EVENT_JOYPAD_RIGHT)
				{
					*p_event = REMOVE_EVENT_JOYPAD_RIGHT;
					ret_value = TRUE;
				}
				pTmpAnixEvent->preAnixEventX_A = EVENT_JOYPAD_MIN;
			}
			else
			{
				if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_LEFT)
				{
					*p_event = REMOVE_EVENT_JOYPAD_LEFT;
					ret_value = TRUE;
				}
				else if (pTmpAnixEvent->preAnixEventX_B == ADD_EVENT_JOYPAD_RIGHT)
				{
					*p_event = REMOVE_EVENT_JOYPAD_RIGHT;
					ret_value = TRUE;
				}
				pTmpAnixEvent->preAnixEventX_B = EVENT_JOYPAD_MIN;
			}
			break;
		default:
			ret_value = TRUE;
			break;
	}
	return ret_value;
}

static int joystick_get_store_index(int js_fd, int start_index)
{
	int iCount = 0;
	
	if (start_index >= STORE_MAX_JSPAD)
	{
		return -1;
	}

	AL_Setting_Read(APP_Data_UserSetting_Handle(), SYS_SET_ID_GAME, 0,
		sizeof(APP_SETTING_GameInfo_t), &(g_stGameData));
	
	for (iCount = start_index; iCount < STORE_MAX_JSPAD; iCount++)
	{
		if ((js_fd == joystick_fd0) && (joystick_fd0 > 0))
		{
			if (strcmp(js_name[0], g_stGameData.js_data[iCount].js_name) == 0)
			{
				js_printf("[%s:%d]iCount: %d,js name: %s, %s,\n", __FUNCTION__,__LINE__,iCount,js_name[0],g_stGameData.js_data[iCount].js_name);
				break;
			}
		}
		else if ((js_fd == joystick_fd1) && (joystick_fd1 > 0))
		{
			if (strcmp(js_name[1], g_stGameData.js_data[iCount].js_name) == 0)
			{
				js_printf("[%s:%d]iCount: %d, js name: %s, %s,\n", __FUNCTION__,__LINE__,iCount,js_name[1],g_stGameData.js_data[iCount].js_name);
				break;
			}
		}
	}

	if (iCount < STORE_MAX_JSPAD)
	{
		return iCount;
	}
	else
	{
		return -1;
	}	
}

static void *joystick_Receive(void *p)
{
	js_event_t js_event;
	int bytes = -1;
	UINT32 event = EVENT_JOYPAD_MIN;
	JoyPadNum js_num = JOYPAD_A;
	int js_info_index = -1;

	prctl(PR_SET_NAME , "joystick_Receive", NULL, NULL, NULL);
	while (1)
	{
		if (joypad_number != JOYPAD_MAX)
		{
			umfsleep(0, IRRECEIVEWAITTIME*2);
			continue;
		}
		
		memset(&js_event, 0, sizeof(js_event_t));
		if (joystick_fd0 > 0)
		{
			bytes = read(joystick_fd0, (void *)(&js_event), sizeof(js_event)); 
			if (bytes == sizeof(js_event))
			{
				js_printf("[%s:%d]joystick_fd0  Event: time %8u, value %8hd, type: %3u, axis/button: %u\n", 
							__FUNCTION__,__LINE__,js_event.time, js_event.value, js_event.type, js_event.number);
				
				js_info_index = joystick_get_store_index(joystick_fd0, 0);
				if (js_info_index >= 0)
				{
					js_num = JOYPAD_A;
					if (joystick_key_check(joystick_fd0, js_info_index, js_num, js_event, &event) && Joy_CallBack != NULL)
					{
						Joy_CallBack(event, js_num);
					}
					else
					{
						js_info_index = joystick_get_store_index(joystick_fd0, js_info_index+1);
						js_printf("[%s:%d] +++++++++++++++++++++js_info_index: %d\n",__FUNCTION__,__LINE__,js_info_index);
						if (js_info_index >= 0)
						{
							js_num = JOYPAD_B;
							if (joystick_key_check(joystick_fd0, js_info_index, js_num, js_event, &event) && Joy_CallBack != NULL)
							{
								Joy_CallBack(event, js_num);
							}
						}
					}
				}
				else
				{
					js_info_index = joystick_get_info_index(joystick_fd0);
					if (js_info_index >= 0)
					{
						if (js_event.type == JS_EVENT_BUTTON)
						{
							if (joystick_get_btn_event(joystick_fd0, js_info_index, js_event, &event, &js_num) && Joy_CallBack != NULL)
							{
								Joy_CallBack(event, js_num);
							}
						}
						else if (js_event.type == JS_EVENT_AXIS)
						{
							if (joystick_get_axis_event(joystick_fd0, js_info_index, js_event, &event, &js_num) && Joy_CallBack != NULL)
							{
								Joy_CallBack(event, js_num);
							}
						}
					}
				}
			}
		}

		memset(&js_event, 0, sizeof(js_event_t));
		if (joystick_fd1 > 0)
		{
			bytes = read(joystick_fd1, (void *)(&js_event), sizeof(js_event)); 
			
			if (bytes == sizeof(js_event))
			{
				js_printf("joystick_fd1 Event: time %8u, value %8hd, type: %3u, axis/button: %u\n", 
						js_event.time, js_event.value, js_event.type, js_event.number);

				js_info_index = joystick_get_store_index(joystick_fd1, 0);
				if (js_info_index >= 0)
				{
					js_num = JOYPAD_B;
					if (joystick_key_check(joystick_fd1 ,js_info_index, js_num, js_event, &event) && Joy_CallBack != NULL)
					{
						Joy_CallBack(event, js_num);
					}
				}
				else
				{
					js_info_index = joystick_get_info_index(joystick_fd1);
					if (js_info_index >= 0)
					{

					}
					if (js_event.type == JS_EVENT_BUTTON)
					{
						if (joystick_get_btn_event(joystick_fd1, js_info_index, js_event, &event, NULL) && Joy_CallBack != NULL)
						{
							Joy_CallBack(event, JOYPAD_B);
						}
					}
					else if (js_event.type == JS_EVENT_AXIS)
					{
						if (joystick_get_axis_event(joystick_fd1, js_info_index, js_event, &event, NULL) && Joy_CallBack != NULL)
						{
							Joy_CallBack(event, JOYPAD_B);
						}
					}
				}
			}
		}

		umfsleep(0, IRRECEIVEWAITTIME / 2);
	}

	return NULL;
}

static void *joystick_AddEvent(void *p)
{
	Control_Key *Event = (Control_Key *)p;
	js_event_t js_key;
	int bytes = -1;
	UINT8 key_number = 0;
	UINT16 i = 0;
	int event_index = -1;
	int fd = -1;
	int j = 0;
	
	prctl(PR_SET_NAME , "joystick_AddEvent", NULL, NULL, NULL);

	if (joypad_number == JOYPAD_A && joystick_fd0 > 0)
	{
		fd = joystick_fd0;
	}
	else if (joypad_number == JOYPAD_B && joystick_fd1 > 0)
	{
		fd = joystick_fd1;
	}
	else
	{
		fd = joystick_fd0;
	}
		
	while (AddEventFinish == FALSE && p_js_number != NULL && fd > 0)
	{
		if (p_js_number[joypad_number].p_js_name)
		{
			if (fd == joystick_fd1)
			{
				memcpy(p_js_number[joypad_number].p_js_name, js_name[1], MAX_JSNAME_LEN);
			}
			else
			{
				memcpy(p_js_number[joypad_number].p_js_name, js_name[0], MAX_JSNAME_LEN);
			}
		}
		if (Event == NULL)
		{
			break;
		}
		
		bytes = read(fd, (void *)(&js_key), sizeof(js_key)); 
		if (bytes == sizeof(js_key))
		{
			js_printf("[%s:%d]joystick_fd0  value %8hd, type: %3u, axis/button: %u\n", 
						__FUNCTION__,__LINE__, js_key.value, js_key.type, js_key.number);

			if (key_number == 0 && js_key.value != 0)
			{
				/* find a same event index */
				for (i = 0; i < MAX_EVENT_SIZE; i++)
				{
					if (p_js_number[joypad_number].p_js_event 
						&& (p_js_number[joypad_number].p_js_event[i].event == *Event))
					{
						p_js_number[joypad_number].p_js_event[i].key_number = 0;
						p_js_number[joypad_number].p_js_event[i].event = 0;
						memset(p_js_number[joypad_number].p_js_event[i].p_js_key, 0, sizeof(js_key_t)*MAX_KEY_SIZE);
						break;
					}
				}

				if (i >= MAX_EVENT_SIZE)
				{
					/* find a not used event index */
					for (i = 0; i < MAX_EVENT_SIZE; i++)
					{
						if (p_js_number[joypad_number].p_js_event && p_js_number[joypad_number].p_js_event[i].key_number == 0)
						{
							p_js_number[joypad_number].event_number++;
							break;
						}
					}
				}

				if (i < MAX_EVENT_SIZE)
				{
					event_index = i;
					/* press event added */
					//p_js_number[joypad_number].js_number = joypad_number;
					p_js_number[joypad_number].p_js_event[event_index].event = *Event;
					p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].value = js_key.value;
					p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].type = js_key.type;
					p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].number = js_key.number;
					p_js_number[joypad_number].p_js_event[event_index].key_number++;
					key_number++;	

					/* find a same event index */
					for (i = 0; i < MAX_EVENT_SIZE; i++)
					{
						if (p_js_number[joypad_number].p_js_event 
							&& (p_js_number[joypad_number].p_js_event[i].event == *Event + REMOVE_EVENT_JOYPAD_UP - ADD_EVENT_JOYPAD_UP))
						{
							p_js_number[joypad_number].p_js_event[i].key_number = 0;
							p_js_number[joypad_number].p_js_event[i].event = 0;
							memset(p_js_number[joypad_number].p_js_event[i].p_js_key, 0, sizeof(js_key_t)*MAX_KEY_SIZE);
							break;
						}
					}

					if (i >= MAX_EVENT_SIZE)
					{
						/* find a not used event index */
						for (i = 0; i < MAX_EVENT_SIZE; i++)
						{
							if (p_js_number[joypad_number].p_js_event && p_js_number[joypad_number].p_js_event[i].key_number == 0)
							{
								p_js_number[joypad_number].event_number++;
								break;
							}
						}
					}

					if (i < MAX_EVENT_SIZE)
					{
						event_index = i;
						/*  release event added */
						p_js_number[joypad_number].p_js_event[event_index].event = *Event+(REMOVE_EVENT_JOYPAD_UP-ADD_EVENT_JOYPAD_UP);
						p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].value = 0;
						p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].type = js_key.type;
						p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].number = js_key.number;
						p_js_number[joypad_number].p_js_event[event_index].key_number++;
						key_number++;
					}
				}
			}
			else if (js_key.value == 0 && key_number != 0)
			{
				AddEventFinish = TRUE;
			}
		}
		else
		{
			umfsleep(0, IRRECEIVEWAITTIME / 2);
		}
	}
	js_printf("\n\n\n");
	if (p_js_number != NULL)
	{
		if (key_number == 2 && event_index > 0)
		{
			if ((p_js_number[joypad_number].p_js_event[event_index-1].event > EVENT_JOYPAD_MIN && p_js_number[joypad_number].p_js_event[event_index-1].event < REMOVE_EVENT_JOYPAD_UP)
				&&(p_js_number[joypad_number].p_js_event[event_index].event >= REMOVE_EVENT_JOYPAD_UP && p_js_number[joypad_number].p_js_event[event_index].event < EVENT_JOYPAD_MAX)
				&& (p_js_number[joypad_number].p_js_event[event_index].event == (p_js_number[joypad_number].p_js_event[event_index-1].event+(REMOVE_EVENT_JOYPAD_UP-ADD_EVENT_JOYPAD_UP))))
			{	
				for (j = 0; j < p_js_number[joypad_number].p_js_event[event_index].key_number; j++)
				{
					if (p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].type == p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[j].type
						&& p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].number == p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[j].number
						&& p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].value != p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[j].value)
					{
						break;
					}
				}
				
				if (j < p_js_number[joypad_number].p_js_event[event_index].key_number)
				{
					p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].type = p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].type;
					p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].value = p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].value;
					p_js_number[joypad_number].p_js_event[event_index].p_js_key[0].number = p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].number;
					p_js_number[joypad_number].p_js_event[event_index].key_number = 1;
					js_printf("[%s:%d] AddEventOk !!!!!!!!!!!!!!!!!!\n",__FUNCTION__,__LINE__);
					AddEventOk = TRUE;
				}
			}
		
			if (AddEventOk == FALSE)
			{
				p_js_number[joypad_number].p_js_event[event_index-1].key_number = 0;
				p_js_number[joypad_number].p_js_event[event_index].key_number = 0;
			}
			
			js_printf("add::  joypad_number: %d,key.value: %d, key.type: %d, key.number: %d\n",joypad_number, p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[0].value,
				p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[0].type, p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[0].number);
			
			
			for (j = 0; j < p_js_number[joypad_number].p_js_event[event_index].key_number; j++)
			{
				js_printf("remove::	joypad_number: %d, key.value: %d, key.type: %d, key.number: %d\n",joypad_number,p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].value,
					p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].type, p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].number);
			}
		}
		else if (event_index == -1)
		{
			/* find a same event index */
			for (i = 0; i < MAX_EVENT_SIZE; i++)
			{
				if (p_js_number[joypad_number].p_js_event 
					&& (p_js_number[joypad_number].p_js_event[i].event == *Event))
				{
					event_index = i+1;
					break;
				}
			}
		
			if ((event_index < MAX_EVENT_SIZE) 
				&& (p_js_number[joypad_number].p_js_event[event_index-1].event > EVENT_JOYPAD_MIN && p_js_number[joypad_number].p_js_event[event_index-1].event < REMOVE_EVENT_JOYPAD_UP)
				&&(p_js_number[joypad_number].p_js_event[event_index].event >= REMOVE_EVENT_JOYPAD_UP && p_js_number[joypad_number].p_js_event[event_index].event < EVENT_JOYPAD_MAX)
				&& (p_js_number[joypad_number].p_js_event[event_index].event == (p_js_number[joypad_number].p_js_event[event_index-1].event+(REMOVE_EVENT_JOYPAD_UP-ADD_EVENT_JOYPAD_UP)))
				&& p_js_number[joypad_number].p_js_event[event_index-1].key_number > 0
				&& p_js_number[joypad_number].p_js_event[event_index].key_number > 0)
			{
				js_printf("[%s:%d] AddEventOk !!!!!!!!!!!!!!!!!!\n",__FUNCTION__,__LINE__);
				AddEventOk = TRUE;

				js_printf("add::  joypad_number: %d,key.value: %d, key.type: %d, key.number: %d\n",joypad_number, p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[0].value,
				p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[0].type, p_js_number[joypad_number].p_js_event[event_index-1].p_js_key[0].number);
			
			
				for (j = 0; j < p_js_number[joypad_number].p_js_event[event_index].key_number; j++)
				{
					js_printf("remove::	joypad_number: %d, key.value: %d, key.type: %d, key.number: %d\n",joypad_number,p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].value,
						p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].type, p_js_number[joypad_number].p_js_event[event_index].p_js_key[j].number);
				}
			}
		}
	}
	js_printf("\n\n\n");
	key_number = 0;
	add_event_thread = 0;
	js_Event = EVENT_JOYPAD_MIN;
	GL_SemaphoreGive(pSemaphore);
    AddEventFinish = TRUE;
	if (Joy_CallBack)
	{
		if (AddEventOk == TRUE)
		{
			Joy_CallBack(APP_GLOBAL_EVENT_JS_ADJUST_OK, 0);
		}
		else
		{
			Joy_CallBack(APP_GLOBAL_EVENT_JS_ADJUST_NG, 0);
		}
	}
	pthread_detach(pthread_self());

	return NULL;
}


int joystick_init(JOY_CallBack_t pJoy_CallBackFunc)
{
	Joy_CallBack = pJoy_CallBackFunc;

	GL_Status_t ret = GL_FAILURE;
	ret = GL_SemaphoreCreate("AddEventSemp", 1, 0, &pSemaphore);
	if (ret != GL_SUCCESS)
    {
		UMFDBG(0, "Error %d: %s call GL_QueueCreate failed!\n", ret, __FUNCTION__);
    }
	AL_Setting_Reload(APP_Data_UserSetting_Handle(), SYS_SET_ID_GAME);
    return S_OK;
}

int joystick_add_dev(void)
{
	if (joystick_fd0 < 0)
	{
		joystick_fd0 = open(JOYSTICK_DEVNAME0, O_RDONLY | O_NONBLOCK); /* read write for force feedback? */
		if (joystick_fd0 < 0)
		{
			UMFDBG(0, "Unable to open /dev/input/js0\n");
		}
		else
		{
			int number_of_axes = 0; 
			int number_of_btns = 0;

            if (pJsAnixEvent1 == NULL)
            {
                pJsAnixEvent1 = malloc(sizeof(js_anix_event_t));
                
                if (pJsAnixEvent1 == NULL)
                {
                    goto Malloc_JsAnixEvent1_Fail;
                }
                
                memset(pJsAnixEvent1, 0, sizeof(js_anix_event_t));
                pJsAnixEvent1->js_fd = joystick_fd0;
                
            }

			ioctl(joystick_fd0, JSIOCGAXES, &number_of_axes);
			js_printf("js0: number_of_axes === %d\n",number_of_axes);
			ioctl(joystick_fd0, JSIOCGBUTTONS, &number_of_btns);
			js_printf("js0: number_of_btns === %d\n",number_of_btns);
			memset(js_name[0], '\0', MAX_JSNAME_LEN);
			ioctl(joystick_fd0, JSIOCGNAME(sizeof(js_name[0])), js_name[0]);
			js_printf("js0: js_name_str === %s,+++++++\n",js_name[0]);
		}
	}
	
	if (joystick_fd1 < 0)
	{
		joystick_fd1 = open(JOYSTICK_DEVNAME1, O_RDONLY | O_NONBLOCK); /* read write for force feedback? */
		if (joystick_fd1 < 0)
		{
			UMFDBG(0, "Unable to open /dev/input/js1\n");
		}
		else
		{
			int number_of_axes = 0; 
			int number_of_btns = 0; 
            
            if (pJsAnixEvent2 == NULL)
            {
                pJsAnixEvent2 = malloc(sizeof(js_anix_event_t));
                
                if (pJsAnixEvent2 == NULL)
                {
                    goto Malloc_JsAnixEvent2_Fail;
                }
                
                memset(pJsAnixEvent2, 0, sizeof(js_anix_event_t));
                pJsAnixEvent2->js_fd = joystick_fd1;
                
            }

			ioctl(joystick_fd1, JSIOCGAXES, &number_of_axes);
			js_printf("js1: number_of_axes === %d\n",number_of_axes);
			ioctl(joystick_fd1, JSIOCGBUTTONS, &number_of_btns);
			js_printf("js1: number_of_btns === %d\n",number_of_btns);
			memset(js_name[1], '\0', MAX_JSNAME_LEN);
			ioctl(joystick_fd1, JSIOCGNAME(sizeof(js_name[1])), js_name[1]);
			js_printf("js1: js_name_str === %s,+++++++\n",js_name[1]);
		}
	}

	if ((joystick_fd0 > 0 || joystick_fd1 > 0))
	{
		joystick_memory_alloc();
	}
	
	if ((joythread == 0) && (joystick_fd0 > 0 || joystick_fd1 > 0))
	{
		size_t stacksize = 16*1024;
		pthread_attr_t attr;
		pthread_attr_init(&attr);
		pthread_attr_setstacksize(&attr, stacksize);
		if (pthread_create(&joythread, &attr, joystick_Receive, NULL) != 0)
	    {
	        UMFDBG(0, "Joy pthread_create fail \n");
	    }
		pthread_attr_destroy(&attr);
	}
	return S_OK;

Malloc_JsAnixEvent2_Fail:
    if (joystick_fd1)
        close(joystick_fd0);

    if (joystick_fd0)
    {
        close(joystick_fd0);
        free(pJsAnixEvent1);
        pJsAnixEvent1 = NULL;
    }

Malloc_JsAnixEvent1_Fail:
    if (joystick_fd0)
        close(joystick_fd0);
    return E_FAIL;
    
}

int joystick_remove_dev(void)
{
	int re = -1;
	int number_of_btns = 0;
	
	re = ioctl(joystick_fd0, JSIOCGBUTTONS, &number_of_btns);
	if (re == -1 && joystick_fd0 > 1)
	{	    
		close(joystick_fd0);
		joystick_fd0 = -1;
        if (pJsAnixEvent1)
        {
            free(pJsAnixEvent1);
            pJsAnixEvent1 = NULL;
        }
        
        Joy_CallBack(APP_GLOBAL_EVENT_JS_REMOVE, 0);
	}
	
	re = -1;
	number_of_btns = 0;
	re = ioctl(joystick_fd1, JSIOCGBUTTONS, &number_of_btns);
	if (re == -1 && joystick_fd1 > 1)
	{
		close(joystick_fd1);
		joystick_fd1 = -1;
        if (pJsAnixEvent2)
        {
            free(pJsAnixEvent2);
            pJsAnixEvent2 = NULL;
        }
        Joy_CallBack(APP_GLOBAL_EVENT_JS_REMOVE, 1);
	}

	if (joystick_fd0 == -1 && joystick_fd1 == -1)
	{
		joystick_memory_free();
	}
	return S_OK;
}

int joystick_AddEvent_Start(UINT32 event)
{
    if (joypad_number >= JOYPAD_MAX)
    {
        return -1;
    }

	if ((add_event_thread == 0) && (joystick_fd0 > 0 || joystick_fd1 > 0) && (p_js_number != NULL))
	{
		js_Event = event;
		AddEventFinish = FALSE;
		size_t stacksize = 16*1024;
		pthread_attr_t attr;
		pthread_attr_init(&attr);
		pthread_attr_setstacksize(&attr, stacksize);
		if (pthread_create(&add_event_thread, &attr, joystick_AddEvent, &js_Event) != 0)
	    {
	        UMFDBG(0, "Joy pthread_create fail \n");
			AddEventOk = FALSE;
			AddEventFinish = TRUE;
			add_event_thread = 0;
			js_Event = EVENT_JOYPAD_MIN;
			pthread_attr_destroy(&attr);
			return -1;
	    }
		pthread_attr_destroy(&attr);
		return 0;
	}

	return -1;
}

int joystick_AddEvent_Finish(void)
{
	if (AddEventFinish == FALSE)
	{
		while (GL_SemaphoreTake(pSemaphore, GL_NO_WAIT) == GL_SUCCESS);
		AddEventFinish = TRUE;
		GL_SemaphoreTake(pSemaphore, GL_INFINITE_WAIT);

		if (AddEventOk)
		{
			AddEventOk = FALSE;
			return 0;
		}
	}

	return -1;
}

void joystick_SetJSNumber(UINT8 js_number)
{
	joypad_number = js_number;
	js_printf("[%s:%d] joypad_number ==================== %d\n",__FUNCTION__,__LINE__,joypad_number);
}

int joystick_GetDevNumber(void)
{
	int number = 0;

	if (joystick_fd0 > 0)
	{
		number++;
	}
	if (joystick_fd1 > 0)
	{
		number++;
	}
	return number;
}

int joystick_Save(UINT8 js_number)
{
	if (p_js_number == NULL || js_number >= 2)
	{
		return -1;
	}
	js_printf("[%s:%d] js_number ==================== %d\n",__FUNCTION__,__LINE__,js_number);
	UINT8 i = 0;
	int store_index = -1;

	for (i = 0; i < STORE_MAX_JSPAD; i++)
	{
		if (strcmp(g_stGameData.js_data[i].js_name, p_js_number[js_number].p_js_name) == 0 && g_stGameData.js_data[i].js_number == js_number)
		{
			memset(&(g_stGameData.js_data[i]), 0, sizeof(APP_SETTING_JSData_t));
			break;
		}
	}

	if (i >= STORE_MAX_JSPAD )
	{
		for (i = 0; i < STORE_MAX_JSPAD; i++)
		{
			if (g_stGameData.js_data[i].event_number == 0)
			{
				break;
			}
		}
	}
	
	if (i < STORE_MAX_JSPAD)
	{
		store_index = i;
	}
	else
	{
		store_index = 0;
		memset(&(g_stGameData.js_data[store_index]), 0, sizeof(APP_SETTING_JSData_t));
	}
	js_printf("[%s:%d] store_index ==================== %d\n",__FUNCTION__,__LINE__,store_index);
	g_stGameData.js_data[store_index].event_number = p_js_number[js_number].event_number;
	g_stGameData.js_data[store_index].js_number = js_number;
	memcpy(g_stGameData.js_data[store_index].js_name, p_js_number[js_number].p_js_name, MAX_JSNAME_LEN);

	for (i = 0; i < p_js_number[js_number].event_number && i < MAX_EVENT_SIZE; i++)
	{
		memcpy(&(g_stGameData.js_data[store_index].js_event[i].js_key), p_js_number[js_number].p_js_event[i].p_js_key, sizeof(js_key_t));
		g_stGameData.js_data[store_index].js_event[i].event = p_js_number[js_number].p_js_event[i].event;
	}

	AL_Setting_Write(APP_Data_UserSetting_Handle(), SYS_SET_ID_GAME, 0, sizeof(g_stGameData),
         &g_stGameData);
	
	AL_Setting_Store(APP_Data_UserSetting_Handle(),SYS_SET_ID_GAME,0,sizeof(g_stGameData));
	return 0;
}
void joystick_Convert_UIEvent_Set(INT32 bConvert)
{
    gConvertUIEventFlag = bConvert;
    js_printf("----------------set----gConvertUIEventFlag = %d-----------------\n", gConvertUIEventFlag);
}

int joystick_Convert_UIEvent_Get(void)
{
    js_printf("----------------get----gConvertUIEventFlag = %d-----------------\n", gConvertUIEventFlag);
    return gConvertUIEventFlag;
}

