目录
- 一,framebuffer介绍
- 二,framebuffer驱动源码分析
- 1.framebuffer驱动框架总览
- 2.framebuffer驱动框架分析
- 3.framebuffer驱动分析
- 三,framebuffer应用编程实践
一,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
(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显示之刷背景和画横线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #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; } } |