数码相框-输入模块

input模块的主要功能 :
  从多个输入设备获得输入事件

input模块包含三个文件,input_manager.c,touchscreen.c和stdin.c,其中touchscreen.ch和stdin.c为支持的输入方式,input_manager.c通过链表管理可支持的设备。

	   input_manager.c
	    |			|
touchscreen.c	 stdin.c

底层的touchscreen.c和stdin.c,向上注册InputOpr结构体,提供该设备的操作函数。

typedef struct InputOpr {
	char *name;          /* 输入模块的名字 */
	pthread_t tTreadID;  /* 子线程ID */
	int (*DeviceInit)(void);  /* 设备初始化函数 */
	int (*DeviceExit)(void);  /* 设备退出函数 */
	int (*GetInputEvent)(PT_InputEvent ptInputEvent);  /* 获得输入数据 */
	struct InputOpr *ptNext;
}T_InputOpr, *PT_InputOpr;

typedef struct InputEvent {
	struct timeval tTime;   /* 发生这个输入事件时的时间 */
	int iType;  /* 类别: stdin, touchsceen */
	int iX;     /* X/Y座标 */
	int iY;
	int iKey;   /* 按键值 */
	int iPressure; /* 压力值 */
}T_InputEvent, *PT_InputEvent;

touchscreen.c

static T_InputOpr g_tTouchScreenOpr = {
	.name          = "touchscreen",
	.DeviceInit    = TouchScreenDevInit,		//触摸屏输入模块的设备初始化函数
	.DeviceExit    = TouchScreenDevExit,		//触摸屏输入模块的设备退出函数
	.GetInputEvent = TouchScreenGetInputEvent,	//触摸屏输入模块的读取数据函数,它在触摸屏输入模块的子线程中被调用
};

static int TouchScreenDevInit(void){
	char *pcTSName = NULL;
	int iBpp;
	if ((pcTSName = getenv("TSLIB_TSDEVICE")) != NULL ) {
		g_tTSDev = ts_open(pcTSName, 0);  /* 以阻塞方式打开 */
	}
	else{
		g_tTSDev = ts_open("/dev/event0", 1);
	}
	ts_config(g_tTSDev)
	GetDispResolution(&giXres, &giYres, &iBpp)
	return 0;
}


static int TouchScreenDevExit(void){
	return 0;
}

static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent){
	struct ts_sample tSamp;
	while (1){
		iRet = ts_read(g_tTSDev, &tSamp, 1); /* 如果无数据则休眠 */
		if (iRet == 1){				//返回原始事件	
			ptInputEvent->tTime     = tSamp.tv;		
			ptInputEvent->iType     = INPUT_TYPE_TOUCHSCREEN;
			ptInputEvent->iX        = tSamp.x;
			ptInputEvent->iY        = tSamp.y;
			ptInputEvent->iPressure = tSamp.pressure;
			return 0;
		}
		else{
			return -1;
		}
	}
	return 0;
}

其中

触摸屏read得到的数据,参考ts_print和tslib.h
struct ts_sample {
	int		x;
	int		y;
	unsigned int	pressure;
	struct timeval	tv;
};

stdin.c

static T_InputOpr g_tStdinOpr = {
	.name          = "stdin",
	.DeviceInit    = StdinDevInit,		//标准输入模块的设备初始化函数,用于设置标准输入的属性,比如默认的标准输入是接收到回车换行符时才返回数据,在本程序里把它改为"接收到任意一个字符即返回数据"
	.DeviceExit    = StdinDevExit,		//标准输入模块的设备退出函数,恢复标准输入的原来属性
	.GetInputEvent = StdinGetInputEvent,	//标准输入模块的读取数据函数,它在标准输入模块的子线程中被调用
};

static int StdinDevInit(void){
    struct termios tTTYState;
    tcgetattr(STDIN_FILENO, &tTTYState);	 //get the terminal state 
    tTTYState.c_lflag &= ~ICANON;	//turn off canonical mode  
    tTTYState.c_cc[VMIN] = 1;   /* 有一个数据时就立刻返回 */	 //minimum of number input read.
    tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); //set the terminal attributes.
	return 0;
}

static int StdinDevExit(void){
    struct termios tTTYState;  
    tcgetattr(STDIN_FILENO, &tTTYState);	//get the terminal state   
    tTTYState.c_lflag |= ICANON;	//turn on canonical mode 
    tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);	//set the terminal attributes.
	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);
	return 0;
 }

input_manager.c

input_manager.c通过链表管理底层支持的显示设备向上注册的InputOpr结构体,并向外部提供对底层的操作函数。其中头文件Input_manager.h包含InputOpr和InputEvent结构体。

int RegisterInputOpr(PT_InputOpr ptInputOpr)	//注册"输入模块"
int AllInputDevicesInit(void)	//调用所有"输入模块"的设备相关的初始化函数并创建用于读取输入数据的子线程
static void *InputEventThreadFunction(void *pVoid)	//"输入模块"的线程函数,每个输入模块都是通过创建子线程来读取输入数据,读到数据后它会唤醒等得数据的其他线程
int GetInputEvent(PT_InputEvent ptInputEvent)	//获得输入数据,它会使得当前线程休眠,当各输入模块的子线程读到数据后会把它唤醒

上层先调用AllInputDevicesInit函数初始化相关设备并创建用于读取输入数据的子线程。在子线程函数中以阻塞方式读取事件进入休眠,在上层函数中调用GetInputEvent获取事件进入休眠。当有输入事件时,子线程函数将上层函数唤醒,则上层函数就得到了输入事件InputEvent结构体。具体实现参考多输入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值