linux应用程序_1_文本浏览器_8_输入设备_2_轮询机制
这里的两种输入设备分别是指标准输入(非阻塞方式)、触摸屏输入,测试代码可以修改前面的draw.c、main.c得到,文末给出相关的draw和main,Makefile也需要作出相应修改
1、增加input目录的Makefile
2、修改顶层Makefile:
编译选项:增加tslib头文件所在目录
链接选项:增加tslib库所在目录
总的来说,具体输入设备所在文件需要完成两项工作
1、设置结构体
2、完善具体操作,向上对接input_manager.c
对触摸屏(ts.c):
初始化:
打开设备
配置参数
获取显示设备参数
static int TsInputInit(void)
{
char *pcTsdevice=NULL;
if(! (pcTsdevice = getenv("TSLIB_TSDEVICE")))
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
g_ptTs = ts_open(pcTsdevice,1);
if(!g_ptTs)
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
if (ts_config(g_ptTs))
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
if(GetSeletedDispRes(&g_iXres, &g_iYres))
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
return 0;
}
获取事件:
采用轮询方式读取触摸屏
事件发生时,过500ms才处理(避免一次按下翻页多次)
static int TsInputGetEvent(PT_InputEventOpr ptInputEventOpr)
{
struct ts_sample tSamp;
int iRet;
static struct timeval tPreTime;
iRet = ts_read(g_ptTs, &tSamp, 1);
if (iRet < 0)
return -1;
iRet = IsOutOf500ms(&tPreTime, &tSamp.tv);
if(!iRet)
return -1;
tPreTime.tv_sec = tSamp.tv.tv_sec;
tPreTime.tv_usec = tSamp.tv.tv_usec;
ptInputEventOpr->iType = INPUT_TYPE_TS;
if(tSamp.x < (g_iXres / 3))
ptInputEventOpr->iVal = INPUT_VAL_PRE;
else if(tSamp.x > (g_iXres * 2 / 3))
ptInputEventOpr->iVal = INPUT_VAL_NEXT;
else
ptInputEventOpr->iVal = INPUT_VAL_EXIT;
return 0;
}
标准输入(stdin.c):
初始化:
1、获取终端参数
2、修改终端参数
static int StdinInputInit(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 StdinInputExit(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;
}
获取事件:
1、清空结构体
2、添加文件描述符
3、select(同poll)
4、有数据则处理,没有则返回
static int StdinInputGetEvent(PT_InputEventOpr ptInputEventOpr)
{
char cOneChar;
struct timeval tTv;
fd_set plFds;
tTv.tv_sec = 0;
tTv.tv_usec = 0;
FD_ZERO(&plFds);
FD_SET(STDIN_FILENO, &plFds); //STDIN_FILENO is 0
select(STDIN_FILENO+1, &plFds, NULL, NULL, &tTv);
if(!FD_ISSET(STDIN_FILENO, &plFds))
{
return -1;
}
cOneChar = fgetc(stdin);
switch(cOneChar)
{
case 'p':
{
ptInputEventOpr->iVal = INPUT_VAL_PRE;
break;
}
case 'n':
{
ptInputEventOpr->iVal = INPUT_VAL_NEXT;
break;
}
case 'q':
{
ptInputEventOpr->iVal = INPUT_VAL_EXIT;
break;
}
default:
ptInputEventOpr->iVal = INPUT_VAL_UNKNOWN;
}
return 0;
}
附代码:
stdin.c
#include <input_manager.h>
#include <config.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
static int StdinInputInit(void);
static int StdinInputExit(void);
static int StdinInputGetEvent(PT_InputEventOpr ptInputEventOpr);
static T_InputOpr g_tStdinInputOpr = {
.pcName = "stdin",
.InputInit = StdinInputInit,
.InputExit = StdinInputExit,
.InputGetEvent = StdinInputGetEvent,
};
static int StdinInputInit(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 StdinInputExit(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 StdinInputGetEvent(PT_InputEventOpr ptInputEventOpr)
{
char cOneChar;
struct timeval tTv;
fd_set plFds;
tTv.tv_sec = 0;
tTv.tv_usec = 0;
FD_ZERO(&plFds);
FD_SET(STDIN_FILENO, &plFds); //STDIN_FILENO is 0
select(STDIN_FILENO+1, &plFds, NULL, NULL, &tTv);
if(!FD_ISSET(STDIN_FILENO, &plFds))
{
return -1;
}
cOneChar = fgetc(stdin);
switch(cOneChar)
{
case 'p':
{
ptInputEventOpr->iVal = INPUT_VAL_PRE;
break;
}
case 'n':
{
ptInputEventOpr->iVal = INPUT_VAL_NEXT;
break;
}
case 'q':
{
ptInputEventOpr->iVal = INPUT_VAL_EXIT;
break;
}
default:
ptInputEventOpr->iVal = INPUT_VAL_UNKNOWN;
}
return 0;
}
int StdinInit(void)
{
return RegisterInputOpr(&g_tStdinInputOpr);
}
ts.c
#include <config.h>
#include <input_manager.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <tslib.h>
#include <draw.h>
static int TsInputInit(void);
static int TsInputExit(void);
static int TsInputGetEvent(PT_InputEventOpr ptInputEventOpr);
static T_InputOpr g_tTsInputOpr = {
.pcName = "ts",
.InputInit = TsInputInit,
.InputExit = TsInputExit,
.InputGetEvent = TsInputGetEvent,
};
static struct tsdev *g_ptTs;
static int g_iXres, g_iYres;
static int TsInputInit(void)
{
char *pcTsdevice=NULL;
if(! (pcTsdevice = getenv("TSLIB_TSDEVICE")))
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
g_ptTs = ts_open(pcTsdevice,1);
if(!g_ptTs)
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
if (ts_config(g_ptTs))
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
if(GetSeletedDispRes(&g_iXres, &g_iYres))
{
DBG_PRINT("Error at %s ,%d", __FILE__, __LINE__);
return -1;
}
return 0;
}
static int TsInputExit(void)
{
return 0;
}
static int IsOutOf500ms(struct timeval *ptPreTime, struct timeval *ptNowTime)
{
int iPreTime, iNowTime;
iPreTime = ptPreTime->tv_sec * 1000 + ptPreTime->tv_usec / 1000;
iNowTime = ptNowTime->tv_sec * 1000 + ptNowTime->tv_usec / 1000;
if((iNowTime - iPreTime) < 500)
return 0;
return 1;
}
static int TsInputGetEvent(PT_InputEventOpr ptInputEventOpr)
{
struct ts_sample tSamp;
int iRet;
static struct timeval tPreTime;
iRet = ts_read(g_ptTs, &tSamp, 1);
if (iRet < 0)
return -1;
iRet = IsOutOf500ms(&tPreTime, &tSamp.tv);
if(!iRet)
return -1;
tPreTime.tv_sec = tSamp.tv.tv_sec;
tPreTime.tv_usec = tSamp.tv.tv_usec;
ptInputEventOpr->iType = INPUT_TYPE_TS;
if(tSamp.x < (g_iXres / 3))
ptInputEventOpr->iVal = INPUT_VAL_PRE;
else if(tSamp.x > (g_iXres * 2 / 3))
ptInputEventOpr->iVal = INPUT_VAL_NEXT;
else
ptInputEventOpr->iVal = INPUT_VAL_EXIT;
return 0;
}
int TsInit(void)
{
return RegisterInputOpr(&g_tTsInputOpr);
}
draw.c
#include <config.h>
//#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <encoding_manager.h>
#include <fonts_manager.h>
#include <disp_manager.h>
#include <fcntl.h>
#include <string.h>
#include <draw.h>
#include <input_manager.h>
typedef struct PageDesc{
int iPage;
unsigned char *pucCurPosAtFile;
struct PageDesc *ptPrePage;
struct PageDesc *ptNextPage;
}T_PageDesc, *PT_PageDesc;
static PT_PageDesc g_ptPageDesc;
static unsigned char *g_pucNextPosAtFile;
static int g_iFd;
static unsigned char *g_pucFileStart;
static unsigned char *g_pucFileEnd;
static PT_EncodingOpr g_ptEncodingOpr;
static PT_DispOpr g_ptDispOpr;
static int g_iFontSize;
int OpenTextFile(char *pcFileName)
{
struct stat tStat;
g_iFd = open(pcFileName, O_RDONLY);
if(g_iFd < 0)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
fstat(g_iFd, &tStat);
g_pucFileStart = mmap(NULL, tStat.st_size, PROT_READ, MAP_SHARED, g_iFd, 0);
if(g_pucFileStart == (unsigned char *)-1)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -2;
}
g_pucFileEnd = g_pucFileStart + tStat.st_size;
g_ptEncodingOpr = SelectEncodingOpr(g_pucFileStart);
if(!g_ptEncodingOpr)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -3;
}
return 0;
}
int SetFontsDetail(char *pcHzkFile, char *pcFreetypeFile, int iFontSize)
{
PT_FontOpr ptFontOprTmp;
PT_FontOpr ptFontOpr = g_ptEncodingOpr->ptFontOprSupportHead;
int iError = 0, iRet = 1;
g_iFontSize = iFontSize;
DBG_PRINT("%s support\r\n",g_ptEncodingOpr->pcName);
while(ptFontOpr)
{
if(strcmp(ptFontOpr->pcName, "ascii") == 0)
{
iError = ptFontOpr->FontInit(NULL, iFontSize);
if(iError)
DBG_PRINT("%s can't support %s\r\n", g_ptEncodingOpr->pcName, "ascii");
}
else if(strcmp(ptFontOpr->pcName, "gbk") == 0)
{
iError = ptFontOpr->FontInit(pcHzkFile, iFontSize);
if(iError)
DBG_PRINT("%s can't support %s\r\n", g_ptEncodingOpr->pcName, "gbk");
}
else
{
iError = ptFontOpr->FontInit(pcFreetypeFile, iFontSize);
if(iError)
DBG_PRINT("%s can't support %s\r\n", g_ptEncodingOpr->pcName, "freetype");
}
ptFontOprTmp = ptFontOpr->ptNext;
if(!iError)
{
iRet = 0;
}
else
{
DBG_PRINT("Need to Del at SetFontsDetail : %s\r\n",ptFontOpr->pcName);
DelFontOprFrmEncoding(g_ptEncodingOpr, ptFontOpr);
}
ptFontOpr = ptFontOprTmp;
}
return iRet;
}
int SelectAndInitDisplay(char *pcName)
{
int iError;
g_ptDispOpr = GetDispOpr(pcName);
if(!g_ptDispOpr)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
iError = g_ptDispOpr->DeviceInit();
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -2;
}
return 0;
}
int GetSeletedDispRes(int *piXres, int *piYres)
{
if(!g_ptDispOpr)
return -1;
*piXres = g_ptDispOpr->iXres;
*piYres = g_ptDispOpr->iYres;
return 0;
}
static int IncY(int iY)
{
if(iY + g_iFontSize >= g_ptDispOpr->iYres)
return 0;
return (iY + g_iFontSize);
}
static int RelocateFontPos(PT_BitMap ptBitMap)
{
int iY;
int iDltX, iDltY;
if(ptBitMap->iYMax > g_ptDispOpr->iYres)
return -1;
if(ptBitMap->iXMax > g_ptDispOpr->iXres)
{
iY = IncY(ptBitMap->iCurOriginY);
if(!iY)
{
return -1;
}
iDltX = 0 - ptBitMap->iCurOriginX;
iDltY = iY - ptBitMap->iCurOriginY;
ptBitMap->iCurOriginX += iDltX;
ptBitMap->iCurOriginY += iDltY;
ptBitMap->iNextOriginX += iDltX;
ptBitMap->iNextOriginY += iDltY;
ptBitMap->iXLeft += iDltX;
ptBitMap->iYTop += iDltY;
ptBitMap->iXMax += iDltX;
ptBitMap->iYMax += iDltY;
}
return 0;
}
static int ReallyShowOneCode(PT_BitMap ptBitMap)
{
int iX, iY;
int iBit,iCnt;
unsigned char cVal = 7;
if(ptBitMap->iBpp == 1)
{
for(iY = ptBitMap->iYTop;iY < ptBitMap->iYMax;iY++)
{
iCnt = (iY - ptBitMap->iYTop) * ptBitMap->iPitch;
for(iX = ptBitMap->iXLeft, iBit = 7;iX < ptBitMap->iXMax;iX++)
{
if(iBit == 7)
cVal = ptBitMap->pucBuf[iCnt++];
if(cVal & (1<<iBit))
g_ptDispOpr->ShowPixel(iX, iY, COLOR_FOREGROUND);
else
;// g_ptDispOpr->ShowPixel(iX, iY, COLOR_BACKGROUND);
if((--iBit) < 0)
{
iBit = 7;
}
}
}
}
else if(ptBitMap->iBpp == 8)
{
for(iY = ptBitMap->iYTop;iY < ptBitMap->iYMax;iY++)
for(iX = ptBitMap->iXLeft;iX < ptBitMap->iXMax;iX++)
g_ptDispOpr->ShowPixel(iX, iY, COLOR_FOREGROUND);
}
else
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
DBG_PRINT("don't suppot bpp %d \r\n", ptBitMap->iBpp);
return -1;
}
return 0;
}
static int ShowOnePage(unsigned char *pucNowPos)
{
unsigned int dwCodeLen;
unsigned int dwCode;
int iHasGetCode = 0, iHasCleanSrceen = 1;
PT_FontOpr ptFontOprTmp;
int iError;
unsigned char *pucBufStart = pucNowPos;
T_BitMap tBitMap;
tBitMap.iCurOriginX = 0;
tBitMap.iCurOriginY = g_iFontSize;
while(1)
{
dwCode = 0;
dwCodeLen = g_ptEncodingOpr->GetCode(pucBufStart, g_pucFileEnd, &dwCode);
if(!dwCodeLen)
{
if(iHasGetCode)
{
printf("Page :%03d\r\n",g_ptPageDesc->iPage);
return 0;
}
else
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
}
pucBufStart += dwCodeLen;
iHasGetCode = 1;
if(dwCode == '\r')
{
continue;
}
else if(dwCode == '\t')
{
dwCode = ' ';
}
else if(dwCode == '\n')
{
g_pucNextPosAtFile = pucBufStart;
tBitMap.iCurOriginX = 0;
tBitMap.iCurOriginY = IncY(tBitMap.iCurOriginY);
if(tBitMap.iCurOriginY == 0)
{
printf("Page :%03d\r\n",g_ptPageDesc->iPage);
return 0;
}
continue;
}
ptFontOprTmp = g_ptEncodingOpr->ptFontOprSupportHead;
while(ptFontOprTmp)
{
iError = ptFontOprTmp->GetBitMap(dwCode, &tBitMap);
if(iError)
{
ptFontOprTmp = ptFontOprTmp->ptNext;
continue;
}
iError = RelocateFontPos(&tBitMap);
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return 0;
}
if(iHasCleanSrceen)
{
g_ptDispOpr->CleanScreen(COLOR_BACKGROUND);
iHasCleanSrceen = 0;
}
iError = ReallyShowOneCode(&tBitMap);
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
tBitMap.iCurOriginX = tBitMap.iNextOriginX;
tBitMap.iCurOriginY = tBitMap.iNextOriginY;
g_pucNextPosAtFile = pucBufStart;
break;
}
}
return 0;
}
int ShowNextPage(void)
{
int iError;
PT_PageDesc ptOnePage;
if(!g_ptPageDesc)
{
g_ptPageDesc = malloc(sizeof(T_PageDesc));
if(!g_ptPageDesc)
return -1;
g_ptPageDesc->iPage = 1;
g_ptPageDesc->ptNextPage = NULL;
g_ptPageDesc->ptPrePage = NULL;
g_ptPageDesc->pucCurPosAtFile = g_pucFileStart + g_ptEncodingOpr->iHeadLen;
}
else
{
if(g_pucNextPosAtFile == g_pucFileEnd)
{
return 0;
}
if(!(g_ptPageDesc->ptNextPage))
{
ptOnePage = malloc(sizeof(T_PageDesc));
if(!ptOnePage)
return -1;
ptOnePage->ptNextPage = NULL;
ptOnePage->pucCurPosAtFile = g_pucNextPosAtFile;
ptOnePage->iPage = g_ptPageDesc->iPage + 1;
g_ptPageDesc->ptNextPage = ptOnePage;
ptOnePage->ptPrePage = g_ptPageDesc;
g_ptPageDesc = ptOnePage;
}
else
{
g_ptPageDesc = g_ptPageDesc->ptNextPage;
}
}
iError = ShowOnePage(g_ptPageDesc->pucCurPosAtFile);
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
return 0;
}
int ShowPrePage(void)
{
int iError;
if(!g_ptPageDesc || !g_ptPageDesc->ptPrePage)
{
return -1;
}
g_ptPageDesc = g_ptPageDesc->ptPrePage;
iError = ShowOnePage(g_ptPageDesc->pucCurPosAtFile);
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
return 0;
}
int DrawInit(void)
{
int iError;
iError = InputInit();
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
iError = DisplaysInit();
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
iError = FontsInit();
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
iError = EncodingsInit();
if(iError)
{
DBG_PRINT("Error at %s,%d\r\n", __FILE__, __LINE__);
return -1;
}
return 0;
}
main.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <config.h>
#include <draw.h>
#include <encoding_manager.h>
#include <fonts_manager.h>
#include <disp_manager.h>
#include <input_manager.h>
int main(int argc, char *argv[])
{
char pcHzkName[20];
char pcFreetypeName[20];
char pcTextName[20];
char pcDispName[20];
int iError;
int iList = 0;
int iFontSize = 16;
T_InputEventOpr tInputEventOpr;
pcHzkName[0] = 0;
pcFreetypeName[0] = 0;
pcTextName[0] = 0;
pcDispName[0] = 0;
#ifdef ONPC
strcpy(pcDispName,"onpc");
#else
strcpy(pcDispName,"fb");
#endif
while ((iError = getopt(argc, argv, "ls:f:h:d:")) != -1)
{
switch(iError)
{
case 'l' :
{
iList = 1;
break;
}
case 's' :
{
iFontSize = strtoul(optarg, NULL, 0);
break;
}
case 'f' :
{
strncpy(pcFreetypeName, optarg, 20);
pcFreetypeName[19] = '0';
break;
}
case 'h' :
{
strncpy(pcHzkName, optarg, 20);
pcHzkName[19] = '0';
break;
}
case 'd' :
{
strncpy(pcDispName, optarg, 20);
pcDispName[19] = '\0';
break;
}
default:
{
printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
printf("Usage: %s -l\n", argv[0]);
return -1;
}
}
}
if (!iList && (optind >= argc))
{
printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
printf("Usage: %s -l\n", argv[0]);
return -1;
}
iError = DrawInit();
if(iError)
{
printf("DrawInit error!\n");
return -1;
}
if(iList)
{
ShowDispOpr();
ShowSupportFont();
ShowSupportEncoding();
ShowInputOpr();
return 0;
}
strncpy(pcTextName, argv[optind], 20);
pcTextName[19] = '\0';
iError = OpenTextFile(pcTextName);
if (iError)
{
printf("OpenTextFile error!\n");
return -1;
}
iError = SetFontsDetail(pcHzkName, pcFreetypeName, iFontSize);
if (iError)
{
printf("SetFontsDetail error!\n");
return -1;
}
iError = SelectAndInitDisplay(pcDispName);
if (iError)
{
printf("SelectAndInitDisplay error!\n");
return -1;
}
iError = ReallyInputInit();
if (iError)
{
printf("SelectAndInitDisplay error!\n");
return -1;
}
printf("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: \r\n");
ShowNextPage();
while(1)
{
while(GetInputEvent(&tInputEventOpr));
switch(tInputEventOpr.iVal)
{
case INPUT_VAL_PRE :
{
ShowPrePage();
break;
}
case INPUT_VAL_NEXT :
{
ShowNextPage();
break;
}
case INPUT_VAL_EXIT :
{
printf("\r\n\r\nexit!\r\n");
DisplayExit();
return 0;
}
}
tInputEventOpr.iVal = INPUT_VAL_UNKNOWN;
}
return 0;
}