Completely parses the mini2440 key driver of the input subsystem Device Model

Source: Internet
Author: User

I am a newbie in development. After three days and three nights of thinking, I finally made the key driver run on mini2440 in combination with the input subsystem. The following shows my results. I hope the experts will give me some advice; (The red part of the Code should be noted)
 
Driver:
# Include <Linux/input. h>
# Include <Linux/module. h>
# Include <Linux/init. h>
# Include <ASM/IRQ. h>
# Include <ASM/IO. h>
# Include <Linux/kernel. h>
# Include <Linux/fs. h>
# Include <Linux/init. h>
# Include <Linux/delay. h>
# Include <Linux/poll. h>
# Include <Linux/IRQ. h>
# Include <ASM/IRQ. h>
# Include <Linux/interrupt. h>
# Include <ASM/uaccess. h>
# Include <Mach/regs-gpio.h>
# Include <Mach/hardware. h>
# Include <Linux/platform_device.h>
# Include <Linux/cdev. h>
# Include <Linux/miscdevice. h>
# Include <Linux/device. h>
 
Static struct input_dev * button_dev;
Static irqreturn_t buttons_interrupt (int irq, void * dummy );
Static int button_open (struct input_dev * Dev );
Static void button_close (struct input_dev * Dev );
Struct button_irq_desc {// defines the structure of the key interrupt
Int IRQ; // The interrupt number.
Int pin; // key pin
Int pin_setting; // key pin settings (set to interrupt)
Int number; // key number
Char * Name; // key name
};
/* Use the struct button_irq_desc to define the information of the six buttons and organize the buttons */
Static struct button_irq_desc button_irqs [] = {
{Irq_eint8, s3c2410_gpg0, s3c2410_gp1__eint8, 1, "key1 "},
{Irq_eint11, s3c2410_gpg3, s3c2410_gpg3_eint11, 2, "key2 "},
{Irq_eint13, s3c2410_gpg5, s3c2410_gpg5_eint13, 3, "key3 "},
{Irq_eint14, s3c2410_gpg6, s3c2410_gpg6_eint14, 4, "key4 "},
{Irq_eint15, s3c2410_gpg7, s3c2410_gpg7_eint15, 5, "key5 "},
{Irq_eint19, s3c2410_gpg11, s3c2410_gpg11_eint19, 6, "key6 "},
};
/* Define the key open function, or put the content of the open function into the init function */
Static int button_open (struct input_dev * Dev)
{
Int I;
Int err = 0;

/* Set the interrupt corresponding to the six buttons to double-edge trigger, that is, both the rising edge and the falling edge will trigger the interrupt */
Set_irq_type (irq_eint8, irq_type_edge_both );
Set_irq_type (irq_eint11, irq_type_edge_both );
Set_irq_type (irq_eint13, irq_type_edge_both );
Set_irq_type (irq_eint14, irq_type_edge_both );
Set_irq_type (irq_eint15, irq_type_edge_both );
Set_irq_type (irq_eint19, irq_type_edge_both );

For (I = 0; I <sizeof (button_irqs)/sizeof (button_irqs [0]); I ++)
{
If (button_irqs [I]. IRQ <0 ){
Continue;
}
 
/* Request for interruption in sequence, and set the six interrupt types to irqf_sample_random,
Ir1__sample_random indicates that the device can be viewed as a random event occurrence source.
The other parameters of request_irq are the interrupt number, the interrupt processing function, and the device name. The last parameter is dev_id,
It must be unique when used for shared interruption. It is represented by the starting address of each struct to ensure the uniqueness of the ID.
*/
Err = request_irq (button_irqs [I]. IRQ, buttons_interrupt, irqf_sample_random,
Button_irqs [I]. Name, (void *) & button_irqs [I]);
If (ERR)
Break;
}
/* Handle an error, disable interruption and release the interrupt Number */
If (ERR ){
I --;
For (; I> = 0; I --){
If (button_irqs [I]. IRQ <0 ){
Continue;
}
Disable_irq (button_irqs [I]. IRQ );
Free_irq (button_irqs [I]. IRQ, (void *) & button_irqs [I]);
}
Return-ebusy;
}

Return 0;
}
Static void button_close (struct input_dev * Dev)
{
Int I;

/* Disable interruption and release the interruption Number */
For (I = 0; I <sizeof (button_irqs)/sizeof (button_irqs [0]); I ++ ){
If (button_irqs [I]. IRQ <0)
{
Continue;
}
Disable_irq (button_irqs [I]. IRQ );
Free_irq (button_irqs [I]. IRQ, (void *) & button_irqs [I]);
}
}

