Chinaunix首页 | 论坛 | 博客
  • 博客访问: 79986
  • 博文数量: 15
  • 博客积分: 346
  • 博客等级: 一等列兵
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-14 17:20
文章分类
文章存档

2012年(15)

分类: LINUX

2012-05-19 10:41:51

--key.c

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/types.h>
  3. #include <linux/fs.h>
  4. #include <linux/errno.h>
  5. #include <linux/sched.h>
  6. #include <linux/init.h>
  7. #include <linux/cdev.h>
  8. #include <linux/device.h>
  9. #include <linux/gpio.h>
  10. #include <linux/mm.h>
  11. #include <linux/irq.h>
  12. #include <linux/interrupt.h>
  13. #include <asm/io.h>
  14. #include <asm/module.h>
  15. #include <asm/uaccess.h>
  16. #include <asm/irq.h>
  17. #include <mach/regs-gpio.h>
  18. #include <mach/hardware.h>

  19. #include "keydev.h"
  20. #define BUTTON_MAJOR 0
  21. #define DEVICE_NAME "button"
  22. #define BUTTON_NR_DEVS 1
  23. static int button_major = BUTTON_MAJOR;

  24. struct button_dev
  25. {
  26.     struct cdev dev;
  27.     wait_queue_head_t button_queue;
  28. };
  29. struct button_dev *devp;
  30. static struct class *button_class;
  31. static volatile int press_no = -1;

  32. struct button_irq_desc
  33. {
  34.     int irq;
  35.     int pin;
  36.     int flags;
  37.     int no;
  38.     char *name;
  39. };

  40. static struct button_irq_desc button_irq_table [] =
  41. {
  42.     {IRQ_EINT8 , S3C2410_GPG(0) , S3C2410_GPG0_EINT8 , 0, "KEY0"},
  43.     {IRQ_EINT11, S3C2410_GPG(3) , S3C2410_GPG3_EINT11 , 1, "KEY1"},
  44.     {IRQ_EINT13, S3C2410_GPG(5) , S3C2410_GPG5_EINT13 , 2, "KEY2"},
  45.     {IRQ_EINT14, S3C2410_GPG(6) , S3C2410_GPG6_EINT14 , 3, "KEY3"},
  46.     {IRQ_EINT15, S3C2410_GPG(7) , S3C2410_GPG7_EINT15 , 4, "KEY4"},
  47.     {IRQ_EINT19, S3C2410_GPG(11), S3C2410_GPG11_EINT19, 5, "KEY5"},
  48. };

  49. static int s3c2440_key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
  50. {
  51.     switch (cmd)
  52.     {
  53.         case KEYDEV_POLL:
  54.             break;
  55.         case KEYDEV_IRQ:
  56.             break;
  57.         default:
  58.             return -EINVAL;
  59.     }
  60.     return 0;
  61. }
  62. /*wait_event_interruptible()*/
  63. /*
  64. static int s3c2440_key_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
    {
        int err;
        if (press_no == -1)
        {
            if (filp->f_flags & O_NONBLOCK)
            {
                return -EAGAIN;
            }
            else
                wait_event_interruptible(devp->button_queue, press_no != -1); //interruptible_sleep_on(&devp->button_queue);
        }
        err = copy_to_user(buf, (void *)&press_no, sizeof(int));
        press_no = -1;
        return err ? -EFAULT : 0;
    }
  65. */

  66. /*自己设置进程状态*/
  67. static int s3c2440_key_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
  68. {
  69.     int ret;
  70.     DECLARE_WAITQUEUE(wait, current);
  71.     add_wait_queue(&devp->button_queue, &wait);
  72.     if (press_no == -1)
  73.     {
  74.         if (filp->f_flags & O_NONBLOCK)
  75.         {
  76.             ret = -EAGAIN;
  77.             goto out;
  78.         }
  79.         __set_current_state(TASK_INTERRUPTIBLE);
  80.         schedule();
  81.         if (signal_pending(current))
  82.         {
  83.             ret = - ERESTARTSYS;
  84.             goto out2;
  85.         }
  86.     }
  87.     copy_to_user(buf, (void *)&press_no, sizeof(int));
  88.     press_no = -1;
  89.     remove_wait_queue(&devp->button_queue, &wait);
  90.     return 0;

  91. out2:
  92.     __set_current_state(TASK_RUNNING);
  93. out:
  94.     remove_wait_queue(&devp->button_queue, &wait);
  95.     return ret;
  96. }


  97. static int s3c2440_key_open(struct inode *inode, struct file *filp)
  98. {
  99.     return 0;
  100. }

  101. static struct file_operations dev_fops =
  102. {
  103.     .owner = THIS_MODULE,
  104.     .ioctl = s3c2440_key_ioctl,
  105.     .open = s3c2440_key_open,
  106.     .read = s3c2440_key_read,
  107. };

  108. static irqreturn_t button_irq_handler(int irq, void *dev_id)
  109. {
  110.     int i = *(int *)dev_id;
  111.     if (!s3c2410_gpio_getpin(button_irq_table[i].pin))
  112.     {
  113.         press_no = i;
  114.         wake_up_interruptible(&devp->button_queue);
  115.     }
  116.     return IRQ_RETVAL(IRQ_HANDLED);
  117. }

  118. static void s3c2440_key_setup_irq(void)
  119. {
  120.     int i, err;
  121.     for (i = 0; i < sizeof(button_irq_table)/sizeof(button_irq_table[0]); ++i)
  122.     {
  123.         err = request_irq(button_irq_table[i].irq, button_irq_handler, IRQ_TYPE_EDGE_BOTH, button_irq_table[i].name, (void *)&button_irq_table[i].no);    

  124.         if (err)
  125.             printk("apply fail-->%d\n", i);
  126.     }
  127. }

  128. static void s3c2440_key_free_irq(void)
  129. {
  130.     int i;
  131.     for (i = 0; i < sizeof(button_irq_table)/sizeof(button_irq_table[0]); ++i)
  132.     {
  133.         free_irq(button_irq_table[i].irq, &button_irq_table[i].no);
  134.     }
  135. }

  136. static int __init s3c2440_key_init(void)
  137. {
  138.     int result;
  139.     struct device *devxx;
  140.     dev_t devno = MKDEV(button_major, 0);

  141.     if (button_major)
  142.         result = register_chrdev_region(devno, BUTTON_NR_DEVS, DEVICE_NAME);
  143.     else
  144.     {
  145.         result = alloc_chrdev_region(&devno, 0, BUTTON_NR_DEVS, DEVICE_NAME);
  146.         button_major = MAJOR(devno);
  147.         printk("Major-->%d\n", button_major);
  148.     }

  149.     if (result < 0)
  150.         return result;

  151.     devp = kmalloc(sizeof(struct button_dev), GFP_KERNEL);
  152.     if (!devp)
  153.     {
  154.         result = -ENOMEM;
  155.         goto fail_malloc;
  156.     }
  157.     memset(devp, 0, sizeof(struct button_dev));

  158.     cdev_init(&devp->dev, &dev_fops);
  159.     devp->dev.owner = THIS_MODULE;

  160.     cdev_add(&devp->dev, devno, BUTTON_NR_DEVS);

  161.     s3c2440_key_setup_irq();
  162.     init_waitqueue_head(&devp->button_queue);
  163.     
  164.     button_class = class_create(THIS_MODULE, "button_class");
  165.     if (IS_ERR(button_class))
  166.     {
  167.         printk("create class fail!\n");
  168.         goto fail_class;
  169.     }
  170.     devxx = device_create(button_class, NULL, devno, NULL, DEVICE_NAME);
  171.     if (IS_ERR(devxx))
  172.     {
  173.         printk("create device fail!\n");
  174.         goto fail_device;
  175.     }
  176.     return 0;

  177. fail_device:
  178.     class_destroy(button_class);
  179. fail_class:
  180.     cdev_del(&devp->dev);
  181. fail_malloc:
  182.     unregister_chrdev_region(devno, BUTTON_NR_DEVS);
  183.     return result;
  184. }


  185. static void __exit s3c2440_key_exit(void)
  186. {
  187.     s3c2440_key_free_irq();
  188.     cdev_del(&devp->dev);
  189.     device_destroy(button_class, MKDEV(button_major, 0));
  190.     class_destroy(button_class);
  191.     unregister_chrdev_region(MKDEV(button_major, 0), BUTTON_NR_DEVS);
  192. }


  193. MODULE_LICENSE("GPL");
  194. MODULE_AUTHOR("Domod");
  195. module_init(s3c2440_key_init);
  196. module_exit(s3c2440_key_exit);
