2016/1/9:深度剖析安卓Framebuffer设备驱动
忙了几天,今天在公司居然没什么活干
,所以早上就用公司的电脑写写之前在公司编写framebuffer的使用心得体会总结,这也算是一点开发经验,不过我还没写全,精华部分还是自己藏着吧。直到下午才开始有点活干,改瑞芯微的摄像头驱动,偶滴天!!特别麻烦,摄像头的代码好几千行,果真不太好看,驱动想改也不好改
,看看我的测试效果就知道了,显示的图片是反的,又到了周末了,这个问题只能留着下周上班再去解决了,今天我们就来了解一下Framebuffer设备驱动,其实Framebuffer驱动跟我这个安卓项目就挂钩了,好,我们来看看:
记住!没有简单的程序,只有头脑简单的程序员!

在此,我借用某内核驱动大牛GQB做的驱动框架图做分析,如有侵权,请联系我删除,谢谢!
struct fb_ops {
struct module *owner;
//检查可变参数并进行设置
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
//根据设置的值进行更新,使之有效
int (*fb_set_par)(struct fb_info *info);
//设置颜色寄存器
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
//显示空白
int (*fb_blank)(int blank, struct fb_info *info);
//矩形填充
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
//复制数据
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
//图形填充
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
};
可以查阅到fbmem.c里定义 register_framebuffer这个函数。通过查看这个函数,我们可以发现其实这个函数在drivers/video/s3c-fb.c中的probe函数中调用了 register_framebuffer,在s3c-fb.c这个文件注册了一个平台总线
struct fb_info {
int node;
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_videomode *mode; /* current mode */
struct fb_ops *fbops;
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
char __iomem *screen_base; /* Virtual address */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */
…………
};
struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* bits/pixel */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin;/* time from picture to sync */
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
…………
};
struct fb_fix_screeninfo {
char id[16];
unsigned long smem_start; /* 开始的framebuffer内存,这里是物理地址要注意 */
__u32 smem_len; /* 物理地址的长度 */
unsigned long mmio_start; /* 开始的物理地址映射 */
__u32 mmio_len; /* IO内存映射的长度 */
…………
};
4、struct fb_videomode *mode 这个结构体主要是设置LCD相应的模式,看看我写的注释就清楚了。
struct fb_videomode {
const char *name; /* optional */
u32 refresh; /* optional */
u32 xres; // x分辨率
u32 yres; // y分辨率
u32 pixclock; // 像素时钟频率,即每个时钟周期显示一个像素点
u32 left_margin; // 行扫描开始脉冲到一行像素数据开始输出的延迟 hsync<==>DEN
u32 right_margin; // 一行像素数据输出完毕到下一行的行扫描开始脉冲间的延迟 DEN <==>hsync
u32 upper_margin; // 帧扫描开始脉冲到第一行像素数据开始输出的延迟 vsync<==>DEN(1st line)
u32 lower_margin; // 最后一行像素数据输出结束到下一帧的那帧扫描开始脉冲间的延迟DEN(last line)<==>vsync
u32 hsync_len; // 行扫描脉冲宽度,单位为pixclock
u32 vsync_len; // 帧扫描脉冲宽度,单位为line
u32 sync; // 各同步信号的极性定义,如hsync、vsync、DEN的极性等。
u32 vmode; // 显示模式,逐行还是隔行扫描
u32 flag; // 一般为0
};
5、struct fb_ops *fbops; 这个结构体是LCDframebuffer操作中最重要的一个,也就是说上面做了LCD的相关设置那只是在设置LCD中的硬件寄存器,
如果你想点亮LCD屏顺便操作它,那么这个结构体必不可少。
struct fb_ops {
int (*fb_open)(struct fb_info *info, int user);
int (*fb_release)(struct fb_info *info, int user);
ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count,
loff_t *ppos);
int (*fb_set_par)(struct fb_info *info);
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info)
int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
……………
}
lantianyu520.blog.chinaunix.net总结了几个可以点亮LCD的步骤:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define RGB(r,g,b)((r<<16)|(g<<8)|b)
#define WIDTH 1280
#define HIGHT 1024
static int Frame_fd ;
static int *FrameBuffer = NULL ;
static int W , H ;
//写framebuffer
int Write_FrameBuffer(const char *buffer);
int main(void)
{
1、设置长宽,打开fb设备
W = 1024 ;
H = 768 ;
Frame_fd = open("/dev/fb0" , O_RDWR);
if(-1 == Frame_fd){
perror("open frame buffer fail");
return -1 ;
}
2、对framebuffer进行内存映射mmap
//头文件 <sys/mman.h>
//函数原型:void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);
//start:映射区的开始地址,设置为0时表示由系统决定映射区的起始地址。
//length:映射区的长度。//长度单位是 以字节为单位,不足一内存页按一内存页处理
//prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
//flags:相关的标志,就跟open函数的标志差不多的,自己百度去查
//fd:有效的文件描述词。一般是由open()函数返回,其值也可以设置为-1,此时需要指定flags参数中的MAP_ANON,表明进行的是匿名映射。
//off_toffset:被映射对象内容的起点。
//PROT_READ //页内容可以被读取
//PROT_WRITE //页可以被写入
//MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
FrameBuffer = mmap(0, 1280*1024*4 , PROT_READ | PROT_WRITE , MAP_SHARED , Frame_fd ,0 );
if(FrameBuffer == (void *)-1){
perror("memory map fail");
return -2 ;
}
3、对framebuffer写数据
char buffer[WIDTH*HIGHT*3]; //我们要写入的数据
while(1) {
Write_FrameBuffer(buffer);
printf("count:%d \n" , count++);
}
4、退出framebuffer
munmap(FrameBuffer , W*H*4); //解除内存映射
close(Frame_fd); //关闭文件描述符
return 0 ;
}
//写framebuffer
int Write_FrameBuffer(const char *buffer)
{
int row , col ;
char *p = NULL ;
//遍历分辨率1024*1280的所有像素点
for(row = 0 ; row <1024 ; row++){
for(col = 0 ; col < 1280 ; col++){
if((row < H) && (col < W)){
p = (char *)(buffer + (row * W+ col ) * 3);
//转RGB格式
FrameBuffer[row*1280+col] = RGB((unsigned char)(*(p+2)),(unsigned char)(*(p+1)),(unsigned char )(*p));
}
}
}
return 0 ;
}
,当然痛苦中就必有甘甜,如果你会写驱动程序了,那么软件层次的调用实质上就是函数传参的原理,太简单了,所以搞驱动的工程师其实是可以往上层去发展的,因为他懂硬件也懂软件,相反,纯软件转底层开发,那就没那么容易了,你要了解很多硬件的知识和原理。今天就到此为止,这是我对framebuffer的理解,或许理想某些地方并不到位,如有高手,欢迎指正,共同探讨这个问题。
我的CSDN博客: http://blog.csdn.net/morixinguan/article/month/2015/12
2016/1/9:深度剖析安卓Framebuffer设备驱动的更多相关文章
- framebuffer设备驱动分析
一.设备驱动相关文件 1.1. 驱动框架相关文件 1.1.1. drivers/video/fbmem.c a. 创建graphics类.注册FB的字符设备驱动 fbmem_init(void) { ...
- 十、LCD的framebuffer设备驱动
在读者学习本章以及后续LCD相关章节之前,最好拥有LCD裸机基础,可以参考:LCD编程. 在内核中,表示LCD使用的是framebuffer(帧缓冲,简写为fb),其内容对应于屏幕上的界面显示.修改f ...
- 《Linux设备驱动开发具体解释(第3版)》进展同步更新
本博实时更新<Linux设备驱动开发具体解释(第3版)>的最新进展. 2015.2.26 差点儿完毕初稿. 本书已经rebase到开发中的Linux 4.0内核,案例多数基于多核CORTE ...
- Linux设备驱动中的软件架构思想
目录 更新记录 一.Linux驱动的软件架构 1.1 出发点 1.2 分离思想 1.3 分层思想 二.platform设备驱动 2.1 platform设备 2.2 platform驱动 2.3 pl ...
- 【渗透课程】第二篇下-HTTP协议的请求与响应深度剖析
[渗透课程]第二篇下-HTTP协议的请求与响应深度剖析 HTTP1.1目前支持以下7种请求方法: 常见的MIME类型如下: 第一个数字有五种可能的取值: 目录 什么是请求方法?什么是请求头? HTTP ...
- DDOS学习笔记(《破坏之王-DDOS攻击与防范深度剖析》)
最近花了点时间把<破坏之王-DDOS攻击与防范深度剖析>看了一遍,坦白来说,这本书比较浅显,可以说是入门书,当然对于我这种对DDOS一知半解的人来说,也是一本不错的书,起码我 ...
- C/C++ Volatile关键词深度剖析(转)
本文转载自博文C/C++ Volatile关键词深度剖析. 背景 前几天,发了一条如下的微博 (关于C/C++ Volatile关键词的使用建议): 此微博,引发了朋友们的大量讨论:赞同者有之:批评者 ...
- (转载)深度剖析 | 可微分学习的自适配归一化 (Switchable Normalization)
深度剖析 | 可微分学习的自适配归一化 (Switchable Normalization) 作者:罗平.任家敏.彭章琳 编写:吴凌云.张瑞茂.邵文琪.王新江 转自:知乎.原论文参考arXiv:180 ...
- linux lcd设备驱动剖析四
在"linux lcd设备驱动剖析二"文章中,我们详细分析了s3c24xxfb_probe函数. 文章链接:http://blog.csdn.net/lwj103862095/ar ...
随机推荐
- Swift类中如何创建一个对外只读对内可读写的属性
很简单用private修饰符,后面跟限制关键字set: class Day{ private(set) var rawValue:Int = 0 func showRawValue(){ print( ...
- Swift基础之自定义PUSH和POP跳转动画
之前用OC代码写过PUSH和POP的转场动画,闲来无事,将其转换成Swift语言,希望对大家有帮助,转载请注明.... 如何实现PUSH和POP的转场动画? 首先,创建一个NSObject的类,分别用 ...
- 【安卓开发】为什么不能往Android的Application对象里存储数据
在一个App里面总有一些数据需要在多个地方用到.这些数据可能是一个 session token,一次费时计算的结果等.通常为了避免activity之间传递对象的开销 ,这些数据一般都会保存到持久化存储 ...
- OpenCV+OpenGL 双目立体视觉三维重建
0.绪论 这篇文章主要为了研究双目立体视觉的最终目标--三维重建,系统的介绍了三维重建的整体步骤.双目立体视觉的整体流程包括:图像获取,摄像机标定,特征提取(稠密匹配中这一步可以省略),立体匹配,三维 ...
- 【SSH系列】-- hibernate基本原理&&入门demo
什么是hibernate? hibernate在英文中是冬眠的意思,当冬季来临,世界万物开始准备冬眠,但是程序猿这种动物好像不冬眠,因为需求变了,要改bug,冬眠,对于对象来说就是持 ...
- 20 ViewPager Demo4自动轮播
MainActivity.java 思想:才用非常大的数 让其看起来可以循环轮播图片并且用户可以从尽头滑到首图的特点 . package com.qf.day20_viewpager_demo4; i ...
- JQuery之事件处理
JQuery不支持捕获模型 冒泡模型解析 <body> <div> <input id="bntShow" type="button&quo ...
- Centos7安装Tair及配置测试
系统环境 Centos7 64位 外网ip 182.254.145.66 内网ip 10.105.23.114 安装位置 /usr/local/tair Tair介绍 参见官网 安装 想了半天,我还是 ...
- DBCP连接池TestOnBorrow的坑
生产环境连接池TestOnBorrow设置为false,导致有时获取的连接不可用.分析如下: TestOnBorrow=false时,由于不检测池里连接的可用性,于是假如连接池中的连接被数据库关闭了, ...
- Dalvik虚拟机
Dalvik虚拟机是google专门为android平台开发的一个java虚拟机,但它并没有使用JVM规范.Dalvik虚拟机主要完成对象生命周期的管理.线程管理.安全和异常管理以及垃圾回收等重要功能 ...