這個範例用最簡單的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