当前位置:网站首页>Summary of weidongshan phase II course content

Summary of weidongshan phase II course content

2022-07-08 00:19:00 Seventeen 47

2 Input subsystem drive

2.1 Introduction to the concept of input subsystem

   In order to write a general driver , We need to integrate the drivers we write into Linux In the existing drive framework , because Linux The kernel is universal , Key drive belongs to Input subsystem frame . We need to find out Linux Kernel driver framework , Add the functions we need , Provide a unified standard upward Linux Interface .

( One ) How to register the driver of each specific device

The pure software code of input subsystem driver is mainly in linux-2.6.22.6\drivers\input\evdev.c in , The code in this file is Linux The kernel is extracted like a touch screen 、 Keys and other input devices have something in common , It is stable. , It does not change with specific hardware . These software mainly manage the input buffer and provide the same file_operations Interface .

About what is evdev, See link https://blog.csdn.net/wanywhn/article/details/83443843

1、evdev.c File implementation of the bottom file_operations Structural instance
stay Z:\linux-2.6.22.6\drivers\input\evdev.c The system creates a file_operations example :evdev_fops, And realize each function .

static const struct file_operations evdev_fops = {
    
	.owner =	THIS_MODULE,
	.read =		evdev_read,
	.write =	evdev_write,
	.poll =		evdev_poll,
	.open =		evdev_open,
	.release =	evdev_release,
	.unlocked_ioctl = evdev_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl =	evdev_ioctl_compat,
#endif
	.fasync =	evdev_fasync,
	.flush =	evdev_flush
};

2、 take file_operations The instance is further encapsulated
stay evdev.c in , take file_operations example :evdev_fops Further encapsulated as a input_handler Structural instance :evdev_handler

static struct input_handler evdev_handler = {
    
	.event =	evdev_event,
	.connect =	evdev_connect,
	.disconnect =	evdev_disconnect,
	.fops =		&evdev_fops,
	.minor =	EVDEV_MINOR_BASE,
	.name =		"evdev",
	.id_table =	evdev_ids,// Express evdev Devices that can be supported , be used for input_attach_handler Match with the device 
};

3、evdev The file entry function registers the implemented input_handler Structural instance :evdev_handler
Again evdev.c in ,evdev Driver entry function static int __init evdev_init(void) Will be implemented input_handler example :evdev_handler Register up .

return input_register_handler(&evdev_handler);

function input_register_handler At the core of the input subsystem , All input peripherals ( keyboard 、 Touch screen, etc. ) In the realization of concrete input_handler example ( includes file_operations example ) After that, you can register up through this function , This function is located in :Z:\linux-2.6.22.6\drivers\input\input.c, The function prototype is :

int input_register_handler(struct input_handler *handler)

4、input_register_handler Function will input_handler Instance registered to input_table In the table
input_table stay input.c In a statement , Is an ordinary pointer array , Capacity of 8.

static struct input_handler *input_table[8];

stay input_register_handler Function according to the secondary device number of the incoming instance ( Initially in evdev File defines input_handler Structural instance :evdev_handler Time passes in , In this example, it is a fixed macro value EVDEV_MINOR_BASE:64), The following statement moves the secondary device number to the left 5 position , In addition to 32, namely input_table[2] Deposit evdev Of documents input_handler Structural instance :evdev_handler.

input_table[handler->minor >> 5] = handler;

thus , The bottom specific driver is registered up , When the system insmod evdev Driving time , The system will call it automatically evdev File driver entry function :static int __init evdev_init(void), Will eventually make input_table There are points to this drive input_handler Structural instance :evdev_handler The pointer to .

5、input_register_handler Function will input_handler Put the instance into the input subsystem handler In the list
input_register_handler As the name suggests, the function is the solution to register the input subsystem up (handler), There are two types of registration , One is the will mentioned above input_handler The instance is put into the array with the secondary device number as the subscript , The second is to make evdev.c Realized input_handler Put an instance Input subsystem handler Linked list in .

list_add_tail(&handler->node, &input_handler_list);

6、input_register_handler Function traverses the input subsystem device Linked list search handler Corresponding equipment
The structure of the subsystem is similar to the bus device driver model , It also separates the drive from the equipment , Drive in input_handler Implementation in instance , Calling input_register_handler Function registration input_handler The instance needs to traverse the input subsystem device Linked list , Determine the input_handler Which devices can be handled . That is, a process of pairing .

