Android系統--輸入系統(六)模擬輸入驅動程序
1. 回顧輸入子系統
-
簡單字符設備驅動:應用程序通過調用驅動所實現的函數使能硬件。
-
輸入子系統:由於有多個應用程序使用輸入子系統,故肯定使用的是早已規定好驅動接口,我們所需要實現的這是實現硬件相關的操作。
2. 輸入子系統特性
-
有多套open/read/write接口
-
當應用程序調用這些接口,驅動程序將提供多套實現方法
-
evdev.c(evdev_open/evdev_read/evdev_write),通過這些接口提供原始數據
-
keyboard.c、mousedev.c,得到的是一些加工之后的數據
-
3. Android的輸入系統特性
-
Android系統只使用evdev.c,只處理原始數據
-
內核具有多個接口,應用程序則通過不同的設備節點,來使用特定節點的驅動接口
-
硬件相關:根據硬件的狀態上報數據(原始數據),我們一般只需要實現該功能
-
硬件
4. 如何實現Input驅動
-
分配/構造:input_device結構體
-
注冊:input_register_device
-
有輸入事件產生時,中斷程序上報:input_event(dev,type,code,value)
5. 具體輸入流程框架
-
APP層
-
4、 應用程序open /dev/input/event
-
6、 應用程序read
-
-
驅動層(evdev.c)
-
3、 connect函數被調用:生成一些信息,導致創建設備節點/dev/input/event
-
5、 evdev_open被調用:根據設備節點與 input_device結構體建立聯系
-
7、 evdev_read被調用:無數據,則休眠
-
12、evde_read被喚醒,有數據,開始讀取數據
-
-
硬件相關的驅動層
-
1、 構造input_device結構體
-
2、 注冊該結構體:input_register_device
-
9、 中斷服務程序被掉用:input_event產生數據,上報數據
-
10、 放入evdev的buffer
-
11、 喚醒讀進程
-
-
硬件層
- 8、用戶按下按鍵,產生中斷
6. 忽略復雜的硬件操作,模擬輸入系統的驅動程序
6.1 實現原理
通過另外一個應用程序,打開設備節點,寫數據,喚醒讀進程。
-
APP open節點
-
寫數據(使用Android系統中有sendevent函數)
6.2 驅動實現
-
分配input_device結構
-
設置該結構體
-
注冊該結構體
6.3 具體實現程序
InputEmulator.c
/* 參考drivers\input\keyboard\gpio_keys.c */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/input.h>
static struct input_dev *input_emulator_dev;
static int input_emulator_init(void)
{
int i;
/* 1. 分配一個input_dev結構體 */
input_emulator_dev = input_allocate_device();;
/* 2. 設置 */
/* 2.1 能產生哪類事件 */
set_bit(EV_KEY, input_emulator_dev->evbit); //產生按鍵類似鍵
set_bit(EV_REP, input_emulator_dev->evbit); //重復上報事件
/* 2.2 能產生所有類型的按鍵*/
for(i=0;i<BITS_TO_LONGS(KEY_CNT);i++)
input_emulator_dev->keybit[i] = ~0UL;
/*2.3 為Android構建一些設備信息*/
input_emulator_dev->name = "InputEmulatorFromLKQ";
input_emulator_dev->id.bustype = 1;
input_emulator_dev->id.vendor = 0x1234;
input_emulator_dev->id.product=0x5678;
input_emulator_dev->id.version=1;
/* 3. 注冊 */
input_register_device(input_emulator_dev);
return 0;
}
static void input_emulator_exit(void)
{
input_unregister_device(input_emulator_dev);
input_free_device(input_emulator_dev);
}
module_init(input_emulator_init);
module_exit(input_emulator_exit);
MODULE_LICENSE("GPL");
Makefile
KERN_DIR = /opt/Tiny4412/KernelSrc/linux-3.0.86
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += InputEmulator.o
6.4測試方法
-
insmod InputEmulator.ko
-
打開開發板任意一個文本輸入框
-
串口輸入:
sendevent /dev/input/event5 1 2 1 // 1 2 1 : EV_KEY, KEY_1, down
sendevent /dev/input/event5 1 2 0 // 1 2 0 : EV_KEY, KEY_1, up
sendevent /dev/input/event5 0 0 0 // sync
-
串口輸入:
sendevent /dev/input/event5 1 3 1
sendevent /dev/input/event5 1 3 0
sendevent /dev/input/event5 0 0 0
6.5 實驗現象
開發板文本輸入框出現1和2兩個字符