核心在fbmem.c这个文件里面,我们就从这个文件着手分析:
module_init(fbmem_init);
fbmem_init
register_chrdev(FB_MAJOR,"fb",&fb_fops)
class_create(THIS_MODULE, "graphics");
这里我们注册了字符设备驱动,创建了类,但是没有在类下创建设备,那么在哪里创建了设备呢?我们在写LCD驱动程序的时候需要调用一个函数:register_framebuffer(struct fb_info *fb_info),我们就从这个函数来寻找线索:
register_framebuffer(struct fb_info *fb_info)
do_register_framebuffer(fb_info);
//现在已经进入到fbmem.c文件里面了
for (i = 0 ; i < FB_MAX; i++)
//在数组registered_fb[]中寻找到一个空项,是fb_info的节点指向其索引
if (!registered_fb[i])
break;
fb_info->node = i;
//在类下创建了设备,次设备号就是 fb_info的节点指向的索引
device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
好了,注册了字符设备驱动,创建了类,又在类下创建了设备,那么现在就可以对设备进行操作了,我们先来看一看open函数:
app:open
.............................................
kernel:fb_open
fb_open(struct inode *inode, struct file *file)
int fbidx = iminor(inode);
//或取次设备号
info = get_fb_info(fbidx);
fb_info = registered_fb[idx];
//根据次设备号找到我们注册的fb_info
if (info->fbops->fb_open) {
//如果我们在fb_info 里面定义了 fb_open 函数,就调用fb_open函数,否则执行默认操作
res = info->fbops->fb_open(info,1);
}
我们再来看一下读函数:
read:
................................................
kernel:fb_read
fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
struct fb_info *info = file_fb_info(file);
int fbidx = iminor(inode);
//获得次设备号
struct fb_info *info = registered_fb[fbidx];
//根据次设备号找到我们注册的fb_info
if (info->fbops->fb_read)
//如果我们注册的fb_info 里面有fb_read函数,就调用它,否则执行默认操作
return info->fbops->fb_read(info, buf, count, ppos);
由此我们就看出来了,LCD驱动程序分为两层,底层是硬件相关的设置与操作函数。底层的设置以及各种操作函数被分装在一个结构体里面被注册到上层,也就是fbmem.c这个文件。在上层根据底层的设置来操作lcd!其实大部分的函数在fbmem.c里面已经实现得很好了,不需要自己去写,我们要做的就是设置底层硬件的相关参数,以便在fbmem.c中使用!