ARM Linux 驱动Input子系统之按键驱动测试

上一篇已经谈过,在现内核的中引入设备树之后对于内核驱动的编写,主要集中在硬件接口的配置上了即xxxx.dts文件的编写。

在自己的开发板上移植按键驱动:

1、根据开发板的原理图

确定按键的硬件接口为:GPIO2_2、GPIO2_3、GPIO2_5、GPIO0_30。

修改dts文件使其与原理图的按键接口一致。

gpio_buttons: [email protected]0 {
        compatible = "gpio-keys";
        #address-cells = <1>;
        #size-cells = <0>;

        switch@1 {
            label = "button0";
            linux,code = <0x100>;
            gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
        };

        switch@2 {
            label = "button1";
            linux,code = <0x101>;
            gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
        };

        switch@3 {
            label = "button2";
            linux,code = <0x102>;
            gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
            gpio-key,wakeup;
        };

        switch@4 {
            label = "button3";
            linux,code = <0x103>;
            gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
        };
    };
gpio_keys_s0: gpio_keys_s0 {
        pinctrl-single,pins = <
            0x94 (PIN_INPUT_PULLDOWN | MUX_MODE7)    /* gpmc_oen_ren.gpio2_3 */
            0x90 (PIN_INPUT_PULLDOWN | MUX_MODE7)    /* gpmc_advn_ale.gpio2_2 */
            0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7)    /* gpmc_wait0.gpio0_30 */
            0x9c (PIN_INPUT_PULLDOWN | MUX_MODE7)    /* gpmc_ben0_cle.gpio2_5 */
        >;
    };

保存编译生成zyr-am335x-evmsk.dtb

在内核中确保xxx/linux3.14.65/drivers/input/keyboard/gpio_key.c被编译进去(可以通过各层的Makefile与Kconfig还有menuconfig来实现)

编译好的内核和dtb文件下载到开发板中查看按键的事件类型:

[[email protected]am335x mnt]#cd
[[email protected]-am335x ]#cat /proc/bus/input/devices
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="gpio_buttons.7"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/gpio_buttons.7/input/input0
U: Uniq=
H: Handlers=event0
B: PROP=0
B: EV=3
B: KEY=f 0 0 0 0 0 0 0 0

[[email protected]-am335x ]#

可以看到按键的事件或者是用户接口吧为event0.。知道了用户的按键接口就可以编写测试程序了。

测试程序目的:实现一个按键对应一个LED灯,按键按一次LED灯的状态变化一次(前提是led子系统对应的LED驱动已经加载入内核中):

#include <stdio.h>
#include <linux/input.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>

void keyboard_test()
{
    int count_sw1 = 0;
    int count_sw2 = 0;
    int count_sw3 = 0;
    int count_sw4 = 0;
    int fd=open("/dev/input/event0",O_RDWR);
    if( fd <= 0 )
    {
        printf("Can not open keyboard input file\n");
    }

    struct input_event *event;
    char buf[128] = {0};
    fd_set rfds;
    FD_ZERO(&rfds);
    FD_SET(fd, &rfds);

    while(1)
    {
        int ret = select(fd + 1,&rfds, NULL,NULL,NULL);
        if(ret < 0)
            continue;
        if( FD_ISSET(fd, &rfds) )
        {
            int readn = read(fd, buf, sizeof(struct input_event));
            if (readn <= 0)
            {
                printf("uart read error %d\n", readn);
                continue;
            }

            struct input_event *my_event=(struct input_event*)buf;
            if(my_event->type == EV_KEY)
            {
                switch( my_event->code )
                {
                    case 256:
                        printf("This is a button:%d %d\n", my_event->code,my_event->value);
                        count_sw1++;
                        if(count_sw1==1)
                        {
                            system("echo 1 > /sys/class/leds/zyrD1:green:usr0/brightness");
                        }
                        else if(count_sw1==4)
                        {
                            system("echo 0 > /sys/class/leds/zyrD1:green:usr0/brightness");
                            count_sw1=0;
                        }
                        break;
                    case 257:
                        printf("This is a button:%d %d\n", my_event->code,my_event->value);
                        count_sw2++;
                        if(count_sw2==1)
                        {
                            system("echo 1 > /sys/class/leds/zyrD2:green:usr1/brightness");
                        }
                        else if(count_sw2==4)
                        {
                            system("echo 0 > /sys/class/leds/zyrD2:green:usr1/brightness");
                            count_sw2=0;
                        }
                        break;
                    case 258:
                        printf("This is a button:%d %d\n", my_event->code,my_event->value);
                        count_sw3++;
                        if(count_sw3==1)
                        {
                            system("echo 1 > /sys/class/leds/zyrD3:green:heartbeat/brightness");
                        }
                        else if(count_sw3==4)
                        {
                            system("echo 0 > /sys/class/leds/zyrD3:green:heartbeat/brightness");
                            count_sw3=0;
                        }
                        break;
                    case 259:
                        printf("This is a button:%d %d\n", my_event->code,my_event->value);
                        count_sw4++;
                        if(count_sw4==1)
                        {
                            system("echo 1 > /sys/class/leds/zyrD4:green:mmc0/brightness");
                        }
                        else if(count_sw4==4)
                        {
                            system("echo 0 > /sys/class/leds/zyrD4:green:mmc0/brightness");
                            count_sw4=0;
                        }
                        break;
                    default:
                        break;

                }
            }

        }

    }
}

int main()
{
    keyboard_test();
    return 0;
}

将生成的可执行文件copy到nfs的共享目录下运行:

