热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

66最简单的linuxframebuffer设备驱动实现

在linux系统中,没有lcd驱动这种叫法,只有framebuffer设备驱动,也就是显存驱动。这种驱动是用于实现提供应用程序的窗口图像的显示接口,如QT窗口程序的显示.struct

在linux系统中,没有lcd驱动这种叫法,只有framebuffer设备驱动,也就是显存驱动。 这种驱动是用于实现提供应用程序的窗口图像的显示接口,如QT窗口程序的显示.

struct fb_info 的一个对象表示一个framebuffer设备
struct fb_info结构体成员比较多, 最起码需要初始化下面列出的几个成员

struct fb_info fbi {
...
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
...
struct fb_ops *fbops;
char __iomem *screen_base; /* Virtual address */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */
void *pseudo_palette; /* Fake palette of 16 colors
....
};

struct fb_var_screeninfo {
__u32 xres; /* visible resolution */

__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 bits_per_pixel; /* guess what */

struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency
....
}

struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */

unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 visual; /* see FB_VISUAL_* */
__u32 line_length; /* length of a line in bytes */ bit
....
}

///////////////////////所用的函数说明////////////////////

extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); //因fb_info结构体比较大,需用这函数动态分配空间. size是除了fb_info对象的空间外,额外还分配多少空间
extern void framebuffer_release(struct fb_info *info); // 回收fb_info对象

extern int register_framebuffer(struct fb_info *fb_info); //注册fb设备
extern int unregister_framebuffer(struct fb_info *fb_info); //反注册fb设备


//显存其实就是在内存里分配出的一个缓冲区,而且这缓冲区还需要禁用数据缓存,为了让显存数据可以实时更新,所以还需要用下面两函数来分配和回收显存的缓冲区

void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag) //申请出来的缓冲区禁用data cache, write buffer
size指申请多大, dma_handle用来存放物理地址, GFP_KERNEL
函数返回值为申请的缓冲区的虚拟地址

void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle)
释放空间. cpu_addr为虚拟地址, dma_handle为物理地址

///////////////
在fb_info里的struct fb_ops成员可以为空间,因为基本的操作如fb_open/release/read/write/ioctl等都已在fbmem.c里有实现
同时fb_fillrect函数功能有在cfbfillrect.c里实现,函数名为cfb_fillrect
fb_copyarea 在cfbcopyarea.c
fb_imageblit 在cfbimgblt.c
fb_cursor 在softcursor.c

//////////////////////////////////////////////////
实现一个最简单的fb设备驱动:
test.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>

#define X 1024
#define Y 768

u32 p_addr; //用于存放显存的物理地址
u8 *v_addr; //用于存放显存的虚拟地址, 在驱动代码,我们也只能操作缓存的虚拟地址

struct fb_ops fops = { //这里不实现操作函数,使用fbmem.c里实现的功能函数
//如果这里实现了功能函数,则会调用这里实现的函数
};

struct fb_info *fbi;
static int __init test_init(void)
{
v_addr = dma_alloc_coherent(NULL, X*Y*4, &p_addr, GFP_KERNEL); //分配显存的缓冲区

//动态分配fb_info的对象空间, 而且额外分配100个字节(这100字节空间的地址==&fbi[1])
fbi = framebuffer_alloc(100, NULL);

fbi->var.xres = X; //分辨率
fbi->var.yres = Y;
fbi->var.xres_virtual = X;
fbi->var.yres_virtual = Y;
fbi->var.bits_per_pixel = 32; // 32位每个像素
fbi->var.red.offset = 16; //像素数据里的红
fbi->var.red.length = 8;
fbi->var.green.offset = 8; //像素数据里的绿
fbi->var.green.length = 8;
fbi->var.blue.offset = 0; //像素数据里的蓝
fbi->var.blue.length = 8;

strcpy(fbi->fix.id, "myfb");
fbi->fix.smem_start = p_addr; //显存的物理地址
fbi->fix.smem_len = X*Y*4; //显存缓冲区大小
fbi->fix.type = FB_TYPE_PACKED_PIXELS; //像素数据是打包的方式
fbi->fix.visual = FB_VISUAL_TRUECOLOR; //真彩色
fbi->fix.line_length = X*4; //每一行多少个字节

fbi->fbops = &fops;
fbi->screen_base = v_addr; // 显示缓冲区的虚拟地址
fbi->screen_size = X*Y*4;


return register_framebuffer(fbi); //注册fb设备
}

static void __exit test_exit(void)
{
unregister_framebuffer(fbi);
framebuffer_release(fbi);

dma_free_coherent(NULL, X*Y*4, v_addr, p_addr);
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");

//////////////////////////////////
加载模块后,在”/dev/”目录下会多一个fb8设备文件。
可以设置QT的环境变量让QT程序从指定的fb设备刷出来.
如: export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb8

让qt程序执行起来后,再从/dev/fb8读出显存数据,加上图像文件头后,就可以看到QT程序在显存里的状况了


推荐阅读
author-avatar
zhenhuaYang
编程、骑行、健身、民谣、生活!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有