Interrupt mode read key driver under Linux

Source: Internet
Author: User

Interrupt mode under Linux Read key driver//include external interrupt hibernate join poll mechanism//Use asynchronous notification method   //driver---> App receive (via Kill_fasync ()// To enable the device to support the asynchronous notification mechanism, the following 3 tasks are involved in the driver://1. Support F_setown command, can be set in this control command processing filp->f_owner for the corresponding process ID. However, this work has been done by the kernel and the device driver is not required to process. 2. Supports the processing of the F_SETFL command, and the Fasync () function in the driver is executed whenever the FASYNC flag changes. The Fasync () function should be implemented in the driver. 3. When the device resource is available, call the Kill_fasync () function to fire the corresponding signal//application://Fcntl (FD, F_setown, Getpid ()); Tell the kernel who to send to  //oflags = Fcntl (fd, F_GETFL);//Fcntl (FD, F_SETFL, Oflags | Fasync); Changing the fasync tag will eventually call to the driver's Faync > Fasync_helper: Initialize/release fasync_struct   //external Interrupt test program contains poll mechanism for asynchronous communication between processes Join atomic Operations//Atomic operations: refers to operations that are not interrupted by other code paths during execution. Semaphore implementation//blocking: Refers to suspending the process if the resource is not available while performing the device operation until the operational conditions are met. The suspended process goes into hibernation and is removed from the running queue of the scheduler until the waiting condition is met.  //non-blocking: The process does not hang when the device is not operational, it either discards or keeps querying until it can be manipulated.  //Adding timer jitter     #include <linux/module.h> #include <linux/kernel.h> #include < linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #include <linux/poll.h>  #define USINGATOMIC (0)//0 using the Semaphore 1 is atomic operation   // Device class static struct class *eint_class;//device node static struct Class_device *eint_class_devs;//address map volatile unsigned long *GPFC On;volatile unsigned long *gpfdat;volatile unsigned long *gpgcon;volatile unsigned long *gpgdat; //global variable holds interrupt read key value St atic unsigned int key_val; //creates a sleep queue static declare_wait_queue_head (BUTTON_WAITQ),  /* interrupt event flag, interrupt service program resets it to 1, Third_drv_read it clear 0 */static volatile int ev_press = 0; //semaphore initialize structure static struct fasync_struct *button_async_queue;  //timer struct struct timer_list buttons_timer; //store external interrupt number and key value structure body variable static struct Pin_desc *irq_pd; //define struct body Hold key pin port key_val key value struct pin_desc{unsigned int pin;unsigned int key_val;};    #if usingatomic//defines the atomic variable V and initializes it to 1atomic_t CANopen = Atomic_init (1); #else//Defines the amount of mutex semaphore static DECLAre_mutex (Button_lock); #endif  //defines the structure body array to hold the interrupt port and the key value struct Pin_desc pins_desc[4]={{s3c2410_gpf0,0x01},{s3c2410_ gpf2,0x02},{s3c2410_gpg3,0x03},{s3c2410_gpg11,0x04}};//Interrupt Service Program//Read key value static irqreturn_t BUTTONS_IRQ (int irq, void * ignored) {irq_pd = (struct Pin_desc *) Ignored;mod_timer (&buttons_timer, jiffies+hz/100);//10ms generate interrupt//return IRQ_ RETVAL (irq_handled); return irq_handled;} Timer interrupt function static void buttons_timer_function (unsigned long data) {struct PIN_DESC *pins_desc= irq_pd;unsigned int pinval;  if (!PINS_DESC) Return; pinval=s3c2410_gpio_getpin (Pins_desc->pin); Read the value of IO if (pinval) {key_val =0x80|pins_desc->key_val;} Else{key_val =pins_desc->key_val;} ev_press = 1; /* Indicates that the interrupt occurred */wake_up_interruptible (&AMP;BUTTON_WAITQ); /* Wake-up hibernation process */ kill_fasync (&button_async_queue, SIGIO, poll_in);//Send signal to app } //open device call//Initialize IO port Configured as input mode//GPF0--&GT;S2 gpf2-->s3 gpg3-->s4 gpg11-->s5static int eint_drv_open (struct inode *inode, struct file * File) {//*gpfcon &amP;=~ ((3<<2*0) | ( 3<<2*2));//*gpgcon &=~ ((3<<3*2) | ( 3<<11*2)); #if Usingatomicif (!atomic_dec_and_test (&canopen))//atomic operation {Atomic_inc (&canopen);// 1PRINTK ("This is a user in the of\n"); return-ebusy;//return busy} #elseif (File->f_flags & O_nonblock) {//non-blocking immediately returns if (Dow N_trylock (&button_lock)) Return-ebusy;} Else{down (&button_lock);} #endifprintk ("Eint_drv_open successed!\n"); Request_irq (IRQ_EINT0,BUTTONS_IRQ, Irqt_bothedge, "S2", &pins_desc[ 0]);//eint0 Edge trigger Mode REQUEST_IRQ (IRQ_EINT2,BUTTONS_IRQ, Irqt_bothedge, "S3", &pins_desc[1]);//eint2 Edge trigger Mode Request_ IRQ (IRQ_EINT11,BUTTONS_IRQ, Irqt_bothedge, "S4", &pins_desc[2]),//eint11 Edge trigger mode REQUEST_IRQ (irq_eint19,buttons_ IRQ, Irqt_bothedge, "S5", &pins_desc[3]);//eint19 edge triggering mode  return 0;} Write time call static ssize_t eint_drv_write (struct file *file, const char __user *buf, size_t count, loff_t * PPOs) { }// Read time call//reading key value ssize_t eint_drv_read (struct file *file, char __user *buf, size_t size, loff_t*ppos) { if (size! = 1) return-einval;if (File->f_flags & O_nonblock) {//non-blocking immediately returns if (!ev_press) Return-eagain;} else{//hibernate wait_event_interruptible (button_waitq,ev_press) If no keystrokes are pressed;} Returns Copy_to_user (BUF, &key_val, 1) If a keystroke action occurs, ev_press = 0;//break flag bit//PRINTK ("Key_val = 0x%x\n", key_val);  }  //shutdown driver call static int eint_drv_colse (struct inode *inode, struct file *file) {#if usingatomicatomic_inc (& CANopen);//self-1#elseup (&button_lock), #endif  free_irq (irq_eint0, &pins_desc[0])//eint0 release interrupt Free_irq ( Irq_eint2, &pins_desc[1]);//eint2 release Interrupt Free_irq (irq_eint11, &pins_desc[2]);//eint11 release Interrupt Free_irq (IRQ_EINT19 , &pins_desc[3]);//eint19 release Interrupt Printk ("Eint_drv_colse successed!\n");}  //poll time to call//in the specified time without pressing the key to return timeout//interrupt does not occur on return 0, in the Do_sys_poll will let the system hibernate, wake-up hibernation is chedule_timeout (__timeou) Timeout// Interrupt occurs return Pollin | Pollrdnorm, Do_sys_poll exit hibernation, wake process static unsigned int eint_drv_poll (struct file *file, poll_table *wait) {unsigned int Mask = 0;poll_wait (file, &button_WAITQ, wait); Join queue does not immediately hibernate  if (ev_press) Mask |= Pollin | Pollrdnorm;return Mask;}  //calls the static int eint_drvl_fasync (int fd, struct file *filp, int on) {PRINTK ("\ndrivec:signal_") when using fcnt () in the application Fasync successed!\n "); return Fasync_helper (FD, Filp, on, &button_async_queue);}  //tells the kernel static struct file_operations eint_drv_fops = {. Owner = This_module,//This is a macro that is automatically created when the module is pushed to compile __this_ Module variable. open = Eint_drv_open,.write = Eint_drv_write,.read = eint_drv_read,.release= Eint_drv_colse,.poll = Eint_drv_ Poll,.fasync = eint_drvl_fasync,};   int major;//Auto Assign main device number//install driver when call//register drive Create device class Create device node create virtual address Create timer task int eint_drv_init (void) { //Create a timer init_timer (&buttons_timer); buttons_timer.function = Buttons_ Timer_function;add_timer (&buttons_timer);   major=register_chrdev (0, "Key_drv", &Eint_drv_fops) ;//Tell kernel register driver  eint_class = class_create (This_module, "key_drv");//Get a Device information class if (Is_err (Eint_class)) return Ptr_err (eint_class);  eint_class_devs =Class_device_create (Eint_class, NULL, MKDEV (major, 0), NULL, "buttons"); if (unlikely (Is_err)) return Ptr_err (Eint_class_devs);  //convert virtual address Gpfcon = (volatile unsigned long *) Ioremap (0x56000050, +); Gpfdat = gpfcon+1;& Nbsp;gpgcon = (volatile unsigned long *) Ioremap (0x56000060,16); Gpgdat =gpgcon+1;printk ("Eint_drv_init successed!\n"); return 0;}  //Uninstall driver when call//uninstall drive Delete device Remove device node delete address map void Eint_drv_exit (void) {Unregister_chrdev (Major, "key_drv");// Uninstall drive Class_device_unregister (EINT_CLASS_DEVS);//Remove Device Class_destroy (eint_class);//Delete Device node Iounmap (gpgcon);// Remove address mapping Iounmap (Gpfcon);p rintk ("\neint_drv_exit successed!\n");} Module_init (Eint_drv_init); Module_exit (Eint_drv_exit); Module_license ("GPL");

Read key driver under Linux interrupt mode

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.