目标:上一个例子运行后,如果没有按键按下,应用程序会在read处一直等待,所以这次在上个例子的基础上添加返回功能,即若没有按键按下,在一定时间后会返回。
环境:TQ2440+Ubuntu12.04,linux-2.6.25
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/init.h>
- #include <linux/device.h>
- #include <linux/miscdevice.h>
- #include <linux/delay.h>
- #include <linux/mm.h>
- #include <linux/types.h>
- #include <linux/cdev.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/poll.h>
- #include <asm/irq.h>
- #include <asm/arch/regs-gpio.h>
- #include <asm/arch/map.h>
- #include <asm/arch/regs-irq.h>
- #include <asm/io.h>
- #include <asm/hardware.h>
- #include <asm/uaccess.h>
- #include <asm/system.h>
- #include <asm/hardware.h>
- static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
- static volatile int ev_press = 0;
- static int major = 0;
- static struct cdev cdev;
- static struct class *cls;
- static struct class_device *cls_dev;
- struct pin_dec
- {
- unsigned int irq;
- unsigned int pin;
- unsigned int pin_setting;
- unsigned int key_val;
- char *name;
- };
- static unsigned int btn;
- struct pin_dec pins_dec[4] =
- {
- {IRQ_EINT0, S3C2410_GPF0, S3C2410_GPF0_EINT0, 0, "S4"},
- {IRQ_EINT1, S3C2410_GPF1, S3C2410_GPF1_EINT1, 1, "S1"},
- {IRQ_EINT2, S3C2410_GPF2, S3C2410_GPF2_EINT2, 2, "S3"},
- {IRQ_EINT4, S3C2410_GPF4, S3C2410_GPF4_EINT4, 3, "S2"},
- };
- static irqreturn_t btn_val_irq(int irq, void *dev_id)
- {
- struct pin_dec *pin = (struct pin_dec *)dev_id;
- int res;
- res = s3c2410_gpio_getpin(pin->pin);
- if (!res)
- {
- btn = pin->key_val | 0x80;
- }
- else
- {
- btn = pin->key_val;
- }
- ev_press = 1;
- wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */
-
- return IRQ_RETVAL(IRQ_HANDLED);
- }
- static int btn_val_open(struct inode *inode, struct file *file)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- s3c2410_gpio_cfgpin(pins_dec[i].pin, pins_dec[i].pin_setting);
- request_irq(pins_dec[i].irq, btn_val_irq, IRQT_BOTHEDGE, pins_dec[i].name, &pins_dec[i]);
- }
-
- return 0;
- }
- ssize_t btn_val_read(struct file *file, char __user * buf,
- size_t len, loff_t * ppos)
- {
- wait_event_interruptible(button_waitq, ev_press);
- /* 如果有按键动作, 返回键值 */
- copy_to_user(buf, &btn, 1);
- ev_press = 0;
-
- return 1;
- return 0;
- }
- static int btn_val_release(struct inode *inode, struct file *file)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- free_irq(pins_dec[i].irq, &pins_dec[i]);
- }
- return 0;
- }
- static unsigned int btn_val_poll(struct file *fp, poll_table * wait)
- {
- unsigned int mask = 0;
- poll_wait(fp, &button_waitq, wait);
- if (ev_press)
- mask |= POLLIN | POLLRDNORM;
- return mask;
- }
- const struct file_operations fops =
- {
- .owner = THIS_MODULE,
- .open = btn_val_open,
- .read = btn_val_read,
- .poll = btn_val_poll,
- .release = btn_val_release,
- };
- static int btn_val_init()
- {
- dev_t devid;
- int rec;
-
- if (major)
- {
- devid = MKDEV(major, 0);
- rec = register_chrdev_region(devid, 1, "button2");
- }
- else
- {
- rec = alloc_chrdev_region(&devid, 0, 1, "button2");
- major = MAJOR(devid);
- }
- if (rec < 0)
- {
- printk(KERN_ERR, "can't get major");
- return -ENODEV;
- }
- cdev_init(&cdev, &fops);
- cdev_add(&cdev, devid, 1);
- cls = class_create(THIS_MODULE, "button2");
- cls_dev = class_device_create(cls, NULL, MKDEV(major, 0), NULL, "button2");
-
- return 0;
- }
- static void btn_val_exit()
- {
- class_device_destroy(cls, MKDEV(major, 0));
- class_destroy(cls);
- cdev_del(&cdev);
- unregister_chrdev_region(MKDEV(major, 0), 1);
- }
- module_init(btn_val_init);
- module_exit(btn_val_exit);
- MODULE_AUTHOR("xiaoming");
- MODULE_DESCRIPTION("interrupt button value");
- MODULE_LICENSE("GPL");
运行结果:
测试小例子:
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <poll.h>
- int main(int argc, char **argv)
- {
- int fd;
- unsigned char key_val;
- int ret;
- struct pollfd fds[1];
-
- fd = open("/dev/button2", O_RDWR);
- if (fd < 0)
- {
- printf("can't open /dev/button2 !\n");
- }
- fds[0].fd = fd;
- fds[0].events = POLLIN;
- while (1)
- {
- ret = poll(fds, 1, 5000);
- if (ret == 0)
- {
- printf("time out!\n");
- }
- else
- {
- read(fd, &key_val, 1);
- printf("key_val=0x%x\n", key_val);
- }
- }
-
- return 0;
- }
运行结果:
当没有按键按下时,每隔5秒就会打印一次time out!当有按键按下时会立刻打印键值
阅读(1128) | 评论(0) | 转发(0) |