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>
touchscreen.c文件: /* 支持从触摸屏点击区域来翻页 */
<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>