最近需要在kernel 的驅動裏邊將事件傳到用戶空間,打算用input子系統做,用戶空間開一個線程用epoll方式來讀取數據,
記錄一下如何快速簡單使用input子系統上報事件。
//定義一個input_dev 類型結構體變量
static struct input_dev* test_input_dev = NULL;
//創建並初始化
test_input_dev = input_allocate_device();
if (test_input_dev == NULL) {
printk(KERN_ERR"failed to allocate test input device\n");
return -1;
}
test_input_dev->name = "test_input_event";
set_bit(EV_MSC, test_input_dev->evbit);
set_bit(MSC_RAW, test_input_dev->mscbit);
//註冊節點
if (input_register_device(test_input_dev)) {
pr_err("%s: failed to register test input device\n", __func__);
input_free_device(test_input_dev);
return -1;
}
/*邏輯處理*/
//上報事件
input_event(test_input_dev, EV_MSC, MSC_RAW, value);
input_sync(test_input_dev);
//隨驅動取消註冊
input_unregister_device(test_input_dev);
input_free_device(test_input_dev);
關於爲何要用EV_MSC類型,是因爲這次上報事件的類型input裏邊沒有定義,並且有時若你要上報的值範圍不在input子系統對應類型規定的值範圍內會出現值報不上去的情況,所以乾脆用EV_MSC比較好。另外一個原因就是以前在Android 8.1(高通驍龍845平臺,kernel 4.9)上用ABS類型可以報上去的值,到了android 9.0(同樣高通驍龍845平臺,kernel 4.9)就報不上去了,具體原因還沒有去深究。
簡單跟了一下源碼,爲何報不上去,應該是初始化的時候需要設定一個上報值的範圍,後面調用input_event()上報事件的時候有一個過濾檢測:
//android/kernel/msm-4.9/drivers/input/input.c
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);
}
}
static inline int is_event_supported(unsigned int code,
unsigned long *bm, unsigned int max)
{
return code <= max && test_bit(code, bm);
}