OK6410按键驱动程序(改)亲测可以运行

  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/fs.h>
  5. #include <linux/gpio.h>
  6. #include <linux/types.h>
  7. #include <linux/cdev.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/sched.h>
  10. #include <linux/device.h>
  11. #include <linux/poll.h>
  12. #include <linux/semaphore.h>
  13. #include <linux/timer.h>
  14. #include <asm/irq.h>
  15. #include <asm/uaccess.h>
  16. //#include <mach/hardware.h>
  17. #include <mach/irqs.h>
  18. #define DEVICE_NAME "keyint"
  19. #define KEYNUM 6
  20. dev_t devid;
  21. //static DEFINE_SEMAPHORE(key_lock);  //declare a mutex lock for keyint
  22. //定义一个信号量
  23. struct semaphore key_lock;
  24. static struct fasync_struct *key_async;
  25. static struct timer_list key_timer;
  26. struct key_irq_desc {
  27. int irq;        //irq num
  28. unsigned long flags;    //irq flags,identified the way of irq here,eq.edge,level
  29. char *name;        //irq name
  30. };
  31. static struct key_irq_desc key_irqs[] = {
  32. //下降沿产生中断
  33. {IRQ_EINT(0), IRQF_TRIGGER_FALLING, "KEY1"},
  34. {IRQ_EINT(1), IRQF_TRIGGER_FALLING, "KEY2"},
  35. {IRQ_EINT(2), IRQF_TRIGGER_FALLING, "KEY3"},
  36. {IRQ_EINT(3), IRQF_TRIGGER_FALLING, "KEY4"},
  37. {IRQ_EINT(4), IRQF_TRIGGER_FALLING, "KEY5"},
  38. {IRQ_EINT(5), IRQF_TRIGGER_FALLING, "KEY6"},
  39. };
  40. /*define a waiting queue here*/
  41. static DECLARE_WAIT_QUEUE_HEAD(key_waitq);
  42. /*define a event flag ev_press*/
  43. static volatile int ev_press = 0;
  44. static volatile int press_cnt[KEYNUM] = {0,0,0,0,0,0};
  45. /*中断处理函数*/
  46. static irqreturn_t keys_interrupt(int irq, void *dev_id)
  47. {
  48. volatile int *press_cnt = (volatile int *) dev_id;
  49. /*set the pressed key flag(must do here due to not be static value)*/
  50. *press_cnt = *press_cnt + 1;
  51. //延时10ms后执行定时器处理函数
  52. mod_timer(&key_timer,jiffies+HZ/100);        //start timer after 10ms
  53. return IRQ_RETVAL(IRQ_HANDLED);
  54. }
  55. //定时器处理函数
  56. static void key_timer_func(unsigned long data)
  57. {
  58. ev_press = 1;
  59. //唤醒等待队列
  60. wake_up_interruptible(&key_waitq);
  61. kill_fasync(&key_async, SIGIO, POLL_IN);
  62. }
  63. static int key_fasync(int fd, struct file *filp, int on)
  64. {
  65. printk("Function key_fasync\n");
  66. return fasync_helper(fd,filp,on,&key_async);
  67. }
  68. static unsigned key_poll(struct file *file, poll_table *wait)
  69. {
  70. unsigned int mask=0;
  71. //指明要使用的等待队列
  72. poll_wait(file,&key_waitq,wait);
  73. //返回掩码
  74. if(ev_press)
  75. mask |= POLL_IN | POLLRDNORM;
  76. printk("poll wait\n");
  77. return mask;
  78. }
  79. static int key_open(struct inode *inode, struct file *file)
  80. {
  81. int num;
  82. if(file->f_flags & O_NONBLOCK) {
  83. if(down_trylock(&key_lock)) return -EBUSY;
  84. }
  85. else {
  86. down(&key_lock);
  87. }
  88. //为每个按键注册中断处理程序
  89. for(num=0;num<KEYNUM;num++) {
  90. request_irq(key_irqs[num].irq, keys_interrupt, key_irqs[num].flags, key_irqs[num].name, (void *)&press_cnt[num]);
  91. }
  92. return 0;
  93. }
  94. static int key_close(struct inode *inode, struct file *file)
  95. {
  96. int num;
  97. //释放中断号
  98. for(num=0;num<6;num++) {
  99. free_irq(key_irqs[num].irq, (void *)&press_cnt[num]);
  100. }
  101. up(&key_lock);
  102. printk("key_close free irqs\n");
  103. return 0;
  104. }
  105. static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
  106. {
  107. //    unsigned int err;
  108. //判断是阻塞读还是非阻塞读
  109. if(filp->f_flags & O_NONBLOCK) {
  110. if(!ev_press)  return -EAGAIN;
  111. }
  112. else {
  113. /*if ev_press==0,then sleep*/
  114. /*阻塞,当有按键按下时(中断)被唤醒*/
  115. wait_event_interruptible(key_waitq,ev_press);
  116. }
  117. //阻塞结束,有键按下了
  118. ev_press = 0;
  119. //拷贝数据到用户空间
  120. copy_to_user(buff,(const void *)press_cnt,min(sizeof(press_cnt),count));
  121. memset((void *)press_cnt,0,sizeof(press_cnt));
  122. //    printk("read and clean press_cnt\n");
  123. return 1;
  124. }
  125. static struct file_operations key_ops = {
  126. .owner     = THIS_MODULE,
  127. .open     = key_open,
  128. .release = key_close,
  129. .read     = key_read,
  130. .poll     = key_poll,
  131. .fasync     = key_fasync,
  132. };
  133. static struct cdev *cdev_keyint;
  134. static struct class *keyint_class;
  135. //模块初始化函数
  136. static int __init s3c6410_keyint_init(void) {
  137. int val;
  138. /*timer initial */
  139. init_timer(&key_timer);
  140. key_timer.function = key_timer_func;
  141. add_timer(&key_timer);
  142. /*初始化信号量*/
  143. init_MUTEX(&key_lock);
  144. /*register device*/
  145. val = alloc_chrdev_region(&devid,0,1,DEVICE_NAME);
  146. if(val) {
  147. return -1;
  148. printk("register keyint error\n");
  149. }
  150. cdev_keyint = cdev_alloc();
  151. cdev_init(cdev_keyint, &key_ops);
  152. cdev_keyint->owner = THIS_MODULE;
  153. cdev_keyint->ops   = &key_ops;
  154. val = cdev_add(cdev_keyint,devid,1);
  155. if(val) {
  156. return -1;
  157. printk("add device error\n");
  158. }
  159. keyint_class = class_create(THIS_MODULE,DEVICE_NAME);
  160. device_create(keyint_class,NULL,devid,NULL,"%s",DEVICE_NAME);
  161. printk("KEY initialezed ^_^\n");
  162. return 0;
  163. }
  164. static void __exit s3c6410_keyint_exit(void)
  165. {
  166. cdev_del(cdev_keyint);
  167. device_destroy(keyint_class,devid);
  168. class_destroy(keyint_class);
  169. unregister_chrdev_region(devid,1);
  170. }
  171. module_init(s3c6410_keyint_init);
  172. module_exit(s3c6410_keyint_exit);
  173. MODULE_LICENSE("GPL");

