内核自带按键驱动的添加与测试

一叶浮萍归大海,人生何处不相逢。——吴承恩《西游记》

   前面学习了非内核自带的按键驱动,而内核自带的按键驱动呢,其实分析的过程和其他的LED,LCD,等等有关input输入子系统的驱动差不多,我这里就不详细分析代码了,直接根据朋友的代码学习一波吧。

本文取自:http://blog.csdn.net/qicheng777/article/details/70745409

顺便为我朋友打句广告,他的声卡驱动写得挺好,有兴趣的可以去瞧一瞧。

进入正题:
内核版本:3.0.54
OS:centos 6.7

linux按键驱动主要是中断的处理,中断分为两个部分,前半部分是实际相应中断的函数,需要用request_irq注册,后半部分由前半部分调度,并在一个更安全的时间来执行函数,该函数即为负责执行中断的内容,前半部分不允许被其他中断干扰,后半部分则可以,这种机制的好处是可以迅速的响应中断。

按键驱动具体的驱动程序是:kernel/linux-3.0.54/drivers/input/keyboard/gpio_keys.c

有兴趣的朋友可以深入研究。下面是我们的修改过程:

1.修改mach-smdk2440.c

根据我们的驱动程序可以找到我们的相关设备信息:
.name = "gpio-keys"
将其添加到我们的mach-smdk2440.c
中:

+++ mach-smdk2440.c 2017-04-22 15:36:58.078925861 -0800  
@@ -52,6 +52,15 @@  
 #include <plat/common-smdk.h>  

 #include <linux/dm9000.h>  //添加DM9000网卡的头文件  
+  
+//add for bubtton  
+#include <linux/input.h>    //添加输入子系统头文件  
+  

 static struct map_desc smdk2440_iodesc[] __initdata = {  
    /* ISA IO Space map (memory space selected by A24) */  
@@ -231,13 +240,102 @@  
     .id= 0,  
 };  

+#if 1  
+//add for button  
+  
+   static struct gpio_keys_button rx1950_gpio_keys_table[] = {    
+    {         
+        .code  = KEY_1,               
+        .gpio       = S3C2410_GPF(0),       
+        .active_low = 1,          
+        .desc       = "Button_1",         
+        .wakeup     = 1,      
+    },    
+    {         
+        .code       = KEY_2,       
+        .gpio       = S3C2410_GPF(2),         
+        .active_low = 1,          
+        .desc       = "Button_2",     
+    },    
+    {         
+        .code       = KEY_3,       
+        .gpio       = S3C2410_GPF(3),         
+        .active_low = 1,          
+        .desc       = "Button_3",     
+    },    
+    {         
+        .code       = KEY_4,       
+        .gpio       = S3C2410_GPF(4),        
+        .active_low = 1,          
+        .desc       = "Button_4",     
+    },  
+};   
+      
+static struct gpio_keys_platform_data rx1950_gpio_keys_data = {   
+    .buttons = rx1950_gpio_keys_table,    
+    .nbuttons = ARRAY_SIZE(rx1950_gpio_keys_table),  
+};  
+  
+static struct platform_device rx1950_device_gpiokeys = {      
+    .name = "gpio-keys",      
+    .dev.platform_data = &rx1950_gpio_keys_data,  
+};  

+#endif  

 static struct platform_device *smdk2440_devices[]  __initdata = {  
    &s3c_device_ohci,  
@@ -253,6 +351,16 @@  
     //add for beeper  
     &s3c_device_timer,  
     &smdk2440_beeper_device,  

+     //add for button  
+    &rx1950_device_gpiokeys,  
+  
 };  

 static void __init smdk2440_map_io(void)

添加完以后呢直接编译即可。而我们的menuconfig不用修改,因为内核默认支持按键。

2.在开发板上搞

~>:ls -l /proc/bus/input
这里可以看见handler这个处理输入设备的接口。

