完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
Framebuffer驱动程序框架
首先framebuffer是一个字符驱动设备,它分为上下两层: fbmem.c:中间承上启下 实现、注册file_operation结构体 把App的调用向下转发到具体的硬件驱动程序 xxxx_fb.c:硬件相关的驱动程序 实现、注册fb_info结构体 实现硬件操作 在文件drivers/video/fbdev/core/fbmem.c中,有fbmem_init函数 static int __init fbmem_init(void) { proc_create("fb", 0, NULL, &fb_proc_fops); if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) //注册fb设备,注册了fb_fops结构体 printk("unable to get major %d for fb devsn", FB_MAJOR); fb_class = class_create(THIS_MODULE, "graphics"); //创建了graphics类 if (IS_ERR(fb_class)) { printk(KERN_WARNING "Unable to create fb class; errno = %ldn", PTR_ERR(fb_class)); fb_class = NULL; } return 0; } 其中这个fb_fops是这样的: static const struct file_operations fb_fops = { .owner = THIS_MODULE, .read = fb_read, .write = fb_write, .unlocked_ioctl = fb_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = fb_compat_ioctl, #endif .mmap = fb_mmap, .open = fb_open, .release = fb_release, #ifdef HAVE_ARCH_FB_UNMAPPED_AREA .get_unmapped_area = get_fb_unmapped_area, #endif #ifdef CONFIG_FB_DEFERRED_IO .fsync = fb_deferred_io_fsync, #endif .llseek = default_llseek, }; 所以对于App来说当他对/dev/fbx文件操作的时候,其实就是调用了fb_fops结构体的各类操作 看一下fb_open操作: static int fb_open(struct inode *inode, struct file *file) __acquires(&info->lock) __releases(&info->lock) { int fbidx = iminor(inode); //获取了次设备号 struct fb_info *info; int res = 0; info = get_fb_info(fbidx); //通过fbidx获取fb_info结构体,它来自registered_fb数组 if (!info) { request_module("fb%d", fbidx); info = get_fb_info(fbidx); if (!info) return -ENODEV; } //... file->private_data = info; if (info->fbops->fb_open) { //如果info->fbops->fb_open函数存在 res = info->fbops->fb_open(info,1); //就调用info->fbops->fb_open函数 if (res) module_put(info->fbops->owner); } //... } 再来看一下read函数: static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; //这里初始化了偏移量 struct fb_info *info = file_fb_info(file); //从文件中获得fb_info结构体 u8 *buffer, *dst; u8 __iomem *src; int c, cnt = 0, err = 0; unsigned long total_size; //... if (info->fbops->fb_read) //如果fbops有fb_read,就直接调用并返回 return info->fbops->fb_read(info, buf, count, ppos); total_size = info->screen_size; //..... buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); //分配buffer if (!buffer) return -ENOMEM; src = (u8 __iomem *) (info->screen_base + p); //src是基地址加上p的偏移量 if (info->fbops->fb_sync) info->fbops->fb_sync(info); while (count) { c = (count > PAGE_SIZE) ? PAGE_SIZE : count; //c是一个PAGE_SIZE或者count dst = buffer; fb_memcpy_fromfb(dst, src, c); //从src复制到dst中,dst dst += c; src += c; if (copy_to_user(buf, buffer, c)) { //把数据发送到用户buffer err = -EFAULT; break; } *ppos += c; buf += c; cnt += c; count -= c; } //..... } fb_info结构体 struct fb_info { atomic_t count; int node; //次设备号 int flags; struct mutex lock; /* Lock for open/release/ioctl funcs 用于open、release、ioctrl功能的锁 */ struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ struct fb_var_screeninfo var; /* Current var LCD可变参数 */ struct fb_fix_screeninfo fix; /* Current fix LCD固定参数 */ struct fb_monspecs monspecs; /* Current Monitor specs LCD显示器标准 */ struct work_struct queue; /* Framebuffer event queue 帧缓冲事件队列 */ struct fb_pixmap pixmap; /* Image hardware mapper 图像硬件mapper */ struct fb_pixmap sprite; /* Cursor hardware mapper 光标硬件mapper */ struct fb_cmap cmap; /* Current cmap 当前颜色表 */ struct list_head modelist; /* mode list 模式队列 */ struct fb_videomode *mode; /* current mode 当前的显示模式 */ #ifdef CONFIG_FB_BACKLIGHT /* assigned backlight device */ /* set before framebuffer registration, remove after unregister */ struct backlight_device *bl_dev; //对应背光设备 /* Backlight level curve */ struct mutex bl_curve_mutex; u8 bl_curve[FB_BACKLIGHT_LEVELS]; //背光调整 #endif #ifdef CONFIG_FB_DEFERRED_IO struct delayed_work deferred_work; struct fb_deferred_io *fbdefio; #endif struct fb_ops *fbops; //对底层硬件设备操作的函数指针 struct device *device; /* This is the parent 父设备节点 */ struct device *dev; /* This is this fb device 当前的帧缓冲设备 */ int class_flag; /* private sysfs flags */ #ifdef CONFIG_FB_TILEBLITTING struct fb_tile_ops *tileops; /* Tile Blitting 图块blitting */ #endif union { char __iomem *screen_base; /* Virtual address 虚拟地址 */ char *screen_buffer; }; unsigned long screen_size; /* Amount of ioremapped VRAM or 0 LCD IO映射的虚拟内存大小 */ void *pseudo_palette; /* Fake palette of 16 colors 伪16色 颜色表 */ #define FBINFO_STATE_RUNNING 0 #define FBINFO_STATE_SUSPENDED 1 u32 state; /* Hardware state i.e suspend LCD挂起或复位的状态 */ void *fbcon_par; /* fbcon use-only private area */ /* From here on everything is device dependent */ void *par; /* we need the PCI or similar aperture base/size not smem_start/size as smem_start may just be an object allocated inside the aperture so may not actually overlap */ struct apertures_struct { unsigned int count; struct aperture { resource_size_t base; resource_size_t size; } ranges[0]; } *apertures; bool skip_vt_switch; /* no VT switch on suspend/resume required */ }; 其中fb_var_screeninfo和fb_fix_screeninfo两个结构体跟LCD硬件属性相关 fb_var_screeninfo代表可修改的LCD显示参数,如分辨率和像素比特数。 fb_fix_screeninfo代表不可修改的LCD属性参数,如显示内存的物理地址和长度等。 另外一个重要成员是fb_ops,其是LCD底层硬件操作接口集。 如何编写Framebuffer驱动程序 分配fb_info 使用framebuffer_alloc分配fb_info 设置fb_info 设置fb_info的var、fbops、硬件相关的操作 注册fb_info 使用register_framebuffer 原作者:习惯就好zz |
|
相关推荐
1个回答
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
基于米尔瑞芯微RK3576核心板/开发板的人脸疲劳检测应用方案
1483 浏览 0 评论
1609 浏览 1 评论
1292 浏览 1 评论
2627 浏览 1 评论
3812 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-4 13:41 , Processed in 0.602491 second(s), Total 74, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号