• 电子书总结


    参考:https://blog.csdn.net/qq_21792169/article/details/51052666

    1.框架

    链接:https://pan.baidu.com/s/1qn0kP3zGUdU6VVtL8GWQTQ
    提取码:mwwe

    2.文件管理

    工程目录结构:

    include头文件目录:

    包含所有头文件

    config.h为配置文件

    #ifndef _CONFIG_H
    #define _CONFIG_H
    
    #include <stdio.h>
    #include <debug_manager.h>
    
    #define FB_DEVICE_NAME "/dev/fb0"
    
    #define COLOR_BACKGROUND   0xE7DBB5  /* 泛黄的纸 */
    #define COLOR_FOREGROUND   0x514438  /* 褐色字体 */
    
    //#define DBG_PRINTF(...)  
    #define DBG_PRINTF DebugPrint
    
    #endif /* _CONFIG_H */
    

    其中Makefile为:https://www.cnblogs.com/huangdengtao/p/12324579.html

    3.流程图

    我只画了一些。

    链接:https://pan.baidu.com/s/1XpkjpMV8ztXE9kwxYODCLA
    提取码:m31u

    链接:https://pan.baidu.com/s/15MQXs7nPHUCQaXjEk0QxNA
    提取码:4fba

    4.各个模块的具体分析

    display模块(display目录)

    Makefile

    obj-y += disp_manager.o
    obj-y += fb.o
    

    display_manager.h

    #ifndef _DISP_MANAGER_H
    #define _DISP_MANAGER_H
    
    typedef struct DispOpr {
    	char *name;
    	int iXres;
    	int iYres;
    	int iBpp;
    	int (*DeviceInit)(void);
    	int (*ShowPixel)(int iPenX, int iPenY, unsigned int dwColor);
    	int (*CleanScreen)(unsigned int dwBackColor);
    	struct DispOpr *ptNext;
    }T_DispOpr, *PT_DispOpr;
    
    int RegisterDispOpr(PT_DispOpr ptDispOpr); // 注册链表
    void ShowDispOpr(void);                    // 打印链表中的每个name
    int DisplayInit(void);                     // fb设备注册金链表
    int FBInit(void);                          // 把结构体注册到链表
    
    #endif /* _DISP_MANAGER_H */
    

    display_manager.c

    #include <config.h>
    #include <disp_manager.h>
    #include <string.h>
    
    static PT_DispOpr g_ptDispOprHead;        // 链表头
    
    int RegisterDispOpr(PT_DispOpr ptDispOpr)
    {
    	PT_DispOpr ptTmp;
    
    	if (!g_ptDispOprHead)
    	{
    		g_ptDispOprHead   = ptDispOpr;
    		ptDispOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptDispOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext	  = ptDispOpr;
    		ptDispOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    void ShowDispOpr(void)
    {
    	int i = 0;
    	PT_DispOpr ptTmp = g_ptDispOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    /*    根据name在链表中查找匹配的链表    */
    PT_DispOpr GetDispOpr(char *pcName)        
    {
    	PT_DispOpr ptTmp = g_ptDispOprHead;
    	
    	while (ptTmp)
    	{
    		if (strcmp(ptTmp->name, pcName) == 0)
    		{
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    int DisplayInit(void)
    {
    	int iError;
    	
    	iError = FBInit();
    
    	return iError;
    }
    

    fb.c

    /*    这里是具体的设备的初始化了    */
    #include <config.h>
    #include <disp_manager.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <linux/fb.h>
    #include <string.h>
    
    /*    函数声明,用来初始化结构体中的成员函数    */
    static int FBDeviceInit(void);
    static int FBShowPixel(int iX, int iY, unsigned int dwColor);
    static int FBCleanScreen(unsigned int dwBackColor);
    
    
    static int g_fd;
    
    static struct fb_var_screeninfo g_tFBVar;
    static struct fb_fix_screeninfo g_tFBFix;			
    static unsigned char *g_pucFBMem;
    static unsigned int g_dwScreenSize;
    
    static unsigned int g_dwLineWidth;
    static unsigned int g_dwPixelWidth;
    
    static T_DispOpr g_tFBOpr = {
    	.name        = "fb",
    	.DeviceInit  = FBDeviceInit,
    	.ShowPixel   = FBShowPixel,
    	.CleanScreen = FBCleanScreen,
    };
    
    static int FBDeviceInit(void)
    {
    	int ret;
    	
        /*    FB_DEVICE_NAME在配置文件中已经声明    */
    	g_fd = open(FB_DEVICE_NAME, O_RDWR);
    	if (0 > g_fd)
    	{
    		DBG_PRINTF("can't open %s
    ", FB_DEVICE_NAME);
    	}
    
    	ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
    	if (ret < 0)
    	{
    		DBG_PRINTF("can't get fb's var
    ");
    		return -1;
    	}
    
    	ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
    	if (ret < 0)
    	{
    		DBG_PRINTF("can't get fb's fix
    ");
    		return -1;
    	}
    	
    	g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;
    	g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);
    	if (0 > g_pucFBMem)	
    	{
    		DBG_PRINTF("can't mmap
    ");
    		return -1;
    	}
    
    	g_tFBOpr.iXres       = g_tFBVar.xres;
    	g_tFBOpr.iYres       = g_tFBVar.yres;
    	g_tFBOpr.iBpp        = g_tFBVar.bits_per_pixel;
    
    	g_dwLineWidth  = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
    	g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;
    	
    	return 0;
    }
    
    
    static int FBShowPixel(int iX, int iY, unsigned int dwColor)
    {
    	unsigned char *pucFB;
    	unsigned short *pwFB16bpp;
    	unsigned int *pdwFB32bpp;
    	unsigned short wColor16bpp; /* 565 */
    	int iRed;
    	int iGreen;
    	int iBlue;
    
    	if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))
    	{
    		DBG_PRINTF("out of region
    ");
    		return -1;
    	}
    
    	pucFB      = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;
    	pwFB16bpp  = (unsigned short *)pucFB;
    	pdwFB32bpp = (unsigned int *)pucFB;
    	
    	switch (g_tFBVar.bits_per_pixel)
    	{
    		case 8:
    		{
    			*pucFB = (unsigned char)dwColor;
    			break;
    		}
    		case 16:
    		{
    			iRed   = (dwColor >> (16+3)) & 0x1f;
    			iGreen = (dwColor >> (8+2)) & 0x3f;
    			iBlue  = (dwColor >> 3) & 0x1f;
    			wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
    			*pwFB16bpp	= wColor16bpp;
    			break;
    		}
    		case 32:
    		{
    			*pdwFB32bpp = dwColor;
    			break;
    		}
    		default :
    		{
    			DBG_PRINTF("can't support %d bpp
    ", g_tFBVar.bits_per_pixel);
    			return -1;
    		}
    	}
    
    	return 0;
    }
    /*    注意这里16bpp和32bpp清屏时时一位一位的清    */
    static int FBCleanScreen(unsigned int dwBackColor)
    {
    	unsigned char *pucFB;
    	unsigned short *pwFB16bpp;
    	unsigned int *pdwFB32bpp;
    	unsigned short wColor16bpp; /* 565 */
    	int iRed;
    	int iGreen;
    	int iBlue;
    	int i = 0;
    
    	pucFB      = g_pucFBMem;
    	pwFB16bpp  = (unsigned short *)pucFB;
    	pdwFB32bpp = (unsigned int *)pucFB;
    
    	switch (g_tFBVar.bits_per_pixel)
    	{
    		case 8:
    		{
    			memset(g_pucFBMem, dwBackColor, g_dwScreenSize);
    			break;
    		}
    		case 16:
    		{
    			iRed   = (dwBackColor >> (16+3)) & 0x1f;
    			iGreen = (dwBackColor >> (8+2)) & 0x3f;
    			iBlue  = (dwBackColor >> 3) & 0x1f;
    			wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
    			while (i < g_dwScreenSize)
    			{
    				*pwFB16bpp	= wColor16bpp;
    				pwFB16bpp++;
    				i += 2;
    			}
    			break;
    		}
    		case 32:
    		{
    			while (i < g_dwScreenSize)
    			{
    				*pdwFB32bpp	= dwBackColor;
    				pdwFB32bpp++;
    				i += 4;
    			}
    			break;
    		}
    		default :
    		{
    			DBG_PRINTF("can't support %d bpp
    ", g_tFBVar.bits_per_pixel);
    			return -1;
    		}
    	}
    
    	return 0;
    }
    
    /*    把结构体注册到链表    */
    int FBInit(void)        
    {
    	return RegisterDispOpr(&g_tFBOpr);
    }
    

    font模块(fonts目录)

    Makefile

    obj-y += ascii.o
    obj-y += fonts_manager.o
    obj-y += freetype.o
    obj-y += gbk.o
    

    fonts_manager.h

    #ifndef _FONTS_MANAGER_H
    #define _FONTS_MANAGER_H
    
    typedef struct FontBitMap {
    	int iXLeft;
    	int iYTop;
    	int iXMax;
    	int iYMax;
    	int iBpp;
    	int iPitch;   /* 对于单色位图, 两行象素之间的跨度 */
    	int iCurOriginX;
    	int iCurOriginY;
    	int iNextOriginX;
    	int iNextOriginY;
    	unsigned char *pucBuffer;
    }T_FontBitMap, *PT_FontBitMap;
    
    typedef struct FontOpr {
    	char *name;
    	int (*FontInit)(char *pcFontFile, unsigned int dwFontSize);
    	int (*GetFontBitmap)(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    	struct FontOpr *ptNext;
    }T_FontOpr, *PT_FontOpr;
    
    
    int RegisterFontOpr(PT_FontOpr ptFontOpr);
    void ShowFontOpr(void);
    int FontsInit(void);        // 初始化ASCIIIni(void), GBKInit(void), FreeTypeInit(void)
    int ASCIIInit(void);
    int GBKInit(void);
    int FreeTypeInit(void);
    PT_FontOpr GetFontOpr(char *pcName);
    
    #endif /* _FONTS_MANAGER_H */
    

    fonts_manager.c

    #include <config.h>
    #include <fonts_manager.h>
    #include <string.h>
    
    static PT_FontOpr g_ptFontOprHead = NULL;
    
    int RegisterFontOpr(PT_FontOpr ptFontOpr)
    {
    	PT_FontOpr ptTmp;
    
    	if (!g_ptFontOprHead)
    	{
    		g_ptFontOprHead   = ptFontOpr;
    		ptFontOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptFontOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext     = ptFontOpr;
    		ptFontOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    void ShowFontOpr(void)
    {
    	int i = 0;
    	PT_FontOpr ptTmp = g_ptFontOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    PT_FontOpr GetFontOpr(char *pcName)
    {
    	PT_FontOpr ptTmp = g_ptFontOprHead;
    	
    	while (ptTmp)
    	{
    		if (strcmp(ptTmp->name, pcName) == 0)
    		{
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    
    int FontsInit(void)
    {
    	int iError;
    	
    	iError = ASCIIInit();
    	if (iError)
    	{
    		DBG_PRINTF("ASCIIInit error!
    ");
    		return -1;
    	}
    
    	iError = GBKInit();
    	if (iError)
    	{
    		DBG_PRINTF("GBKInit error!
    ");
    		return -1;
    	}
    	
    	iError = FreeTypeInit();
    	if (iError)
    	{
    		DBG_PRINTF("FreeTypeInit error!
    ");
    		return -1;
    	}
    
    	return 0;
    }
    

    asiic.c

    #include <config.h>
    #include <fonts_manager.h>
    
    #define FONTDATAMAX 4096
    
    static int ASCIIFontInit(char *pcFontFile, unsigned int dwFontSize);
    static int ASCIIGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    
    static T_FontOpr g_tASCIIFontOpr = {
    	.name          = "ascii",
    	.FontInit      = ASCIIFontInit,
    	.GetFontBitmap = ASCIIGetFontBitmap,
    };
    
    
    static const unsigned char fontdata_8x16[FONTDATAMAX] = {
    /*    英文点阵(略)    */
    };
    
    static int ASCIIFontInit(char *pcFontFile, unsigned int dwFontSize)
    {
    	if (dwFontSize != 16)
    	{
    		//DBG_PRINTF("ASCII can't support %d font size
    ", dwFontSize);
    		return -1;
    	}
    	return 0;
    }
    
    /*    编码的位图转化为字体的位图    */
    static int ASCIIGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
    {
    	int iPenX = ptFontBitMap->iCurOriginX;
    	int iPenY = ptFontBitMap->iCurOriginY;
    	
    	if (dwCode > (unsigned int)0x80)
    	{
    		//DBG_PRINTF("don't support this code : 0x%x
    ", dwCode);
    		return -1;
    	}
    
    	ptFontBitMap->iXLeft    = iPenX;
    	ptFontBitMap->iYTop     = iPenY - 16;
    	ptFontBitMap->iXMax     = iPenX + 8;
    	ptFontBitMap->iYMax     = iPenY;
    	ptFontBitMap->iBpp      = 1;
    	ptFontBitMap->iPitch    = 1;
    	ptFontBitMap->pucBuffer = (unsigned char *)&fontdata_8x16[dwCode * 16];;	
    
    	ptFontBitMap->iNextOriginX = iPenX + 8;
    	ptFontBitMap->iNextOriginY = iPenY;
    	
    	return 0;
    }
    
    int ASCIIInit(void)
    {
    	return RegisterFontOpr(&g_tASCIIFontOpr);
    }
    

    gbk.c

    #include <config.h>
    #include <fonts_manager.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <unistd.h>
    
    
    static int GBKFontInit(char *pcFontFile, unsigned int dwFontSize);
    static int GBKGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    
    static T_FontOpr g_tGBKFontOpr = {
    	.name          = "gbk",
    	.FontInit      = GBKFontInit,
    	.GetFontBitmap = GBKGetFontBitmap,
    };
    
    static int g_iFdHZK;
    static unsigned char *g_pucHZKMem;
    static unsigned char *g_pucHZKMemEnd;
    
    static int GBKFontInit(char *pcFontFile, unsigned int dwFontSize)
    {
    	struct stat tStat;
    
    	if (16 != dwFontSize)
    	{
    		DBG_PRINTF("GBK can't support %d fontsize
    ", dwFontSize);
    		return -1;
    	}
    	
    	g_iFdHZK = open(pcFontFile, O_RDONLY);
    	if (g_iFdHZK < 0)
    	{
    		DBG_PRINTF("can't open %s
    ", pcFontFile);
    		return -1;
    	}
    	if(fstat(g_iFdHZK, &tStat))
    	{
    		DBG_PRINTF("can't get fstat
    ");
    		return -1;
    	}
    	g_pucHZKMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ, MAP_SHARED, g_iFdHZK, 0);
    	if (g_pucHZKMem == (unsigned char *)-1)
    	{
    		DBG_PRINTF("can't mmap for hzk16
    ");
    		return -1;
    	}
    	g_pucHZKMemEnd = g_pucHZKMem + tStat.st_size;
    	return 0;
    }
    
    static int GBKGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
    {
    	int iArea;
    	int iWhere;
    
    	int iPenX = ptFontBitMap->iCurOriginX;
    	int iPenY = ptFontBitMap->iCurOriginY;
    
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    
    	if (dwCode & 0xffff0000)
    	{
    		DBG_PRINTF("don't support this code : 0x%x
    ", dwCode);
    		return -1;
    	}	
    
    	iArea  = (int)(dwCode & 0xff) - 0xA1;
    	iWhere = (int)((dwCode >> 8) & 0xff) - 0xA1;
    
    	if ((iArea < 0) || (iWhere < 0))
    	{
    		DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    		return -1;
    	}
    	
    	ptFontBitMap->iXLeft    = iPenX;
    	ptFontBitMap->iYTop     = iPenY - 16;
    	ptFontBitMap->iXMax     = iPenX + 16;
    	ptFontBitMap->iYMax     = iPenY;
    	ptFontBitMap->iBpp      = 1;
    	ptFontBitMap->iPitch    = 2;
    	ptFontBitMap->pucBuffer = g_pucHZKMem + (iArea * 94 + iWhere)*32;;	
    
    	if (ptFontBitMap->pucBuffer >= g_pucHZKMemEnd)
    	{
    		return -1;
    	}
    
    	ptFontBitMap->iNextOriginX = iPenX + 16;
    	ptFontBitMap->iNextOriginY = iPenY;
    	
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    	return 0;
    }
    
    int GBKInit(void)
    {
    	return RegisterFontOpr(&g_tGBKFontOpr);
    }
    

    freetype.c

    #include <config.h>
    #include <fonts_manager.h>
    #include <ft2build.h>
    #include FT_FREETYPE_H
    #include FT_GLYPH_H
    
    static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize);
    static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    
    static T_FontOpr g_tFreeTypeFontOpr = {
    	.name          = "freetype",
    	.FontInit      = FreeTypeFontInit,
    	.GetFontBitmap = FreeTypeGetFontBitmap,
    };
    
    static FT_Library g_tLibrary;
    static FT_Face g_tFace;
    static FT_GlyphSlot g_tSlot;
    
    static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize)
    {
    	int iError;
    
    	/* 显示矢量字体 */
    	iError = FT_Init_FreeType(&g_tLibrary );			   /* initialize library */
    	/* error handling omitted */
    	if (iError)
    	{
    		DBG_PRINTF("FT_Init_FreeType failed
    ");
    		return -1;
    	}
    	
    	iError = FT_New_Face(g_tLibrary, pcFontFile, 0, &g_tFace); /* create face object */
    	/* error handling omitted */
    	if (iError)
    	{
    		DBG_PRINTF("FT_Init_FreeType failed
    ");		
    		return -1;
    	}
    	
    	g_tSlot = g_tFace->glyph;
    
    	iError = FT_Set_Pixel_Sizes(g_tFace, dwFontSize, 0);
    	if (iError)
    	{
    		DBG_PRINTF("FT_Set_Pixel_Sizes failed : %d
    ", dwFontSize);
    		return -1;
    	}
    	
    	
    	return 0;
    }
    
    static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
    {
    	int iError;
    	int iPenX = ptFontBitMap->iCurOriginX;
    	int iPenY = ptFontBitMap->iCurOriginY;
    #if 0
    	FT_Vector tPen;
    
    	tPen.x = 0;
    	tPen.y = 0;
    	
    	/* set transformation */
    	FT_Set_Transform(g_tFace, 0, &tPen);
    #endif
    
    	/* load glyph image into the slot (erase previous one) */
    	//iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER );
    	iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
    	if (iError)
    	{
    		DBG_PRINTF("FT_Load_Char error for code : 0x%x
    ", dwCode);
    		return -1;
    	}
    
    	//DBG_PRINTF("iPenX = %d, iPenY = %d, bitmap_left = %d, bitmap_top = %d, width = %d, rows = %d
    ", iPenX, iPenY, g_tSlot->bitmap_left, g_tSlot->bitmap_top, g_tSlot->bitmap.width, g_tSlot->bitmap.rows);
    	ptFontBitMap->iXLeft    = iPenX + g_tSlot->bitmap_left;
    	ptFontBitMap->iYTop     = iPenY - g_tSlot->bitmap_top;
    	ptFontBitMap->iXMax     = ptFontBitMap->iXLeft + g_tSlot->bitmap.width;
    	ptFontBitMap->iYMax     = ptFontBitMap->iYTop  + g_tSlot->bitmap.rows;
    	ptFontBitMap->iBpp      = 1;
    	ptFontBitMap->iPitch    = g_tSlot->bitmap.pitch;
    	ptFontBitMap->pucBuffer = g_tSlot->bitmap.buffer;
    	
    	ptFontBitMap->iNextOriginX = iPenX + g_tSlot->advance.x / 64;
    	ptFontBitMap->iNextOriginY = iPenY;
    
    	//DBG_PRINTF("iXLeft = %d, iYTop = %d, iXMax = %d, iYMax = %d, iNextOriginX = %d, iNextOriginY = %d
    ", ptFontBitMap->iXLeft, ptFontBitMap->iYTop, ptFontBitMap->iXMax, ptFontBitMap->iYMax, ptFontBitMap->iNextOriginX, ptFontBitMap->iNextOriginY);
    
    	return 0;
    }
    
    int FreeTypeInit(void)
    {
    	return RegisterFontOpr(&g_tFreeTypeFontOpr);
    }
    

    enconding模块(enconding目录)

    Makefile

    obj-y += ascii.o
    obj-y += encoding_manager.o
    obj-y += utf-16be.o
    obj-y += utf-16le.o
    obj-y += utf-8.o
    

    enconding_manager.h

    #ifndef _ENCODING_MANAGER_H
    #define _ENCODING_MANAGER_H
    
    #include <fonts_manager.h>
    #include <disp_manager.h>
    
    typedef struct EncodingOpr {
    	char *name;
    	int iHeadLen;            // 头部的长度
    	PT_FontOpr ptFontOprSupportedHead;        // 
    	int (*isSupport)(unsigned char *pucBufHead);        // 支持
    	int (*GetCodeFrmBuf)(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);    // 得到编码
    	struct EncodingOpr *ptNext;
    }T_EncodingOpr, *PT_EncodingOpr;
    
    int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr);
    void ShowEncodingOpr(void);
    PT_DispOpr GetDispOpr(char *pcName);
    PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead);        // 根据文件的头部编码在链表中寻找匹配的字形编码
    int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
    int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
    int EncodingInit(void);
    int AsciiEncodingInit(void);
    int  Utf16beEncodingInit(void);
    int  Utf16leEncodingInit(void);
    int  Utf8EncodingInit(void);
    
    #endif /* _ENCODING_MANAGER_H */
    

    enconding_manager.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    #include <stdlib.h>
    
    static PT_EncodingOpr g_ptEncodingOprHead;
    
    int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr)
    {
    	PT_EncodingOpr ptTmp;
    
    	if (!g_ptEncodingOprHead)
    	{
    		g_ptEncodingOprHead   = ptEncodingOpr;
    		ptEncodingOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptEncodingOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext	      = ptEncodingOpr;
    		ptEncodingOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    
    void ShowEncodingOpr(void)
    {
    	int i = 0;
    	PT_EncodingOpr ptTmp = g_ptEncodingOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead)
    {
    	PT_EncodingOpr ptTmp = g_ptEncodingOprHead;
    
    	while (ptTmp)
    	{	
    		if (ptTmp->isSupport(pucFileBufHead))
    			return ptTmp;
    		else
    			ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    /*    在链表中加入每个编码支持的字形    */
    int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
    {
    	PT_FontOpr ptFontOprCpy;
    	
    	if (!ptEncodingOpr || !ptFontOpr)
    	{
    		return -1;
    	}
    	else
    	{
    		ptFontOprCpy = malloc(sizeof(T_FontOpr));
    		if (!ptFontOprCpy)
    		{
    			return -1;
    		}
    		else
    		{
    			memcpy(ptFontOprCpy, ptFontOpr, sizeof(T_FontOpr));
    			ptFontOprCpy->ptNext = ptEncodingOpr->ptFontOprSupportedHead;
    			ptEncodingOpr->ptFontOprSupportedHead = ptFontOprCpy;
    			return 0;
    		}		
    	}
    }
    
    /*    在链表中删除每个编码支持的字形    */
    int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
    {
    	PT_FontOpr ptTmp;
    	PT_FontOpr ptPre;
    		
    	if (!ptEncodingOpr || !ptFontOpr)
    	{
    		return -1;
    	}
    	else
    	{
    		ptTmp = ptEncodingOpr->ptFontOprSupportedHead;
    		if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
    		{
    			/* 删除头节点 */
    			ptEncodingOpr->ptFontOprSupportedHead = ptTmp->ptNext;
    			free(ptTmp);
    			return 0;
    		}
    
    		ptPre = ptEncodingOpr->ptFontOprSupportedHead;
    		ptTmp = ptPre->ptNext;
    		while (ptTmp)
    		{
    			if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
    			{
    				/* 从链表里取出、释放 */
    				ptPre->ptNext = ptTmp->ptNext;
    				free(ptTmp);
    				return 0;
    			}
    			else
    			{
    				ptPre = ptTmp;
    				ptTmp = ptTmp->ptNext;
    			}
    		}
    
    		return -1;
    	}
    }
    
    int EncodingInit(void)
    {
    	int iError;
    
    	iError = AsciiEncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("AsciiEncodingInit error!
    ");
    		return -1;
    	}
    
    	iError = Utf16leEncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("Utf16leEncodingInit error!
    ");
    		return -1;
    	}
    	
    	iError = Utf16beEncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("Utf16beEncodingInit error!
    ");
    		return -1;
    	}
    	
    	iError = Utf8EncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("Utf8EncodingInit error!
    ");
    		return -1;
    	}
    
    	return 0;
    }
    

    asiic.c(具体的编码文件)

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isAsciiCoding(unsigned char *pucBufHead);
    static int AsciiGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tAsciiEncodingOpr = {
    	.name          = "ascii",
    	.iHeadLen      = 0,
    	.isSupport     = isAsciiCoding,
    	.GetCodeFrmBuf = AsciiGetCodeFrmBuf,
    };
    
    static int isAsciiCoding(unsigned char *pucBufHead)
    {
    	const char aStrUtf8[]    = {0xEF, 0xBB, 0xBF, 0};
    	const char aStrUtf16le[] = {0xFF, 0xFE, 0};
    	const char aStrUtf16be[] = {0xFE, 0xFF, 0};
    	
    	if (strncmp((const char*)pucBufHead, aStrUtf8, 3) == 0)
    	{
    		/* UTF-8 */
    		return 0;
    	}
    	else if (strncmp((const char*)pucBufHead, aStrUtf16le, 2) == 0)
    	{
    		/* UTF-16 little endian */
    		return 0;
    	}
    	else if (strncmp((const char*)pucBufHead, aStrUtf16be, 2) == 0)
    	{
    		/* UTF-16 big endian */
    		return 0;
    	}
    	else
    	{
    		return 1;
    	}
    }
    
    /*    Get字的编码    */
    static int AsciiGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    	unsigned char *pucBuf = pucBufStart;
    	unsigned char c = *pucBuf;
    	
        /* 当判断出来不支持UTF-8,UTF-16Be和UTF-16le后。还需要判断为asiic值还是GBK码
         * (pucBuf < pucBufEnd) && (c < (unsigned char)0x80):判断为asiic值
         * ((pucBuf + 1) < pucBufEnd) && (c >= (unsigned char)0x80):判断为GBK码。注:因为GBK码为2字节所以这里需要加1
         */
    	if ((pucBuf < pucBufEnd) && (c < (unsigned char)0x80))
    	{
    		/* 返回ASCII码 */
    		*pdwCode = (unsigned int)c;
    		return 1;
    	}
    
    	if (((pucBuf + 1) < pucBufEnd) && (c >= (unsigned char)0x80))
    	{
    		/* 返回GBK码 */
    		*pdwCode = pucBuf[0] + (((unsigned int)pucBuf[1])<<8);
    		return 2;
    	}
    
    	if (pucBuf < pucBufEnd)
    	{
    		/* 可能文件有损坏, 但是还是返回一个码, 即使它是错误的 */
    		*pdwCode = (unsigned int)c;
    		return 1;
    	}
    	else
    	{
    		/* 文件处理完毕 */
    		return 0;
    	}
    }
    
    /*    使当前编码支持freetype, ascii, gbk字形。同时注册链表    */
    int AsciiEncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("ascii"));
    	AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("gbk"));
    	return RegisterEncodingOpr(&g_tAsciiEncodingOpr);
    }
    

    utf-8.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isUtf8Coding(unsigned char *pucBufHead);
    static int Utf8GetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tUtf8EncodingOpr = {
    	.name          = "utf-8",
    	.iHeadLen	   = 3,
    	.isSupport     = isUtf8Coding,
    	.GetCodeFrmBuf = Utf8GetCodeFrmBuf,
    };
    
    static int isUtf8Coding(unsigned char *pucBufHead)
    {
    	const char aStrUtf8[]    = {0xEF, 0xBB, 0xBF, 0};
    	if (strncmp((const char*)pucBufHead, aStrUtf8, 3) == 0)
    	{
    		/* UTF-8 */
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    /* 获得前导为1的位的个数
    * 比如二进制数 11001111 的前导1有2位
    *              11100001 的前导1有3位
    */
    static int GetPreOneBits(unsigned char ucVal)
    {
    	int i;
    	int j = 0;
    	
    	for (i = 7; i >= 0; i--)
    	{
    		if (!(ucVal & (1<<i)))
    			break;
    		else
    			j++;
    	}
    	return j;
    
    }
    
    static int Utf8GetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    #if 0
    	对于UTF-8编码中的任意字节B,如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符;
    	如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码;
    	如果B的前两位为1,第三位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示;
    	如果B的前三位为1,第四位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示;
    	如果B的前四位为1,第五位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示;
    
    	因此,对UTF-8编码中的任意字节,根据第一位,可判断是否为ASCII字符;
    	根据前二位,可判断该字节是否为一个字符编码的第一个字节; 
    	根据前四位(如果前两位均为1),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;
    	根据前五位(如果前四位为1),可判断编码是否有错误或数据传输过程中是否有错误。
    #endif
    
    	int i;	
    	int iNum;
    	unsigned char ucVal;
    	unsigned int dwSum = 0;
    
    	if (pucBufStart >= pucBufEnd)
    	{
    		/* 文件结束 */
    		return 0;
    	}
        /*    注意下面的构造    */
    	ucVal = pucBufStart[0];
    	iNum  = GetPreOneBits(pucBufStart[0]);
    
    	if ((pucBufStart + iNum) > pucBufEnd)
    	{
    		/* 文件结束 */
    		return 0;
    	}
    
    	if (iNum == 0)
    	{
    		/* ASCII */
    		*pdwCode = pucBufStart[0];
    		return 1;
    	}
    	else
    	{
    		ucVal = ucVal << iNum;
    		ucVal = ucVal >> iNum;
    		dwSum += ucVal;
    		for (i = 1; i < iNum; i++)
    		{
    			ucVal = pucBufStart[i] & 0x3f;
    			dwSum = dwSum << 6;
    			dwSum += ucVal;			
    		}
    		*pdwCode = dwSum;
    		return iNum;
    	}
    }
    
    int  Utf8EncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("ascii"));
    	return RegisterEncodingOpr(&g_tUtf8EncodingOpr);
    }
    

    utf-16be.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isUtf16beCoding(unsigned char *pucBufHead);
    static int Utf16beGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tUtf16beEncodingOpr = {
    	.name          = "utf-16be",
    	.iHeadLen	   = 2,
    	.isSupport     = isUtf16beCoding,
    	.GetCodeFrmBuf = Utf16beGetCodeFrmBuf,
    };
    
    /*    用两字节表示一个字:注意大字节序和小字节序    */
    static int isUtf16beCoding(unsigned char *pucBufHead)
    {
    	const char aStrUtf16be[] = {0xFE, 0xFF, 0};
    	
    	if (strncmp((const char*)pucBufHead, aStrUtf16be, 2) == 0)
    	{
    		/* UTF-16 big endian */
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    static int Utf16beGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    	if (pucBufStart + 1 < pucBufEnd)
    	{
    		*pdwCode = (((unsigned int)pucBufStart[0])<<8) + pucBufStart[1];
    		return 2;
    	}
    	else
    	{
    		/* 文件结束 */
    		return 0;
    	}
    }
    
    int  Utf16beEncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tUtf16beEncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tUtf16beEncodingOpr, GetFontOpr("ascii"));
    	return RegisterEncodingOpr(&g_tUtf16beEncodingOpr);
    }
    

    utf-16le.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isUtf16leCoding(unsigned char *pucBufHead);
    static int Utf16leGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tUtf16leEncodingOpr = {
    	.name          = "utf-16le",
    	.iHeadLen	   = 2,
    	.isSupport     = isUtf16leCoding,
    	.GetCodeFrmBuf = Utf16leGetCodeFrmBuf,
    };
    
    static int isUtf16leCoding(unsigned char *pucBufHead)
    {
    	const char aStrUtf16le[] = {0xFF, 0xFE, 0};
    	if (strncmp((const char *)pucBufHead, aStrUtf16le, 2) == 0)
    	{
    		/* UTF-16 little endian */
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    static int Utf16leGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    	if (pucBufStart + 1 < pucBufEnd)
    	{
    		*pdwCode = (((unsigned int)pucBufStart[1])<<8) + pucBufStart[0];
    		return 2;
    	}
    	else
    	{
    		/* 文件结束 */
    		return 0;
    	}
    }
    
    int  Utf16leEncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tUtf16leEncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tUtf16leEncodingOpr, GetFontOpr("ascii"));
    	return RegisterEncodingOpr(&g_tUtf16leEncodingOpr);
    }
    

    input模块(input目录)

    Makefile

    obj-y += input_manager.o
    obj-y += stdin.o
    obj-y += touchscreen.o
    

    input_manager.h

    #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;            // 线程ID
    	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 */
    

    input_manager.c

    #include <config.h>
    #include <input_manager.h>
    #include <string.h>
    
    static PT_InputOpr g_ptInputOprHead;        // PT_InputOpr结构体
    static T_InputEvent g_tInputEvent;          // T_InputEvent 结构体
    
    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
    ", 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;
    }
    

    stdin.c

    /*    使用轮询的方式去访问    */
    #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);
    }
    

    touchscreen.c

    #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;
    
        /*    getenv从环境中取字符串,获取环境变量的值    
         *    指定触摸屏设备 TSLIB_TSDEVICE=/dev/input/touchscreen0
         */
    	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(APP_ERR"ts_open error!
    ");
    		return -1;
    	}
    
        /*    配置    */
    	if (ts_config(g_tTSDev)) {
    		DBG_PRINTF("ts_config error!
    ");
    		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);
    }
    

    debug模块(debug目录)

    Makefile

    	obj-y += debug_manager.o
    obj-y += stdout.o
    obj-y += netprint.o
    

    debug_manager.h

    #ifndef _DEBUG_MANAGER_H
    #define _DEBUG_MANAGER_H
    
    #define	APP_EMERG	"<0>"	/* system is unusable			*/
    #define	APP_ALERT	"<1>"	/* action must be taken immediately	*/
    #define	APP_CRIT	"<2>"	/* critical conditions			*/
    #define	APP_ERR	    "<3>"	/* error conditions			*/
    #define	APP_WARNING	"<4>"	/* warning conditions			*/
    #define	APP_NOTICE	"<5>"	/* normal but significant condition	*/
    #define	APP_INFO	"<6>"	/* informational			*/
    #define	APP_DEBUG	"<7>"	/* debug-level messages			*/
    
    #define DEFAULT_DBGLEVEL  4
    
    typedef struct DebugOpr {
    	char *name;
    	int isCanUse;
    	int (*DebugInit)(void);
    	int (*DebugExit)(void);
    	int (*DebugPrint)(char *strData);
    	struct DebugOpr *ptNext;
    }T_DebugOpr, *PT_DebugOpr;
    
    int RegisterDebugOpr(PT_DebugOpr ptDebugOpr);
    void ShowDebugOpr(void);
    PT_DebugOpr GetDebugOpr(char *pcName);
    int SetDbgLevel(char *strBuf);
    int SetDbgChanel(char *strBuf);
    int DebugInit(void);
    int DebugPrint(const char *pcFormat, ...);
    int InitDebugChanel(void);
    
    #endif /* _DEBUG_MANAGER_H */
    
    #ifndef _DEBUG_MANAGER_H
    #define _DEBUG_MANAGER_H
    
    /*    打印优先级设置    */
    #define	APP_EMERG	"<0>"	/* system is unusable			*/
    #define	APP_ALERT	"<1>"	/* action must be taken immediately	*/
    #define	APP_CRIT	"<2>"	/* critical conditions			*/
    #define	APP_ERR	    "<3>"	/* error conditions			*/
    #define	APP_WARNING	"<4>"	/* warning conditions			*/
    #define	APP_NOTICE	"<5>"	/* normal but significant condition	*/
    #define	APP_INFO	"<6>"	/* informational			*/
    #define	APP_DEBUG	"<7>"	/* debug-level messages			*/
    
    #define DEFAULT_DBGLEVEL  4
    
    typedef struct DebugOpr {
    	char *name;
    	int isCanUse;
    	int (*DebugInit)(void);
    	int (*DebugExit)(void);
    	int (*DebugPrint)(char *strData);
    	struct DebugOpr *ptNext;
    }T_DebugOpr, *PT_DebugOpr;
    
    int RegisterDebugOpr(PT_DebugOpr ptDebugOpr);
    void ShowDebugOpr(void);
    PT_DebugOpr GetDebugOpr(char *pcName);
    int SetDbgLevel(char *strBuf);
    int SetDbgChanel(char *strBuf);
    int DebugInit(void);
    int DebugPrint(const char *pcFormat, ...);
    int InitDebugChanel(void);
    
    #endif /* _DEBUG_MANAGER_H */
    

    debug_manager.c

    #include <config.h>
    #include <debug_manager.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdarg.h>
    
    static PT_DebugOpr g_ptDebugOprHead;
    static int g_iDbgLevelLimit = 8;
    
    int RegisterDebugOpr(PT_DebugOpr ptDebugOpr)
    {
    	PT_DebugOpr ptTmp;
    
    	if (!g_ptDebugOprHead)
    	{
    		g_ptDebugOprHead   = ptDebugOpr;
    		ptDebugOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptDebugOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext	  = ptDebugOpr;
    		ptDebugOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    void ShowDebugOpr(void)
    {
    	int i = 0;
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    PT_DebugOpr GetDebugOpr(char *pcName)
    {
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    	
    	while (ptTmp)
    	{
    		if (strcmp(ptTmp->name, pcName) == 0)
    		{
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    
    /* strBuf = "dbglevel=6" */
    int SetDbgLevel(char *strBuf)
    {
    	g_iDbgLevelLimit = strBuf[9] - '0';
    	return 0;
    }
    
    /*
    * stdout=0			   : 关闭stdout打印
    * stdout=1			   : 打开stdout打印
    * netprint=0		   : 关闭netprint打印
    * netprint=1		   : 打开netprint打印
    */
    
    int SetDbgChanel(char *strBuf)
    {
    	char *pStrTmp;
    	char strName[100];
    	PT_DebugOpr ptTmp;
        /*    strchr函数功能为在一个串中查找给定字符的第一个匹配之处    */
    	pStrTmp = strchr(strBuf, '=');
    	if (!pStrTmp)
    	{
    		return -1;
    	}
    	else
    	{
    		strncpy(strName, strBuf, pStrTmp-strBuf);
    		strName[pStrTmp-strBuf] = '';
    		ptTmp = GetDebugOpr(strName);
    		if (!ptTmp)
    			return -1;
    
    		if (pStrTmp[1] == '0')
    			ptTmp->isCanUse = 0;
    		else
    			ptTmp->isCanUse = 1;
    		return 0;
    	}
    	
    }
    
    
    int DebugPrint(const char *pcFormat, ...)
    {
    	char strTmpBuf[1000];
    	char *pcTmp;
    	va_list tArg;
    	int iNum;
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    	int dbglevel = DEFAULT_DBGLEVEL;
    	
        /*    va_start函数来获取参数列表中的参数    */
    	va_start (tArg, pcFormat);
    
        /*     int vsprintf(char *string, char *format, va_list param);//将param 按格式format写入字符串string中    */
    	iNum = vsprintf (strTmpBuf, pcFormat, tArg);
    	va_end (tArg);
    	strTmpBuf[iNum] = '';
    
    
    	pcTmp = strTmpBuf;
    	
    	/* 根据打印级别决定是否打印 */
    	if ((strTmpBuf[0] == '<') && (strTmpBuf[2] == '>'))
    	{
    		dbglevel = strTmpBuf[1] - '0';
    		if (dbglevel >= 0 && dbglevel <= 9)
    		{
    			pcTmp = strTmpBuf + 3;
    		}
    		else
    		{
    			dbglevel = DEFAULT_DBGLEVEL;
    		}
    	}
    
    	if (dbglevel > g_iDbgLevelLimit)
    	{
    		return -1;
    	}
    
    	/* 调用链表中所有isCanUse为1的结构体的DebugPrint函数 */
    	while (ptTmp)
    	{
    		if (ptTmp->isCanUse)
    		{
    			ptTmp->DebugPrint(pcTmp);
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    
    	return 0;
    	
    }
    
    int DebugInit(void)
    {
    	int iError;
    
    	iError = StdoutInit();
    	iError |= NetPrintInit();
    	return iError;
    }
    
    int InitDebugChanel(void)
    {
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    	while (ptTmp)
    	{
    		if (ptTmp->isCanUse && ptTmp->DebugInit)
    		{
    			ptTmp->DebugInit();
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    
    	return 0;}
    

    stdout.c

    #include <config.h>
    #include <debug_manager.h>
    #include <stdio.h>
    #include <string.h>
    
    
    static int StdoutDebugPrint(char *strData)
    {
    	/* 直接把输出信息用printf打印出来 */
    	printf("%s", strData);
    	return strlen(strData);	
    }
    
    static T_DebugOpr g_tStdoutDbgOpr = {
    	.name       = "stdout",
    	.isCanUse   = 1,
    	.DebugPrint = StdoutDebugPrint,
    };
    
    int StdoutInit(void)
    {
    	return RegisterDebugOpr(&g_tStdoutDbgOpr);
    }
    

    netprint.c(不难看出采用的是UDP协议)

    #include <config.h>
    #include <debug_manager.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    #define SERVER_PORT 5678
    /*    分配16k的buf    */
    #define PRINT_BUF_SIZE   (16*1024)
    
    static int g_iSocketServer;
    static struct sockaddr_in g_tSocketServerAddr;
    static struct sockaddr_in g_tSocketClientAddr;
    static int g_iHaveConnected = 0;
    static char *g_pcNetPrintBuf;
    static int g_iReadPos  = 0;
    static int g_iWritePos = 0;
    
    static pthread_t g_tSendTreadID;
    static pthread_t g_tRecvTreadID;
    
    static pthread_mutex_t g_tNetDbgSendMutex  = PTHREAD_MUTEX_INITIALIZER;
    static pthread_cond_t  g_tNetDbgSendConVar = PTHREAD_COND_INITIALIZER;
    
    /*    环形缓冲区    */
    static int isFull(void)
    {
    	return (((g_iWritePos + 1) % PRINT_BUF_SIZE) == g_iReadPos);
    }
    
    static int isEmpty(void)
    {
    	return (g_iWritePos == g_iReadPos);
    }
    
    
    static int PutData(char cVal)
    {
    	if (isFull())
    		return -1;
    	else
    	{
    		g_pcNetPrintBuf[g_iWritePos] = cVal;
    		g_iWritePos = (g_iWritePos + 1) % PRINT_BUF_SIZE;
    		return 0;
    	}	
    }
    
    static int GetData(char *pcVal)
    {
    	if (isEmpty())
    		return -1;
    	else
    	{
    		*pcVal = g_pcNetPrintBuf[g_iReadPos];
    		g_iReadPos = (g_iReadPos + 1) % PRINT_BUF_SIZE;
    		return 0;
    	}
    }
    
    
    static void *NetDbgSendTreadFunction(void *pVoid)
    {
    	char strTmpBuf[512];
    	char cVal;
    	int i;
    	int iAddrLen;
    	int iSendLen;
    	
    	while (1)
    	{
    		/* 平时休眠 */
    		pthread_mutex_lock(&g_tNetDbgSendMutex);
    		pthread_cond_wait(&g_tNetDbgSendConVar, &g_tNetDbgSendMutex);	
    		pthread_mutex_unlock(&g_tNetDbgSendMutex);
    
    		while (g_iHaveConnected && !isEmpty())
    		{
    			i = 0;
    
    			/* 把环形缓冲区的数据取出来, 最多取512字节 */
    			while ((i < 512) && (0 == GetData(&cVal)))
    			{
    				strTmpBuf[i] = cVal;
    				i++;
    			}
    			
    			/* 执行到这里, 表示被唤醒 */
    			/* 用sendto函数发送打印信息给客户端 */
    			iAddrLen = sizeof(struct sockaddr);
    			iSendLen = sendto(g_iSocketServer, strTmpBuf, i, 0,
    								(const struct sockaddr *)&g_tSocketClientAddr, iAddrLen);
    
    		}
    
    	}
    	return NULL;
    }
    
    static void *NetDbgRecvTreadFunction(void *pVoid)
    {
    	socklen_t iAddrLen;
    	int iRecvLen;
    	char ucRecvBuf[1000];
    	struct sockaddr_in tSocketClientAddr;
    
    	while (1)
    	{
    		iAddrLen = sizeof(struct sockaddr);
    		DBG_PRINTF("in NetDbgRecvTreadFunction
    ");
    		iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
    		
    		if (iRecvLen > 0)	
    		{
    			ucRecvBuf[iRecvLen] = '';
    			DBG_PRINTF("netprint.c get msg: %s
    ", ucRecvBuf);
    			
    			/* 解析数据:
    			* setclient            : 设置接收打印信息的客户端
    			* dbglevel=0,1,2...    : 修改打印级别
    			* stdout=0             : 关闭stdout打印
    			* stdout=1             : 打开stdout打印
    			* netprint=0           : 关闭netprint打印
    			* netprint=1           : 打开netprint打印
    			*/
    			if (strcmp(ucRecvBuf, "setclient")  == 0)
    			{
    				g_tSocketClientAddr = tSocketClientAddr;
    				g_iHaveConnected = 1;
    			}
    			else if (strncmp(ucRecvBuf, "dbglevel=", 9) == 0)
    			{
    				SetDbgLevel(ucRecvBuf);
    			}
    			else
    			{
    				SetDbgChanel(ucRecvBuf);
    			}
    		}
    		
    	}
    	return NULL;
    }
    
    
    static int NetDbgInit(void)
    {
    	/* socket初始化 */
    	int iRet;
    	
    	g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
    	if (-1 == g_iSocketServer)
    	{
    		printf("socket error!
    ");
    		return -1;
    	}
    
    	g_tSocketServerAddr.sin_family      = AF_INET;
    	g_tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
    	g_tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    	memset(g_tSocketServerAddr.sin_zero, 0, 8);
    	
    	iRet = bind(g_iSocketServer, (const struct sockaddr *)&g_tSocketServerAddr, sizeof(struct sockaddr));
    	if (-1 == iRet)
    	{
    		printf("bind error!
    ");
    		return -1;
    	}
    
    	g_pcNetPrintBuf = malloc(PRINT_BUF_SIZE);
    	if (NULL == g_pcNetPrintBuf)
    	{
    		close(g_iSocketServer);
    		return -1;
    	}
    
    
    	/* 创建netprint发送线程: 它用来发送打印信息给客户端 */
    	pthread_create(&g_tSendTreadID, NULL, NetDbgSendTreadFunction, NULL);			
    	
    	/* 创建netprint接收线否: 用来接收控制信息,比如修改打印级别,打开/关闭打印 */
    	pthread_create(&g_tRecvTreadID, NULL, NetDbgRecvTreadFunction, NULL);			
    
    	return 0;	
    }
    
    static int NetDbgExit(void)
    {
    	/* 关闭socket,... */
    	close(g_iSocketServer);
    	free(g_pcNetPrintBuf);
    }
    
    static int NetDbgPrint(char *strData)
    {
    	/* 把数据放入环形缓冲区 */
    	int i;
    	
    	for (i = 0; i < strlen(strData); i++)
    	{
    		if (0 != PutData(strData[i]))
    			break;
    	}
    	
    	/* 如果已经有客户端连接了, 就把数据通过网络发送给客户端 */
    	/* 唤醒netprint的发送线程 */
    	pthread_mutex_lock(&g_tNetDbgSendMutex);
    	pthread_cond_signal(&g_tNetDbgSendConVar);
    	pthread_mutex_unlock(&g_tNetDbgSendMutex);
    
    	return i;
    	
    }
    
    
    static T_DebugOpr g_tNetDbgOpr = {
    	.name       = "netprint",
    	.isCanUse   = 1,
    	.DebugInit  = NetDbgInit,
    	.DebugExit  = NetDbgExit,
    	.DebugPrint = NetDbgPrint,
    };
    
    int NetPrintInit(void)
    {
    	return RegisterDebugOpr(&g_tNetDbgOpr);
    }
    

    netprintclien.c(工程目录下)

    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    
    /* socket
    * connect
    * send/recv
    */
    
    #define SERVER_PORT 5678
    
    
    /*
    * ./netprint_client <server_ip> dbglevel=<0-9>
    * ./netprint_client <server_ip> stdout=0|1
    * ./netprint_client <server_ip> netprint=0|1
    * ./netprint_client <server_ip> show // setclient,并且接收打印信息
    */
    
    int main(int argc, char **argv)
    {
    	int iSocketClient;
    	struct sockaddr_in tSocketServerAddr;
    	
    	int iRet;
    	unsigned char ucRecvBuf[1000];
    	int iSendLen;
    	int iRecvLen;
    	int iAddrLen;
    
    	if (argc != 3)
    	{
    		printf("Usage:
    ");
    		printf("%s <server_ip> dbglevel=<0-9>
    ", argv[0]);
    		printf("%s <server_ip> stdout=0|1
    ", argv[0]);
    		printf("%s <server_ip> netprint=0|1
    ", argv[0]);
    		printf("%s <server_ip> show
    ", argv[0]);
    		return -1;
    	}
    
    	iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);
    
    	tSocketServerAddr.sin_family      = AF_INET;
    	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
    	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
    	{
    		printf("invalid server_ip
    ");
    		return -1;
    	}
    	memset(tSocketServerAddr.sin_zero, 0, 8);
    
    	if (strcmp(argv[2], "show") == 0)
    	{
    		/* 发送数据 */
    		iAddrLen = sizeof(struct sockaddr);
    		iSendLen = sendto(iSocketClient, "setclient", 9, 0,
    							(const struct sockaddr *)&tSocketServerAddr, iAddrLen);
    
    		while (1)
    		{
    			/* 循环: 从网络读数据, 打印出来 */
    			iAddrLen = sizeof(struct sockaddr);
    			iRecvLen = recvfrom(iSocketClient, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketServerAddr, &iAddrLen);
    			if (iRecvLen > 0)
    			{
    				ucRecvBuf[iRecvLen] = '';
    				printf("%s
    ", ucRecvBuf);
    			}
    		}
    	}
    	else
    	{
    		/* 发送数据 */
    		iAddrLen = sizeof(struct sockaddr);
    		iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0,
    							(const struct sockaddr *)&tSocketServerAddr, iAddrLen);
    	}
    
    	return 0;
    }
    

    draw模块(draw目录)

    Makefile

    obj-y += draw.o
    

    draw.c

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <config.h>
    #include <draw.h>
    #include <encoding_manager.h>
    #include <fonts_manager.h>
    #include <disp_manager.h>
    #include <string.h>
    
    
    typedef struct PageDesc {
    	int iPage;
    	unsigned char *pucLcdFirstPosAtFile;
    	unsigned char *pucLcdNextPageFirstPosAtFile;
    	struct PageDesc *ptPrePage;
    	struct PageDesc *ptNextPage;
    } T_PageDesc, *PT_PageDesc;
    
    static int g_iFdTextFile;
    static unsigned char *g_pucTextFileMem;
    static unsigned char *g_pucTextFileMemEnd;
    static PT_EncodingOpr g_ptEncodingOprForFile;
    
    static PT_DispOpr g_ptDispOpr;
    
    /*    在lcd上第一个字符在文件中的位置    */
    static unsigned char *g_pucLcdFirstPosAtFile;
    /*    lcd上下一页的第一个字符在文件中的位置    */
    static unsigned char *g_pucLcdNextPosAtFile;
    
    static int g_dwFontSize;
    
    static PT_PageDesc g_ptPages   = NULL;
    static PT_PageDesc g_ptCurPage = NULL;
    
    
    int OpenTextFile(char *pcFileName)
    {
    	struct stat tStat;
    
    	g_iFdTextFile = open(pcFileName, O_RDONLY);
    	if (0 > g_iFdTextFile)
    	{
    		DBG_PRINTF("can't open text file %s
    ", pcFileName);
    		return -1;
    	}
    
    	if(fstat(g_iFdTextFile, &tStat))
    	{
    		DBG_PRINTF("can't get fstat
    ");
    		return -1;
    	}
    	g_pucTextFileMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ, MAP_SHARED, g_iFdTextFile, 0);
    	if (g_pucTextFileMem == (unsigned char *)-1)
    	{
    		DBG_PRINTF("can't mmap for text file
    ");
    		return -1;
    	}
    
    	g_pucTextFileMemEnd = g_pucTextFileMem + tStat.st_size;
    	
    	g_ptEncodingOprForFile = SelectEncodingOprForFile(g_pucTextFileMem);
    
    	if (g_ptEncodingOprForFile)
    	{
    
            /*    注意:这里加上了文件前面的特殊编码空间    */
    		g_pucLcdFirstPosAtFile = g_pucTextFileMem + g_ptEncodingOprForFile->iHeadLen;
    		return 0;
    	}
    	else
    	{
    		return -1;
    	}
    
    }
    
    /*    根据得到的编码中的字形结构体来确定,字形    */
    int SetTextDetail(char *pcHZKFile, char *pcFileFreetype, unsigned int dwFontSize)
    {
    	int iError = 0;
    	PT_FontOpr ptFontOpr;
    	PT_FontOpr ptTmp;
    	int iRet = -1;
    
    	g_dwFontSize = dwFontSize;
    	
    
    	ptFontOpr = g_ptEncodingOprForFile->ptFontOprSupportedHead;
    	while (ptFontOpr)
    	{
            /*    根据名字选择,传入的字体文件,设置大小    */
    		if (strcmp(ptFontOpr->name, "ascii") == 0)
    		{
    			iError = ptFontOpr->FontInit(NULL, dwFontSize);
    		}
    		else if (strcmp(ptFontOpr->name, "gbk") == 0)
    		{
    			iError = ptFontOpr->FontInit(pcHZKFile, dwFontSize);
    		}
    		else
    		{
    			iError = ptFontOpr->FontInit(pcFileFreetype, dwFontSize);
    		}
    
    		DBG_PRINTF("%s, %d
    ", ptFontOpr->name, iError);
    
    		ptTmp = ptFontOpr->ptNext;
    
    		if (iError == 0)
    		{
    			/* 比如对于ascii编码的文件, 可能用ascii字体也可能用gbk字体, 
    			* 所以只要有一个FontInit成功, SetTextDetail最终就返回成功
    			*/
    			iRet = 0;
    		}
    		else
    		{
    			DelFontOprFrmEncoding(g_ptEncodingOprForFile, ptFontOpr);
    		}
    		ptFontOpr = ptTmp;
    	}
    	return iRet;
    }
    
    int SelectAndInitDisplay(char *pcName)
    {
    	int iError;
    	g_ptDispOpr = GetDispOpr(pcName);
    	if (!g_ptDispOpr)
    	{
    		return -1;
    	}
    
    	iError = g_ptDispOpr->DeviceInit();
    	return iError;
    }
    
    int GetDispResolution(int *piXres, int *piYres)
    {
    	if (g_ptDispOpr)
    	{
    		*piXres = g_ptDispOpr->iXres;
    		*piYres = g_ptDispOpr->iYres;
    		return 0;
    	}
    	else
    	{
    		return -1;
    	}
    }
    
    int IncLcdX(int iX)
    {
    	if (iX + 1 < g_ptDispOpr->iXres)
    		return (iX + 1);
    	else
    		return 0;
    }
    
    /*    换行    */
    int IncLcdY(int iY)
    {
    	if (iY + g_dwFontSize < g_ptDispOpr->iYres)
    		return (iY + g_dwFontSize);
    	else
    		return 0;
    }
    
    int RelocateFontPos(PT_FontBitMap ptFontBitMap)
    {
    	int iLcdY;
    	int iDeltaX;
    	int iDeltaY;
    
    	if (ptFontBitMap->iYMax > g_ptDispOpr->iYres)
    	{
    		/* 满页了 */
    		return -1;
    	}
    
    	/* 超过LCD最右边 */
    	if (ptFontBitMap->iXMax > g_ptDispOpr->iXres)
    	{
    		/* 换行 */		
    		iLcdY = IncLcdY(ptFontBitMap->iCurOriginY);
    		if (0 == iLcdY)
    		{
    			/* 满页了 */
    			return -1;
    		}
    		else
    		{
    			/* 没满页,重新计算位置 */
    			iDeltaX = 0 - ptFontBitMap->iCurOriginX;
    			iDeltaY = iLcdY - ptFontBitMap->iCurOriginY;
    
    			ptFontBitMap->iCurOriginX  += iDeltaX;
    			ptFontBitMap->iCurOriginY  += iDeltaY;
    
    			ptFontBitMap->iNextOriginX += iDeltaX;
    			ptFontBitMap->iNextOriginY += iDeltaY;
    
    			ptFontBitMap->iXLeft += iDeltaX;
    			ptFontBitMap->iXMax  += iDeltaX;
    
    			ptFontBitMap->iYTop  += iDeltaY;
    			ptFontBitMap->iYMax  += iDeltaY;;
    			
    			return 0;	
    		}
    	}
    	
    	return 0;
    }
    
    int ShowOneFont(PT_FontBitMap ptFontBitMap)
    {
    	int x;
    	int y;
    	unsigned char ucByte = 0;
    	int i = 0;
    	int bit;
    	
    	if (ptFontBitMap->iBpp == 1)
    	{
    		for (y = ptFontBitMap->iYTop; y < ptFontBitMap->iYMax; y++)
    		{
    			i = (y - ptFontBitMap->iYTop) * ptFontBitMap->iPitch;
    			for (x = ptFontBitMap->iXLeft, bit = 7; x < ptFontBitMap->iXMax; x++)
    			{
    				if (bit == 7)
    				{
    					ucByte = ptFontBitMap->pucBuffer[i++];
    				}
    				
    				if (ucByte & (1<<bit))
    				{
    					g_ptDispOpr->ShowPixel(x, y, COLOR_FOREGROUND);
    				}
    				else
    				{
    					/* 使用背景色, 不用描画 */
    					// g_ptDispOpr->ShowPixel(x, y, 0); /* 黑 */
    				}
    				bit--;
    				if (bit == -1)
    				{
    					bit = 7;
    				}
    			}
    		}
    	}
    	else if (ptFontBitMap->iBpp == 8)
    	{
    		for (y = ptFontBitMap->iYTop; y < ptFontBitMap->iYMax; y++)
    			for (x = ptFontBitMap->iXLeft; x < ptFontBitMap->iXMax; x++)
    			{
    				//g_ptDispOpr->ShowPixel(x, y, ptFontBitMap->pucBuffer[i++]);
    				if (ptFontBitMap->pucBuffer[i++])
    					g_ptDispOpr->ShowPixel(x, y, COLOR_FOREGROUND);
    			}
    	}
    	else
    	{
    		DBG_PRINTF("ShowOneFont error, can't support %d bpp
    ", ptFontBitMap->iBpp);
    		return -1;
    	}
    	return 0;
    }
    
    int ShowOnePage(unsigned char *pucTextFileMemCurPos)
    {
    	int iLen;
    	int iError;
    	unsigned char *pucBufStart;
    	unsigned int dwCode;
    	PT_FontOpr ptFontOpr;
    	T_FontBitMap tFontBitMap;
    	
    	int bHasNotClrSceen = 1;
    	int bHasGetCode = 0;
    
    	tFontBitMap.iCurOriginX = 0;
    	tFontBitMap.iCurOriginY = g_dwFontSize;
    	pucBufStart = pucTextFileMemCurPos;
    
    	
    	while (1)
    	{
    		iLen = g_ptEncodingOprForFile->GetCodeFrmBuf(pucBufStart, g_pucTextFileMemEnd, &dwCode);
    		if (0 == iLen)
    		{
    			/* 文件结束 */
    			if (!bHasGetCode)
    			{
    				return -1;
    			}
    			else
    			{
    				return 0;
    			}
    		}
    
    		bHasGetCode = 1;
    		
    		pucBufStart += iLen;
    
    		/* 有些文本, 
    
    两个一起才表示回车换行
    		* 碰到这种连续的
    
    , 只处理一次
    		*/
    		if (dwCode == '
    ')
    		{
    			g_pucLcdNextPosAtFile = pucBufStart;
    			
    			/* 回车换行 */
    			tFontBitMap.iCurOriginX = 0;
    			tFontBitMap.iCurOriginY = IncLcdY(tFontBitMap.iCurOriginY);
    			if (0 == tFontBitMap.iCurOriginY)
    			{
    				/* 显示完当前一屏了 */
    				return 0;
    			}
    			else
    			{
    				continue;
    			}
    		}
    		else if (dwCode == '
    ')
    		{
    			continue;
    		}
    		else if (dwCode == '	')
    		{
    			/* TAB键用一个空格代替 */
    			dwCode = ' ';
    		}
    
    		DBG_PRINTF("dwCode = 0x%x
    ", dwCode);
    		
    		ptFontOpr = g_ptEncodingOprForFile->ptFontOprSupportedHead;
    		while (ptFontOpr)
    		{
    			DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    			iError = ptFontOpr->GetFontBitmap(dwCode, &tFontBitMap);
    			DBG_PRINTF("%s %s %d, ptFontOpr->name = %s, %d
    ", __FILE__, __FUNCTION__, __LINE__, ptFontOpr->name, iError);
    			if (0 == iError)
    			{
    				DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    				if (RelocateFontPos(&tFontBitMap))
    				{
    					/* 剩下的LCD空间不能满足显示这个字符 */
    					return 0;
    				}
    				DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    
    				if (bHasNotClrSceen)
    				{
    					/* 首先清屏 */
    					g_ptDispOpr->CleanScreen(COLOR_BACKGROUND);
    					bHasNotClrSceen = 0;
    				}
    				DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    				/* 显示一个字符 */
    				if (ShowOneFont(&tFontBitMap))
    				{
    					return -1;
    				}
    				
    				tFontBitMap.iCurOriginX = tFontBitMap.iNextOriginX;
    				tFontBitMap.iCurOriginY = tFontBitMap.iNextOriginY;
    				g_pucLcdNextPosAtFile = pucBufStart;
    
    				/* 继续取出下一个编码来显示 */
    				break;
    			}
    			ptFontOpr = ptFontOpr->ptNext;
    		}		
    	}
    
    	return 0;
    }
    
    /*    记录下当前这一页的数据,保存到链表    */
    static void RecordPage(PT_PageDesc ptPageNew)
    {
    	PT_PageDesc ptPage;
    		
    	if (!g_ptPages)
    	{
    		g_ptPages = ptPageNew;
    	}
    	else
    	{
    		ptPage = g_ptPages;
    		while (ptPage->ptNextPage)
    		{
    			ptPage = ptPage->ptNextPage;
    		}
    		ptPage->ptNextPage   = ptPageNew;
    		ptPageNew->ptPrePage = ptPage;
    	}
    }
    
    int ShowNextPage(void)
    {
    	int iError;
    	PT_PageDesc ptPage;
    	unsigned char *pucTextFileMemCurPos;
    
        /*    如果当前页面不为空,则保存当前页面
         *    否则,则证明,这是第一页。则把第一页的数据放进了
         */
    	if (g_ptCurPage)
    	{
    		pucTextFileMemCurPos = g_ptCurPage->pucLcdNextPageFirstPosAtFile;
    	}
    	else
    	{
    		pucTextFileMemCurPos = g_pucLcdFirstPosAtFile;
    	}
    	iError = ShowOnePage(pucTextFileMemCurPos);
    	DBG_PRINTF("%s %d, %d
    ", __FUNCTION__, __LINE__, iError);
    	if (iError == 0)
    	{
            /*    iError == 0表示显示完当前页,此时把链表指向下一页    */
    		if (g_ptCurPage && g_ptCurPage->ptNextPage)
    		{
    			g_ptCurPage = g_ptCurPage->ptNextPage;
    			return 0;
    		}
    		
    		ptPage = malloc(sizeof(T_PageDesc));
    		if (ptPage)
    		{
    			ptPage->pucLcdFirstPosAtFile         = pucTextFileMemCurPos;
    			ptPage->pucLcdNextPageFirstPosAtFile = g_pucLcdNextPosAtFile;
    			ptPage->ptPrePage                    = NULL;
    			ptPage->ptNextPage                   = NULL;
    			g_ptCurPage = ptPage;
    			DBG_PRINTF("%s %d, pos = 0x%x
    ", __FUNCTION__, __LINE__, (unsigned int)ptPage->pucLcdFirstPosAtFile);
    			RecordPage(ptPage);
    			return 0;
    		}
    		else
    		{
    			return -1;
    		}
    	}
    	return iError;
    }
    
    int ShowPrePage(void)
    {
    	int iError;
    
    	DBG_PRINTF("%s %d
    ", __FUNCTION__, __LINE__);
    	if (!g_ptCurPage || !g_ptCurPage->ptPrePage)
    	{
    		return -1;
    	}
    
    	DBG_PRINTF("%s %d, pos = 0x%x
    ", __FUNCTION__, __LINE__, (unsigned int)g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
    	iError = ShowOnePage(g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
    	if (iError == 0)
    	{
    		DBG_PRINTF("%s %d
    ", __FUNCTION__, __LINE__);
    		g_ptCurPage = g_ptCurPage->ptPrePage;
    	}
    	return iError;
    }
    

    main.c

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <config.h>
    #include <draw.h>
    #include <encoding_manager.h>
    #include <fonts_manager.h>
    #include <disp_manager.h>
    #include <input_manager.h>
    #include <string.h>
    
    
    /* ./show_file [-s Size] [-f freetype_font_file] [-h HZK] <text_file> */
    int main(int argc, char **argv)
    {
    	int iError;
    	unsigned int dwFontSize = 16;
    	char acHzkFile[128];
    	char acFreetypeFile[128];
    	char acTextFile[128];
    
    	char acDisplay[128];
    
    	int bList = 0;
    
    	T_InputEvent tInputEvent;
    
    	acHzkFile[0]  = '';
    	acFreetypeFile[0] = '';
    	acTextFile[0] = '';
    
    	strcpy(acDisplay, "fb");
    
    	iError = DebugInit();
    	if (iError)
    	{
    		DBG_PRINTF("DebugInit error!
    ");
    		return -1;
    	}
    
    	InitDebugChanel();
    	
        /*    getopt得到输入的命令    */
    	while ((iError = getopt(argc, argv, "ls:f:h:d:")) != -1)
    	{
    		switch(iError)
    		{
    			case 'l':
    			{
    				bList = 1;
    				break;
    			}
    			case 's':
    			{
    				dwFontSize = strtoul(optarg, NULL, 0);
    				break;
    			}
    			case 'f':
    			{
    				strncpy(acFreetypeFile, optarg, 128);
    				acFreetypeFile[127] = '';
    				break;
    			}			
    			case 'h':
    			{
    					strncpy(acHzkFile, optarg, 128);
    					acHzkFile[127] = '';
    					break;
    			}
    			case 'd':
    			{
    				strncpy(acDisplay, optarg, 128);
    				acDisplay[127] = '';
    				break;
    			}
    			default:
    			{
    					DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>
    ", argv[0]);
    					DBG_PRINTF("Usage: %s -l
    ", argv[0]);
    					return -1;
    					break;
    			}
    		}
    	}
    
    	if (!bList && (optind >= argc))
    	{
    		DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>
    ", argv[0]);
    		DBG_PRINTF("Usage: %s -l
    ", argv[0]);
    		return -1;
    	}
    		
    	iError = DisplayInit();
    	if (iError)
    	{
    		DBG_PRINTF("DisplayInit error!
    ");
    		return -1;
    	}
    
    	iError = FontsInit();
    	if (iError)
    	{
    		DBG_PRINTF("FontsInit error!
    ");
    		return -1;
    	}
    
    	iError = EncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("EncodingInit error!
    ");
    		return -1;
    	}
    
    
    	iError = InputInit();
    	if (iError)
    	{
    		DBG_PRINTF("InputInit error!
    ");
    		return -1;
    	}
    
    
    
    	if (bList)
    	{
    		DBG_PRINTF("supported display:
    ");
    		ShowDispOpr();
    
    		DBG_PRINTF("supported font:
    ");
    		ShowFontOpr();
    
    		DBG_PRINTF("supported encoding:
    ");
    		ShowEncodingOpr();
    
    		DBG_PRINTF("supported input:
    ");
    		ShowInputOpr();
    
    		DBG_PRINTF("supported debug chanel:
    ");
    		ShowDebugOpr();
    		
    		return 0;
    	}
    
    	strncpy(acTextFile, argv[optind], 128);
    	acTextFile[127] = '';
    		
    	iError = OpenTextFile(acTextFile);
    	if (iError)
    	{
    		DBG_PRINTF("OpenTextFile error!
    ");
    		return -1;
    	}
    
    	iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);
    	if (iError)
    	{
    		DBG_PRINTF("SetTextDetail error!
    ");
    		return -1;
    	}
    
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    
    	iError = SelectAndInitDisplay(acDisplay);
    	if (iError)
    	{
    		DBG_PRINTF("SelectAndInitDisplay error!
    ");
    		return -1;
    	}
    
    	iError = AllInputDevicesInit();
    	if (iError)
    	{
    		DBG_PRINTF("Error AllInputDevicesInit
    ");
    		return -1;
    	}
    	
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    	iError = ShowNextPage();
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    	if (iError)
    	{
    		DBG_PRINTF("Error to show first page
    ");
    		return -1;
    	}
    
    	DBG_PRINTF("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: ");
    
    	while (1)
    	{
    
    		if (0 == GetInputEvent(&tInputEvent))
    		{
    			if (tInputEvent.iVal == INPUT_VALUE_DOWN)
    			{
    				ShowNextPage();
    			}
    			else if (tInputEvent.iVal == INPUT_VALUE_UP)
    			{
    				ShowPrePage();			
    			}
    			else if (tInputEvent.iVal == INPUT_VALUE_EXIT)
    			{
    				return 0;
    			}
    		}
    	}
    	return 0;
    }
    

    5.测试代码

    ./show_file -s 24 -d fb -f ./simsun.ttc ./dazhuzai.txt
  • 相关阅读:
    Linux 系统高级编程 ¶
    手表维修_机械表维修_手表维修网
    epel
    集合包含关系的快速算法 simcity 博客园
    微软的无线鼠标的电池用的快啊,今天又换新的了
    VIM字符集编码设置_icewater_新浪博客
    【索尼LT29i】索尼(SONY)LT29i 3G手机(黑色)WCDMA/GSM 【行情 报价 价格 评测】
    Python模块学习 fileinput 成长的点滴,记录与分享 博客频道 CSDN.NET
    fedora8 使用小记之:终端字体设置
    Wen Quan Yi Open Source Chinese: About
  • 原文地址:https://www.cnblogs.com/huangdengtao/p/12362149.html
Copyright © 2020-2023  润新知