Linux驱动开发input子系统
Posted XXX_UUU_XXX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux驱动开发input子系统相关的知识,希望对你有一定的参考价值。
input子系统负责处理输入事件,属于字符设备。input子系统分为input驱动层、input核心层和input事件层。系统启动后,在/sys/class/input/路径下显示input子系统。
- input驱动层:输入设备的具体驱动程序,如按键驱动,向内核层报告输入内容。
- input核心层:为驱动层提供输入设备注册和操作接口,通知事件层对输入事件进行处理。
- input事件层:与用户空间进行信息交互。
input子系统的主设备号都是13,不需要注册字符设备,只需注册一个input设备。
Linux定义input_dev结构体表示input设备,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;
;
xxbit表示输入事件类型,事件类型和事件值在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 /* 声音 */
#define EV_REP 0x14 /* 重复事件 */
#define EV_FF 0x15 /* 压力事件 */
#define EV_PWR 0x16 /* 电源事件 */
#define EV_FF_STATUS 0x17 /* 压力状态事件 */
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
使用input_allocate_device申请一个input_dev。
struct input_dev *input_allocate_device(void)
- 返回值:申请到的input_dev。
使用input_free_device释放input_dev。
void input_free_device(struct input_dev *dev);
- dev:要释放的input_dev。
- 返回值:无。
使用input_register_device向Linux内核注册input_dev。
int input_register_device(struct input_dev *dev);
- dev:要注册的input_dev。
- 返回值:0,成功;负值,失败。
使用input_register_device注销input_dev。
void input_unregister_device(struct input_dev *dev);
- dev:要注销的input_dev。
- 返回值:无。
input_dev注册流程
- 使用input_allocate_device申请一个input_dev。
- 初始化input_dev的事件类型和事件值,三种设置方法。
- 使用input_register_device向Linux内核注册input_dev。
- 卸载input驱动,先使用input_unregister_device,然后使用input_free_device。
#define INPUT_DEV_NAME "input_name"
struct input_dev *inputdev; /* input结构体变量 */
static int __init xxx_init(void)
inputdev = input_allocate_device(); /* 申请一个input_dev */
inputdev->name = INPUT_DEV_NAME;
/* 设置事件类型和事件值,以按键为例 */
/* 方法一 */
__set_bit(EV_KEY, inputdev->evbit); /* 设置产生按键事件 */
__set_bit(EV_REP, inputdev->evbit); /* 设置重复事件 */
__set_bit(KEY_0, inputdev->keybit); /* 设置事件值,这里是按键的值 */
/* 方法二 */
inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
inputdev->keybit[BIT_WORD(KEY_0)] |= BIT_MASK(KEY_0);
/* 方法三 */
inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(inputdev, EV_KEY, KEY_0);
input_register_device(inputdev); /* 注册input_dev */
return 0;
static void __exit xxx_exit(void)
input_unregister_device(inputdev); /* 注销input_dev */
input_free_device(inputdev); /* 删除input_dev */
input_dev设备注册成功后,需要上报输入事件(输入的值)。
使用input_event上报事件和对应的值,Linux也提供了其他针对具体事件的上报函数,如input_report_key、input_report_rel、input_report_abs等都是基于input_event函数的,include/linux/input.h。
void input_event(struct input_dev *dev,
unsigned int type,
unsigned int code,
int value)
- dev:要上报的input_dev。
- type:上报的事件类型。
- code:事件码,例如注册的按键值KEY_0等。
- value:事件值,例如1按键按下,0按键松开。
- 返回值:无。
上报事件后,使用input_sync通知Linux内核input子系统上报结束,input_sync本质是上报一个同步事件。
void input_sync(struct input_dev *dev);
- dev:要上报同步的input_dev。
- 返回值:无。
Linux定义input_event结构体表示所有输入事件,include/uapi/linux/input.h。
struct timeval
long tv_sec; /* 秒 */
long tv_usec; /* 微秒 */
;
struct input_event
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
;
- time:事件发生的时间,秒和微秒都是long类型。
- type:事件类型,如按键事件EV_KEY。
- code:事件码,如按键事件中KEY_0、KEY_1等键值。
- value:事件值,如按键事件中1,按键按下;0,按键松开。
input_event类型的原始事件数据值,以KEY_0按键按下和松开为例,使用命令查看input事件信息。
hexdump /dev/input/event1
/* 编号 */ /* tv_sec */ /* tv_usec */ /* type */ /* code */ /* value */
0000000 0c41 0000 d7cd 000c 0001 000b 0001 0000
0000010 0c41 0000 d7cd 000c 0000 0000 0000 0000
0000020 0c42 0000 54bb 0000 0001 000b 0000 0000
0000030 0c42 0000 54bb 0000 0000 0000 0000 0000
- 第 1 行,表示EV_KEY事件,按下按键事件。EV_KEY事件值为1;KEY_0按键编号为11,对应的十六进制为0xb;按键值,1表示按下,0的话表示松开。
- 第 2 行,表示EV_SYN事件,同步。
- 第 3 行,表示EV_KEY事件,松开按键事件。
- 第 4行,表示EV_SYN事件,同步。
以上是关于Linux驱动开发input子系统的主要内容,如果未能解决你的问题,请参考以下文章
i.MX6ULL驱动开发 | 20 - Linux input 子系统