linux 的input 子系统主要分:input驱动层、input core层,input handle层与应用空间层,应用空间层不属于内核,处于应用的范畴。
input core 与 input handle是linux 内核实现好的部分,不需驱动程序员来处理,如果想完成输入设备的驱动,只需现实input driver层的代码。
实现一个input 设备驱动主要实现这几步代码。
1. 包含头文件
#include <linux/input.h>
2. 申请input 设备并初始化
struct input_dev *input_allocate_device(void)
{
struct input_dev *dev;
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
dev->dev.type = &input_dev_type;
dev->dev.class = &input_class;
device_initialize(&dev->dev);
mutex_init(&dev->mutex);
spin_lock_init(&dev->event_lock);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
__module_get(THIS_MODULE);
}
return dev;
}
3. 注册input 设备到系统
int input_register_device(struct input_dev *dev)
4. 注销input 设备
void input_unregister_device(struct input_dev *dev)
5. 释放input 设备
void input_free_device(struct input_dev *dev)
简单例子:G-sensor 设备BMA250的input 驱动实现代码:
(1). 申请设备并注册部分代码
static int bma250_input_init(struct bma250_data *bma250)
{
struct input_dev *dev;
int err;
dev = input_allocate_device();
if (!dev)
return -ENOMEM;
dev->name = "acc"; //SENSOR_NAME; changed for sku1 compatible
dev->id.bustype = BUS_I2C;
/* X */
input_set_capability(dev, EV_REL, REL_RX);
input_set_abs_params(dev, REL_RX, ABSMIN_2G, ABSMAX_2G, 0, 0);
/* Y */
input_set_capability(dev, EV_REL, REL_RY);
input_set_abs_params(dev, REL_RY, ABSMIN_2G, ABSMAX_2G, 0, 0);
/* Z */
input_set_capability(dev, EV_REL, REL_RZ);
input_set_abs_params(dev, REL_RZ, ABSMIN_2G, ABSMAX_2G, 0, 0);
input_set_drvdata(dev, bma250);
err = input_register_device(dev);
if (err < 0) {
input_free_device(dev);
return err;
}
bma250->input = dev;
return 0;
}
(2). 注销部分代码
static void bma250_input_delete(struct bma250_data *bma250)
{
struct input_dev *dev = bma250->input;
input_unregister_device(dev);
input_free_device(dev);
}
input 子系统的驱动层先调用input_alloc_device申请input device并初始化,接着调用input_register_device把input device注册到input core层。
input core层通过handle处理把input device与input handler绑定在一起,驱动层通过timer轮询或中断的方式把设备端提供的数据通过一定的处理传到handle层的buffer,用户空间先打开该input device, 再调用read来获取驱动传给handle层的数据。