input子系统介绍
Linux内核为了能够处理各种不同类型的输入设备,比如: 触摸屏 ,鼠标 , 键盘 , 操纵杆等设备 ,设计并实现了Linux 输入子系统 ,它为驱动和应用提供了统一的接口函数,方便实现各种输入设备的驱动。
input子系统架构
(1)驱动层功能 :负责和底层的硬件设备打交道,将底层硬件设备对用户输入的响应转换为标准的输入事件以后再向上发送给输入子系统核心层。
(2)Input系统核心层 :由driver/input/input.c及相关头文件实现,它对下提供了设备驱动层的接口,对上提供了事件处理层的编程接口。
(3)事件处理层 :将硬件设备上报的事件分发到用户空间和内核。
重要结构体
//输入设备
struct input_dev {
const char *name; //设备名称
const char *phys; //设备的物理路径
const char *uniq; //唯一ID
struct input_id id; //输入ID
unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; //设备属性
//所支持的input事件,(键盘, 按键,坐标等)
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)]; //音效
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; //力反馈效果
unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; //带开关
unsigned int hint_events_per_packet; //每个包中的平均事件数
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode; //扫描码到键码的映射
int (*setkeycode)(struct input_dev *dev,
const struct input_keymap_entry *ke,
unsigned int *old_keycode);
int (*getkeycode)(struct input_dev *dev,
struct input_keymap_entry *ke);
struct ff_device *ff;
unsigned int repeat_key; //保存上次按下的按键
struct timer_list timer;
int rep[REP_CNT];
struct input_mt *mt; //多点触摸状态
struct input_absinfo *absinfo; //绝对坐标信息
//保存设备的当前状态
unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
struct input_handle __rcu *grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
bool going_away;
struct device dev; //设备
struct list_head h_list;
struct list_head node;
unsigned int num_vals;
unsigned int max_vals;
struct input_value *vals;
};
input_dev代表了一个输入设备,结构体里面就是保存了输入设备的信息,以及不同输入设备的不同事件。
API函数
//分配一个输入设备
struct input_dev *input_allocate_device(void)
//释放输入设备
void input_free_device(struct input_dev *dev)
//注册输入设备到输入核心层
int input_register_device(struct input_dev *dev)
//注销输入设备
void input_unregister_device(struct input_dev *dev)
/*
报告输入事件
参数说明:
dev: 产生事件的设备
type: 事件的类型
code:事件码
value:事件的值
*/
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
//报告按键事件,内部调用input_event
void input_report_key(struct input_dev *dev, unsigned int code, int value)
//报告相对坐标
void input_report_rel(struct input_dev *dev, unsigned int code, int value)
//报告绝对坐标
void input_report_abs(struct input_dev *dev, unsigned int code, int value)
//报告同步事件,用来告诉上层,本次的事件已经完成了
void input_sync(struct input_dev *dev)
//用来设置设备所产生的事件以及上报的按键值
#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p)
输入设备事件类型
EV_SYN 0x00 //同步事件
EV_KEY 0x01 //按键事件
EV_REL 0x02 //相对坐标
EV_ABS 0x03 //绝对坐标
EV_MSC 0x04 //其它
EV_LED 0x11 //LED
EV_SND 0x12 //声音
EV_REP 0x14 //Repeat
EV_FF 0x15 //力反馈
EV_PWR //电源
EV_FF_STATUS //状态
每个事件类型下面会有一些事件码(Event Codes),它会更精准的描述事件类型。
总结
输入设备驱动的内容并不多,主要还是要对设备的工作原理有深入的了解,才能编写对应驱动。
全部0条评论
快来发表一下你的评论吧 !