Chinaunix首页 | 论坛 | 博客
  • 博客访问: 830950
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: LINUX

2017-02-21 21:12:20

5. 按键应用层编程
    AP-283Demo 板上有 5 个独立按键。当需要使用这些按键时,要短接 J8C 的 2.6、 2.5、
    2.4、 1.18、 1.17 跳线。
    
    光盘为 AP-283Demo 板上的 5 个独立按键提供了 imx28x_key.ko 驱动文件。把该驱动文
    件上传到 EasyARM-i.MX283A,然后加载驱动:
    root@EasyARM-iMX283 ~# insmod imx28x_key.ko
    input: EasyARM-i.MX28x_key as /devices/virtual/input/input1
    EasyARM-i.MX28x key driver up
    
    驱动模块加载完成后,将在/dev/input 目录生成设备文件,在 EasyARM-i.MX283A 没有
    插入 USB 鼠标和 USB 键盘的情况下,生成的设备文件为/dev/input/event1:
    root@EasyARM-iMX283 ~# ls /dev/input/event*
    /dev/input/event0 /dev/input/event1
    
    在驱动使用完成后,输入下面命令卸载驱动:
    root@EasyARM-iMX283 ~# rmmod imx28x_key.ko
    EasyARM-i.MX28x key driver remove
    
    
5.1 按键编程
    按键驱动加载完成后,应用程序可以读取按键事件,只是应用程序代码中必须包含
    头文件。
    
    1. 按键事件
        通常情况下,输入事件封装成 input_event 结构, 其定义如程序清单 5.1 所示。
        程序清单 5.1 input_event 结构体的定义
            typedef unsigned short int uint16_t;
            typedef short int int16_t;
            typedef uint16_t __u16;
            typedef int16_t __s16;
            struct input_event {
                struct timeval time;
                __u16 type;
                __u16 code;
                __s32 value;
            }
            
        input_event 结构体的 time 成员表示输入事件发生的时间。该成员是一个 timeval 结构体,
        定义如程序清单 5.2 所示。
        程序清单 5.2 timeval 结构体的定义
            typedef long __kernel_time_t;
            typedef long __kernel_suseconds_t
            struct timeval {
                __kernel_time_t tv_sec;
                __kernel_suseconds_t tv_usec;
            }
        其中, tv_sec 为 Epoch( 1970-01-01 00:00)到 timeval 结构体创建时的秒数, tv_usec 为
        秒数后面的零头。
        input_event 结构体的 type 成员表示输入事件的类型。 Linux 定义的输入事件类型如程序
        清单 5.3 所示。
            程序清单 5.3 输入事件类型
            #define EV_SYN 0x00 /* 事件提交,当一个输入事件完成后,要报告一个这样的事件 */
            #define EV_KEY 0x01 /* 按键事件 */
            #define EV_REL 0x02 /* 相对坐标事件,一般为鼠标产生 */
            #define EV_ABS 0x03 /* 绝对坐标事件,一般为触摸屏产生 */
            #define EV_MSC 0x04
            #define EV_SW 0x05
            #define EV_LED 0x11
            #define EV_SND 0x12
            #define EV_REP 0x14
            #define EV_FF 0x15
            #define EV_PWR 0x16
            #define EV_FF_STATUS 0x17
        input_event 结构体的 code 成员表示输入事件的码值。对于不同的输入事件其码值有不
        同的意义。对于按键事件,码值表示用户按下键值。 imx28x_key.ko 驱动支持的健值为:
            #define KEY_A 30
            #define KEY_B 48
            #define KEY_C 46
            #define KEY_D 32
            #define KEY_E 18
        input_event结构体的 value 成员对于不同的输入事件有不同的意义。对于按键事件,value
        可取值为: 1(表示键按下)和 0(表示键提起)。
        
    2. 打开设备文件
        应用程序在使用输入设备时,先调用 open()函数打开输入设备文件,如程序清单 5.4
        所示。
        程序清单 5.4 打开输入设备文件
        fd = open ("/dev/input/event1", RDWR);
        if (fd < 0) {
            printf ("open device failed\n");
            exit(0);
        }
        open()函数调用成功后,将返回文件描述符。
        
    3. 关闭设备文件
        应用程序在不再需要使用输入设备时,调用 close()函数关闭设备文件,如下所示:
        close(fd);    
        
    4. 读取按键事件
        调用 read()函数可以读取按键事件,代码如程序清单 5.5 所示。
        程序清单 5.5 读取按键事件
        int count;
        struct input_event input_event_value;
        count=read(fd, &input_event_value, sizeof(struct input_event));
        if (count < 0) {
            printf("read iput device event error \n");
            return -1;
        }
        read()函数调用时,如果没有输入事件发生会一直等待(进入休眠不返回),直到输入事件发生后才会返回。
        read()函数需要读入数据的大小为 input_event 结构体的大小。 read()函数调用成功后,返
        回一个 input_event 的结构体。在这个返回的 input_event 结构体中,就可以获取输入事件的
        信息。
            