测试程序:

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

测试现象

时间: 2025-01-01 11:34:39

OK6410按键驱动程序(改)亲测可以运行的相关文章

大数据开发环境需要的安装包合集,亲测没问题

大数据环境需要的安装包合集,包括: apache-flume-1.7.0-bin.tar.gz apache-hive-1.2.1-bin.tar.gz hadoop-2.7.2.tar.gz hbase-1.3.1-bin.tar.gz jdk-8u144-linux-x64.tar kafka_2.11-0.11.0.2.tgz mysql-5.7.20-1.el7.x86_64.rpm-bundle.tar scala-2.11.8.tgz spark-2.1.1-bin-hadoop2.

亲测VS2010纯静态编译QT4.8.0,实现VS2010编译调试Qt程序,QtCreator静态发布程序(图文并茂,非常详细)

下载源代码,注意一定是源码压缩包如qt-everywhere-opensource-src-4.8.0.zip,不是Qt发布的已编译的不同版本的标准库如qt-win-opensource-4.8.0-vs2010.exe,这些版本都只是动态编译的,不是我们所需要的.只有用源码包才能做真正的纯静态编译,如果用Qt官网已编译的标准库.exe文件进行编译,有可能出现各种错误,而且编译后的文件巨大,我当时就在这里绕了很大的弯子,请童鞋们注意啦!!可能有些老鸟会笑话,但我本着最严肃的态度告诉菜鸟们,上网查

