input目录下的结构:
Makefile
<span style="font-size:18px;">obj-y += input_manager.o obj-y += stdin.o obj-y += touchscreen.o </span>
input_manager.h文件:
<span style="font-size:18px;">#ifndef _INPUT_MANAGER_H #define _INPUT_MANAGER_H #include <sys/time.h> #include <pthread.h> #define INPUT_TYPE_STDIN 0 #define INPUT_TYPE_TOUCHSCREEN 1 #define INPUT_VALUE_UP 0 #define INPUT_VALUE_DOWN 1 #define INPUT_VALUE_EXIT 2 #define INPUT_VALUE_UNKNOWN -1 typedef struct InputEvent { struct timeval tTime; int iType; /* stdin, touchsceen */ int iVal; /* */ }T_InputEvent, *PT_InputEvent; typedef struct InputOpr { char *name; pthread_t tTreadID; int (*DeviceInit)(void); int (*DeviceExit)(void); int (*GetInputEvent)(PT_InputEvent ptInputEvent); struct InputOpr *ptNext; }T_InputOpr, *PT_InputOpr; int InputInit(void); int RegisterInputOpr(PT_InputOpr ptInputOpr); void ShowInputOpr(void); int AllInputDevicesInit(void); int GetInputEvent(PT_InputEvent ptInputEvent); int StdinInit(void); int TouchScreenInit(void); #endif /* _INPUT_MANAGER_H */ </span>
input_manager.c文件:
<span style="font-size:18px;">#include <config.h> #include <input_manager.h> #include <string.h> static PT_InputOpr g_ptInputOprHead; static T_InputEvent g_tInputEvent; static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t g_tConVar = PTHREAD_COND_INITIALIZER; int RegisterInputOpr(PT_InputOpr ptInputOpr) { PT_InputOpr ptTmp; if (!g_ptInputOprHead) { g_ptInputOprHead = ptInputOpr; ptInputOpr->ptNext = NULL; } else { ptTmp = g_ptInputOprHead; while (ptTmp->ptNext) { ptTmp = ptTmp->ptNext; } ptTmp->ptNext = ptInputOpr; ptInputOpr->ptNext = NULL; } return 0; } void ShowInputOpr(void) { int i = 0; PT_InputOpr ptTmp = g_ptInputOprHead; while (ptTmp) { printf("%02d %s\n", i++, ptTmp->name); ptTmp = ptTmp->ptNext; } } static void *InputEventTreadFunction(void *pVoid) { T_InputEvent tInputEvent; /* 定义函数指针 */ int (*GetInputEvent)(PT_InputEvent ptInputEvent); GetInputEvent = (int (*)(PT_InputEvent))pVoid; while (1) { if(0 == GetInputEvent(&tInputEvent)) { /* 唤醒主线程, 把tInputEvent的值赋给一个全局变量 */ /* 访问临界资源前,先获得互斥量 */ pthread_mutex_lock(&g_tMutex); g_tInputEvent = tInputEvent; /* 唤醒主线程 */ pthread_cond_signal(&g_tConVar); /* 释放互斥量 */ pthread_mutex_unlock(&g_tMutex); } } return NULL; } int AllInputDevicesInit(void) { PT_InputOpr ptTmp = g_ptInputOprHead; int iError = -1; while (ptTmp) { if (0 == ptTmp->DeviceInit()) { /* 创建子线程 */ pthread_create(&ptTmp->tTreadID, NULL, InputEventTreadFunction, ptTmp->GetInputEvent); iError = 0; } ptTmp = ptTmp->ptNext; } return iError; } int GetInputEvent(PT_InputEvent ptInputEvent) { /* 休眠 */ pthread_mutex_lock(&g_tMutex); pthread_cond_wait(&g_tConVar, &g_tMutex); /* 被唤醒后,返回数据 */ *ptInputEvent = g_tInputEvent; pthread_mutex_unlock(&g_tMutex); return 0; } int InputInit(void) { int iError; iError = StdinInit(); iError |= TouchScreenInit(); return iError; } </span>
stdin.c文件: /* 支持从终端串口输入数据来控制翻页 */
<span style="font-size:18px;">#include <input_manager.h> #include <termios.h> #include <unistd.h> #include <stdio.h> static int StdinDevInit(void) { struct termios tTTYState; //get the terminal state tcgetattr(STDIN_FILENO, &tTTYState); //turn off canonical mode tTTYState.c_lflag &= ~ICANON; //minimum of number input read. tTTYState.c_cc[VMIN] = 1; /* 有一个数据时就立刻返回 */ //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); return 0; } static int StdinDevExit(void) { struct termios tTTYState; //get the terminal state tcgetattr(STDIN_FILENO, &tTTYState); //turn on canonical mode tTTYState.c_lflag |= ICANON; //set the terminal attributes. tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); return 0; } static int StdinGetInputEvent(PT_InputEvent ptInputEvent) { /* 如果有数据就读取、处理、返回 * 如果没有数据, 立刻返回, 不等待 */ /* select, poll 可以参数 UNIX环境高级编程 */ char c; /* 处理数据 */ ptInputEvent->iType = INPUT_TYPE_STDIN; c = fgetc(stdin); /* 会休眠直到有输入 */ gettimeofday(&ptInputEvent->tTime, NULL); if (c == 'u') { ptInputEvent->iVal = INPUT_VALUE_UP; } else if (c == 'n') { ptInputEvent->iVal = INPUT_VALUE_DOWN; } else if (c == 'q') { ptInputEvent->iVal = INPUT_VALUE_EXIT; } else { ptInputEvent->iVal = INPUT_VALUE_UNKNOWN; } return 0; } static T_InputOpr g_tStdinOpr = { .name = "stdin", .DeviceInit = StdinDevInit, .DeviceExit = StdinDevExit, .GetInputEvent = StdinGetInputEvent, }; int StdinInit(void) { return RegisterInputOpr(&g_tStdinOpr); } </span>
<span style="font-size:18px;">#include <config.h> #include <input_manager.h> #include <stdlib.h> #include <tslib.h> #include <draw.h> /* 参考tslib里的ts_print.c */ static struct tsdev *g_tTSDev; static int giXres; static int giYres; /* 注意: 由于要用到LCD的分辨率, 此函数要在SelectAndInitDisplay之后调用 */ static int TouchScreenDevInit(void) { char *pcTSName = NULL; if ((pcTSName = getenv("TSLIB_TSDEVICE")) != NULL ) { g_tTSDev = ts_open(pcTSName, 0); /* 以阻塞方式打开 */ } else { g_tTSDev = ts_open("/dev/event0", 1); } if (!g_tTSDev) { DBG_PRINTF("ts_open error!\n"); return -1; } if (ts_config(g_tTSDev)) { DBG_PRINTF("ts_config error!\n"); return -1; } if (GetDispResolution(&giXres, &giYres)) { return -1; } return 0; } static int TouchScreenDevExit(void) { return 0; } static int isOutOf500ms(struct timeval *ptPreTime, struct timeval *ptNowTime) { int iPreMs; int iNowMs; iPreMs = ptPreTime->tv_sec * 1000 + ptPreTime->tv_usec / 1000; iNowMs = ptNowTime->tv_sec * 1000 + ptNowTime->tv_usec / 1000; return (iNowMs > iPreMs + 500); } static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent) { struct ts_sample tSamp; struct ts_sample tSampPressed; struct ts_sample tSampReleased; int iRet; int bStart = 0; int iDelta; static struct timeval tPreTime; while (1) { iRet = ts_read(g_tTSDev, &tSamp, 1); /* 如果无数据则休眠 */ if (iRet == 1) { if ((tSamp.pressure > 0) && (bStart == 0)) { /* 刚按下 */ /* 记录刚开始压下的点 */ tSampPressed = tSamp; bStart = 1; } if (tSamp.pressure <= 0) { /* 松开 */ tSampReleased = tSamp; /* 处理数据 */ if (!bStart) { return -1; } else { iDelta = tSampReleased.x - tSampPressed.x; ptInputEvent->tTime = tSampReleased.tv; ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN; if (iDelta > giXres/5) { /* 翻到上一页 */ ptInputEvent->iVal = INPUT_VALUE_UP; } else if (iDelta < 0 - giXres/5) { /* 翻到下一页 */ ptInputEvent->iVal = INPUT_VALUE_DOWN; } else { ptInputEvent->iVal = INPUT_VALUE_UNKNOWN; } return 0; } } } else { return -1; } } return 0; } static T_InputOpr g_tTouchScreenOpr = { .name = "touchscreen", .DeviceInit = TouchScreenDevInit, .DeviceExit = TouchScreenDevExit, .GetInputEvent = TouchScreenGetInputEvent, }; int TouchScreenInit(void) { return RegisterInputOpr(&g_tTouchScreenOpr); } </span>