Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43518
  • 博文数量: 4
  • 博客积分: 185
  • 博客等级: 入伍新兵
  • 技术积分: 231
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-31 16:56
文章分类
文章存档

2012年(4)

我的朋友

分类: LINUX

2012-11-30 09:13:31

目标:上一个例子运行后,如果没有按键按下,应用程序会在read处一直等待,所以这次在上个例子的基础上添加返回功能,即若没有按键按下,在一定时间后会返回。

环境:TQ2440+Ubuntu12.04linux-2.6.25


 

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <linux/init.h>
  5. #include <linux/device.h>
  6. #include <linux/miscdevice.h>
  7. #include <linux/delay.h>
  8. #include <linux/mm.h>
  9. #include <linux/types.h>
  10. #include <linux/cdev.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/irq.h>
  13. #include <linux/poll.h>

  14. #include <asm/irq.h>
  15. #include <asm/arch/regs-gpio.h>
  16. #include <asm/arch/map.h>
  17. #include <asm/arch/regs-irq.h>
  18. #include <asm/io.h>
  19. #include <asm/hardware.h>
  20. #include <asm/uaccess.h>
  21. #include <asm/system.h>
  22. #include <asm/hardware.h>



  23. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);


  24. static volatile int ev_press = 0;

  25. static int major = 0;
  26. static struct cdev cdev;
  27. static struct class *cls;
  28. static struct class_device *cls_dev;

  29. struct pin_dec
  30. {
  31.     unsigned int irq;
  32.     unsigned int pin;
  33.     unsigned int pin_setting;
  34.     unsigned int key_val;
  35.     char *name;
  36. };

  37. static unsigned int btn;

  38. struct pin_dec pins_dec[4] =
  39. {
  40.     {IRQ_EINT0, S3C2410_GPF0, S3C2410_GPF0_EINT0, 0, "S4"},
  41.     {IRQ_EINT1, S3C2410_GPF1, S3C2410_GPF1_EINT1, 1, "S1"},
  42.     {IRQ_EINT2, S3C2410_GPF2, S3C2410_GPF2_EINT2, 2, "S3"},
  43.     {IRQ_EINT4, S3C2410_GPF4, S3C2410_GPF4_EINT4, 3, "S2"},
  44. };


  45. static irqreturn_t btn_val_irq(int irq, void *dev_id)
  46. {
  47.     struct pin_dec *pin = (struct pin_dec *)dev_id;
  48.     int res;
  49.     res = s3c2410_gpio_getpin(pin->pin);
  50.     if (!res)
  51.     {
  52.         btn = pin->key_val | 0x80;
  53.     }
  54.     else
  55.     {
  56.         btn = pin->key_val;
  57.     }

  58.     ev_press = 1;
  59.     wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */

  60.     
  61.     return IRQ_RETVAL(IRQ_HANDLED);
  62. }


  63. static int btn_val_open(struct inode *inode, struct file *file)
  64. {
  65.     int i;
  66.     for (i = 0; i < 4; i++)
  67.     {
  68.         s3c2410_gpio_cfgpin(pins_dec[i].pin, pins_dec[i].pin_setting);
  69.         request_irq(pins_dec[i].irq, btn_val_irq, IRQT_BOTHEDGE, pins_dec[i].name, &pins_dec[i]);
  70.     }
  71.     
  72.     return 0;
  73. }

  74. ssize_t btn_val_read(struct file *file, char __user * buf,
  75.          size_t len, loff_t * ppos)
  76. {
  77.     wait_event_interruptible(button_waitq, ev_press);

  78.     /* 如果有按键动作, 返回键值 */
  79.     copy_to_user(buf, &btn, 1);
  80.     ev_press = 0;
  81.     
  82.     return 1;
  83.     return 0;
  84. }

  85. static int btn_val_release(struct inode *inode, struct file *file)
  86. {
  87.     int i;
  88.     for (i = 0; i < 4; i++)
  89.     {
  90.         free_irq(pins_dec[i].irq, &pins_dec[i]);
  91.     }
  92.     return 0;
  93. }

  94. static unsigned int btn_val_poll(struct file *fp, poll_table * wait)
  95. {
  96.     unsigned int mask = 0;

  97.     poll_wait(fp, &button_waitq, wait);
  98.     if (ev_press)
  99.         mask |= POLLIN | POLLRDNORM;
  100.     return mask;
  101. }



  102. const struct file_operations fops =
  103. {
  104.     .owner = THIS_MODULE,
  105.     .open = btn_val_open,
  106.     .read = btn_val_read,
  107.     .poll = btn_val_poll,
  108.     .release = btn_val_release,
  109. };

  110. static int btn_val_init()
  111. {
  112.     dev_t devid;
  113.     int rec;
  114.     
  115.     if (major)
  116.     {
  117.         devid = MKDEV(major, 0);
  118.         rec = register_chrdev_region(devid, 1, "button2");
  119.     }
  120.     else
  121.     {
  122.         rec = alloc_chrdev_region(&devid, 0, 1, "button2");
  123.         major = MAJOR(devid);
  124.     }
  125.     if (rec < 0)
  126.     {
  127.         printk(KERN_ERR, "can't get major");
  128.         return -ENODEV;
  129.     }
  130.     cdev_init(&cdev, &fops);
  131.     cdev_add(&cdev, devid, 1);

  132.     cls = class_create(THIS_MODULE, "button2");
  133.     cls_dev = class_device_create(cls, NULL, MKDEV(major, 0), NULL, "button2");

  134.     
  135.     return 0;
  136. }

  137. static void btn_val_exit()
  138. {
  139.     class_device_destroy(cls, MKDEV(major, 0));
  140.     class_destroy(cls);
  141.     cdev_del(&cdev);
  142.     unregister_chrdev_region(MKDEV(major, 0), 1);
  143. }

  144. module_init(btn_val_init);
  145. module_exit(btn_val_exit);

  146. MODULE_AUTHOR("xiaoming");
  147. MODULE_DESCRIPTION("interrupt button value");
  148. 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. int main(int argc, char **argv)
  7. {
  8.     int fd;
  9.     unsigned char key_val;
  10.     int ret;

  11.     struct pollfd fds[1];
  12.     
  13.     fd = open("/dev/button2", O_RDWR);
  14.     if (fd < 0)
  15.     {
  16.         printf("can't open /dev/button2 !\n");
  17.     }

  18.     fds[0].fd = fd;
  19.     fds[0].events = POLLIN;
  20.     while (1)
  21.     {
  22.         ret = poll(fds, 1, 5000);
  23.         if (ret == 0)
  24.         {
  25.             printf("time out!\n");
  26.         }
  27.         else
  28.         {
  29.             read(fd, &key_val, 1);
  30.             printf("key_val=0x%x\n", key_val);
  31.         }
  32.     }
  33.     
  34.     return 0;
  35. }


运行结果:

当没有按键按下时,每隔5秒就会打印一次time out!当有按键按下时会立刻打印键值


阅读(1128) | 评论(0) | 转发(0) |
0

上一篇:一步一步学驱动(2)

下一篇:没有了

给主人留下些什么吧!~~