1、将按键以input设备类型注册进内核,下边是input子系统的框架结构
设备节点:是已经注册进内核的设备编程接口,通过它可以实现对输入设备进行硬件操作;
时间处理层:为不同类型的硬件提供用户访问及处理接口
核心层:实现输入子系统的核心功能,屏蔽了用户到设备驱动的交互细节,为事件处理层和设备驱动层提供了相互通信的统一界面,
设备驱动层:实现同具体硬件的交互。
2、input子系统的事件处理机制
3、按键设备驱动涉及的数据结构
//input设备结构/include/linux/input.h,处于硬件驱动层,代表一个input设备
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned longevbit[BITS_TO_LONGS(EV_CNT)];
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
unsigned longrelbit[BITS_TO_LONGS(REL_CNT)];
unsigned longabsbit[BITS_TO_LONGS(ABS_CNT)];
unsigned longmscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned longledbit[BITS_TO_LONGS(LED_CNT)];
unsigned longsndbit[BITS_TO_LONGS(SND_CNT)];
unsigned longffbit[BITS_TO_LONGS(FF_CNT)];
unsigned longswbit[BITS_TO_LONGS(SW_CNT)];
unsigned intkeycodemax;
unsigned intkeycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
int(*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
struct ff_device *ff;
unsigned int repeat_key;
struct timer_listtimer;
int sync;
int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];
unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned longled[BITS_TO_LONGS(LED_CNT)];
unsigned longsnd[BITS_TO_LONGS(SND_CNT)];
unsigned longsw[BITS_TO_LONGS(SW_CNT)];
int absmax[ABS_MAX +1];
int absmin[ABS_MAX +1];
int absfuzz[ABS_MAX +1];
int absflat[ABS_MAX +1];
int absres[ABS_MAX +1];
int (*open)(structinput_dev *dev);
void (*close)(structinput_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*grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
int going_away;
struct devicedev;
struct list_head h_list;
struct list_head node;
};
//标示设备驱动特征/include/linux/input.h
struct input_id {
__u16 bustype;//总线类型
__u16 vendor;//厂商ID
__u16 product;//产品类型
__u16 version;//版本
};
//事件处理器的结构体,处于事件处理层,代表一个事件处理器
struct input_handler {
void*private;
void (*event)(struct input_handle *handle, unsigned int type, unsigned intcode, int value);
int(*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
void(*start)(struct input_handle *handle);
const struct file_operations *fops;
int minor;
const char *name;
const structinput_device_id *id_table;
const structinput_device_id *blacklist;
struct list_head h_list;
struct list_head node;
};
//保存配对成功的一组input_dev和input_handler,处于核心层
struct input_handle {
void *private;
int open;
const char *name;
struct input_dev *dev;
struct input_handler*handler;
struct list_head d_node;
struct list_head h_node;
};
//表述按键的数据和属性
struct gpio_button_data {
struct gpio_keys_button*button;
struct input_dev*input;
struct timer_listtimer;
struct work_structwork;
};
//标示按键驱动数据 在driver文件中创建
struct gpio_keys_drvdata {
struct input_dev*input;
struct gpio_button_datadata[0];
};
//保存按键的硬件特性和配置
struct gpio_keys_button {
/* Configurationparameters */
int code; /* input event code (KEY_*, SW_*) */
int gpio;
int active_low;
char *desc;
int type; /* input event type (EV_KEY, EV_SW) */
int wakeup; /* configure the button as a wake-upsource */
int debounce_interval; /* debounce ticks interval in msecs */
};
//按键的平台数据 在device文件中创建
struct gpio_keys_platform_data {
struct gpio_keys_button*buttons;
int nbuttons;
unsigned int rep:1; /* enable input subsystem auto repeat */
};
4、按键驱动重要代码和函数分析
endev.c:该文件实现了事件处理层的函数,为应用层的事件处理提供了交互的接口,
input.c:该文件实现了注册input设备、事件处理器、input_handle的函数,以及其他一些核心层的公共函数
gpio-keys.c:该文件实现了对按键硬件层的操作接口,
详细代码,请查阅对应文件。