list_for_each_entry(dev, &input_dev_list, node)
		input_attach_handler(dev, handler);

The function of the above procedure is to input_dev_list Each of them input_dev All instances execute input_attach_handler(dev, handler) function , This function will register input_handler Instance with each input_dev Case contrast , Determine whether the two match , The function prototype is :

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)

input_attach_handler Call in function input_match_device function :

id = input_match_device(handler->id_table, dev);

This function compares input_handler Example of id and input_dev Of id, So as to determine whether it matches , If the match , call input_handler Example of connect Function to establish the link between the device and the driver , Every input_handler Example of connect Functions are linked in different ways :

error = handler->connect(handler, dev, id);

problem : In practice, there are many specific input devices , Every one needs it insmod Once ? It feels unrealistic ( answer : Hot plug )

( Two ) How to register each specific device

( One ) Explained how to register a relatively stable driver , Such as evdev.c Such files are stable , Included in the kernel . The files for registering each specific device are generally created by the author . For the input subsystem, the device registration function is also input.c in , The function prototype is :

int input_register_device(struct input_dev *dev)

There are two main tasks in this function , One is to input_dev Instance join to Input subsystem device Linked list in :

list_add_tail(&dev->node, &input_dev_list);

The second is to traverse the input subsystem handler Linked list , Find out which drivers can support the registered device instance .

list_for_each_entry(handler, &input_handler_list, node)
		input_attach_handler(dev, handler);

This part of the code is basically compared with the driver registration , If the device and driver match successfully, call the same input_handler Example of connect function .
in other words , After registering the device or driver , If there is a match , Will call input_handler Example of connect function , This part will be completed before the user program uses the driver , Before the user program uses the driver connect The function has been run .

( 3、 ... and ) After two-way registration , Exactly how connect

connect The specific implementation of the function is in the files of each driver , We are here evdev.c in , The function prototype is :

static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
			 const struct input_device_id *id)

1、 Declare and assign a evdev Structural instance
stay evdev.c Of connect Function , First declare a evdev Structural instance :

struct evdev *evdev;

Structure struct evdev The statement of evdev.c in :

struct evdev {
    
	int exist;
	int open;
	int minor;
	char name[16];
	struct input_handle handle;// Focus on , Pay attention to the comparison with the previous handler Compared with no r 了 
	wait_queue_head_t wait;
	struct evdev_client *grab;
	struct list_head client_list;
};

Then in connect Specific allocation definitions in function struct evdev *evdev:

evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);

2、 Set up evdev In the structure instance evdev->handle
From above we know struct evdev Contained in the struct input_handle handle member , This structure is declared in input.h in :

struct input_handle {
    

	void *private;

	int open;
	const char *name;

	struct input_dev *dev;
	struct input_handler *handler;

	struct list_head	d_node;
	struct list_head	h_node;
};

stay connect The function assigns the registered input device and driver to struct input_handle Corresponding member of :

evdev->handle.dev = dev;
evdev->handle.handler = handler;

3、 register evdev In the structure instance evdev->handle
Also in connect Function , Register already set evdev->handle example :

error = input_register_handle(&evdev->handle);

input_register_handle The concrete realization is input.c in :

int input_register_handle(struct input_handle *handle)
{
    
	struct input_handler *handler = handle->handler;
	list_add_tail(&handle->d_node, &handle->dev->h_list);
	list_add_tail(&handle->h_node, &handler->h_list);

	if (handler->start)
		handler->start(handle);

	return 0;
}

Our registered device input_dev Now it is &handle->dev, Registered input_handler yes &handle->handler, The above function will register the device and handler Of h_list All point to input_handle example , use c The language can be summarized as :

input_handler->h_list= &input_handle;
input_dev->h_list= &input_handle;

in other words , stay connect After the function runs , We can go straight through input_handler->h_list perhaps input_dev->h_list Find the corresponding input_handle example , Again from input_handle Extract the required input_dev and input_handler.input_handle An example is equivalent to an intermediary . thus , Registration and linking have been completed .

