c结构体 linux6,linux中LCD设备驱动(6)——Fbmem.c文件

前面几篇主要关注的是LCD驱动在6410平台上的实现,这一篇来说下linux帧缓冲设备驱动的上层建筑Fbmem.c文件。

1、先上第一道菜:

1.1、那我们现在来说Fbmem.c (linux2.6.28\drivers\video)文件中的应用程序访问帧缓冲设备的接口,大家对下面这些应该都不陌生吧。:

/**

*fbmem_init - init frame buffer subsystem

*

*Initialize the frame buffer subsystem.

*

*NOTE: This function is _only_ to be called by drivers/char/mem.c.

*

*/

static int __init

fbmem_init(void)

{

proc_create("fb", 0, NULL, &fb_proc_fops);看名字就知道与proc文件系统有关,其中fb_proc_fops是个file_operations的结构体,在同一个文件中定义。

static const struct file_operations fb_proc_fops = {

.owner = THIS_MODULE,

.open= proc_fb_open,

.read= seq_read,

.llseek = seq_lseek,

.release = seq_release,

};

对应的 open函数实例proc_fb_open源码如下:

static int proc_fb_open(struct inode *inode, struct file *file)

{

return seq_open(file, &proc_fb_seq_ops);

}

同样proc_fb_seq_ops是seq_operations类型的结构体实例。如下所示:

static const struct seq_operations proc_fb_seq_ops = {

.start = fb_seq_start,

.next= fb_seq_next,

.stop= fb_seq_stop,

.show= fb_seq_show,

};

这些函数都在这个文件中被定义,现在想想fbmem.c文件已经被我们去掉很多东西了。

if (register_chrdev(FB_MAJOR,"fb",&fb_fops))这个函数就太常见了,字符设备一出现,就肯定会出现,不过以前我们有时看到的是分开的那三个函数,现在把它们和在一起了。

其中fb_fops是file_operations结构体的实例,如下所示:

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

};printk("unable to get major %d for fb devs\n", FB_MAJOR);

fb_class = class_create(THIS_MODULE, "graphics");创建一个类

if (IS_ERR(fb_class)) {

printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));

fb_class = NULL;

}

return 0;

}

module_init(fbmem_init);

static void __exit

fbmem_exit(void)  做和init函数相反的事。

{

remove_proc_entry("fb", NULL);

class_destroy(fb_class);

unregister_chrdev(FB_MAJOR, "fb");

}

module_exit(fbmem_exit);

2、在Fbmem.c (linux2.6.28\drivers\video)文件中还有很多函数是关于LOGO显示的,这个我们也不用关心,所以其实在这个文件中我们主要关心的就是struct file_operations fb_fops这个结构体中的函数。

2.1、简要分析几个struct file_operations fb_fops结构体中的函数:

先来看fb_read函数,源码如下:

static ssize_t

fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)

{

unsigned long p = *ppos;

struct inode *inode = file->f_path.dentry->d_inode;

int fbidx = iminor(inode);这个函数看下面的源码,应该知道它的作用了:

static inline unsigned iminor(const struct inode *inode)

{

return MINOR(inode->i_rdev);

}

struct fb_info *info = registered_fb[fbidx];这个全局的结构数组,我们以前说过

u32 *buffer, *dst;

u32 __iomem *src;

int c, i, cnt = 0, err = 0;

unsigned long total_size;

if (!info || ! info->screen_base)

return -ENODEV;

if (info->state != FBINFO_STATE_RUNNING)

return -EPERM;

if (info->fbops->fb_read)如果定义了fb_read函数,就调用具体的read函数,也就是我们在前面说过的

fb_ops s3cfb_ops结构体中定义的函数。

return info->fbops->fb_read(info, buf, count, ppos);

struct fb_ops s3cfb_ops = {

.owner= THIS_MODULE,

.fb_check_var = s3cfb_check_var,

.fb_set_par = s3cfb_set_par,

.fb_blank = s3cfb_blank,

.fb_pan_display= s3cfb_pan_display,

.fb_setcolreg = s3cfb_setcolreg,

.fb_fillrect = cfb_fillrect,

.fb_copyarea = cfb_copyarea,

.fb_imageblit = cfb_imageblit,

.fb_cursor = soft_cursor,

.fb_ioctl = s3cfb_ioctl,

};

total_size = info->screen_size;

if (total_size == 0)

total_size = info->fix.smem_len;

if (p >= total_size)

return 0;

if (count >= total_size)

count = total_size;

if (count + p > total_size)

count = total_size - p;

buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,

GFP_KERNEL);

if (!buffer)

return -ENOMEM;

src = (u32 __iomem *) (info->screen_base + p);

if (info->fbops->fb_sync)

info->fbops->fb_sync(info);

