目录
一,framebuffer介绍
1、什么是framebuffer
(1)很多人都会说操纵lcd显示就是操纵framebuffer,表面上来看是这样的。实际上是frambuffer就是linux内核驱动申请的一片内存空间,然后lcd内有一片sram,cpu内部有个lcd控制器,它有个单独的dma用来将frambuffer中的数据拷贝到lcd的sram中去 拷贝到lcd的sram中的数据就会显示在lcd上,LCD驱动和framebuffer驱动没有必然的联系,它只是驱动LCD正常工作的,比如有信号传过来,那么LCD驱动负责把信号转成显示屏上的内容,至于什么内容这就是应用层要处理的。
(2)framebuffer帧缓冲(简称fb)是linux内核中虚拟出的一个设备
(3)framebuffer向应用层提供一个统一标准接口的显示设备
(4)从驱动来看,fb是一个典型的字符设备,而且创建了一个类/sys/class/graphics
2、帧缓冲设备驱动的结构
3、framebuffer的使用步骤
(1)打开设备文件 /dev/fb0
(2)获取当前设备信息 #include <linux/fb.h>
(3)mmap做映射
(4)填充framebuffer
二,framebuffer驱动源码分析
1.framebuffer驱动框架总览
1、驱动框架部分
- drivers/video/fbmem.c主要任务:fbmen_init()函数负责创建graphics类、注册FB的字符设备驱动、register_framebuffer()函数提供接口给具体framebuffer驱动编写着来注册fb设备。本文件相对于fb来说,地位和作用和misc.c文件相对于杂散类设备来说一样的,结构和分析方法也是类似的。
- drivers/video/fbsys.c这个文件是处理fb在/sys目录下的一些属性文件的。
- drivers/video/modedb.c这个文件是管理显示模式(譬如VGA、720P等就是显示模式)的。
- drivers/video/fb_notify.c这个文件是frame buff用来管理相关通知的。
2、驱动部分
- drivers/video/samsung/s3cfb.c驱动主体
- drivers/video/samsung/s3cfb_fimd6x.c里面有很多LCD硬件操作的函数
- arch/arm/mach-s5pv210/mach-x210.c负责提供platform_device的
- arch/arm/plat-s5p/devs.c为platform_device提供一些硬件描述信息的
3、如何分析
(1)经验
(2)分析menuconfig、Makefile、Kconfig等
(3)内核编译后检查编译结果中的.o文件
2.framebuffer驱动框架分析
1、fbmem_init函数
(1)#ifdef MODULE
(2)fb_proc_fops和fb在proc文件系统中的表现
(3)register_chrdev注册fb设备
(4)class_create创建graphics类
(5)fbmem_exit的对应
2、fb_fops
(1)read/write/mmap/ioctl
(2)registered_fb和num_registered_fb
(3)struct fb_info
3、register_framebuffer和unregister_framebuffer
3.framebuffer驱动分析
1、s3cfb.c
2、s3c_device_fb
3、probe函数分析
(1)struct s3c_platform_fb :这个结构体是fb的platform_data结构体,这个结构体变量就是platform设备的私有数据,这个数据在platform_device.device.platform_data中存储。在mach文件中去准备并填充这些数据,在probe函数中通过传参的platform_device指针取出来。
(2)struct s3cfb_global: 这个结构体主要作用是在驱动部分的2个文件(s3cfb.c和s3cfb_fimd6x.c)的函数中做数据传递用的。
4、
5、
三,framebuffer应用编程实践
实验步骤:
1、打开设备
2、获取设备信息
(1)不可变信息FSCREENINFO,使用ioctl的FBIOGET_FSCREENINFO名
(2)可变信息VSCREENINFO,使用ioctl的FBIOGET_VSCREENINFO名
3、mmap做映射
做完了mmap后fb在当前进程中就已经就绪了,随时可以去读写LCD显示器了。
4、fb显示之刷背景和画横线
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
// 宏定义
#define FBDEVICE "/dev/fb0"
#define WIDTH 1024
#define HEIGHT 600
#define WHITE 0xffffffff // test ok
#define BLACK 0x00000000
#define RED 0xffff0000
#define GREEN 0xff00ff00 // test ok
#define BLUE 0xff0000ff
#define GREENP 0x0000ff00 // 一样,说明前2个ff透明位不起作用
// 函数声明
void draw_back(unsigned int width, unsigned int height, unsigned int color);
void draw_line(unsigned int color);
// 全局变量
unsigned int *pfb = NULL;
int main(void)
{
int fd = -1, ret = -1;
struct fb_fix_screeninfo finfo = {0};
struct fb_var_screeninfo vinfo = {0};
// 第1步:打开设备
fd = open(FBDEVICE, O_RDWR);
if (fd < 0)
{
perror("open");
return -1;
}
printf("open %s success.\n", FBDEVICE);
// 第2步:获取设备的硬件信息
ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("smem_start = 0x%x, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
printf("bpp = %u.\n", vinfo.bits_per_pixel);
// 第3步:进行mmap
unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
printf("len = %ld\n", len);
pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (NULL == pfb)
{
perror("mmap");
return -1;
}
printf("pfb = %p.\n", pfb);
draw_back(WIDTH, HEIGHT, WHITE);
draw_line(RED);
close(fd);
return 0;
}
//刷背景函数
void draw_back(unsigned int width, unsigned int height, unsigned int color)
{
unsigned int x, y;
for (y=0; y<height; y++)
{
for (x=0; x<width; x++)
{
*(pfb + y * WIDTH + x) = color;
}
}
}
//画线函数
void draw_line(unsigned int color)
{
unsigned int x, y;
for (x=50; x<600; x++)
{
*(pfb + 200 * WIDTH + x) = color;
}
}