poll机制的作用:使阻塞型函数超时返回,避免一直阻塞。
实例:
driver.c
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 <linux/irq.h>
7 #include <asm/uaccess.h>
8 #include <asm/irq.h>
9 #include <asm/io.h>
10 #include <asm/arch/regs-gpio.h>
11 #include <asm/hardware.h>
12 #include <linux/poll.h>
13
14
15 static int major;
16
17 static struct class *myKey_class;
18 static struct class_device *myKey_class_dev;
19
20 volatile unsigned long *gpfcon;
21 volatile unsigned long *gpfdat;
22
23 volatile unsigned long *gpgcon;
24 volatile unsigned long *gpgdat;
25
26 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
27 static volatile int ev_press = 0;
28
29 //normal:1; press:0;
30 static unsigned char
keyVal = 0;
31
32 struct pin_desc {
33 unsigned int pin;
34 unsigned int key_val;
35 };
36
37 /*
38 * 按键按下键值为0x01,...; 松开键值为0x81,...
39 */
40 struct pin_desc pins_desc[3] = {
41 {S3C2410_GPF0, 0x01},
42 {S3C2410_GPF2, 0x02},
43 {S3C2410_GPG11, 0x03},
44 };
45
46
47 static int myKey_open(struct inode *inode, struct file *file);
48 static int myKey_close(struct inode *inode, struct file *file);
49 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
50 static unsigned int myKey_poll(struct file *file, struct poll_table_struct *poll_table_struct);
51
52
53 static struct file_operations myKey_fops = {
54 .open = myKey_open,
55 .read = myKey_read,
56 .owner = THIS_MODULE,
57 .release = myKey_close,
58 .poll = myKey_poll,
59 };
60
61
62 static irqreturn_t handle_buttons(int irq, void *dev)
63 {
64 unsigned int kval;
65 struct pin_desc *pinDesc = dev;
66
67 kval = s3c2410_gpio_getpin(pinDesc->pin);
68 if (kval) //松开
69 {
70 keyVal = 0x80 | pinDesc->key_val;
71 }
72 else { //按下
73 keyVal = pinDesc->key_val;
74 }
75
76 //唤醒休眠进程
77 ev_press = 1; //中断发生标志
78 wake_up_interruptible(&button_waitq);
79
80 return IRQ_RETVAL(IRQ_HANDLED);
81 }
82
83
84 static int myKey_open(struct inode *inode, struct file *file)
85 {
86 request_irq(IRQ_EINT0, handle_buttons, IRQT_BOTHEDGE, "S2", &pins_desc[0]);
87 request_irq(IRQ_EINT2, handle_buttons, IRQT_BOTHEDGE, "S3", &pins_desc[1]);
88 request_irq(IRQ_EINT19, handle_buttons, IRQT_BOTHEDGE, "S5", &pins_desc[2]);
89
90 return 0;
91 }
92
93
94 static int myKey_close(struct inode *inode, struct file *file)
95 {
96 free_irq(IRQ_EINT0, &pins_desc[0]);
97 free_irq(IRQ_EINT2, &pins_desc[1]);
98 free_irq(IRQ_EINT19, &pins_desc[2]);
99
100 return 0;
101 }
102
103
104 static unsigned int myKey_poll(struct file *file, struct poll_table_struct *wait)
105 {
106 unsigned int mask = 0;
107
108 poll_wait(file, &button_waitq, wait); //不会立即休眠
109
110 if (ev_press)
111 {
112 mask |= POLLIN | POLLRDNORM;
113 }
114
115 return mask;
116 }
117
118
119 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
120 {
121 //无中断进入休眠
122 wait_event_interruptible(button_waitq, ev_press);
123
124 ev_press = 0; //清除中断发生标志
125 copy_to_user(buf, &keyVal, 1);
126 return 0;
127 }
128
129 static int __init myKey_init(void)
130 {
131 /* 物理地址映射成虚拟地址 */
132 gpfcon = (volatile unsigned long*)ioremap(0x56000050, 16);
133 gpfdat = gpfcon + 1;
134
135 gpgcon = (volatile unsigned long*)ioremap(0x56000060, 16);
136 gpgdat = gpgcon + 1;
137
138 major = register_chrdev(0, "myKey", &myKey_fops);
139
140 myKey_class = class_create(THIS_MODULE, "myKeyclass");
141 myKey_class_dev = class_device_create(myKey_class, NULL, MKDEV(major, 0), NULL, "myKey");
142
143 return 0;
144 }
145
146 static void __exit myKey_exit(void)
147 {
148 /* 释放虚拟地址映射 */
149 iounmap(0x56000050);
150 iounmap(0x56000060);
151
152 unregister_chrdev(major, "myKey");
153
154 class_device_unregister(myKey_class_dev);
155 class_destroy(myKey_class);
156 return;
157 }
158
159 module_init(myKey_init);
160 module_exit(myKey_exit);
app.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <poll.h>
6
7 int main (void)
8 {
9 int fd;
10 unsigned char keyVal;
11 int ret;
12 struct pollfd fds[1];
13
14 printf("test app!\n");
15
16 fd = open("/dev/myKey", O_RDWR);
17 if(fd < 0)
18 {
19 printf("open failed! %d\n", fd);
20 return -1;
21 }
22
23 fds[0].fd = fd;
24 fds[0].events = POLLIN;
25
26 while(1)
27 {
28 ret = poll(fds, 1, 5000);
29 if (!ret)
30 {
31 printf("time out(5s)\n");
32 }
33 else {
34 read(fd, &keyVal, 1);
35 printf("keyVal: 0x%x\n", keyVal);
36 }
37 }
38 return 0;
39 }
Makefile
1 KERN_DIR =
/work/system/linux-2.6.22.6
2
3 all:
4 make -C $(KERN_DIR) M=`pwd` modules
5
6 clean:
7 make -C $(KERN_DIR) M=`pwd` modules clean
8 rm -rf modules.order
9
10 obj-m += myKey_pollmcn.o