The keyboard is one of the simplest of all drivers, but it contains the basic driver framework, which is useful for further learning of other complex drivers, and the following is a step-by-step analysis of drive development. The Query method is used.
Embed Network (www.embedfans.com)--to build the most professional embedded learning garden
I. Registration and revocation of kernel modules
When loading a module, the kernel module's registration function is run first. Its functions include kernel registration devices and the initialization of variables.
static int head,tail;
int _init keypad_init (void)
{
int result;
Result=register_chrdev (Key_led_major,key_led_name,&keypad_fops);
Keypad_clear ();
Init_waitqueue_head (&queue);
Prink ("%s%s initialized./n", key_led_name,key_led_version);//cannot be used Prinf
return 0;
}
Module_init (Keypad_init)//Loading module
void _exit keypad_cleanup (void)
{
Del_timer (&timer);
Unregister_chrdev (Key_led_major,key_led_name);
Prink ("keypad driver removed/n");
}
Module_exit (keypad_cleanup);//Uninstall the module
Two. virtual file system and hardware-driven interface
static struct File_operations keypad_fops={
Open:keypad_open,
Read:keypad_read,
Poll:keypad_poll,
Fasync:keypad_fasync,
Release:keypad_release,
};
After the interface is defined, some implementations of these specific functions are implemented. Now let's go to the next step together, do not think there is no difficulty in fact. Don't be happy so early.
Embed Network (www.embedfans.com)--to build the most professional embedded learning garden
The implementation of these functions, involves a lot of technology, including the kernel timer, * waiting for the specific implementation of the queue (blocking mode), asynchronous way of the specific implementation techniques, loop queue. See
Do you feel excited about so many techniques? The following I will be in a popular way for you to explain, I hope you can understand.
Three. The device opens the Operation interface function concrete Realization (Keypad_open)
Device opening generally includes two major operations, one is to complete the initialization of equipment, the second is the device reference counter plus 1
static int Keypad_open (struct inode *inode,struct file *filp)
{
Read_xy ();
Try_module_get (This_module)//This function is added to the Linux 2.6 kernel, different from the 2.4 kernel, the function is the value of the counter plus 1
return 0;
}
static void Read_xy (void)
{
New_data ()//Get the key value function
Keypad_starttimer ()//Open kernel timer, get new keyboard changes during fixed cycle time
}
The following implements the keyboard key value get function Read_xy ()
Mainly from Key_cs (corresponding to the read address, before the specific hardware device definition, such as #define KEY_CS (* (volatile unsigned short *) (0xf820000)) here should be based on specific differences.
Embed Network (www.embedfans.com)--to build the most professional embedded learning garden
The Read key value is stored in the buf[] cache, and the write pointer to the loop buffer is the head, and the read pointer is tail, which has been defined before
Data structure definition for keyboard events/////////////////////////////////
typedef struct{
ULONG the value of the status;//key
ULONG click;//Whether there is a button pressed, 1 means there is, 0 means no
}key_event
Static key_event cur_data,buf[bufsize];//bufsize is defined for macros to define the size of the ring buffer
static void New_data (void)
{
if ((Key_cs & 0xff)!=0XFF)//reads the data from the Key_cs address, if one is 0, it means that a key is pressed (the hardware circuit is at a low level)
{
Switch (Key_cs & 0xff) {
Case ~key0 & 0xFF:
The CUR_DATA.STATUS=1;///////1 was pressed
Break
Case ~key1 & 0xFF:
The CUR_DATA.STATUS=2;//2 was pressed
Break
Other like add, understand ...
}
cur_data.click=1;
}
else if (Key_cs & 0xff==0xff) {
cur_data.click=0;
cur_data.status=0;
}
The application of the IF (head!=tail) {////////Cyclic queue buffer is started here ^_^
int last=head--;
if (last<0)////////jumps to the end of the queue before it is first, to implement the loop line
last=bufsize-1;
}
Key information is stored in the loop queue buffer
Buf[head]=cur_data;
if (++head==bufsize)
Head=0;
if (Head==tail && tail++=bufsize)
tail=0;
if (Fasync)
Kill_fasync (&fasyc,sigio,poll_in);
Wake_up_interruptible (&queue);
}
Next we introduce the implementation of several other file interface functions
Four. First introduce the Close function keypad_release (), why introduce it first. The reason is very simple, it should be relatively simple, first let everyone do the warm-up exercise, after introducing this, continue to
Will introduce a more complex function.