最近学习了一下Linux的输入子系统编程,做个记录。
简单分为3个部分,一是注册输入设备和键值,二是gpio的配置和申请,最后是中断来临后键值的上报流程。
linux设备的注册都是固定套路,主要区别还是在于硬件平台的不同需要做不同的处理。
static struct input_dev *key_dev;
static irqreturn_t key_interrupt(int irq, void *dummy) //中断处理函数
{
int flag;
s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0)); // 设置gpio为input模式
flag = gpio_get_value(S5PV210_GPH0(2)); // 读取gpio判断是抬起还是按下
s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f)); // 再次设置为中断模式
input_report_key(key_dev, KEY_LEFT, !flag); //上报键值
input_sync(key_dev); //上报同步值
return IRQ_HANDLED;
}
static int __init key_init(void)
{
int error = -1;
key_dev = input_allocate_device(); // 向内核申请输入设备
input_set_capability(key_dev, EV_KEY, KEY_LEFT); //注册键值
error = input_register_device(key_dev); //注册输入设备
error = gpio_request(S5PV210_GPH0(2), "GPH0_2"); // 申请gpio
s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f)); // 配置gpio为中断模式
request_irq(IRQ_EINT2, key_interrupt, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "button-x210", NULL) //配置中断触发方式,上升沿加下降沿触发
return 0;
}
static void __exit key_exit(void)
{
input_unregister_device(key_dev);
free_irq(IRQ_EINT2, button_interrupt); //释放gpio
}
module_init(key_init);
module_exit(key_exit);
代码去掉了错误处理,便于理解流程。
另外通过open /dev/uinput 然后wirte 同样可以上报键值,对于一些小按键很方便。