偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.
全部博文(1748)
分类: LINUX
2012-09-16 19:17:15
Linux 内核下的 drivers/input/keyboard/gpio_keys.c实现了一个体系结构无关的GPIO按键驱动,使用此按键驱动,只需在arch/arm/mach-s3c2410/mach-smdk2410.c中定义相关的数据即可。驱动的实现非常简单,但是较适合于实现独立式按键驱动,且按键所接端口为中断引脚,如本书硬件平台矩阵按键对应的EINT0,EINT2,EINT11,EINT19中断对应的引脚。如果是矩阵按键,相应代码的改动较大,不宜提倡。
假设在S3C2410开发平台上, 使用GPG3,GPG11,GPF0,GPF2实现了DOWN、ENTER、HOME、POWER四个按键,该法实现驱动程序首先在头文件位置键入以下头文件:
#include
#include
#include
然后在mach-smdk2410.c中键入按键的定义信息:
static struct gpio_keys_button s3c2410_buttons [ ] = {
{
.gpio = S3C2410_GPG3,
.code = KEY_DOWN,
.desc = "Down" ,
.active_low = 1,
},
{
.gpio = S3C2410_GPG11,
.code = KEY_ENTER,
.desc = "Enter " ,
.active_low = 1,
},
{
.gpio = S3C2410_GPF0,
.code = KEY_HOME,
.desc = "Home" ,
.active_low = 1,
},
{
.gpio = S3C2410_GPF2,
.code = KEY_POWER,
.desc = "Power " ,
.active_low = 1,
},
};
static struct gpio_keys_platform_data s3c2410_button_data = {
.buttons = s3c2410_buttons,
.nbuttons = ARRAY_SIZE(s3c2410_buttons) ,
};
static struct platform_device s3c2410_device_button = {
.name = "gpio-keys",
.id =-1,
.dev = {
.platform_data = &s3c2410_button_data,
}
};
其中
n gpio是连接按键的IO管脚。
n code是这个按键上报的键值, 在input.h中定义。
n desc是按键的name。
n active_low为1是表示低电平触发。
将“&s3c2410_device_button,”语句填入 struct platform_device *s3c2410_devices[]数组,作为该数组的一个成员。
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_rtc,
&s3c_device_ts,
&s3c2410_device_button,};
编译内核时选择:
Device Drivers >
Input device support >
[*] Keyboards
<*> GPIO Buttons
如果要修改按键对应的GPIO和键值,只需要简单的修改s3c2410_buttons[]数组中的内容。
这样在内核的启动过程中,会发现如下的提示:
input: gpio-keys as /class/input/input0
同时在文件系统dev目录下有event0设备节点,event1是触摸屏节点,对gpio-keys按键的访问可以通过event0来完成。
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv)
{
int key_state;
int fd;
int ret;
int code;
struct input_event buf;
int repeat_param[2];
fd = open("/dev/input/event0", O_RDONLY);
if (fd < 0)
{
printf("Open gpio-keys failed.\n");
return -1;
}
else
{
printf("Open gpio-keys success.\n");
}
repeat_param[0]=500;//ms重复按键第一次间隔
repeat_param[1]=66;//ms重复按键后续间隔
ret = ioctl(fd,EVIOCSREP,(int *)repeat_param);//设置重复按键参数
if(ret != 0)
{
printf("set repeat_param fail!\n");
}
else
{
printf("set repeat_param ok.\n");
}
while(1)
{
ret = read(fd,&buf,sizeof(struct input_event));
if(ret <= 0)
{
printf("read fail!\n");
return -1;
}
code = buf.code;
key_state = buf.value;
switch(code)
{
case KEY_DOWN:
code = '1';
break;
case KEY_ENTER:
code = '2';
break;
case KEY_HOME:
code = '3';
break;
case KEY_POWER:
code = '4';
break;
default:
code = 0;
break;
}
if(code!=0)
{
printf("Key_%c state= %d.\n",code,key_state);
}
}
close(fd);
printf("Key test finished.\n");
return 0;
}
上述按键驱动涉及到Linux内核的platform设备驱动模型相关知识,读者可自行参考相关内容。