key.c

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/miscdevice.h>
  4 #include <linux/fs.h>
  5 #include <linux/interrupt.h>
  6 #include <linux/io.h>
  7 #include <linux/wait.h>
  8 #include <linux/uaccess.h>
  9 
 10 #define GPNCON  0x7F008830
 11 
 12 struct my_key_struct {
 13     int irq;
 14     int id;
 15     char name[16];
 16 };
 17 
 18 struct my_key_struct my_key_config[6] = {
 19     {S3C_EINT(0), 0, "key0"},
 20     {S3C_EINT(1), 1, "key1"},
 21     {S3C_EINT(2), 2, "key2"},
 22     {S3C_EINT(3), 3, "key3"},
 23     {S3C_EINT(4), 4, "key4"},
 24     {S3C_EINT(5), 5, "key5"},
 25 };
 26 
 27 static int __g_key_value;
 28 
 29 int volatile condition = 0;
 30 DECLARE_WAIT_QUEUE_HEAD(key_wqh);
 31 
 32 irqreturn_t key_irqhandler (int irq, void *p_arg)
 33 {
 34     //printk("eint %d\n", *((int *)p_arg));
 35     
 36     __g_key_value = *((int *)p_arg);
 37 
 38     condition = 1;
 39     wake_up_interruptible(&key_wqh);
 40 
 41     return 0;
 42 }
 43 
 44 static int key_open (struct inode *p_inode, struct file *p_file)
 45 {
 46     int ret, i;
 47     int *p_gpncon;
 48     int temp;
 49     
 50     p_gpncon = ioremap(GPNCON, 4);
 51     temp = readl(p_gpncon);
 52     temp &= ~(0xFFF);
 53     temp |= 0xAAA;
 54     writel(temp, p_gpncon);
 55      
 56     for (i = 0; i < 6; i++) {
 57         ret = request_irq(my_key_config[i].irq, 
 58                           key_irqhandler, 
 59                           IRQF_TRIGGER_FALLING, 
 60                           my_key_config[i].name, 
 61                           (void*)&my_key_config[i].id);
 62 
 63         if (ret != 0) {
 64 
 65             i--;
 66             while (i >= 0) {
 67                 free_irq(my_key_config[i].irq, (void*)&my_key_config[i].id);
 68             }
 69             return -1;
 70         }
 71     }
 72     return 0;
 73 }
 74 
 75 static int key_close (struct inode *p_inode, struct file *p_file)
 76 {
 77      int i;
 78 
 79     for (i = 0; i < 6; i++) {
 80         free_irq(my_key_config[i].irq, (void*)&my_key_config[i].id);
 81     }  
 82 
 83     return 0;
 84 }
 85 
 86 static ssize_t key_read (struct file *p_file, char __user *p_dat, size_t size, loff_t *p_loff)
 87 {
 88     
 89     wait_event_interruptible(key_wqh, condition);
 90     condition = 0;
 91 
 92     copy_to_user(p_dat, &__g_key_value, 4);
 93 
 94     //printk("**************\n");
 95 
 96     return 4;
 97 }
 98 
 99 
100 static struct file_operations fops = {
101     .owner = THIS_MODULE,
102     .open = key_open,
103     .release = key_close,
104     .read = key_read,
105 };
106 
107 static struct miscdevice key_dev = {
108     .minor = MISC_DYNAMIC_MINOR,
109     .name = "mykey",
110     .fops = &fops,
111 };
112 
113 static int __init key_init (void)
114 {
115     misc_register(&key_dev);
116 
117     return 0;
118 }
119 
120 static void __exit key_exit (void)
121 {
122     misc_deregister(&key_dev);
123 }
124 
125 module_init(key_init);
126 module_exit(key_exit);
127 
128 MODULE_LICENSE("GPL");

key_app.c

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 
 6 int main(int argc, const char *argv[])
 7 {
 8     int fd;
 9     int key_val;
10 
11     fd = open("/dev/mykey", O_RDWR);
12 
13     while (1) {
14         if (4 == read(fd, &key_val, 4)) {
15             printf("key_val = %d\n", key_val);
16         } else {
17             printf("fail to read\n");
18         }
19     }
20 
21     return 0;
22 }

这样调用read的时候回阻塞,直到中断发生