分类: 嵌入式
2015-08-23 16:44:40
fb.c
15年8月22日14:27:31
#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;
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;
}
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);
}
下面来分析这个文件:
(1)设备初始化函数:当main函数选择对应的显示器后,需要调用这个函数进行显示器的初始化。
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_dwScreenSize的单位是byte */
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结构体。 */
g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;
/* 计算一行的宽度和像素宽度,在后面的显示函数中将要使用,会在多个函数中使用,在初始化函 * 数中设置,方便以后使用。
*/
return 0;
}
函数返回值: 成功 --- 0;
(2)显示像素函数:
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;
/* pucFB就是指向内存的一个指针,在2440中LCD控制器直接从内存中取值显示在LCD上面,如 * 果想要在屏幕的(x,y)处显示红色,就要在(x,y)所对应的内存处写入红色。 g_pucFBMem是指 * 向映射后内存初始值的一个指针,想要算出任意点(x,y)在内存中的位置,需要在内存初始值的 * 基础上,加上一行的位宽乘以y,再加上像素宽度乘以x,即是这个式子。
*/
pwFB16bpp = (unsigned short *)pucFB;
pdwFB32bpp = (unsigned int *)pucFB;
switch (g_tFBVar.bits_per_pixel)
{
case 8:
{
*pucFB = (unsigned char)dwColor;
break;
/* 8bpp的时候,需要用到调色板了,直接这样设置就好 */
}
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;
}
/* 这个函数传入的颜色参数dwColor是这样表示的0x00RRGGBB,需要将他们转 * 换成RGB:565的格式。如果这个不好理解的话,可以看下面的:
* iRed = (dwColor >> 16) & 0xff;
* iGreen = (dwColor >> 8) & 0xff;
* iBlue = (dwColor >> 0) & 0xff;
* wColor16bpp = (((iRed >> 3) << 11) | ((iGreen >> 2) << 5) | * (iBlue >> 3));
* *pwFB16bpp = wColor16bpp;
*/
case 32:
{
*pdwFB32bpp = dwColor;
break;
}
default :
{
DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
return -1;
}
}
return 0;
}
函数返回值: 成功 --- 0;
(3)清屏函数:跟上面的函数很相似。就不再详细解释了。
(4)FBInit函数:只是给display_manager.c提供一个接口,用于将 g_tFBOpr结构体添加进链表里面。
int FBInit(void)
{
return RegisterDispOpr(&g_tFBOpr);
}