How to write a layered drive (complex character driver)----LCD drive as an example **************
Idea: Complex drivers are built on the basis of simple drives, so first know how the kernel simple character device driver writes
1. How to simply drive a program
1.1 Construction File_operations
. open = Drv_open
. Read = Drv_read
1.2 Tell the kernel there are 1.1 this structure, Register_chrdev (main device number, fop,name)
The above can be replaced by the following three words
assigning Cdev
Set Cdev
Cdev_add
1.3 Entry function: Call 1.2 's registration function
1.4 Exit Function: Unregister_chrdev
2. Complex device drivers: 1. Simple Driver Framework + tiering
The first layer: similar to the simple driver framework, where FBMEM.C is the example
2.1. Construction File_operations
Open/read/write
2.2.register_chrdev
2.3. Inlet/outlet
Second layer: drive layer: Hardware related (Specific drive specific): three axes
3.1. Assigning a fb_info structure: framebuffer_alloc
3.2. Settings
3.3. Registration: Register_framebuffer: Essence: Register_framebuffer: Set the value of the REGISTERED_FB array
3.4. Hardware-related operations
****************************************************************************************
Overall architecture:
Analysis FBMEM.C
static const struct File_operations Fb_fops = {//-------2.1
. Owner = This_module,
. Read = Fb_read,
. Write = Fb_write,
. IOCTL = Fb_ioctl,
. mmap = Fb_mmap,
. Open = Fb_open,
. Release = Fb_release,
};
static int __init
Fbmem_init (void)------2.3
{
Create_proc_read_entry ("FB", 0, NULL, FBMEM_READ_PROC, NULL);
if (Register_chrdev (Fb_major, "FB", &fb_fops))//----------2.2
PRINTK ("Unable to get major%d for FB devs\n", fb_major);
Fb_class = Class_create (This_module, "graphics"); Registering Device classes
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;
}
Example: Specific analysis: LCD driver//To be specific from app to kernel to drive analysis to know how the entire architecture is formed
Assume:
App:open ("/dev/fb0", ...) Main device number: 29, secondary device number: 0
--------------------------------------------------------------
Kernel
Fb_open The first layer of the General Code effect: 1. Transfer function: Judge the parameters and set the parameters, become the polymorphic function parameters of the subclass 2. Provides a common operation: if the subclass does not overwrite calls to the method, use common code to implement polymorphic
int fbidx = Iminor (inode); This is the Register_framebuffer time set, the second device number is the subscript of the array
struct Fb_info *info = = Registered_fb[0]; Get the 3.3-drive registered structure
File->private_data = info;Method 1: Re-set the file's FOP, set to the FOP provided in info
Method 2: Do not reset the file fop, according to the secondary device number to obtain the driver settings of the FOP, call the driver-provided function
if (Info->fbops->fb_open) {
res = Info->fbops->fb_open (info,1);
if (res)
Module_put (Info->fbops->owner);
}
App:read ()
---------------------------------------------------------------
Kernel
Fb_read
int fbidx = Iminor (inode);
struct Fb_info *info = Registered_fb[fbidx];With Fb_open
if (!info | |! info->screen_base)Relay function: The judgment of parameter legality
Return-enodev;
if (info->state! = fbinfo_state_running)
Return-eperm;
if (Info->fbops->fb_read)Polymorphic: Subclasses have their own implementations, then use the subclass function
return Info->fbops->fb_read (info, buf, count, PPOs);
Provides a generic method for a base class if the subclass does not overwrite the method
src = (u32 __iomem *) (info->screen_base + p);
DST = buffer;
*dst++ = Fb_readl (src++);
Copy_to_user (buf, buffer, c)
Appendix: Register_framebuffer Analysis
Int
Register_framebuffer (struct fb_info *fb_info)
{
int i;
struct Fb_event event;
struct Fb_videomode mode;
if (NUM_REGISTERED_FB = = Fb_max)
Return-enxio;
num_registered_fb++;
1. Algorithm: Find the secondary device number
for (i = 0; i < Fb_max; i++)
if (!registered_fb[i])
Break
Fb_info->node = i;
2. Set up the device node
Fb_info->dev = Device_create (Fb_class, Fb_info->device,Establish the device node with the secondary device number
MKDEV (Fb_major, i), "fb%d", I);//In the app open fb%d, there is a second device number is passed in
//Drive can take advantage of this secondary device number
if (Is_err (Fb_info->dev)) {
/* Not fatal */
PRINTK (kern_warning "Unable to create device for framebuffer%d; errno =%ld\n ", I, Ptr_err (Fb_info->dev));
Fb_info->dev = NULL;
} else
Fb_init_device (Fb_info);
return 0;
}
Be faithful to your dreams and practice
How to write a layered drive (complex character driver)----LCD Driver as an example