~>:cat /proc/bus/input/devices
可以看见为按键时间分配了一个设备节点:
sysfs=/devices/platform/gpio-keys.0/input/input0

Handlers=kbd event0

接下来可以用hexdupm进行简单的测试:
>:hexdump /dev/event0
可以发现每按一个键都会出现四行数据,因为每一次按键包括按下和抬起两个动作,而每个动作结束后还会发生一个同步事件发生。

  每行的倒数第四个数据到倒数第二个数据分别对应***input_event***数据结构:
struct input_event{  
   struct timeval time;
   _u16 type;  //按键类型
   _u16 code;  //按键代码
   _u16 value; //按键的值
};

倒数第三行是我们的按键代码,每个按键代码是唯一的,进过测试得到每个按键代码值为:

KEY_1:2
KEY_2:3
KEY_3:4
KEY_4:5

接下来就根据code值写程序来控制led灯咯。

#include <stdio.h>    
#include<stdint.h>    
#include<string.h>    
#include<fcntl.h>    
#include<unistd.h>    
#include<linux/input.h>    
#include<unistd.h>    


#include <stdlib.h>    

#include <linux/input.h>    

#define EV_PRESS     1  
#define EV_RELEASE   0  
int main(void)    

{    
    char buf[50];   
    int fd_button;    
    int fd_led[4];    
    int i;  

    struct input_event ev_key;    

    fd_button= open("/dev/event0", 666);    

    if(fd_button < 0)    

    {    

        perror("open device buttons");    

        exit(1);    

    }    

    for(i=1;i<=4;i++)  
    {  
        snprintf((char *)buf,sizeof(buf),"/sys/class/leds/led%d/brightness",i);  
        fd_led[i] = open(buf, O_RDWR);  
        if(fd_led[i]<0)  
        {  
             printf("can't open the file led%d",i);  
             return -1;  
        }  
    }   

    while(1)  
    {  
        read(fd_button,&ev_key,sizeof(struct input_event));  
        if(EV_KEY==ev_key.type && EV_PRESS==ev_key.value)   //value=1 表示现在是按下  
        {  
            switch(ev_key.code)    //通过对code传值来确定是哪个按键    
            {   static int count_key1 = 0;                          //定义一个静态变量count_key1 ,来计算按键按下次数  
                case KEY_1:  
                    if(count_key1%2==0)  
                    {     
                        write(fd_led[1],"1",1);    
                        count_key1++;  
                    }  
                    else  
                    {  
                        write(fd_led[1],"0",1);  
                        count_key1++;  
                    }   
                    break;    
                case KEY_2:    
                    write(fd_led[2],"1",1);    
                    sleep(1);    
                    write(fd_led[2],"0",1);    
                    break;    
                case KEY_3:    
                    write(fd_led[3],"1",1);    
                    sleep(1);    
                    write(fd_led[3],"0",1);    
                    break;    
                case KEY_4:    
                    write(fd_led[4],"1",1);    
                    sleep(1);    
                    write(fd_led[4],"0",1);    
                    break;    
                default:    
                    break;        

            }    
        }  
        else if(EV_KEY==ev_key.type && EV_RELEASE==ev_key.value)   //value=0表示现在按键释放  
        {  
            printf("relase the key!\n");  
        }  

    }      

        for(i=1;i<=4;i++)  
        {  
            close(fd_led[i]);  
        }  


    close(fd_button);    
    return 0;    

}    

snprintf( )函数从源码字符串中拷贝n-1到目标串中,再在后面加个0,这里要防止溢出哦。

循环打开led1,led2,led3,led4

char buf[50];
int led[4];


for(i=0; i<=4; i++)
{
   snprintf((char *)buf,sizeof(buf),"/sys/class/leds/led%d/brightness",i);  
   fd_led[i] = open(buf, O_RDWR);  
    if(fd_led[i]<0)
    {
        printf("can't open the file led%d",i);  
        return -1; 
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值