linux驱动——input输入子系统(2)——handler

时间:2020-12-31 17:56:53


linux驱动——input输入子系统(1)—输入子系统核心层(Input Core)的链接地址



input_handler一般称为handler处理器,表示对输入事件的具体处理。 input_handler为输入设备的功能实现了一个接口,输入事件最终传递到handler处理器,handler处理器根据一定的规则,然后对事件进行处理。

input_handler是输入设备的事件处理接口,为处理事件提供一个统一的函数模板,程序员应该根据具体的需要实现其中的一些函数,并将其注册到输入子系统中。

1、struct input_handler结构体

/**
 * struct input_handler - implements one of interfaces for input devices
 * @private: driver-specific data    驱动的数据
 * @event: event handler. This method is being called by input core with
 * interrupts disabled and dev->event_lock spinlock held and so
 * it may not sleep 被输入子系统调用去处理发送给设备的事件,不可睡眠
 * @connect: called when attaching a handler to an input device用来连接handle和input device(用input_dev表示)
 * @disconnect: disconnects a handler from input device  断开连接
 * @start: starts handler for given handle. This function is called by
 * input core right after connect() method and also when a process
 * that "grabbed" a device releases it

 * @fops: file operations this driver implements    handler实现的文件操作集
 * @minor: beginning of range of 32 minors for devices this driver
 * can provide   次设备号
 * @name: name of the handler, to be shown in /proc/bus/input/handlers  
 * @id_table: pointer to a table of input_device_ids this driver can
 * handle  表示驱动能处理的表

 * @blacklist: pointer to a table of input_device_ids this driver should
 * ignore even if they match @id_table这个表包含了驱动应该忽略的设备
 * @h_list: list of input handles associated with the handler
 * @node: for placing the driver onto input_handler_list  连接到全局的 input_handler_list 链表中。
 *
 * Input handlers attach to input devices and create input handles. There
 * are likely several handlers attached to any given input device at the
 * same time. All of them will get their copy of input event generated by
 * the device.
 *
 * Note that input core serializes calls to connect() and disconnect()
 * methods.
 */
struct input_handler {


void *private;

void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, 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 struct input_device_id *id_table;
const struct input_device_id *blacklist;


struct list_headh_list;
struct list_headnode;
};

2、注册input_handler

input_register_handler()函数注册一个新的input handler处理器。这个handler将为输入设备使用,一个handler可以添加到多个支持它的设备中,也就是一个handler可以处理多个输入设备的事件。

函数源码在Input.c (linux2.6.28\drivers\input)文件中,如下:

/**
 * input_register_handler - register a new input handler  注册一个新的input handler
 * @handler: handler to be registered
 *
 * This function registers a new input handler (interface) for input
 * devices in the system and attaches it to all input devices that
 * are compatible with the handler.

 */
int input_register_handler(struct input_handler *handler)
{
struct input_dev *dev;
int retval;

retval = mutex_lock_interruptible(&input_mutex);加锁
if (retval)
return retval;


INIT_LIST_HEAD(&handler->h_list);初始化h_list链表


if (handler->fops != NULL) {    看到这,是否想起上一篇中说到的内容了呢?
if (input_table[handler->minor >> 5]) {
retval = -EBUSY;
goto out;
}
input_table[handler->minor >> 5] = handler;  以handler->minor右移5位作为索引值插入到input_table[ ]中
}


list_add_tail(&handler->node, &input_handler_list);  将handler加入全局的input_handler_list链表中

其中有:static LIST_HEAD(input_handler_list);


list_for_each_entry(dev, &input_dev_list, node)  其中有:static LIST_HEAD(input_dev_list);
input_attach_handler(dev, handler);    input_attach_handler()这个函数的作用是匹配 input_dev_list链表中的input_dev与handler。如果成功会将input_dev与handler联系起来。


input_wakeup_procfs_readers();


 out:
mutex_unlock(&input_mutex);   解锁
return retval;
}

3、下面来介绍struct input_handle结构体,注意与上面的区别。

/**
 * struct input_handle - links input device with an input handler用来连接input_dev和input_handler
 * @private: handler-specific data      handler的数据
 * @open: counter showing whether the handle is 'open', i.e. should deliver
 * events from its device   一个变量,表示handle是否正在被使用,当使用时,会将事件分发给设备
 * @name: name given to the handle by handler that created it   表示handle的名字
 * @dev: input device the handle is attached to  
 * @handler: handler that works with the device through this handle
 * @d_node: used to put the handle on device's list of attached handles
 * @h_node: used to put the handle on handler's list of handles from which
 * it gets events
 */
struct input_handle {


void *private;


int open;
const char *name;   表示handle的名字


struct input_dev *dev;    表示该handle依附的input_dev设备
struct input_handler *handler;  该handler处理器就是与设备相关的处理器


struct list_headd_node;  将handle放到设备相关的链表中,也就是放到input_dev->h_list表示的链表中。
struct list_headh_node;  将handle放到input_handler相关的链表中,也就是放到handler->h_list表示的链表中。
};

4、注册函数input_register_handle()

/**
 * input_register_handle - register a new input handle
 * @handle: handle to register
 *
 * This function puts a new input handle onto device's
 * and handler's lists
so that events can flow through
 * it once it is opened using input_open_device().
 *
 * This function is supposed to be called from handler's
 * connect() method.
 */
int input_register_handle(struct input_handle *handle)
{
struct input_handler *handler = handle->handler;
struct input_dev *dev = handle->dev;
int error;
/*
* We take dev->mutex here to prevent race with
* input_release_device().
*/
error = mutex_lock_interruptible(&dev->mutex);   加锁
if (error)
return error;
list_add_tail_rcu(&handle->d_node, &dev->h_list);  此函数将handle加入到输入设备的dev->h_list链表中。
mutex_unlock(&dev->mutex);
synchronize_rcu();


/*
* Since we are supposed to be called from ->connect()
* which is mutually exclusive with ->disconnect()
* we can't be racing with input_unregister_handle()
* and so separate lock is not needed here.
*/
list_add_tail(&handle->h_node, &handler->h_list);此函数将handle加入input_handler的handler->h_list链表中。


if (handler->start)  如果定义了start函数,则调用它。
handler->start(handle);


return 0;
}

这样通过input_handle结构体把input_dev和input_handler连接起来了。看下图:

linux驱动——input输入子系统(2)——handler


linux驱动——input输入子系统(3)——evdev的地址链接