Linux Key Interrupt Driver example

Source: Internet
Author: User
Tags volatile

#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h > #include <linux/delay.h> #include <asm/irq.h> #include <linux/interrupt.h> #include <asm/ uaccess.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #define Key_device_count1#define Key_device_name"Key"/*key character device structure body */struct Key_dev{struct CDEVCdev;unsigned char*sth_of_key;Reserved};struct Key_dev*key_device;/* Automatically create Device node class */struct class *key_dev_class = null;struct Class_device *key_dev_class_dev = NULL;/* Used to specify the external interrupt pin used by the key and the interrupt trigger mode, name */struct key_irq_desc {intIrq unsigned longFlags Char*name;}; static struct Key_irq_desc Key_irqs [] = {{irq_eint19, irqf_trigger_falling, ' KEY1 '},/* K1 */{irq_eint11, irqf_tr Igger_falling, "KEY2"},/* K2 */{irq_eint2, irqf_trigger_falling, "KEY3"},/* K3 */{irq_eint0, Irqf_trigger_fall ING, "KEY4"},/* K4 */};/* the number of times the button was pressed (to be precise, the number of interrupts) */static volatile int press_cnt [] = {0, 0, 0, 0};/* wait queue: When no keystrokes are pressed , if there is a process called key_dev_read function, it will hibernate */static Declare_wait_queue_head (KEY_WAITQ);/* Interrupt event Flag, interrupt service program will set it to clear 0 */ static volatile int ev_press = 0;static irqreturn_t keys_interrupt (int irq, void *dev_id) {volatile int *press_cnt = (v        olatile int *) dev_id; *press_cnt = *press_cnt + 1;/* Key count plus 1 */ev_press = 1;/* Indicates that the interrupt has occurred */wake_up_interruptible (&AMP;KEY_WAITQ);/* Wake up hibernation process */        return irq_retval (irq_handled);} /*  application to device file/dev/keys Execute open (...) , the Key_dev_open function is called */static int key_dev_open (struct inode *inode, struct file *file) {    int i;    in  T err;        for (i = 0; i < sizeof (KEY_IRQS)/sizeof (Key_irqs[0]); i++) {       //Register interrupt handling function         err = REQUEST_IRQ (KEY_IRQS[I].IRQ, Keys_interrupt, Key_irqs[i].flags, key_i Rqs[i].name, (void *) &press_cnt[i]);        if (err)             Brea k;   }    if (err) {       //release a registered interrupt         i--;  &N Bsp     for (; I >= 0; i--)             FREE_IRQ (KEY_IRQS[I].IRQ, (void *) &press _cnt[i]);        return-ebusy;   }    return 0;} /*  application to device file/dev/keys Execute close (...) The Key_dev_close letter is called when theNumber */static int key_dev_close (struct inode *inode, struct file *file) {    int i;        F  or (i = 0; i < sizeof (KEY_IRQS)/sizeof (Key_irqs[0]) i++) {       //release registered interrupts         FREE_IRQ (KEY_IRQS[I].IRQ, (void *) &press_cnt[i]);   }    return 0;} /*  application to device file/dev/keys Execute read (...) , the Key_dev_read function is called */static int key_dev_read (struct file *filp, char __user *buff, size_t count, loff_t *OFFP) {  &NB Sp unsigned long err;       /* If ev_press equals 0, Hibernate */    wait_event_interruptible (key_ WAITQ, ev_press);   /* When executed here, ev_press equals 1, it is cleared 0 */    ev_press = 0;   /* The key state is copied to the user */&nbsp ;   Err = Copy_to_user (buff, (const void *) press_cnt, min (sizeof (PRESS_CNT), count));   //memset ((void *) PR ess_cnt, 0, sizeof (press_cnt));    return err? -efault:0;} /*  This structure is the core of the character device driver, and when the application operates the device file, the function called open, read, write, and so on, the mostThe corresponding function in this structure will be called */static struct file_operations key_dev_fops = {   . Owner   =   This_module,   &NB  sp;/* This is a macro that points to the __this_module variable that is automatically created when the module is compiled */   . Open    =   key_dev_open,   . Release =   key_dev_close,    . Read    =   key_dev_read,};/* perform "Insmod Key_int_driver.ko"  This function is called when the command is */dev_t key_devno = 0;int Key_major = 0;int Key_minor = 0;static int __init initialization_key_dev (void) {   /* Register character device driver      * parameter master device number, device name, file_operations structure;     * So, the main device number is the specific file_ The operations structure is linked,     * when the device file that operates the master device is key_major, the related member functions in Key_dev_fops are called      * Key_ Major can be set to 0, which means the kernel automatically assigns the main device number      */int ret = 0;/* Apply for device number */PRINTK ("before register Major =%d\n", key_major);if (key_major) {Key_devno = MKDEV (Key_major, Key_minor);ret = Register_chrdev_region (Key_devno, Key_device_count, key_device_name);} else {ret = Alloc_chrdev_region (&key_devno, Key_minor, Key_device_count, key_device_name);Key_major = Major (Key_devno);Key_minor = minor (Key_devno);}if (Ret < 0){PRINTK ("Can ' t get key Major:%d.\n", key_major);return ret;} PRINTK ("after register Major =%d\n", key_major);/* Apply for device structure in vivo */Key_device = kmalloc (sizeof (struct key_dev), gfp_kernel);if (NULL = = Key_device) {PRINTK ("Kmalloc failed.\n");Unregister_chrdev_region (Key_devno, Key_device_count);Return-enomem;}/* Character Device registration */Cdev_init (&key_device->cdev, &key_dev_fops);Key_device->cdev.owner = This_module;Key_device->cdev.ops = &key_dev_fops;ret = Cdev_add (&key_device->cdev, Key_devno, Key_device_count);if (Ret < 0){PRINTK ("Cdev add failed.\n");Kfree (Key_device);Unregister_chrdev_region (Key_devno, Key_device_count);return ret;}/* Automatically generate device node */Key_dev_class = Class_create (This_module, "key_drv");Class Name: Key_drvKey_dev_class_dev = Class_device_create (Key_dev_class, Key_devno, NULL, key_device_name);/* Module initialization successful must return 0 */PRINTK (key_device_name "initialized ok.\n"); return 0;} /* This function is called when the "rmmod Key_int_driver.ko" command is executed */static void __exit Cleanup_key_dev (void) {/* Unload driver */Cdev_del (&key_device->cdev);Kfree (Key_device);Unregister_chrdev_region (Key_devno, Key_device_count);Class_device_unregister (Key_dev_class_dev);Class_destroy (Key_dev_class);PRINTK ("Module unregister ok.\n");} /* These two lines specify the driver initialization function and unload function */module_init (Initialization_key_dev); Module_exit (Cleanup_key_dev);/*insmod Pass: Insmod key_ Int_driver.ko Key_major=key Key_minor=0*/module_param (key_major, int, s_irugo); Module_param (Key_minor, int, S_IRUGO) */* Some information describing the driver is not required */module_author ("Lhbo");Driver author Module_description ("Key INT Driver");  //Some descriptive information module_license ("GPL");                  //Follow the Protocol/********************** application test program ******************** /#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h>int main ( int argc, char **argv) {    int i;    int ret;    int fd;    INT press_cnt[4];&nbsp ;       FD = open ("/dev/key", 0);  //Open Device     if (FD < 0) {        printf ("Can ' t open/dev/key\n");    &NBSP ;   return-1;   }   //This is an infinite loop, the process may hibernate in the Read function, and it returns     while (1) {  &nbs When a key is pressed. P    //read-out button pressed times         ret = read (FD, press_cnt, sizeof (PRESS_CNT));      & nbsp  if (Ret < 0) {            printf ("Read err!\n");            Continue;       }         for (i = 0; i < sizeof (press_cnt)/sizeof (press_cnt [0]); i++) {                printf ("k%d has been pressed%d times!\n", i+1, Press_cnt[i] );       }   }    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.