這個範例用最簡單的input device driver來解釋必要的部分,首先用input_allocate_device()取得"struct input_dev",接著填入必要欄位,如evbit,這個範例是只會產生EV_KEY event type,且key/event code只有KEY_UP(103)與KEY_DOWN(108),之後呼叫input_register_device(btn_dev)向系統註冊一個input device。
我用QEMU跑,沒有實際的硬體可以驅動該input device,所以我在sys底下創建一個sysfs_report_key讓input device送event。
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/device.h>
#include <linux/sysfs.h>
static struct input_dev *btn_dev;
static ssize_t sysfs_report_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n)
{
int key, value;
if (sscanf(buf, "%d %d", &key, &value) != 2) {
printk("invalid format:%s", buf);
return n;
}
printk("key:%d, value:%d", key, value);
input_report_key(btn_dev, key, value);
input_sync(btn_dev);
return n;
}
static DEVICE_ATTR_WO(sysfs_report_key);
static int __init button_init(void)
{
int ret;
btn_dev = input_allocate_device();
if (btn_dev == NULL) {
printk(KERN_ERR "Not enough memory\n");
return -ENOMEM;
}
btn_dev->name = "brook-input-dev";
btn_dev->evbit[0] = BIT(EV_KEY);
set_bit(KEY_UP, btn_dev->keybit);
set_bit(KEY_DOWN, btn_dev->keybit);
ret = input_register_device(btn_dev);
if (ret) {
dev_err(&(btn_dev->dev), "Failed to register device\n");
goto err_free_dev;
}
/* used for send event from user-space. please ignore it */
ret = device_create_file(&(btn_dev->dev), &dev_attr_sysfs_report_key);
if (ret) {
dev_err(&(btn_dev->dev), "cannot create sysfs attribute\n");
goto err_unreg_dev;
}
return 0;
err_unreg_dev:
input_unregister_device(btn_dev);
err_free_dev:
input_free_device(btn_dev);
return ret;
}
static void __exit button_exit(void)
{
input_unregister_device(btn_dev);
input_free_device(btn_dev);
}
module_init(button_init);
module_exit(button_exit);
MODULE_LICENSE("GPL");
執行結果
/ # insmod inputdev.ko
[60145.219561] inputdev: loading out-of-tree module taints kernel.
[60145.277803] input: brook-input-dev as /devices/virtual/input/input3
/ # ./input_test /dev/input/event1 &
送出KEY_UP(103)後,input_test會收到event。
/ # echo '103 1' > /sys/devices/virtual/input/input3/sysfs_report_key
type:1, code:103, val:1
type:0, code:0, val:0
重複的送出KEY_UP(103),input_test不會收到event。
/ # echo '103 1' > /sys/devices/virtual/input/input3/sysfs_report_key
[60174.829756] key:103, value:1
/ # echo '103 0' > /sys/devices/virtual/input/input3/sysfs_report_key
[60182.965543] key:103, value:1
type:1, code:103, val:0
/ # type:0, code:0, val:0
Key value只有0/1。
/ # echo '103 2' > /sys/devices/virtual/input/input3/sysfs_report_key
[60189.286751] key:103, value:0
type:1, code:103, val:1
/ # type:0, code:0, val:0
其他的key/event code是不會被送出。
/ # echo '105 2' > /sys/devices/virtual/input/input3/sysfs_report_key
[60194.705307] key:103, value:2
/ # echo '108 2' > /sys/devices/virtual/input/input3/sysfs_report_key
[60201.887535] key:105, value:2
type:1, code:108, val:1
type:0, code:0, val:0
基本上,所有的input_report_xxx()/input_sync底層都是呼叫input_event,input_report_key的value只有0/1。
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_KEY, code, !!value);
}
static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_REL, code, value);
}
static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_ABS, code, value);
}
static inline void input_report_ff_status(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_FF_STATUS, code, value);
}
static inline void input_report_switch(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_SW, code, !!value);
}
static inline void input_sync(struct input_dev *dev)
{
input_event(dev, EV_SYN, SYN_REPORT, 0);
}
input_event() 在送出key/event code之前,會先判斷送的event type與當初device設定的是否一致。
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
unsigned long flags;
if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);
input_handle_event(dev, type, code, value);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
重複的KEY value是不會被設成INPUT_PASS_TO_HANDLERS,也就是INPUT_IGNORE_EVENT。
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
int disposition = input_get_disposition(dev, type, code, &value);
...
}
static int input_get_disposition(struct input_dev *dev,
unsigned int type, unsigned int code, int *pval)
{
int disposition = INPUT_IGNORE_EVENT;
int value = *pval;
switch (type) {
...
case EV_KEY:
if (is_event_supported(code, dev->keybit, KEY_MAX)) {
/* auto-repeat bypasses state updates */
if (value == 2) {
disposition = INPUT_PASS_TO_HANDLERS;
break;
}
if (!!test_bit(code, dev->key) != !!value) {
__change_bit(code, dev->key);
disposition = INPUT_PASS_TO_HANDLERS;
}
}
break;
...
}
*pval = value;
return disposition;
}
參考資料:
- Documentation/input/input-programming.rst