( Four ) After driver and device registration , How does the upper layer call

1、 Of all input devices open All calls go through input Of open Function to transfer
All input subsystems open The call will eventually call input.c Medium open function , stay input.c The entry function in static int __init input_init(void) in :

err = register_chrdev(INPUT_MAJOR, "input", &input_fops);

This statement registers a master device with the number INPUT_MAJOR(13) Character device program , Be careful Only the main equipment number is registered here , It is temporarily considered that all character devices of the input subsystem share a master device number , The secondary device number is defined in each specific driver ( In this case evdev) Of input_handler Structural instance :evdev_handler in , And then through input_register_handler Register up .

input_fops For one file_operations example :

static const struct file_operations input_fops = {
    
	.owner = THIS_MODULE,
	.open = input_open_file,
};

Note that only one is registered here open Function instance input_open_file. The function is also in input.c In the definition of , Archetype :

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

use insmod take input.c After the driver registration implemented in , Call... In the application open Function time ( call open Parameters will be passed in when struct inode inode, struct file file, These two parameters contain information about primary and secondary equipment numbers ), Will be called to input_open_file function . Because each specific device driver has been in ( One )** Through the secondary device number, I registered myself to input_table in , stay input_open_file Function will be input_table[iminor(inode) >> 5] Get specific equipment input_handler example , And then through fops_get obtain input_handler In the instance file_operations example , Will be file_operations Examples are assigned to new_fops, Finally through new_fops->open(inode, file) Call to specific driver file_operations Specific in the example open function .

struct input_handler *handler = input_table[iminor(inode) >> 5];
new_fops = fops_get(handler->fops));
err = new_fops->open(inode, file);
return err;

experience : The whole process above has two points , One is in file_operations The structure is further encapsulated as input_handler Structure , At present, I guess the purpose of doing this is to achieve Linux Of Bus - equipment - Drive model ; The second is to input all the data into the subsystem open It's all done through input.c Medium open Function to transfer , I guess this reflects Linux The idea of layering in driving framework . concrete 《Linux Detailed description of device driven development 》 The third version P287.
2、open After calling , The various calls of the application will eventually call evdev.c Various calls to
open After the call, the application knows the file handle , Follow up read/write Such calls don't need to pass input.c Transfer , Directly call evdev.c in file_operations example evdev_fops Medium evdev_read and evdev_write Such as function . These functions mainly deal with some general events , Such as buffer 、 Event management . The next section will explain in detail evdev_read function .

3、 How to read the key value ,evdev_read function
Application space call read The function will call evdev_read function , The processing of this function is as simple as what we wrote before read Function similar to , It mainly reads the value in the ring buffer . If the value is successfully read, call evdev_event_to_user Send the value to the user through the event handler :

if (evdev_event_to_user(buffer + retval, event))
			return -EFAULT;

If it is not read and opened in a non blocking way , Go straight back :

if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
		return -EAGAIN;

In case of blocking mode , Go into sleep and wait for wake up

retval = wait_event_interruptible(evdev->wait,
		client->head != client->tail || !evdev->exist);

read If you pass wait_event_interruptible Fall into hibernation , By the same in evdev.c Medium evdev_event Wake up the .

4、evdev_event Who calls
evdev_event The function is evdev.c The following functions are specially used to handle events , The function prototype is :

static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)

call evdev_event The code of the function is generally handled by the driver writer , That is what we need to do , Most of the above are Linux What has been done , What we need to do is, for example, report in a key interruption “ There are buttons to press ” This incident , Then... Will be called evdev_event Function to process . To sum up , Write driver based on subsystem , What we need to do is in the file of a specific device ( For example, in the interrupt service program ), Determine what happened , Then call the corresponding. input_handler Medium event Processing function .
Linux There is one in the kernel GPIO Drive example ,linux-2.6.22.6\drivers\input\keyboard\gpio_keys.c, You can see its interrupt handling function :

static irqreturn_t gpio_keys_isr(int irq, void *dev_id)

The interrupt handler function calls input_event function :

input_event(input, type, button->code, !!state);
			input_sync(input);

The function is in input.c To realize , The function prototype is :

/** * input_event() - report new input event * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event * * This function should be used by drivers implementing various input devices * See also input_inject_event() */
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

