一、input子系统简介
input 子系统用于管理输入,系统框架如下:
编写驱动时,只要向核心层上报输入的事件,核心层会为用户提供一个存储了输入信息的设备节点。
1、核心层简介
核心层文件定义在 drivers/input/inut.c 。
核心层会向内核注册一个 input 类,系统启动后可以在 /sys/class 目录下找到一个 input 的子目录。
核心层注册了一个字符设备,主设备号为 INPUT_MAJOR(13),因此所有 input 子系统的设备的主设备号都是 13。
2、驱动层编写
1)input_dev结构体
使用 input 子系统需要注册一个 input_dev,结构体定义在 include/linux/input.h:
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; /* 事件类型的位图 */
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; /* 按键值的位图 */
unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; /* 相对坐标的位图 */
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; /* 绝对坐标的位图 */
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; /* 杂项事件的位图 */
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; /*LED相关的位图 */
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];/* sound有关的位图 */
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; /* 压力反馈的位图 */
unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; /*开关状态的位图 */
......
bool devres_managed;
};
第 9 行,evbit 表示输入事件类型,可选事件定义在 include/uapi/linux/input.h 中:
#define EV_SYN 0x00 /* 同步事件 */
#define EV_KEY 0x01 /* 按键事件 */
#define EV_REL 0x02 /* 相对坐标事件 */
#define EV_ABS 0x03 /* 绝对坐标事件 */
#define EV_MSC 0x04 /* 杂项(其他)事件 */
#define EV_SW 0x05 /* 开关事件 */
#define EV_LED 0x11 /* LED */
#define EV_SND 0x12 /* sound(声音) */
#define EV_REP 0x14 /* 重复事件 */
#define EV_FF 0x15 /* 压力事件 */
#define EV_PWR 0x16 /* 电源事件 */
#define EV_FF_STATUS 0x17 /* 压力状态事件 */
第 10~17 行都是存放不同事件对应的值,如果使用 key 则用到 keybit,linux 内核在 include/uapi/linux/input.h 定义了很多键值:
#define KEY_RESERVED 0
#define KEY_ESC 1
#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5
#define KEY_5 6
#define KEY_6 7
#define KEY_7 8
#define KEY_8 9
#define KEY_9 10
#define KEY_0 11
......
#define BTN_TRIGGER_HAPPY39 0x2e6
#define BTN_TRIGGER_HAPPY40 0x2e7
2)input_allocate_device函数
input_allocate_device 函数用于申请一个 input_dev,函数原型如下:
struct input_dev *input_allocate_device(void)
返回值:申请到的 input_dev。
3)input_free_device函数
input_free_device 函数用于释放申请的 input_dev,函数原型如下:
void input_free_device(struct input_dev *dev)
dev:要释放的 input_dev。
4)input_register_device函数
在申请 input_dev 后,需要对成员进行初始化,初始化完成后要使用 input_register_device 函数向内核注册 input_dev,函数原型如下:
int input_register_device(struct input_dev *dev)
dev:要注册的 input_dev。
返回值:0,成功;负值,失败。
5)input_unregister_device函数
注销驱动时要使用 input_unregister_device 函数来注销 input_dev,函数原型如下:
void input_unregister_device(struct input_dev *dev)
dev:要注销的 input_dev。
6)input_dev 注册框架