OK6410按键驱动程序(Linux),测试通过后分享给大家

如果你的飞凌Linux-3.0.1内核源码没有编译过,编译时可能会出现:

scripts/basic/fixdep: 1: scripts/basic/fixdep: ELF: not found
scripts/basic/fixdep: 2: scripts/basic/fixdep: Syntax error: "(" unexpected

这时要先到Linux-3.0.1目录下 执行make scripts


注意:由于OK6410的GPIO按键中断已经被飞凌自带的按键驱动注册,所以运行我们编写的按键驱动前要先去掉飞凌自带的按键驱动,方法:make menuconfig->Device Drivers->input device support->Key Boards->GPIO Buttons 去掉前面的*,即不选该项即可。


按键驱动:

[cpp]  view plain  copy
  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/poll.h>  
  7. #include <linux/irq.h>  
  8. #include <asm/irq.h>  
  9. #include <linux/interrupt.h>  
  10. #include <asm/uaccess.h>  
  11. #include <mach/regs-gpio.h>  
  12. #include <mach/hardware.h>  
  13. #include <linux/platform_device.h>  
  14. #include <linux/cdev.h>  
  15. #include <linux/miscdevice.h>  
  16. #include <linux/sched.h>  
  17. #include <linux/gpio.h>  
  18. #include <mach/gpio-bank-n.h>  
  19.   
  20. #define DEVICE_NAME     "buttons"  
  21.   
  22. struct button_irq_desc {  
  23.     int irq;  
  24.     int pin;  
  25.     int pin_setting;  
  26.     int number;  
  27.     char *name;   
  28. };  
  29.   
  30. static struct button_irq_desc button_irqs [] = {  
  31.     {IRQ_EINT(0), S3C64XX_GPN(0) ,  S3C64XX_GPN0_EINT0 , 0, "KEY0"},  
  32.     {IRQ_EINT(1), S3C64XX_GPN(1) ,  S3C64XX_GPN1_EINT1 , 1, "KEY1"},  
  33.     {IRQ_EINT(2), S3C64XX_GPN(2) ,  S3C64XX_GPN2_EINT2 , 2, "KEY2"},  
  34.     {IRQ_EINT(3), S3C64XX_GPN(3) ,  S3C64XX_GPN3_EINT3 , 3, "KEY3"},  
  35.     {IRQ_EINT(4), S3C64XX_GPN(4) ,  S3C64XX_GPN4_EINT4 , 4, "KEY4"},  
  36.     {IRQ_EINT(5), S3C64XX_GPN(5),   S3C64XX_GPN5_EINT5 , 5, "KEY5"},  
  37. };  
  38. static volatile int key_values [] = {0, 0, 0, 0, 0, 0};  
  39.   
  40. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
  41.   
  42. static volatile int ev_press = 0;  
  43.   
  44.   
  45. static irqreturn_t buttons_interrupt(int irq, void *dev_id)  
  46. {  
  47.     struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;  
  48.     int down;  
  49.   
  50.     // udelay(0);  
  51.     down = !gpio_get_value(button_irqs->pin);  
  52.   
  53.     //按键发生了变化  
  54.     if (down != (key_values[button_irqs->number] & 1)) { // Changed  
  55.   
  56.         key_values[button_irqs->number] = 0 + down;  
  57.       
  58.         ev_press = 1;  
  59.         wake_up_interruptible(&button_waitq);  
  60.     }  
  61.       
  62.     return IRQ_RETVAL(IRQ_HANDLED);  
  63. }  
  64.   
  65.   
  66. static int s3c24xx_buttons_open(struct inode *inode, struct file *file)  
  67. {  
  68.     int i;  
  69.     int err = 0;  
  70.       
  71.     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {  
  72.     if (button_irqs[i].irq < 0) {  
  73.         continue;  
  74.     }  
  75.     /*注册中断,六个按钮全都由buttons_interrupt中断函数处理,上升下降沿都触发中断 
  76.      这里用button_irqs[i]的地址作为dev_id,保证dev_id的唯一性,发生中断的时候, 
  77.      会把这个指针传递给中断处理函数*/  
  78.         err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,   
  79.                           button_irqs[i].name, (void *)&button_irqs[i]);  
  80.         if (err)  
  81.             break;  
  82.     }  
  83.   
  84.     //如果注册中断过程中出错,则注销注册成功的中断  
  85.     if (err) {  
  86.         i--;  
  87.         for (; i >= 0; i--) {  
  88.             if (button_irqs[i].irq < 0) {  
  89.             continue;  
  90.             }  
  91.             disable_irq(button_irqs[i].irq);  
  92.             free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);  
  93.         }  
  94.         return -EBUSY;  
  95.     }  
  96.   
  97.     ev_press = 1;  
  98.       
  99.     return 0;  
  100. }  
  101.   
  102.   
  103. static int s3c24xx_buttons_close(struct inode *inode, struct file *file)  
  104. {  
  105.     int i;  
  106.     //注销中断  
  107.     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {  
  108.         if (button_irqs[i].irq < 0) {  
  109.             continue;  
  110.         }  
  111.         free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);  
  112.     }  
  113.   
  114.     return 0;  
  115. }  
  116.   
  117.   
  118. static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)  
  119. {  
  120.     unsigned long err;  
  121.   
  122.     if (!ev_press) {  
  123.         //没有新按键事件处理,如果用户要求不阻塞就直接返回,否则阻塞在button_waitq队列上。  
  124.         if (filp->f_flags & O_NONBLOCK)  
  125.             return -EAGAIN;  
  126.         else  
  127.             wait_event_interruptible(button_waitq, ev_press);  
  128.     }  
  129.       
  130.     ev_press = 0;  
  131.   
  132.     err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));  
  133.   
  134.     return err ? -EFAULT : min(sizeof(key_values), count);  
  135. }  
  136.   
  137. static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait)  
  138. {  
  139.     unsigned int mask = 0;  
  140.     //使用poll_wait将等待队列添加到poll_table中  
  141.     poll_wait(file, &button_waitq, wait);  
  142.     //返回掩码:设备可读通常返回(POLLIN|POLLRDNORM)。设备可写通常返回(POLLOUT|POLLWRNORM)  
  143.     if (ev_press)  
  144.         mask |= POLLIN | POLLRDNORM;  
  145.     return mask;  
  146. }  
  147.   
  148.   
  149. static struct file_operations dev_fops = {  
  150.     .owner   =   THIS_MODULE,  
  151.     .open    =   s3c24xx_buttons_open,  
  152.     .release =   s3c24xx_buttons_close,   
  153.     .read    =   s3c24xx_buttons_read,  
  154.     .poll    =   s3c24xx_buttons_poll,  
  155. };  
  156.   
  157. static struct miscdevice misc = {  
  158.     .minor = MISC_DYNAMIC_MINOR,  
  159.     .name = DEVICE_NAME,  
  160.     .fops = &dev_fops,  
  161. };  
  162.   
  163. static int __init dev_init(void)  
  164. {  
  165.     int ret;  
  166.   
  167.     ret = misc_register(&misc);  
  168.   
  169.     printk (DEVICE_NAME"\tinitialized\n");  
  170.   
  171.     return ret;  
  172. }  
  173.   
  174. static void __exit dev_exit(void)  
  175. {  
  176.     misc_deregister(&misc);  
  177. }  
  178.   
  179. module_init(dev_init);  
  180. module_exit(dev_exit);  
  181. MODULE_LICENSE("GPL");  
  182. MODULE_AUTHOR("wuwuchuan");  

