1:概述
按键驱动实现的过程,主要完成:input_dev的申请和注册,按键中断的实现,中断底半部的实现,在中断底半部调用事件上报函数,完成按键键值的上报;如果增加按键防抖,需要实现一个内核定时器。本文主要分析的是内核中的gpio_keys.c的文件,这是内核提供的参考,我们就借鉴这个文件,来实现我们的按键驱动,首先,看看内核中已经实现的和按键驱动有关的数据结构;
2:和按键相关的数据结构
我们的按键驱动是挂在平台设备上的,所以先看和platform_device有关的数据结构;
2.1:gpio_keys_button:描述一个物理按键,包括基本的按键信息
struct gpio_keys_button {
/* Configuration parameters */
unsigned int code; //键值
int gpio; //io口
int active_low; //低电平收否有效
const char *desc; //按键名字
unsigned int type; //事件支持的事件类型,常用EV_KEY
int wakeup; //是否配置这个按键为唤醒源
int debounce_interval; //按键防抖延迟,单位为ms
bool can_disable;
int value; //按键事件为EV_ABS时用
};
2.2:gpio_keys_platgorm_data:平台设备的私有数据结构,用来描述驱动中所有按键的信息,以及一些通用的方法;这些值全部由用户设置
struct gpio_keys_platform_data {
struct gpio_keys_button *buttons; //指向具体的一个按键
int nbuttons; //驱动中按键的个数
unsigned int poll_interval;
unsigned int rep:1; //使能按键的重复上报
int (*enable)(struct device *dev); //使能设备的方法,用户可提供
void (*disable)(struct device *dev); //禁止设备的方法,用户可提供
const char *name; //用户设置的input_dev的名字
};
然后就是和驱动相关的数据结构:
2.3:gpio_button_data:上面看了一个具体的物理案件的结构描述,这个就是驱动中描述具体一个按键的具体结构;
struct gpio_button_data {
struct gpio_keys_button *button; //指向这个按键的物理描述
struct input_dev *input; //指向输入设备结构
struct timer_list timer; //定义一个定时器,用于防抖
struct work_struct work; //工作队列,作为按键中断和定时器中断的底半部
int timer_debounce; //防抖时间
bool disabled; //标志为
};
2.4:上面我们看了驱动中一个按键描述结构,不过一般的设备中存在多个按键,此时,就需要下面的结构,来描述整个驱动中的所有按键;
struct gpio_keys_drvdata {
struct input_dev *input; //输入设备
struct mutex disable_lock; //互斥锁
unsigned int n_buttons; //设备中按键的数量
int (*enable)(struct device *dev); //使能设备函数
void (*disable)(struct device *dev); //禁止设备函数
struct gpio_button_data data[0]; //空指针,不占用结构体内存,这个结构描述一个单独的按键设备
};
以上的结构就是内核提供的按键驱动的数据结构,为什么要贴这些出来,以为数据结构的构建对与内核来说,是整个骨架。驱动的难点也是构建合理科学的数据结构来描述设备,下面,看看具体代码中的实现,