目錄
一,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;
}
}