数码相框——5、2 支持多输入——select方式

任务:在之前的框架上编写 使用按键和触摸屏 的代码(select方式)

1、介绍select

int select (int maxfd + 1, fd_set* readset, fd_set* writeset, fd_set* exceptset, const struct timeval* timeout);
监测多个文件,只要有一个文件可读/可写/异常或超时,即返回。
休眠检测,CPU占用率低,适用于简单的场合。

头文件:
#include <sys/select.h>

参数:

int maxfd最大文件句柄
fd_set* readset被监测是否可读的文件
fd_set* writeset被检测是否可写的文件
fd_set* exceptset被检测是否有异常的文件
const struct timeval* timeout超时时间

timeval结构的定义:

   struct timeval {
         long    tv_sec;         /* seconds */
         long    tv_usec;        /* microseconds */
     };

轮询方式:在input_manager.c里的GetInputEvent,不管有没有数据不停去调用stdin.c里的StdinGetInputEvent获取输入事件,去调用touchscreen.c里的TouchScreenGetInputEvent获取输入事件。

select方式:在input_manager.c里用select监测数据,得到数据了才去调用stdin.c里的StdinGetInputEvent获取输入事件,去调用touchscreen.c里的TouchScreenGetInputEvent获取输入事件。没有数据就休眠,有数据内核去唤醒。

参考:UNIX高级编程——I/O多路转接

2、在Input_manager.h里
修改 结构体InputOpr, 添加文件句柄

typedef struct InputOpr {
	char *name;
	int iFd;
	int (*DeviceInit)(void);
	int (*DeviceExit)(void);
	int (*GetInputEvent)(PT_InputEvent ptInputEvent);
	struct InputOpr *ptNext;
}T_InputOpr, *PT_InputOpr;

3、在stdin.c里

3.1、修改StdinDevInit():

g_tstdinOpr.iFd = STDIN_FILEON;

完整代码:

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);

	g_tStdinOpr.iFd = STDIN_FILENO;

	return 0;
}

4、在touchscreen.c里

4.1、修改TouchScreenDevInit():

g_tTouchScreenOpr.iFd = ts_fd(g_tTSDev); //获得文件句柄

完整代码:

/* 注意: 由于要用到LCD的分辨率, 此函数要在SelectAndInitDisplay之后调用 */
static int TouchScreenDevInit(void)
{
	char *pcTSName = NULL;

	if ((pcTSName = getenv("TSLIB_TSDEVICE")) != NULL ) 
	{
		g_tTSDev = ts_open(pcTSName, 1);
	}
	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;
	}

	g_tTouchScreenOpr.iFd = ts_fd(g_tTSDev); //获得文件句柄

	return 0;
}

5、在input_manager.c 里

static fd_set g_tRFds;
static int g_iMaxFd = -1;

int AllInputDevicesInit(void)
{
	PT_InputOpr ptTmp = g_ptInputOprHead;
	int iError = -1;

	FD_ZERO(&g_tRFds); //全清零

	while (ptTmp)
	{
		if (0 == ptTmp->DeviceInit())
		{
			FD_SET(ptTmp->iFd, &g_tRFds); //设置检测对象, 设置g_tRFds里的某一位给ptTmp->iFd
			if (g_iMaxFd < ptTmp->iFd)  //记录最大文件句柄
				g_iMaxFd = ptTmp->iFd;
			iError = 0;
		}
		ptTmp = ptTmp->ptNext;
	}

	g_iMaxFd++; //因为select是最大文件句柄+1
	return iError;
}

select 方式

int GetInputEvent(PT_InputEvent ptInputEvent)
{

	/* 用select函数监测stdin,touchscreen,
	   有数据时再调用它们的GetInputEvent或获得具体事件
	 */

	PT_InputOpr ptTmp = g_ptInputOprHead;
	fd_set tRFds;
	int iRet;

	tRFds = g_tRFds;
 
	iRet = select(g_iMaxFd, &tRFds, NULL, NULL, NULL); //超时时间设为NULL,有输入事件的数据再返回
	if (iRet > 0) //大于0表示有数据
	{
	
		while (ptTmp)
		{
			if (FD_ISSET(ptTmp->iFd, &tRFds)) //是否可读
			{
				if(0 == ptTmp->GetInputEvent(ptInputEvent))
				{
					return 0;
				}
			}
			ptTmp = ptTmp->ptNext;
		}
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值