20150303 IMX257 输入子系统(二)之键盘模拟

20150303 IMX257 输入子系统(二)之键盘模拟

2015-03-03 李海沿

前面我们已经详细介绍了基本的知识:地址http://www.cnblogs.com/lihaiyan/p/4309329.html

接下来,我们使用IMX257的IO引脚中断+Linux输入子系统实现一个模拟键盘按键。实现的效果是,我们使用IO模拟按键L、按键S和Enter键 这三个按键。

这次我们就不再多废话了,直接上程序,大家看代码:

实验效果图:

如图所示: 我们依次按下三个按键

第一个按键 显示的键值为 38   ,也就是我们的L键

第二个按键  31   自然就是S 键

第三个按键  28  自然就是enter键

驱动代码:

  1 /******************************
  2     linux key_inputSystem
  3  *****************************/
  4 #include <linux/module.h>
  5 #include <linux/init.h>
  6 #include <linux/fs.h>
  7 #include <linux/interrupt.h>
  8 #include <linux/irq.h>
  9 #include <linux/sched.h>
 10 #include <linux/pm.h>
 11 #include <linux/sysctl.h>
 12 #include <linux/proc_fs.h>
 13 #include <linux/delay.h>
 14 #include <linux/input.h>
 15
 16 #include <mach/hardware.h>
 17
 18
 19 #include "mx257_gpio.h"
 20 #include "mx25_pins.h"
 21 #include "iomux.h"
 22
 23 #define Driver_NAME "key_input"
 24
 25 #define GPIO2_9     MX25_PIN_A23
 26 #define GPIO2_10    MX25_PIN_A24
 27 #define GPIO2_11    MX25_PIN_A25
 28
 29 //定义各个按键按下的键值
 30 struct pin_desc{
 31     unsigned int pin;
 32     char *name;
 33     unsigned int key_val;
 34 };
 35 //当按键按下时,键值分别为 以下值
 36 struct pin_desc pins_desc[3] = {
 37     {GPIO2_9,  "KEY_L_9",    KEY_L},
 38     {GPIO2_10,  "KEY_R_10",    KEY_S},
 39     {GPIO2_11, "KEY_Enter_11",    KEY_ENTER},
 40 };
 41
 42 static struct input_dev *key_input_dev;//输入子系统设备结构体
 43 static struct timer_list key_timer;    //定时器结构体
 44 static struct pin_desc *pin_desc_irq; //保存发生中断的引脚信息
 45
 46 //定时器到时函数
 47 static int key_timer_function(unsigned long data){
 48     struct pin_desc *pin_desc_tmp = pin_desc_irq;    //发生中断的引脚信息
 49     unsigned int pinval_tmp;        //按键键值缓冲
 50     if(!pin_desc_tmp)
 51         return 0;
 52     pinval_tmp = gpio_get_value(IOMUX_TO_GPIO(pin_desc_tmp->pin));//获取键值
 53     if(pinval_tmp){
 54         //松开 :0   按下:1
 55         input_event(key_input_dev,EV_KEY,pin_desc_tmp->key_val ,0);
 56         input_sync(key_input_dev);                //报告完毕,通知接收者
 57     }else{
 58         input_event(key_input_dev,EV_KEY,pin_desc_tmp->key_val ,1);
 59         input_sync(key_input_dev);                //报告完毕,通知接收者
 60     }
 61     return 0;
 62 }
 63 /* 中断程序key_irq */
 64 static irqreturn_t key_irq_function(int irq, void *dev_id)
 65 {
 66     pin_desc_irq = (struct pin_desc *)dev_id; //获取中断引脚的信息
 67     mod_timer(&key_timer,jiffies+HZ/50);    //开启定时器,时间20ms
 68
 69     return IRQ_RETVAL(IRQ_HANDLED);
 70 }
 71 //初始化函数
 72 static int __init  key_input_init(void)
 73  {
 74     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
 75
 76     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);//设备引脚为GPIO模式
 77     mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);//设备引脚为GPIO模式
 78     mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);//设备引脚为GPIO模式
 79      gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");//申请IO端口使用
 80      gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");//申请IO端口使用
 81      gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");//申请IO端口使用
 82     gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));//设备引脚为输入
 83     gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));//设备引脚为输入
 84     gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));//设备引脚为输入
 85     //设备引脚为上拉输入
 86     mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PU);
 87     mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PU);
 88     mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PU);
 89     //申请中断
 90     if(request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq_function, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[0]))
 91         return -1;
 92     if(request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq_function, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[1]))
 93         return -1;
 94     if(request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq_function, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[2]))
 95         return -1;
 96
 97     //input输入子系统设置
 98     key_input_dev = input_allocate_device();//分配一个input_dev结构体
 99     //设置能产生哪些事件