stay input_event Function :

list_for_each_entry(handle, &dev->h_list, d_node)
			if (handle->open)
				handle->handler->event(handle, type, code, value);

list_for_each_entry Statement means to dev->h_list Every one in the linked list handle Perform the following if (handle->open) sentence , This statement indicates if handle Medium open Function has been called , Then execute the corresponding event function .

( 5、 ... and )input Subsystem summary

1、 Registration and link of devices and drivers
equipment input_dev Instances and drivers input_handler The examples pass input_register_device and input_register_handler To register ,input_register_handler The function of registration is to input_handler Instance registered to input_table In the table 、 take input_handler Put the instance into the input subsystem handler In the list ,input_register_device The function of registration is to input_dev Instances are added to the input subsystem device In the list ; Both of them will traverse the linked list to find a match while registering ; After successful matching, it will call input_handler In the instance connect function , This function will create and register a input_handle example , This structure will contain registered input_dev Instance and input_handler example , stay connect After the function runs , We can go straight through input_handler->h_list perhaps input_dev->h_list Find the corresponding input_handle example , Again from input_handle Extract the required input_dev and input_handler.input_handle An example is equivalent to an intermediary . thus , Registration and linking have been completed .

2、 Call to driver
The call to the driver can be divided into two parts , First, the user program passes open、read、write Active invocation of , The second is the passive invocation of interrupts triggered by the behavior of specific devices . For the first call , First of all, we must open, Of all input devices open All calls go through input Of open Function to transfer ,open File handle will be returned later , Follow up read、write It will directly call the corresponding file handler Function of . For the second call , It is mainly written in the interrupt function of the specific device file , The interrupt function determines what happened , And then call input_event function , This function will be used in the previous two-way registration connect Function created handle The structure finds input_handler Medium event Processing function .

Several concepts :kobject、kset、subsystem;device、device_deiver、bus_type;/sysfs、/dev

2.2 Write driver based on input subsystem

The video writes a key driver based on the input subsystem , We just need to complete the following steps :
1、 Create a device related file , such as buttons.c
2、 Write driven init Functions and exit function , Let's talk about it init function ,exit Function is the opposite operation . stay init The following steps are mainly done in the function :
(1) Allocate one input_dev Structure , That is to define a input_dev example , This example represents the actual device
(2) Set what kind of events the device can generate , And what operations can produce such events . Event classes and event operations are represented by defined macros .
(3) call input_register_device Function to register the device up
(4)ioremap, Register Related interrupt functions
3、 Pressing and releasing the key will trigger the interrupt function , Call... In the interrupt function input_event Function to report the event .
From then on, the driver we want to write is over .

problem : evdev Will handle the reported events in detail , Some information may be printed , Where to look at this information ? What kind of process will it actually run after it is written ? Go and watch the video

3 Layered separation drive

( One ) Connections and differences between subsystems and bus device driver models

1、 Two way registration and pairing
Subsystem take the input subsystem as an example , It indicates that the structure of the input device is input_dev, Indicates that the input driven structure is input_handler, Its device registration function is input_register_device, Its driver registration function is input_register_handler, These two functions will input_dev Instance and input_handler Instances are added to the input subsystem device Linked list and input subsystem handler In the list , And every time the device or driver registers and joins the corresponding linked list, it will traverse the linked list to seek pairing , Traversal functions are input_attach_handler, This function calls input_match_device To match . The processing core of the subsystem lies in its corresponding handler example , For example, input subsystem input_handler example , There is an event handler , There are corresponding open、write、read Functions, etc , These functions deal with the input buffer generally needed by input devices , These are unique to the input subsystem .

The bus device driver model also needs two-way registration and pairing , Next, the model is used to refer to the bus device driver model . The model is lower than the subsystem , Implement each subsystem on the model , The model itself does not contain the ability to handle input buffers like the input subsystem , The implementation of the model depends on the next level kobject and kset etc. . For model bus_type、device、device_diver Three structures are used to represent the bus 、 Devices and drivers . Generally, we don't need to initialize or register the bus anymore , Bus is used Linux Just bring it with you . Various devices are attached to various buses , Such as pci etc. , Virtual platform bus is generally used if there is no connection platform. Generally will device、device_diver Further encapsulated as devices and drivers corresponding to the bus , For example, the package is platform_device、platform_diver.platform_device and platform_diver Pass respectively platform_device_register and platform_driver_register To register , The function specifically calls device_register and driver_register To register .platform_diver and platform_device The registration of will platform_diver and platform_device Instance join to platform The list of drivers and devices managed by the bus , And every time the device or driver registers and joins the corresponding linked list, it will traverse the linked list to seek pairing , Traversal functions are bus_type In structure match Members of the function .