5.2 编程范例
    程序清单 5.6 所示的程序代码循环读取输入事件,并判断输入事件的类型,然后打印
    输入事件的所有信息。
    程序清单 5.6 读取按键示例程序    
      

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <linux/input.h>
  8. int main (int argc, char * argv[])
  9. {
  10.     int fd,count;
  11.     struct input_event input_event_value;
  12.     char input_type[20];
  13.     
  14.     if (argc !=2 ) { /* 判断程序是否有输入参数,如果没有程序退出 */
  15.         printf("usage : input_type /dev/input/eventX\n");
  16.         return 0;
  17.     }
  18.     
  19.     fd = open (argv[1], O_RDWR); /* 打开输入设备,设备的名称为程序的输入参数提供*/
  20.     if (fd < 0) {
  21.         printf ("open %s failed\n", argv[1]);
  22.         exit(0);
  23.     }
  24.     
  25.     /* 循环读取输入事件,然后打印事件信息 */
  26.     while(1) {
  27.         count=read(fd, &input_event_value, sizeof(struct input_event));
  28.         if (count < 0) {
  29.             printf("read iput device event error \n");
  30.             return -1;
  31.         }
  32.         switch(input_event_value.type) { /* 判断事件的类型 */
  33.             case EV_SYN:
  34.                 strcpy(input_type, "SYNC");
  35.             break;

  36.             case EV_REP:
  37.                 strcpy(input_type, "REP");
  38.             break;
  39.             
  40.             case EV_REL:
  41.                 strcpy(input_type, "REL");
  42.             break;
  43.             
  44.             case EV_ABS:
  45.                 strcpy(input_type, "ABS");
  46.             break;
  47.             
  48.             case EV_KEY:
  49.                 strcpy(input_type, "KEY");
  50.             break;
  51.             
  52.             default:
  53.                 printf("even type unkown \n");
  54.                 return -1;
  55.         }
  56.         /* 打印输入事件的时间 */
  57.         printf("time:%ld.%ld",input_event_value.time.tv_sec,input_event_value.time.tv_usec);
  58.         
  59.         /* 打印输入事件的类型、码值、 value 值 */
  60.         printf(" type:%s code:%d value:%d\n",input_type,input_event_value.code,input_event_value.value);
  61.     }
  62.         return 0;
  63. }


    该程序代码打开的输入设备文件名由程序的输入参数提供,所以该程序代码不但可以测
    试按键设备,还可以测试鼠标和触摸屏设备。
    把上述代码交叉编译成 keyInput 程序文件, 其测试方法可以为:
    (1) 把 keyInput 上传到 EasyARM-i.MX283A
    (2) 加载驱动章节编写的驱动程序:input_drv.ko
        root@EasyARM-iMX283 /mnt/drivers/8th_input# insmod input_drv.ko
            input: mx28_inputDevice as /devices/virtual/input/input1
            
        测试是否成功加载按键驱动:可以按下任意按键,可以看到打印输出
        root@EasyARM-iMX283 /mnt/drivers/8th_input# hexdump /dev/input/event1
            0000000 037c 0000 84a2 0003 0001 001f 0001 0000
            0000010 037c 0000 84a2 0003 0000 0000 0000 0000
            0000020 037c 0000 5d0c 0005 0001 001f 0000 0000
            0000030 037c 0000 5ea2 0005 0000 0000 0000 0000
        这说明,按键驱动对应的设备文件为: /dev/input/event1
    
    (3) 输入下面命令执行 keyInput 程序:
        root@EasyARM-iMX28x /mnt# ./keyInput /dev/input/event1        
    
    (4) 测试:
        root@EasyARM-iMX283 /mnt/app_for_hardware/5th_keyInput# ./keyInput /dev/input/event1
        time:1102.720531 type:KEY code:31 value:1   // 按下按键,提交的按键按下事件
        time:1102.720562 type:SYNC code:0 value:0   // 提交的同步SYNC事件
        time:1102.970468 type:KEY code:31 value:2   // 我这里实现了重复事件,就是如果按键一直按下,则提交重复REP事件
        time:1102.970468 type:SYNC code:0 value:1
        time:1103.250437 type:KEY code:31 value:2
        time:1103.250468 type:SYNC code:0 value:1
        time:1103.267812 type:KEY code:31 value:0   // 按键抬起,提交的按键抬起事件
        time:1103.268062 type:SYNC code:0 value:0   // 提交的同步SYNC事件
阅读(1133) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~