100     set_bit(EV_KEY, key_input_dev->evbit); //按键事件
101     set_bit(KEY_L, key_input_dev->keybit); // L键 按键
102     set_bit(KEY_S, key_input_dev->keybit); // S键 按键
103     set_bit(KEY_ENTER, key_input_dev->keybit); // ENTER键 按键
104     set_bit(KEY_LEFTSHIFT, key_input_dev->keybit); // LEFTSHIFT键 按键
105     //注册
106     input_register_device(key_input_dev);
107
108     init_timer(&key_timer);    //初始化定时器
109     key_timer.function = &key_timer_function;    //设置定时器处理函数
110     add_timer(&key_timer);    //将该定时器加入内核
111
112     printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !\n");
113     printk("Input system initialize successfu!\n\n");
114     return 0;
115 }
116 //exit
117 static void __exit key_input_exit(void)
118 {
119     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
120     /* free gpios */
121     free_irq(IOMUX_TO_IRQ(GPIO2_9),  &pins_desc[0]);
122     free_irq(IOMUX_TO_IRQ(GPIO2_10),  &pins_desc[1]);
123     free_irq(IOMUX_TO_IRQ(GPIO2_11),  &pins_desc[2]);
124     mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
125     mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
126     mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
127     gpio_free(IOMUX_TO_GPIO(GPIO2_9));
128     gpio_free(IOMUX_TO_GPIO(GPIO2_10));
129     gpio_free(IOMUX_TO_GPIO(GPIO2_11));
130
131     del_timer(&key_timer);        //删除定时器
132     input_unregister_device(key_input_dev);    //注销驱动
133     input_free_device(key_input_dev);        //释放结构体内存
134     printk("Input system unregister successfu!\n\n");
135 }
136
137 /* 这两行指定驱动程序的初始化函数和卸载函数 */
138 module_init(key_input_init);
139 module_exit(key_input_exit);
140
141 /* 描述驱动程序的一些信息,不是必须的 */
142 MODULE_AUTHOR("Lover雪");
143 MODULE_VERSION("0.1.0");
144 MODULE_DESCRIPTION("IMX257 key Driver");
145 MODULE_LICENSE("GPL");

应用程序代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <fcntl.h>
 7 #include <termios.h>
 8 #include <errno.h>
 9 #include <limits.h>
10 #include <time.h>
11 #include <linux/input.h>
12 #include "mx257_gpio.h"
13
14
15 int main(int argc, char **argv)
16 {
17     int fd;
18     int key_value,i=0,count;
19     struct input_event ev_key;
20
21     fd = open("/dev/input/event1",O_RDWR);
22     if(fd < 0){
23         printf("can‘t open !!!\n");
24         exit(1);
25     }
26     printf("open successful!\n");
27     while(1){
28         count = read(fd,&ev_key,sizeof(struct input_event));
29         for(i = 0; i<(int)count/sizeof(struct input_event); i++){
30             if(EV_KEY == ev_key.type)
31                 printf("type: %d ,code: %d ,value: %d \n",ev_key.type, ev_key.code,ev_key.value);
32             if(EV_SYN == ev_key.type)
33                 printf("syn event\n\n");
34         }
35     }
36     close(fd);
37     return 0;
38 }
时间: 2024-12-18 13:48:26

20150303 IMX257 输入子系统(二)之键盘模拟的相关文章

20150301 IMX257 输入子系统