2、 Link after pairing
Subsystem take the input subsystem as an example , After the pairing is successful, it will call input_handler In the instance connect function , Specifically connect See above for operation , Be careful connect The operation is basically Linux It's written , Is constant , Below probe Functions should be written by yourself .

Bus device driver model , Model for short , After successful pairing , Automatically called platform_diver In the instance probe function . Specific in probe Function , No hard requirements , The model only provides such a mechanism , It can automatically call to probe function . such as Linux There is one in the kernel GPIO Drive example gpio_keys.c, Because the keys belong to the input subsystem , So in this file probe Function also carries out some registration work related to the input subsystem , So as to link the model with the subsystem .

problem : gpio_keys.c Medium probe How does the function link to the input subsystem ? answer : similar 2.2, See song Baohua's third edition for details 302

In fact, if we add subsystems according to the normal bus device driver model , We are 2.2 What is written in should be put in probe Function .

problem : Since we are 2.2 Subsystem can be used directly without equipment model , Why use probe Function? , Directly similar to 2.2 Not to go ?
answer : It is possible that the subsystem is not perfect , For example, which subsystem should be used for lighting ?
( Two ) Actually write a program that conforms to the bus device driver model
Two c file , One is the device file , One is the driver file .
For device files , Store hardware related code , When changing the program, only the equipment files are changed , Do not change the driver file . In the device file init Function to register the platform bus device , Indicate the resources that the device can use resource( For the description and reference of resources Linux Detailed explanation of device driven development Third Edition 295), Define when the device is released release function . The modification of equipment is often the modification of its own resources .

problem : What is the difference between the equipment here and the equipment of the input subsystem , stay 2.2 We also registered the input subsystem device .

For driver files , stay init Function to register the platform driver , The driver mainly realizes probe and remove Two functions , In addition, it is established separately files_operation example , To write open and write function , No, close function . After the platform device is paired with the platform driver, it runs first probe function , Get the resource information of the platform device in this function , then ioremap, Then, the files_operation Instance to register , Finally through mdev Automatically create device nodes ,probe The function does the same work as before without bus device driver model init Function similar to ,probe After the function runs , The driver has been registered , The address corresponding to the device has also been mapped . User program call open and write The function will automatically call the corresponding driver . Automatically call when the driver is unloaded remove function , Function and previous close Function similar to .

Because we are here led drive , It's lighting , It's not input , So there's no need to be in probe And then connect the input subsystem . If a subsystem is connected , We don't need to write the corresponding files_operation example , Subsystem handler The example has been written , We need to drive the file in probe Write something similar in the function 2.2 Section content , Register devices and resources in the device file .

4 LCD drive

4.1 LCD Driven analytic hierarchy process

Video introduction : It introduces frame buffer Basic framework of subsystem , Pay attention to and input Subsystem differentiation .
( One ) Level introduction
LCD The drive belongs to frame buffer Subsystem , The overall framework is also similar to input The subsystems are similar , First, based on the bus device driver model , Call to the corresponding probe function , stay probe Function linked to frame buffer Subsystem .

frame buffer The subsystem is Linux Kernel pair frame buffer The abstraction of the device , similar input Subsystems are abstractions of input devices ,frame buffer The main code of the subsystem is \linux-2.6.22\drivers\video\fbmem.c in .

stay fbmem.c The entry function in fbmem_init(void) in , adopt :

register_chrdev(FB_MAJOR,"fb",&fb_fops)

Register one up file_operation Structural instance fb_fops, This example is also in fbmem.c in :

tatic const struct file_operations fb_fops = {
    
	.owner =	THIS_MODULE,
	.read =		fb_read,
	.write =	fb_write,
	.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
};

