Linux input 子系统应用之按键驱动
硬件平台:s5pv210
软件平台:Linux2.6.35.7
应用程序:inputk2_app.c
#include <stdio.h>
#include <fcntl.h>
#include <linux/input.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int fd;
int count;
int i = 0;
int j = 0;
struct input_event key2;
//在根文件系统用cat /proc/bus/input/devices查看是event几
fd = open("/dev/event1", O_RDWR);
if (fd < 0)
{
perror("open");
return -1;
}
while (1)
{
lseek(fd, 0, SEEK_SET);
count = read(fd, &key2, sizeof(struct input_event));
if(count != sizeof(struct input_event))
{
perror("read");
}
if(EV_KEY == key2.type)
{
printf("\r\ni = %d, type:%d, code:%d, value:%d\r\n", i, key2.type, key2.code, key2.value);
if (key2.value)
{
i++;
printf("***********the k2 down %d times***********\r\n", i);
}
else
{
printf("****************the k2 up*****************\r\n");
}
}
if(EV_SYN == key2.type)
{
printf("syn event\r\n");
if (++j == 2)
{
j = 0;
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n\n");
}
}
}
close(fd);
return 0;
}
驱动程序:inputk2_drv.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <asm/gpio.h>
#include <linux/timer.h>
static struct input_dev *button_dev;//定义输入设备
struct timer_list my_timer;//定义定时器结构体timer_list
//定义定时器超时处理函数
void timer_func(unsigned long data)
{
int key_value = gpio_get_value(S5PV210_GPH2(0));
//上报事件给input核心层
input_report_key(button_dev, KEY_A, !key_value);//按下为1
//告诉input子系统上报已经完成
input_sync(button_dev);
//printk("[%d][%s], data=[%lu]\r\n", __LINE__, __FUNCTION__, data);
}
static irqreturn_t button_interrupt(int irq, void *dev_id)
{
//the value of timeout is decided by the n of "jiffies + n"
//timeout = n*(1000/HZ) ms(HZ=256 in this project)
//the empirical value of timeout ≈ 10~100ms
mod_timer(&my_timer, jiffies + 5);//timeout≈5*4=20ms
return IRQ_HANDLED;
}
static int __init button_init(void)
{
int ret;
ret = gpio_request(S5PV210_GPH2(0), "key2");
if (ret)
{
printk(KERN_ERR "gpio_request Failed to register device\r\n");
goto error1;
}
//为新输入设备分配内存并初始化
button_dev = input_allocate_device();
if (!button_dev)
{
printk(KERN_ERR "can‘t allocate input mem!\r\n");
goto error2;
}
button_dev->name = "gec_input";
button_dev->id.bustype = 0x1;
button_dev->id.product = 0x2;
button_dev->id.vendor = 0x3;
button_dev->id.version = 0x4;
button_dev->evbit[BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY);//set_bit(EV_KEY,button_dev->evbit[BIT_WORD(EV_KEY)])
button_dev->keybit[BIT_WORD(KEY_A)] = BIT_MASK(KEY_A);//set_bit(KEY_A, button_dev->keybit[BIT_WORD(KEY_A)])
//注册一个输入设备
ret = input_register_device(button_dev);
if (ret)
{
printk(KERN_ERR "Failed to register device\r\n");
goto error3;
}
//申请中断注册中断处理函数
ret = request_irq(IRQ_EINT(16), button_interrupt,\
IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING | IRQF_DISABLED, "button", NULL);
if (ret)
{
printk(KERN_ERR "Can‘t request irq %d\r\n", IRQ_EINT(16));
goto error4;
}
//定时器
init_timer(&my_timer);//初始化定时器
my_timer.function = timer_func;//注册定时器超时处理函数
return 0;
error4:
free_irq(IRQ_EINT(16), NULL);//释放分配给已定中断的内存
input_unregister_device(button_dev);
error3:
input_free_device(button_dev);
error2:
ret = -ENOMEM;
error1:
gpio_free(S5PV210_GPH2(0));
return ret;
}
static void __exit button_exit(void)
{
gpio_free(S5PV210_GPH2(0));
free_irq(IRQ_EINT(16), NULL);
input_unregister_device(button_dev);
del_timer(&my_timer);//删除内核定时器
}
module_init(button_init);
module_exit(button_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_LICENSE("GPL");
Makefile:
obj-m += inputk2_drv.o
PWD ?= shell pwd
KDIR := /opt/03.kernel_transplant/android-kernel-samsung-dev
all:
make -C $(KDIR) M=$(PWD) modules
cp ./inputk2_drv.ko /mini_rootfs/modules
cp ./inputk2_app /mini_rootfs/modules
rm -rf ./*.o
rm -rf ./*.order
rm -rf ./*.symvers
rm -rf ./*.mod.c
rm -rf ./.*.cmd
rm -rf ./.*.tmp*
rm -rf ./.tmp_versions
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。