[[email protected] ]#cd mnt/
[[email protected]-am335x mnt]#ls
LED_zixitong       gpio_keys.ko       leds-gpio.ko       zyr-hello.ko
gpio_buttons_leds  led_test           zleds-gpio.ko
[[email protected]-am335x mnt]#./gpio_buttons_leds
This is a button:257 1
This is a button:257 0
This is a button:258 1
This is a button:258 0
This is a button:259 1
This is a button:259 0
This is a button:256 1
This is a button:256 0
This is a button:256 1
This is a button:256 0
This is a button:257 1
This is a button:257 0
This is a button:258 1
This is a button:258 0
This is a button:259 1
This is a button:259 0其中的256,257,258,259分别对应dts文件中的linux,code = <0x101>;linux,code = <0x102>;linux,code = <0x103>;linux,code = <0x104>;
				
时间: 2024-11-03 03:32:48

ARM Linux 驱动Input子系统之按键驱动测试的相关文章

linux kernel input 子系统分析

Linux 内核为了处理各种不同类型的的输入设备 , 比如说鼠标 , 键盘 , 操纵杆 , 触摸屏 , 设计并实现了一个对上层应用统一的试图的抽象层 , 即是Linux 输入子系统 . 输入子系统的层次结构体如下 从底层到上层 , input 子系统由 设备驱动层 , 核心层 , 以及事件处理层3个部分组成 当一个鼠标移动, 一个按键按下或弹起 , 它都需要从底层设备驱动-->核心层-->事件处理层 -->用户空间 , 层层上报 , 一直到运用程序. 应用这个input  子系统有如下优

Linux/Android——input子系统核心

之前的博客有涉及到linux的input子系统,这里学习记录一下input模块. input子系统,作为管理输入设备与系统进行交互的中枢,任何的输入设备驱动都要通过input向内核注册其设备, 常用的输入设备也就是鼠标,键盘,触摸屏. 稍微细分一点整个输入体系,就是 硬件驱动层,input核心中转层,事件处理层.层次之间传递都以event事件的形式,这其中input连接上下层,分别提供接口. 之前有分析usbtouchscreen的驱动,也就是硬件驱动部分,这里简单记录一下input核心中转处理

Linux/Android——input子系统核心 (三)【转】

本文转载自:http://blog.csdn.net/jscese/article/details/42123673 之前的博客有涉及到linux的input子系统,这里学习记录一下input模块. input子系统,作为管理输入设备与系统进行交互的中枢,任何的输入设备驱动都要通过input向内核注册其设备, 常用的输入设备也就是鼠标,键盘,触摸屏. 稍微细分一点整个输入体系,就是 硬件驱动层,input核心中转层,事件处理层.层次之间传递都以event事件的形式,这其中input连接上下层,分

输入子系统之按键驱动

上一篇博文<input输入子系统框架分析>,尝试使用这种驱动模型来看一个按键驱动程序. 下面的程序是根据韦东山老师写的代码进行修改的,我的开发板是tq2440. button.c文件: #include <linux/module.h> #include <linux/version.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/interrupt.h>

input子系统——架构、驱动、应用程序

一.input子系统架构 input子系统由驱动层drivers,输入子系统核心层input core,事件处理层event handler组成. 一个输入事件,通过输入设备发给系统如鼠标移动,键盘按键按下等通过device driver->input core(handler->event函数)->event handler->user space的顺序到达用户空间传给应用程序. 一个输出事件,通过系统发给输入设备,通过user space->event handler-&

linux系统下标准GPIO按键驱动

前言: linux下platform平台驱动是为了方便隔离bsp与driver,利于移植.体现好代码的高内聚,低耦合.Linux设备驱动模型中,关心总线,设备和驱动三个实体.总线将设备和驱动绑定.在系统每注册一个设备的时候,都会寻找与之相匹配的驱动,相反的,每加载一个驱动的时候,也会寻找与之匹配的设备.匹配由总线完成.linux发明了一种虚拟的总线,称之为platform总线,相应的设备称之为platform_device,驱动为platform_driver. 基于这个模型,又根据面向对象的思

linux的Input子系统获取Device Name

linux内核提供了一个Input子系统来实现的,Input子系统会在/dev/input/路径下创建我们硬件输入设备的节点,一般情况下在我们的 手机中这些节点是以eventXX来命名的,如event0,event1等等,可以利用EVIOCGNAME获取此事件结点名称.这就是android 中对于input事件处理数据的来源点. --------------- 通过ioctl命令EVIOCGNAME,能获取dev/input/event*对应的Device Name. 实例: openInput

linux driver: input子系统

<韦东山Linux视频第2期_从零写驱动\第13课第1节 输入子系统概念介绍_P.wmv> 本视频对输入子系统的结构进行了详细的剖析,通过本视频,可以了解到input核心包括了设备和handler,设备和handler之间是如何建立联系的,一个输入事件是如何响应的. <韦东山Linux视频第2期_从零写驱动\第13课第2节 输入子系统第编写驱动程序_P.wmv> 本视频主要教授如何在系统的框架下,编写一个输入子系统的驱动.一个输入事件的具体响应函数,注册等.

Linux input子系统编程、分析与模板

输入设备都有共性:中断驱动+字符IO,基于分层的思想,Linux内核将这些设备的公有的部分提取出来,基于cdev提供接口,设计了输入子系统,所有使用输入子系统构建的设备都使用主设备号13,同时输入子系统也支持自动创建设备文件,这些文件采用阻塞的IO读写方式,被创建在"/dev/input/"下.如下图所示.内核中的输入子系统自底向上分为设备驱动层,输入核心层,事件处理层.由于每种输入的设备上报的事件都各有不同,所以为了应用层能够很好识别上报的事件,内核中也为应用层封装了标准的接口来描述