In the file_operation Structural instance fb_fops Implemented in the open、read Wait for the operation , The preconditions for specific operations inside these functions all need :

	struct inode *inode = file->f_path.dentry->d_inode;
	int fbidx = iminor(inode);
	struct fb_info *info = registered_fb[fbidx];

That is, through the secondary equipment number of the corresponding equipment fbidx, The index to the registered_fb The corresponding struct fb_info structure ,struct fb_info The structure records specific frame buffer Device information , All for frame buffer The operation of the equipment depends on this structure ,struct fb_info The structure is declared in linux-2.6.22\include\linux\fb.h in , It includes frame buffer All details of the equipment , Generally, we need to pay attention to :

struct fb_info {
    
	int node;
	int flags;
	struct fb_var_screeninfo var;	/* Current var */ Variable parameters 
	struct fb_fix_screeninfo fix;	/* Current fix */  Fixed parameter 
	struct fb_ops *fbops;                             Operation function 
	struct device *device;		/* This is the parent */
	struct device *dev;		/* This is this fb device */
	char __iomem *screen_base;	/* Virtual address */
};

The fixed parameters are :

struct fb_fix_screeninfo {
    
	char id[16];			/* identification string eg "TT Builtin" */ name , Write casually 
	unsigned long smem_start;	/* Start of frame buffer mem */frame buffr, That is, video memory ( An area divided in memory ) The first address 
					/* (physical address) */ Note that these are physical addresses 
	__u32 smem_len;	/* Length of frame buffer mem */frame buffr length , This needs to see LCD manual , The resolution of the ( Number of pixels ) Multiply by the number of bits each pixel occupies 
	__u32 type;			/* see FB_TYPE_* */LCD species , Go and see FB_TYPE_ Choose a macro 
	__u32 type_aux;			/* Interleave for interleaved Planes */
	__u32 visual;			/* see FB_VISUAL_* */  Color categories , monochrome 、 Two colors 、 True color, etc 
	__u16 xpanstep;			/* zero if no hardware panning */
	__u16 ypanstep;			/* zero if no hardware panning */
	__u16 ywrapstep;		/* zero if no hardware ywrap */
	__u32 line_length;		/* length of a line in bytes */ How many pixels in a row * How many bits per pixel 
	unsigned long mmio_start;	/* Start of Memory Mapped I/O */
					/* (physical address) */
	__u32 mmio_len;			/* Length of Memory Mapped I/O */
	__u32 accel;			/* Indicate to driver which */
					/* specific chip/card we have */
	__u16 reserved[3];		/* Reserved for future compatibility */
};

Among them, the variable parameters are :

struct fb_var_screeninfo {
    
	__u32 xres;			/* visible resolution */x Directional resolution 
	__u32 yres;	                                      y Directional resolution 
	__u32 xres_virtual;		/* virtual resolution */ fictitious X Directional resolution , In fact, the screen resolution has been fixed at the factory ,
	 But my computer desktop can still adjust the resolution , The adjustment is the virtual resolution , We are different from this 
	__u32 yres_virtual;
	__u32 xoffset;			/* offset from virtual to visible */
	__u32 yoffset;			/* resolution */
	__u32 bits_per_pixel;		/* guess what */ How many bits per pixel 
	__u32 grayscale;		/* != 0 Graylevels instead of colors */
	struct fb_bitfield red;		/* bitfield in fb mem if true color, */ In the color of each pixel , Who starts red , Who ends 
	struct fb_bitfield green;	/* else only length is significant */
	struct fb_bitfield blue;
	struct fb_bitfield transp;	/* transparency */	
	__u32 nonstd;			/* != 0 Non standard pixel format */
	__u32 activate;			/* see FB_ACTIVATE_* */
	__u32 height;			/* height of picture in mm */
	__u32 width;			/* width of picture in mm */
	__u32 accel_flags;		/* (OBSOLETE) see fb_info.flags */
	/* Timing: All values in pixclocks, except pixclock (of course) */
	__u32 pixclock;			/* pixel clock in ps (pico seconds) */
	__u32 left_margin;		/* time from sync to picture */
	__u32 right_margin;		/* time from picture to sync */
	__u32 upper_margin;		/* time from sync to picture */
	__u32 lower_margin;
	__u32 hsync_len;		/* length of horizontal sync */
	__u32 vsync_len;		/* length of vertical sync */
	__u32 sync;			/* see FB_SYNC_* */
	__u32 vmode;			/* see FB_VMODE_* */
	__u32 rotate;			/* angle we rotate counter clockwise */
	__u32 reserved[5];		/* Reserved for future compatibility */
};