Static irqreturn_t buttons_interrupt (int irq, void * dummy)
{
/* When the interruption occurs, report the status of the six buttons. The key value is 0 when the key is pressed, because I want to display the key value as 1 when the key is pressed, therefore, the value obtained from the gpio port is reversed. Note: report all the six buttons.
The second parameter key number is associated with the third parameter key value (getting the key value from the specific gpio port), so that you can
The hardware (that is, keys) on the Development Board can be connected to the system. The input_sync function informs the system that the report has been completed */
Input_report_key (button_dev, key_esc ,! S3c2410_gpio_getpin (s3c2410_gpg0 ));
Input_report_key (button_dev, key_1 ,! S3c2410_gpio_getpin (s3c2410_gpg3 ));
Input_report_key (button_dev, key_2 ,! S3c2410_gpio_getpin (s3c2410_gpg5 ));
Input_report_key (button_dev, key_3 ,! S3c2410_gpio_getpin (s3c2410_gpg6 ));
Input_report_key (button_dev, key_4 ,! S3c2410_gpio_getpin (s3c2410_gpg7 ));
Input_report_key (button_dev, key_5 ,! S3c2410_gpio_getpin (s3c2410_gpg11 ));
Input_sync (button_dev );
Return irq_handled;
}
Static int _ init button_init (void)
{
Int error;
 
Printk ("S3C2440 my_keyboard module start/N ");
Struct input_dev * input_dev;

/* Allocate space to the input_dev struct pointer */
Input_dev = input_allocate_device ();
If (! Input_dev)
{
Printk (kern_err "unable to allocate the input device !! /N ");
Return-enomem;
}
Button_dev = input_dev;
 
/* Set the key type and supported keys, ev_key is the key type, key_esc, KEY_1-5 is the supported key, because I want my keys
Take 1-6 and query related macros from include/Linux/input. H. You can see that the supported keys are 1-6. Of course, you can also choose your preferred one.
The key value of huan. If you choose not 1-6, the key number ev_key.code obtained by the application will also change according to your settings */
Set_bit (ev_key, button_dev-> evbit );
Set_bit (key_esc, button_dev-> keybit );
Set_bit (key_1, button_dev-> keybit );
Set_bit (key_2, button_dev-> keybit );
Set_bit (key_3, button_dev-> keybit );
Set_bit (key_4, button_dev-> keybit );
Set_bit (key_5, button_dev-> keybit );
 
/* Fill in the name of the device. setting this name allows you to query the purpose of the device. The name will be saved to the name in the input/event * directory.
, Cat name will display the name you set */
Button_dev-> name = "buttons_yzx ";
/* Set the name of my input subsystem. After the module is loaded, the/sys/class/input directory will contain the name you set */
Button_dev-> Dev. init_name = "input_yzx ";
 
/* Set the callback function in the struct */
Button_dev-> open = button_open;
Button_dev-> close = button_close;
 
Printk ("input device has allocated/N ");
 
/* Register the device */
Error = input_register_device (button_dev );
If (error)
{
Printk (kern_err "button. C: failed to register device \ n ");
Input_free_device (button_dev );

Return Error;
}
 
Printk ("register device has success \ n ");
 
Return 0;
}
Static void _ exit button_exit (void)
{
/* Delete the device */
Input_unregister_device (button_dev );
}
Module_init (button_init );
Module_exit (button_exit );
Module_license ("GPL ");
Module_author ("snowboy Inc .");
 
Test procedure:
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <sys/IOCTL. h>
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <fcntl. h>
# Include <sys/select. h>
# Include <sys/time. h>
# Include <errno. h>
# Include <Linux/input. h>
Int main (void)
{
Int FD;
Int key_value, I = 0, count;
Struct input_event ev_key;
FD = open ("/dev/event1", 666); // you can specify the file name based on the device number in the/sys/class/input directory.
If (FD <0 ){
Perror ("open device buttons ");
Exit (1 );
}
For (;;){
Count = read (FD, & ev_key, sizeof (struct input_event ));
For (I = 0; I <(INT) count/sizeof (struct input_event); I ++)
If (ev_key = ev_key.type)
Printf ("type: % d, code: % d, value: % d \ n", ev_key.type, ev_key.code, ev_key.value );
If (ev_syn = ev_key.type)
Printf ("syn event \ n ");
}
Close (FD );
Return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.