电子书总结
参考: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\n", 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\n", FB_DEVICE_NAME);
}
ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
if (ret < 0)
{
DBG_PRINTF("can't get fb's var\n");
return -1;
}
ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
if (ret < 0)
{
DBG_PRINTF("can't get fb's fix\n");
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\n");
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\n");
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\n", 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\n", 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\n", 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!\n");
return -1;
}
iError = GBKInit();
if (iError)
{
DBG_PRINTF("GBKInit error!\n");
return -1;
}
iError = FreeTypeInit();
if (iError)
{
DBG_PRINTF("FreeTypeInit error!\n");
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\n", 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\n", 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\n", dwFontSize);
return -1;
}
g_iFdHZK = open(pcFontFile, O_RDONLY);
if (g_iFdHZK < 0)
{
DBG_PRINTF("can't open %s\n", pcFontFile);
return -1;
}
if(fstat(g_iFdHZK, &tStat))
{
DBG_PRINTF("can't get fstat\n");
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\n");
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\n", __FILE__, __FUNCTION__, __LINE__);
if (dwCode & 0xffff0000)
{
DBG_PRINTF("don't support this code : 0x%x\n", dwCode);
return -1;
}
iArea = (int)(dwCode & 0xff) - 0xA1;
iWhere = (int)((dwCode >> 8) & 0xff) - 0xA1;
if ((iArea < 0) || (iWhere < 0))
{
DBG_PRINTF("%s %s %d\n", __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\n", __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\n");
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\n");
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\n", 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\n", dwCode);
return -1;
}
//DBG_PRINTF("iPenX = %d, iPenY = %d, bitmap_left = %d, bitmap_top = %d, width = %d, rows = %d\n", 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\n", 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\n", 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!\n");
return -1;
}
iError = Utf16leEncodingInit();
if (iError)
{
DBG_PRINTF("Utf16leEncodingInit error!\n");
return -1;
}
iError = Utf16beEncodingInit();
if (iError)
{
DBG_PRINTF("Utf16beEncodingInit error!\n");
return -1;
}
iError = Utf8EncodingInit();
if (iError)
{
DBG_PRINTF("Utf8EncodingInit error!\n");
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\n", i++, ptTmp->name);
ptTmp = ptTmp->ptNext;
}
}
/* 线程函数 */
static void *InputEventTreadFunction(void *pVoid)
{
T_InputEvent tInputEvent;
/* 定义函数指针 */
int (*GetInputEvent)(PT_InputEvent ptInputEvent);
GetInputEvent = (int (*)(PT_InputEvent))pVoid;
while (1)
{
if(0 == GetInputEvent(&tInputEvent))
{
/* 唤醒主线程, 把tInputEvent的值赋给一个全局变量 */
/* 访问临界资源前,先获得互斥量 */
/* 上锁 */
pthread_mutex_lock(&g_tMutex);
g_tInputEvent = tInputEvent;
/* 唤醒主线程 */
pthread_cond_signal(&g_tConVar);
/* 释放互斥量 */
pthread_mutex_unlock(&g_tMutex);
}
}
return NULL;
}
int AllInputDevicesInit(void)
{
PT_InputOpr ptTmp = g_ptInputOprHead;
int iError = -1;
while (ptTmp)
{
if (0 == ptTmp->DeviceInit())
{
/* 创建子线程 */
pthread_create(&ptTmp->tTreadID, NULL, InputEventTreadFunction, ptTmp->GetInputEvent);
iError = 0;
}
ptTmp = ptTmp->ptNext;
}
return iError;
}
int GetInputEvent(PT_InputEvent ptInputEvent)
{
/* 休眠 */
pthread_mutex_lock(&g_tMutex);
pthread_cond_wait(&g_tConVar, &g_tMutex);
/* 被唤醒后,返回数据 */
*ptInputEvent = g_tInputEvent;
pthread_mutex_unlock(&g_tMutex);
return 0;
}
int InputInit(void)
{
int iError;
iError = StdinInit();
iError |= TouchScreenInit();
return iError;
}
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!\n");
return -1;
}
/* 配置 */
if (ts_config(g_tTSDev)) {
DBG_PRINTF("ts_config error!\n");
return -1;
}
if (GetDispResolution(&giXres, &giYres))
{
return -1;
}
return 0;
}
static int TouchScreenDevExit(void)
{
return 0;
}
static int isOutOf500ms(struct timeval *ptPreTime, struct timeval *ptNowTime)
{
int iPreMs;
int iNowMs;
iPreMs = ptPreTime->tv_sec * 1000 + ptPreTime->tv_usec / 1000;
iNowMs = ptNowTime->tv_sec * 1000 + ptNowTime->tv_usec / 1000;
return (iNowMs > iPreMs + 500);
}
static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent)
{
struct ts_sample tSamp;
struct ts_sample tSampPressed;
struct ts_sample tSampReleased;
int iRet;
int bStart = 0;
int iDelta;
static struct timeval tPreTime;
while (1)
{
iRet = ts_read(g_tTSDev, &tSamp, 1); /* 如果无数据则休眠 */
if (iRet == 1)
{
if ((tSamp.pressure > 0) && (bStart == 0))
{
/* 刚按下 */
/* 记录刚开始压下的点 */
tSampPressed = tSamp;
bStart = 1;
}
if (tSamp.pressure <= 0)
{
/* 松开 */
tSampReleased = tSamp;
/* 处理数据 */
if (!bStart)
{
return -1;
}
else
{
iDelta = tSampReleased.x - tSampPressed.x;
ptInputEvent->tTime = tSampReleased.tv;
ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN;
if (iDelta > giXres/5)
{
/* 翻到上一页 */
ptInputEvent->iVal = INPUT_VALUE_UP;
}
else if (iDelta < 0 - giXres/5)
{
/* 翻到下一页 */
ptInputEvent->iVal = INPUT_VALUE_DOWN;
}
else
{
ptInputEvent->iVal = INPUT_VALUE_UNKNOWN;
}
return 0;
}
}
}
else
{
return -1;
}
}
return 0;
}
static T_InputOpr g_tTouchScreenOpr = {
.name = "touchscreen",
.DeviceInit = TouchScreenDevInit,
.DeviceExit = TouchScreenDevExit,
.GetInputEvent = TouchScreenGetInputEvent,
};
int TouchScreenInit(void)
{
return RegisterInputOpr(&g_tTouchScreenOpr);
}
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\n", 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] = '\0';
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] = '\0';
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\n");
iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
if (iRecvLen > 0)
{
ucRecvBuf[iRecvLen] = '\0';
DBG_PRINTF("netprint.c get msg: %s\n", 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!\n");
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!\n");
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:\n");
printf("%s <server_ip> dbglevel=<0-9>\n", argv[0]);
printf("%s <server_ip> stdout=0|1\n", argv[0]);
printf("%s <server_ip> netprint=0|1\n", argv[0]);
printf("%s <server_ip> show\n", 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\n");
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] = '\0';
printf("%s\n", 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\n", pcFileName);
return -1;
}
if(fstat(g_iFdTextFile, &tStat))
{
DBG_PRINTF("can't get fstat\n");
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\n");
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\n", 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\n", 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;
/* 有些文本, \n\r两个一起才表示回车换行
* 碰到这种连续的\n\r, 只处理一次
*/
if (dwCode == '\n')
{
g_pucLcdNextPosAtFile = pucBufStart;
/* 回车换行 */
tFontBitMap.iCurOriginX = 0;
tFontBitMap.iCurOriginY = IncLcdY(tFontBitMap.iCurOriginY);
if (0 == tFontBitMap.iCurOriginY)
{
/* 显示完当前一屏了 */
return 0;
}
else
{
continue;
}
}
else if (dwCode == '\r')
{
continue;
}
else if (dwCode == '\t')
{
/* TAB键用一个空格代替 */
dwCode = ' ';
}
DBG_PRINTF("dwCode = 0x%x\n", dwCode);
ptFontOpr = g_ptEncodingOprForFile->ptFontOprSupportedHead;
while (ptFontOpr)
{
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
iError = ptFontOpr->GetFontBitmap(dwCode, &tFontBitMap);
DBG_PRINTF("%s %s %d, ptFontOpr->name = %s, %d\n", __FILE__, __FUNCTION__, __LINE__, ptFontOpr->name, iError);
if (0 == iError)
{
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
if (RelocateFontPos(&tFontBitMap))
{
/* 剩下的LCD空间不能满足显示这个字符 */
return 0;
}
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
if (bHasNotClrSceen)
{
/* 首先清屏 */
g_ptDispOpr->CleanScreen(COLOR_BACKGROUND);
bHasNotClrSceen = 0;
}
DBG_PRINTF("%s %s %d\n", __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\n", __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\n", __FUNCTION__, __LINE__, (unsigned int)ptPage->pucLcdFirstPosAtFile);
RecordPage(ptPage);
return 0;
}
else
{
return -1;
}
}
return iError;
}
int ShowPrePage(void)
{
int iError;
DBG_PRINTF("%s %d\n", __FUNCTION__, __LINE__);
if (!g_ptCurPage || !g_ptCurPage->ptPrePage)
{
return -1;
}
DBG_PRINTF("%s %d, pos = 0x%x\n", __FUNCTION__, __LINE__, (unsigned int)g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
iError = ShowOnePage(g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
if (iError == 0)
{
DBG_PRINTF("%s %d\n", __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] = '\0';
acFreetypeFile[0] = '\0';
acTextFile[0] = '\0';
strcpy(acDisplay, "fb");
iError = DebugInit();
if (iError)
{
DBG_PRINTF("DebugInit error!\n");
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] = '\0';
break;
}
case 'h':
{
strncpy(acHzkFile, optarg, 128);
acHzkFile[127] = '\0';
break;
}
case 'd':
{
strncpy(acDisplay, optarg, 128);
acDisplay[127] = '\0';
break;
}
default:
{
DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
DBG_PRINTF("Usage: %s -l\n", argv[0]);
return -1;
break;
}
}
}
if (!bList && (optind >= argc))
{
DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
DBG_PRINTF("Usage: %s -l\n", argv[0]);
return -1;
}
iError = DisplayInit();
if (iError)
{
DBG_PRINTF("DisplayInit error!\n");
return -1;
}
iError = FontsInit();
if (iError)
{
DBG_PRINTF("FontsInit error!\n");
return -1;
}
iError = EncodingInit();
if (iError)
{
DBG_PRINTF("EncodingInit error!\n");
return -1;
}
iError = InputInit();
if (iError)
{
DBG_PRINTF("InputInit error!\n");
return -1;
}
if (bList)
{
DBG_PRINTF("supported display:\n");
ShowDispOpr();
DBG_PRINTF("supported font:\n");
ShowFontOpr();
DBG_PRINTF("supported encoding:\n");
ShowEncodingOpr();
DBG_PRINTF("supported input:\n");
ShowInputOpr();
DBG_PRINTF("supported debug chanel:\n");
ShowDebugOpr();
return 0;
}
strncpy(acTextFile, argv[optind], 128);
acTextFile[127] = '\0';
iError = OpenTextFile(acTextFile);
if (iError)
{
DBG_PRINTF("OpenTextFile error!\n");
return -1;
}
iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);
if (iError)
{
DBG_PRINTF("SetTextDetail error!\n");
return -1;
}
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
iError = SelectAndInitDisplay(acDisplay);
if (iError)
{
DBG_PRINTF("SelectAndInitDisplay error!\n");
return -1;
}
iError = AllInputDevicesInit();
if (iError)
{
DBG_PRINTF("Error AllInputDevicesInit\n");
return -1;
}
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
iError = ShowNextPage();
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
if (iError)
{
DBG_PRINTF("Error to show first page\n");
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