Makefile

[cpp]  view plain  copy
  1. ifneq ($(KERNELRELEASE),)    
  2.     
  3. obj-m := buttons.o    
  4.     
  5. else    
  6.         
  7. KDIR := /home/wu55uw/forlinx/linux-3.0.1    
  8. all:    
  9.     make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-    
  10. clean:    
  11.     rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*    
  12.     
  13. endif    


测试程序:

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <sys/ioctl.h>  
  5.   
  6. int main(int argc, char **argv)  
  7. {  
  8.     int fd;  
  9.     int val;  
  10.     int i;  
  11.     int key_value[6];  
  12.         
  13.     fd = open("/dev/buttons",0);  
  14.     if(fd<0) {  
  15.       printf("open devie error\n");  
  16.       return -1;  
  17.     }  
  18.   
  19.     while(1) {  
  20.       val = read(fd,key_value, sizeof(key_value));  
  21.       if(val<0) {  
  22.         printf("read error\n");  
  23.         continue;  
  24.       }  
  25.   
  26.       for(i=0;i<6;i++) {  
  27.          if(key_value[i])  
  28.             printf("KEY%d pressed\n",(i+1),key_value[i]);  
  29.       else  
  30.         printf("KEY%d released\n",(i+1),key_value[i]);  
  31.       }    
  32.       printf("----------------new key event----------------\n");  
  33.     }  
  34.     close(fd);  
  35.     return 0;  
  36. }  




测试结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值