All need to use frame buffer Device driven device , In their respective xxxfb.c The document will pass

register_framebuffer(struct fb_info *fb_info)

Function will own frame buffer The equipment corresponds to struct fb_info The structure is registered to registered_fb[fbidx] Array ,register_framebuffer The concrete realization of is fbmem.c in .
( Two ) What we need to do
What we need to do is write our own xxxfb.c file ,Linux There are many ready-made examples in the kernel , such as \linux-2.6.22\drivers\video\s3c2410fb.c, You can see how the example is done . In this document init Function :

static struct platform_driver s3c2410fb_driver = {
    
	.probe		= s3c2410fb_probe,
	.remove		= s3c2410fb_remove,
	.suspend	= s3c2410fb_suspend,
	.resume		= s3c2410fb_resume,
	.driver		= {
    
		.name	= "s3c2410-lcd",
		.owner	= THIS_MODULE,
	},
};

int __devinit s3c2410fb_init(void)
{
    
	return platform_driver_register(&s3c2410fb_driver);
}

According to the bus device driver model , Registered a platform bus driver s3c2410fb_driver, It's realized probe Such as function .

4.2 LCD Hardware operation of driver

Video introduction : Let's talk briefly again LCD Hardware principle of , If you don't like watching the first video, you can get a general idea through this video .

4.3-1 LCD The writing of driver, the preliminary writing of code

Video introduction : Explain what we need to do , Talked about it. struct fb_info Medium fixed parameters 、 Variable parameters 、 The specific meaning of the operation function . All we have to do is write xxxfb.c file .
The main operations are init Function ( The actual standard should use the bus device model , Put it in probe Function ):
1、 Allocate one fb_info Structure
2、 Set up
2.1 According to the actual equipment , Set up fb_info Fixed parameters in the structure 、 Variable parameters
2.2 Set the operation function ( Three general functions )
2.3 Other settings
3、 Hardware related operations
3.1 Set up GPIO be used for LCD
3.2 according to LCD Manual settings LCD controller , such as VCLK And so on
3.3 Allocate video memory (framebuffer), And give me the address LCD controller
4、 The above operations enrich fb_info Structure , call register_framebuffer take fb_info The structure is registered upwards , The registration here will submit the secondary device number , When applied in the future , User space passes the secondary device number to the kernel ,Linux The kernel registers here by calling the secondary device number fb_info Structure .

4.3-2 LCD Hardware settings of driver coding

4.3 LCD Driver coding, video memory and palette settings

4.4 LCD Compile and test the driver code

17:30 Introduced the kernel comes with s3c2410fb.c The framework after applying the bus device driver model , Wei wrote this without driving model .

5 Touch screen drive

5.1 Introduction to the concept of touch screen drive

The previous brief introduction ,3min Then start writing code , Reference resources Linux Self contained s3c2410 Touch screen driver ,s3c2410_ts.c, But the code doesn't drive the model with bus devices , It's like 2.2, Write directly according to the input subsystem .

5.2 Writing driver of touch screen driver

Didn't see , The difference from the subsystem without input is that the structure is similar 2.2, Then the processing in the interrupt becomes to identify the event and report the event . Be careful One point is where to see the results of the processing after the event is reported in the input subsystem ( The test method ), We used to print the position of the touch screen directly , After the link is input into the subsystem, you can use hexdump See the output information of the event , The specific operation is 2.2,5.3 There are specific touch screen applications .

5.3 Use of touch screen driver TSLIB test

9min Before , Include 5.2, It just realizes that clicking the touch screen can output voltage information , Not yet LCD Connect .9min Then start to explain TSLIB Connect the touch screen and LCD Connect , The first phase of the touch screen part specifically talks about how to make wheels ( Five point correction ), Here is how to call TSLIB library .

原网站

版权声明
本文为[Seventeen 47]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/189/202207072220428764.html