电脑IP改变后oracle em无法登陆的解决办法(亲测)

以下方法为本人亲测 情况:假设电脑初次安装oracle时的ip是192.168.133.110 那么进入em的地址就是http://192.168.133.110:1158/em/console/logon/logon 假设电脑的IP改变为192.168.88.66 那么进入em的地址应该是http://192.168.88.66:1158/em/console/logon/logon 但是测试后,输入上述地址无法进入em,原因是电脑ip改变了,oracle需要修改配置文件才可以访问,一般修改配

【Android】Activity生命周期(亲测)

测试手机:Nexus 5   系统:4.4 一.测试 测试代码: 1 package com.example.androidalarm; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.content.res.Configuration; 6 import android.os.Bundle; 7 import android.util.AttributeSet; 8 impo

【亲测有效】主页锁定神器,妈妈再也不用担心我电脑浏览器主页被劫持篡改了

很多朋友都在网上下载一些软件或者重装系统后发现,浏览器主页被锁定了,不管怎么修改都改不过来,即便是杀毒软件也拿它没办法,这次给大家一个自己亲测的主页锁定神器,稳妥的解决主页问题. 注意:主页锁定神器会出现报毒的情况,这是正常现象,退出杀毒软件后进行配置以及使用,锁定自己的主页后,即可正常开启杀毒软件.(链接: https://pan.baidu.com/s/1S7dch7nm7DW6IK4Go1nODg 密码: zhph) 1.解压并打开主页锁定神器的文件夹 2.双击打开"buildlock.e

解决ERROR 1045 (28000): Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password: YES)【亲测有效】

文件转自:https://blog.csdn.net/hua1011161696/article/details/80666025 问题:(MySQL 5.6社区版windows版) 忘记密码或其他一些原因导致无法连接上MySQL服务器端,在命令行报错:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) 解决方案: 步骤一:关闭数据库服务端mysqld程序 两种方式: ①快捷键 w

Android蓝牙自动配对Demo,亲测好使!!!

蓝牙自动配对,即搜索到其它蓝牙设备之后直接进行配对,不需要弹出配对确认框或者密钥输入框. 转载请注明出处http://blog.csdn.net/qq_25827845/article/details/52400782 经过最近一段时间得研究,针对网上给出的案例.总结了一个亲测好使的Demo. 说明如下: 1.本Demo用来连接蓝牙设备HC-05,如果你要连接其他蓝牙设备,注意修改相关名字以及修改设备初试pin值. 2.将Demo安装在Android手机上,点击按钮,可以实现与目标蓝牙设备的自动

微信现金红包高级红包接口开发亲测

微信现金红包高级红包接口开发时遇到了不少问题,网上搜索发现 微信现金红包高级红包接口开发注意事项 这篇文章问题总结得很完整,里面给的demo是VS高版本写的,运行过程中还是有些参数问题对于首次调试来说有点难度,还有微信支付现金红包接口 的接口介绍,下面的几个问题特别提出: 商户证书,下载的demo需要证书才能正确运行(可调成服务器模拟发送),而证书需要安装到服务器上,demo是控制台程序,需要的证书可直接安装后使用,其中指出的是方法X509Certificate2 Find()中m_Subjec

【原创】Centos下telnet的安装和配置(完全版,Centos5.5亲测)

Centos下telnet的安装和配置(完全版,Centos5.5亲测) 一.查看本机是否有安装telnet(centOS5默认有安装telnet) # rpm -qa |grep telnet 如果显示结果为: telnet-0.17-39.el5 telnet-server-0.17-39.el5 那恭喜你,机器上已经安装了telnet.如果没有安装,请看下一步. 特别说明: telnet分为telnet-client (简称为telnet)和telnet-server.telnet-cli