while (count) {

c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;

dst = buffer;

for (i = c >> 2; i--; )

*dst++ = fb_readl(src++);

if (c & 3) {

u8 *dst8 = (u8 *) dst;

u8 __iomem *src8 = (u8 __iomem *) src;

for (i = c & 3; i--;)

*dst8++ = fb_readb(src8++);

src = (u32 __iomem *) src8;

}

if (copy_to_user(buf, buffer, c)) {

err = -EFAULT;

break;

}

*ppos += c;

buf += c;

cnt += c;

count -= c;

}

kfree(buffer);

return (err) ? err : cnt;

}

2.2、fb_ioctl函数:源码如下:

static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

__acquires(&info->lock)

__releases(&info->lock)

{

struct inode *inode = file->f_path.dentry->d_inode;

int fbidx = iminor(inode);

struct fb_info *info;

long ret;

info = registered_fb[fbidx];

mutex_lock(&info->lock);

ret =do_fb_ioctl(info, cmd, arg);

此函数源码如下:

static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,

unsigned long arg)

{

struct fb_ops *fb;

struct fb_var_screeninfo var;

struct fb_fix_screeninfo fix;

struct fb_con2fbmap con2fb;

struct fb_cmap_user cmap;

struct fb_event event;

void __user *argp = (void __user *)arg;

long ret = 0;

fb = info->fbops;

if (!fb)

return -ENODEV;

switch (cmd) {

case FBIOGET_VSCREENINFO:  获得可变的屏幕参数

ret = copy_to_user(argp, &info->var,

sizeof(var)) ? -EFAULT : 0;

break;

case FBIOPUT_VSCREENINFO:设置可变的屏幕参数

if (copy_from_user(&var, argp, sizeof(var))) {

ret =  -EFAULT;

break;

}

acquire_console_sem();

info->flags |= FBINFO_MISC_USEREVENT;

ret = fb_set_var(info, &var);

info->flags &= ~FBINFO_MISC_USEREVENT;

release_console_sem();

if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))

ret = -EFAULT;

break;

case FBIOGET_FSCREENINFO:获得固定的屏幕参数设置

ret = copy_to_user(argp, &info->fix,

sizeof(fix)) ? -EFAULT : 0;

break;

case FBIOPUTCMAP:设置颜色表

if (copy_from_user(&cmap, argp, sizeof(cmap)))

ret = -EFAULT;

else

ret = fb_set_user_cmap(&cmap, info);

break;

case FBIOGETCMAP: 获得颜色表

if (copy_from_user(&cmap, argp, sizeof(cmap)))

ret = -EFAULT;

else

ret = fb_cmap_to_user(&info->cmap, &cmap);

break;

case FBIOPAN_DISPLAY:

if (copy_from_user(&var, argp, sizeof(var))) {

ret = -EFAULT;

break;

}

acquire_console_sem();

ret = fb_pan_display(info, &var);

release_console_sem();

if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))

ret = -EFAULT;

break;

case FBIO_CURSOR:

ret = -EINVAL;

break;

case FBIOGET_CON2FBMAP:

if (copy_from_user(&con2fb, argp, sizeof(con2fb)))

ret = -EFAULT;

else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)

ret = -EINVAL;

else {

con2fb.framebuffer = -1;

event.info = info;

event.data = &con2fb;

fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,

&event);

ret = copy_to_user(argp, &con2fb,

sizeof(con2fb)) ? -EFAULT : 0;

}

break;

case FBIOPUT_CON2FBMAP:

if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {

ret = -EFAULT;

break;

}

if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {

ret = -EINVAL;

break;

}

if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {

ret = -EINVAL;

break;

}

if (!registered_fb[con2fb.framebuffer])

request_module("fb%d", con2fb.framebuffer);

if (!registered_fb[con2fb.framebuffer]) {

ret = -EINVAL;

break;

}

event.info = info;

event.data = &con2fb;

ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,

&event);

break;

case FBIOBLANK:

acquire_console_sem();

info->flags |= FBINFO_MISC_USEREVENT;

ret = fb_blank(info, arg);

info->flags &= ~FBINFO_MISC_USEREVENT;

release_console_sem();

break;;

default:

if (fb->fb_ioctl == NULL)

ret = -ENOTTY;

else

ret = fb->fb_ioctl(info, cmd, arg);

}

return ret;

}

mutex_unlock(&info->lock);

return ret;

}

fb_mem.c文件分析到这里差不多也结束了,当然,我们还有很多没分析,只是分析了一小部分,但是这个文件的大致结构和作用我们应该清楚了。

在这个文件中其他重要的函数,我们都没有分析,如:fb_mmap、register_framebuffer、unregister_framebuffer函数等等,后面这两个函数,我们前面有涉及,所以,要走的路还有很长。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值