20150301 IMX257 输入子系统 2015-03-01 李海沿 一.输入子系统 1.输入子系统结构体定义 struct input_dev{ const char *name; 设备名 const char *phys; 设备在系统中路径 const char *uniq; struct input_id id; 用于匹配input hander参数 unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; unsigned long

输入子系统------键盘按键驱动程序

由上一节的输入子系统的框架分析可知,其分三层:设备驱动层,核心层,事件驱动层 我们在为某种设备的编写驱动层,只需要关心设备驱动层,即如何驱动设备并获得硬件数据(如按下的按键数据),然后调用核心层提供的接口,核心层就会自动把数据提交给事件处理层.在输入子系统中,事件驱动是标准的,适用于所有输入类的.我们的设备可以利用一个已经存在的,合适的输入事件驱动,通过输入核心,和用户应用程序接口. 一.编写设备驱动层的流程 1.分配一个input--dev结构体 2.设置input_dev的成员 3.注册in

输入子系统分析 (二)

输入子系统是由输入子系统核心层( Input Core ),驱动层和事件处理层(Event Handler)三部份组成.一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 input driver -> Input core -> Event handler -> userspace 到达用户空间传给应用程序. input子系统的3个基本的数据结构struct input_dev { struct list_head    h_list;    //h_list是一个

linux 输入子系统(1) -Event types

输入系统协议用类型types和编码codecs来表示输入设备的值并用此来通知用户空间的应用程序. input协议是一个基于状态的协议,只有当相应事件编码对应的参数值发生变化时才会发送该事件.不过,状态是由Linux的输入子系统进行维护,驱动程序无需维护输入的状态,就算参数值没有变化时向输入子系统发出事件也不会有问题.用户空间可以用linux/input.h 中定义的EVIOCG*ioctls来获得当前事件编码和参数的状态.设备的所支持的上报事件种类也可以通过sysfs的class/input/e

input子系统(二)

二.内核代码 2.1输入子系统设备驱动层 我们先从设备驱动层进行讲解 首先设备驱动层调用input_allocate_device进行申请input_dev结构体,接着对该结构体进行赋值,然后调用input_register_device进行注册设备.同时我们在open函数里定义中断函数,中断函数里实现input_report_key的操作,向核心层报告按键消息. 通过上面分析我们主要关注input_allocate_device.input_register_device和input_repo

Linux学习:输入子系统 input

一.输入子系统 针对输入设备设计:触摸屏.键盘.按键.传感器.鼠标...... 二.每种设备都属于字符设备驱动,程序的写法步骤也相同 1.实现入口函数 xxx_init() 和卸载函数 xxx_exit() 2.申请设备号 register_chrdev() --- 与内核相关 3.创建设备文件(节点) class_create() 和 device_create() --- 与内核相关 4.硬件初始化 GPIO操作 --- 与硬件相关 注册中断 --- 与硬件相关 初始化等待队列 --- 与内

[python3.5][PyUserInput]模拟鼠标和键盘模拟

一.PyUserInput安装 python3.5的PyMouse和PyKeyboard模块都集成到了PyUserInput模块中.在python3.5中,直接安装PyUserInput模块即可 PyUserInput模块安装前需要安装pywin32和pyHook模块 pywin32模块默认已安装 pyHook模块可从这里下载 http://www.lfd.uci.edu/~gohlke/pythonlibs/ 在python官网找了很多个pyHook都不适用于python3.5版本 PyUse

Linux 输入子系统

Technorati 标签: Kernel 输入子系统 Input      在Linux中,输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理,是底层在按键.触摸时,触发一个中断,或者驱动通过定时器定时查询,通过这两种方式通知CPU,CPU然后通过SPI.I2C或I/O接口读取键值.坐标等数据,放入缓冲区,字符设备驱动管理该缓冲区,向上提供read接口供应用程序使用.      在上述的工作流程中,只有终端.读取数值是根具体硬件设备相关,而输入事件的缓冲区管理以及字符设

Linux输入子系统框架分析(1)

在Linux下的输入设备键盘.触摸屏.鼠标等都可以用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层,事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备驱动层将输入事件上报给核心层input.c,核心层找到匹配的事件层,将事件交给事件层处理,事件层处理完后传递到用户空间. 我们最终要搞清楚的是在用户空间调用open和read最终在内核中是怎样处理的,向内核上报的事件又是谁处理的,处理完后是怎样传递到用户空间的? 上面两个图是输入子系统的框架. 下面