matrix5-custom-buttons.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #include <linux/config.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>
  5. #include <linux/miscdevice.h>
  6. #include <linux/sched.h>
  7. #include <linux/delay.h>
  8. #include <linux/poll.h>
  9. #include <linux/spinlock.h>
  10. #include <linux/irq.h>
  11. #include <linux/delay.h>
  12. #include <asm/hardware.h>
  13. #define DEVICE_NAME "custom-buttons"
  14. #define BUTTON_MAJOR 235
  15. static struct key_info {
  16. int irq_no;
  17. unsigned int gpio_port;
  18. int key_no;
  19. } key_info_tab[3] = {
  20. { IRQ_EINT0, GPIO_F0, 1 },
  21. { IRQ_EINT11, GPIO_G3, 2 },
  22. { IRQ_EINT19, GPIO_G11, 3 },
  23. };
  24. static int ready = 0;
  25. static int key_value = 0;
  26. static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);
  27. static void buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
  28. {
  29. struct key_info *k;
  30. int i;
  31. int found = 0;
  32. int up;
  33. int flags;
  34. for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) {
  35. k = key_info_tab + i;
  36. if (k->irq_no == irq) {
  37. found = 1;
  38. break;
  39. }
  40. }
  41. if (!found) {
  42. printk("bad irq %d in buttonn", irq);
  43. return;
  44. }
  45. save_flags(flags);
  46. cli();
  47. set_gpio_mode_user(k->gpio_port, GPIO_MODE_IN);
  48. up = read_gpio_bit(k->gpio_port);
  49. set_external_irq(k->irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);
  50. restore_flags(flags);
  51.         if (up) {
  52.                key_value = k->key_no + 0x80;
  53.         } else {
  54.                key_value = k->key_no;
  55.         }
  56.         ready = 1;
  57. wake_up_interruptible(&buttons_wait);
  58. }
  59. static int request_irqs(void)
  60. {
  61. struct key_info *k;
  62. int i;
  63. for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) {
  64. k = key_info_tab + i;
  65. set_external_irq(k->irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);
  66. if (request_irq(k->irq_no, &buttons_irq, SA_INTERRUPT, DEVICE_NAME, &buttons_irq)) {
  67. return -1;
  68. }
  69. }
  70. return 0;
  71. }
  72. static void free_irqs(void)
  73. {
  74. struct key_info *k;
  75. int i;
  76. for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) {
  77. k = key_info_tab + i;
  78. free_irq(k->irq_no, buttons_irq);
  79. }
  80. }
  81. static int matrix4_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
  82. {
  83. static int key;
  84. int flags;
  85. int repeat;
  86.         if (!ready)
  87.                 return -EAGAIN;
  88.         if (count != sizeof key_value)
  89.                 return -EINVAL;
  90. save_flags(flags);
  91. if (key != key_value) {
  92. key = key_value;
  93. repeat = 0;
  94. } else {
  95. repeat = 1;
  96. }
  97. restore_flags(flags);
  98. if (repeat) {
  99. return -EAGAIN;
  100. }
  101.         copy_to_user(buffer, &key, sizeof key);
  102.         ready = 0;
  103.         return sizeof key_value;
  104. }
  105. static unsigned int matrix4_buttons_select(
  106.         struct file *file,
  107.         struct poll_table_struct *wait)
  108. {
  109.         if (ready)
  110.                 return 1;
  111.         poll_wait(file, &buttons_wait, wait);
  112.         return 0;
  113. }
  114. static int matrix4_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  115. {
  116. switch(cmd) {
  117. default:
  118. return -EINVAL;
  119. }
  120. }
  121. static struct file_operations matrix4_buttons_fops = {
  122. owner: THIS_MODULE,
  123. ioctl:  matrix4_buttons_ioctl,
  124. poll: matrix4_buttons_select,
  125. read: matrix4_buttons_read,
  126. };
  127. static devfs_handle_t devfs_handle;
  128. static int __init matrix4_buttons_init(void)
  129. {
  130. int ret;
  131. ready = 0;
  132. ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &matrix4_buttons_fops);
  133. if (ret < 0) {
  134.   printk(DEVICE_NAME " can't register major numbern");
  135.   return ret;
  136. }
  137. ret = request_irqs();
  138. if (ret) {
  139. unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
  140. printk(DEVICE_NAME " can't request irqsn");
  141. return ret;
  142. }
  143. devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
  144. BUTTON_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &matrix4_buttons_fops, NULL);
  145. return 0;
  146. }
  147. static void __exit matrix4_buttons_exit(void)
  148. {
  149. devfs_unregister(devfs_handle);
  150. free_irqs();
  151. unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
  152. }
  153. module_init(matrix4_buttons_init);
  154. module_exit(matrix4_buttons_exit);
  155. MODULE_LICENSE("GPL");