韦东山驱动视频笔记——3.字符设备驱动程序之poll机制

linux内核版本:linux-2.6.30.4 

目的:我们在中断方式的按键应用程序中,如果没有按键按下,read就会永远在那等待,所以如果在这个程序里还想做其他事就不可能了。因此我们这次改进它,让它在等待5秒钟,如果5秒钟内没有按键按下就返回,可以在read后面做其他事,只需要在驱动程序里加入poll机制就可以完成目的。

  1 #include <linux/module.h>  
  2 #include <linux/kernel.h>  
  3 #include <linux/fs.h>  
  4 #include <linux/init.h>  
  5 #include <linux/delay.h>  
  6 #include <asm/uaccess.h>  
  7 #include <asm/irq.h>  
  8 #include <asm/io.h>  
  9 #include <linux/device.h>  
 10 #include <linux/irq.h>  
 11 #include <linux/interrupt.h>  
 12 #include <mach/regs-gpio.h>  
 13 #include <linux/poll.h>  
 14   
 15 static struct class *fourth_drv_class;  
 16 static struct class_device  *fourth_drv_class_dev;  
 17   
 18 static volatile unsigned long *gpfcon;  
 19 static volatile unsigned long *gpfdat;  
 20 static int major;  
 21   
 22 struct pin_desc   
 23 {  
 24     unsigned int pin;  
 25     unsigned int key_val;  
 26 };  
 27   
 28 static unsigned char key_val;  
 29   
 30 static struct pin_desc pins_desc[4] =   
 31 {  
 32     {S3C2410_GPF1, 0x01},  
 33     {S3C2410_GPF4, 0x02},  
 34     {S3C2410_GPF2, 0x03},  
 35     {S3C2410_GPF0, 0x04},  
 36 };  
 37   
 38 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
 39 static volatile int ev_press = 0;  
 40   
 41 static irqreturn_t buttons_irq(int irq, void *dev_id)  
 42 {  
 43     struct pin_desc *pin = (struct pin_desc *)dev_id;  
 44     unsigned int pinval;  
 45     pinval = s3c2410_gpio_getpin(pin->pin);  
 46   
 47     if (pinval)  
 48     {  
 49         //松开  
 50         key_val = 0x80 | pin->key_val;  
 51     }  
 52     else  
 53     {  
 54         //按下  
 55         key_val = pin->key_val;  
 56     }  
 57   
 58     wake_up_interruptible(&button_waitq);  
 59     ev_press = 1;  
 60       
 61     return IRQ_HANDLED;  
 62 }  
 63   
 64   
 65 static int fourth_drv_open(struct inode *inode, struct file *file)  
 66 {  
 67     request_irq(IRQ_EINT1, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S1", &pins_desc[0]);  
 68     request_irq(IRQ_EINT4, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S2", &pins_desc[1]);  
 69     request_irq(IRQ_EINT2, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S3", &pins_desc[2]);  
 70     request_irq(IRQ_EINT0, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S4", &pins_desc[3]);  
 71     return 0;  
 72 }  
 73   
 74   
 75 static ssize_t fourth_drv_read(struct file *file, char __user *buf,  
 76             size_t count, loff_t *ppos)  
 77 {  
 78     if (count != 1)  
 79         return -EINVAL;  
 80     /*如果没有按键动作,休眠*/  
 81     wait_event_interruptible(button_waitq, ev_press);  
 82       
 83   
 84     /*如果有按键动作发生,返回键值*/  
 85     copy_to_user(buf, &key_val, 1);  
 86     ev_press = 0;  
 87     return 1;  
 88 }  
 89   
 90 static int fourth_drv_release(struct inode *inode, struct file *file)  
 91 {  
 92     free_irq(IRQ_EINT1, &pins_desc[0]);  
 93     free_irq(IRQ_EINT4, &pins_desc[1]);  
 94     free_irq(IRQ_EINT2, &pins_desc[2]);  
 95     free_irq(IRQ_EINT0, &pins_desc[3]);  
 96     return 0;  
 97 }  
 98   
 99 static unsigned int fourth_drv_poll(struct file *file, poll_table *wait)  
100   
101 {  
102     unsigned int mask = 0;  
103   
104     /*这并不会休眠,只是把当前进程挂到队列里*/  
105     poll_wait(file, &button_waitq, wait);  
106   
107     if (ev_press)  
108     {  
109         mask |= (POLLIN | POLLRDNORM);  
110     }  
111     return mask;  
112 }  
113   
114   
115 static struct file_operations fourth_fops = {  
116     .owner = THIS_MODULE,  
117     .open = fourth_drv_open,  
118     .read = fourth_drv_read,  
119     .poll = fourth_drv_poll,  
120     .release  = fourth_drv_release,  
121 };  
122   
123 int fourth_init()  
124 {  
125     int ret;  
126     major = register_chrdev(0, "fourth_drv", &fourth_fops);  
127     fourth_drv_class = class_create(THIS_MODULE, "fourth_drv");  
128     device_create(fourth_drv_class, NULL, MKDEV(major, 0), NULL, "buttons");  
129   
130     gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);  
131     gpfdat = gpfcon + 1;  
132       
133     return 0;  
134 }  
135 static void fourth_exit()  
136 {  
137     unregister_chrdev(major, "fourth_drv");  
138     device_destroy(fourth_drv_class, MKDEV(major, 0));  
139     class_destroy(fourth_drv_class);  
140     iounmap(gpfcon);  
141 }  
142   
143 module_init(fourth_init);  
144 module_exit(fourth_exit);  
145   
146 MODULE_LICENSE("GPL");  

测试程序:

 1 #include <sys/types.h>  
 2 #include <sys/stat.h>  
 3 #include <fcntl.h>  
 4 #include <stdio.h>  
 5 #include <poll.h>  
 6   
 7 /* fourthdrvtest  
 8   */  
 9 int main(int argc, char **argv)  
10 {  
11     int fd;  
12     unsigned char key_val;  
13     int ret;  
14     struct pollfd fds[1];  
15       
16       
17     fd = open("/dev/buttons", O_RDWR);  
18     if (fd < 0)  
19     {  
20         printf("can't open!\n");  
21     }  
22   
23     fds[0].fd = fd;  
24     fds[0].events = POLLIN;  
25     while (1)  
26     {  
27         ret = poll(fds, 1, 5000);  
28         if (ret == 0)  
29         {  
30             printf("time out!\n");  
31         }  
32         else  
33         {  
34             read(fd, &key_val, 1);  
35             printf("key_val === 0x%x\n", key_val);  
36         }  
37     }  
38       
39     return 0;  
40 }  

运行效果:

 

posted @ 2013-08-08 11:19  linux_rookie  阅读(735)  评论(0编辑  收藏  举报