--keydev.h

点击(此处)折叠或打开

  1. #ifndef __KEYDEV_H__
  2. #define __KEYDEV_H__

  3. #include <linux/ioctl.h>
  4. #define KEYDEV_IOC_MAGIC 'k'

  5. #define KEYDEV_POLL _IO(KEYDEV_IOC_MAGIC, 1)
  6. #define KEYDEV_IRQ _IO(KEYDEV_IOC_MAGIC, 2)

  7. #define KEYDEV_IOC_MAXNR 2

  8. #endif
--app-key.c

点击(此处)折叠或打开

  1. #include "keydev.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/ioctl.h>


  6. int main(int argc, char **argv)
  7. {
  8.     int no;
  9.     int fd;
  10.     fd = open("/dev/button", 0);
  11.     if (fd < 0)
  12.     {
  13.         perror("open device key!");
  14.         exit(1);
  15.     }
  16.     while (1)
  17.     {
  18.         if (!read(fd, &no, 4))
  19.             printf("key%d is pressing!\n", no);
  20.     }

  21. }
--Makefile

点击(此处)折叠或打开

  1. ifneq ($(KERNELRELEASE),)

  2. obj-m := key.o

  3. else

  4. KDIR := /home/domod/arm/kernel/src/linux-2.6.32.2
  5. all:
  6. make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
  7. app:
  8. arm-linux-gcc app-key.c -o key
  9. clean:
  10. rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul*


  11. endif


阅读(1123) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~