链表里的元素为结构体, 这样建立多个链表,每个链表里面管理同一类设备,这样方便我们为一个链表里面的设备写出一个大致通用的程序,通过name区分设备。
往链表里面添加元素即可看做像内核里面注册设备一样。在mian.c里面就只需要调用封装好的接口就可以调用设备资源,实现分层管理。
配置结构体
typedef struct DispOpr {
char *name; /* 显示模块的名字 */
int iXres; /* X分辨率 */
int iYres; /* Y分辨率 */
int iBpp; /* 一个象素用多少位来表示 */
int iLineWidth; /* 一行数据占据多少字节 */
unsigned char *pucDispMem; /* 显存地址 */
int (*DeviceInit)(void); /* 设备初始化函数 */
int (*ShowPixel)(int iPenX, int iPenY, unsigned int dwColor); /* 把指定座标的象素设为某颜色 */
int (*CleanScreen)(unsigned int dwBackColor); /* 清屏为某颜色 */
int (*ShowPage)(PT_PixelDatas ptPixelDatas); /* 显示一页,数据源自ptVideoMem */
struct DispOpr *ptNext; /* 链表 */
}T_DispOpr, *PT_DispOpr;
配置设备信息
static int FBDeviceInit(void)
{
int ret;
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_tFBOpr.iLineWidth = g_tFBVar.xres * g_tFBOpr.iBpp / 8;
g_tFBOpr.pucDispMem = g_pucFBMem;
g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;
return 0;
}
static T_DispOpr g_tFBOpr = {
.name = "fb",
.DeviceInit = FBDeviceInit, //仅列出FBDeviceInit(在上面 举例)
.ShowPixel = FBShowPixel,
.CleanScreen = FBCleanScreen,
.ShowPage = FBShowPage,
};
注册设备
//尾插法
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;
}
// 注册设备
int FBInit(void)
{
return RegisterDispOpr(&g_tFBOpr);
}
外部调用 mian.c 可以直接使用 当然可以进一步封装 FBInit ('name') 用name 来选择初始化哪一个设备
FBInit();