首页 > 代码库 > LCD驱动分析(一)字符设备驱动框架分析
LCD驱动分析(一)字符设备驱动框架分析
LCD驱动也是字符设备驱动,也遵循字符设备驱动的流程:
a. 分配主设备号
b. 构建file_operations结构体中的open,write,read...等函数
c. 调用register_chrdev()函数注册字符设备
d. 调用class_register()注册类
e. 调用device_create()创建设备,linux会在sysfs目录下自动创建字符设备。
以上的步骤同样适用于分析输入子系统,只不过上面的各个步骤可能分散在不同的文件与函数中完成。
1.linux/drivers/video/fbmem.c中的fbmem_init()函数完成a,b,c,d完成以上四步。
1 static const struct file_operations fb_fops = { 2 .owner = THIS_MODULE, 3 .read = fb_read, 4 .write = fb_write, 5 .unlocked_ioctl = fb_ioctl, 6 .mmap = fb_mmap, 7 .open = fb_open, 8 .release = fb_release, 9 .llseek = default_llseek, 10 }; 11 static int __init fbmem_init(void) 12 { 13 proc_create("fb", 0, NULL, &fb_proc_fops); 14 15 if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) 16 printk("unable to get major %d for fb devs\n", FB_MAJOR); 17 18 fb_class = class_create(THIS_MODULE, "graphics"); 19 if (IS_ERR(fb_class)) { 20 printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class)); 21 fb_class = NULL; 22 } 23 return 0; 24 }
2. 那么谁来调用device_create()创建设备?这里直接给出结论,后面再分析过程。
fbmem.c中定义的fb_info结构体的全局指针数组,fb_info结构体是LCD驱动的关键。register_framebuffer()函数中会调用device_create()函数创建设备节点。
struct fb_info *registered_fb[FB_MAX] __read_mostly; //FB_MAX=32
int register_framebuffer(struct fb_info *fb_info)
-->ret = do_register_framebuffer(fb_info);
-->找到空的registered_fb[i]
-->fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
-->设置fb_info
-->registered_fb[i] = fb_info;
3. 如何打开设备?
fb_open(struct inode *inode, struct file *file)
-->int fbidx = iminor(inode);
-->struct fb_info *info=get_fb_info(fbidx);//根据此设备号找到fb_info结构体
-->fb_info = registered_fb[fbidx];
--> file->private_data = http://www.mamicode.com/info;
--> if (info->fbops->fb_open) res = info->fbops->fb_open(info,1);//如果结构体中定义了open函数,执行新的open函数
4.如何读取设备?这里的关键是info->screen_base,设置为LCD控制器帧缓冲区的起始地址。
fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-->struct fb_info *info = file_fb_info(file);//找到打开的fb_info结构体
--> if (info->fbops->fb_read)//如果fb_info中定义的读函数,则执行新的读函数
return info->fbops->fb_read(info, buf, count, ppos);
//没有定义新的读函数则执行下面
-->src = http://www.mamicode.com/(u8 __iomem *) (info->screen_base + p);//设置源地址
-->buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);//设置目的地址
-->dst = buffer;
-->fb_memcpy_fromfb(dst, src, c);//读到用户空间
-->copy_to_user(buf, buffer, c)
LCD驱动分析(一)字符设备驱动框架分析