3. 关于input_handler
//Evdev--> Event char devices, giving access to raw input device events.
接下来以evdev(Input driver event char devices)为例,探究基本的handler;
3.1 input_handler数据结构
struct input_handler {
void *private; /*私有数据*/
/*@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
*/
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
/*
* @filter: similar to @event; separates normal event handlers from
*"filters".*/
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
/** @match: called after comparing device's id with handler's id_table
* to perform fine-grained matching between device and handler
*/
bool (*match)(struct input_handler *handler, struct input_dev *dev);
/* * @connect: called when attaching a handler to an input device*/
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
/* * @disconnect: disconnects a handler from input device*/
void (*disconnect)(struct input_handle *handle);
/*
* @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*/
void (*start)(struct input_handle *handle);
/* @fops: file operations this driver implements*/
const struct file_operations *fops;
/** @minor: beginning of range of 32 minors for devices this driver
**can provide*/
int minor;
/*@name: name of the handler, to be shown in /proc/bus/input/handlers*/
const char *name;
/* * @id_table: pointer to a table of input_device_ids this driver can
* handle,匹配的时候用*/
const struct input_device_id *id_table;
/** @h_list: list of input handles associated with the handler*/
struct list_head h_list;
/*@node: for placing the driver onto input_handler_list*/
struct list_head node;
};
3.2 初始化evdev
static int __init evdev_init(void)
{
return input_register_handler(&evdev_handler);
}
直接看--input_register_handler
/**
* input_register_handler - register a new 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, 用于handle
if (handler->fops != NULL) {
if (input_table[handler->minor >> 5]) {
retval = -EBUSY;
goto out;
}
input_table[handler->minor >> 5] = handler; //将handler填入全局变量input_table中
}
list_add_tail(&handler->node, &input_handler_list); //将handler添加到input_handler_list全局handler链表中
/**input_attach_handler这个函数在注册input_dev设备时调用到,在注册input_handler驱动时也调用到*/
list_for_each_entry(dev, &input_dev_list, node) //遍历input_dev_list设备链表,匹配handler和input_device
input_attach_handler(dev, handler);
input_wakeup_procfs_readers();
out:
mutex_unlock(&input_mutex); //解锁
return retval;
}
/******************接下来分析****handler->connect**************************/
在evdev中handler->connect=evdev_connect;
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
int minor;
int error;
/*查找全局evdev_table中可用的号码*/
for (minor = 0; minor < EVDEV_MINORS; minor++) //minor < 32
if (!evdev_table[minor])
break;
if (minor == EVDEV_MINORS) {
pr_err("no more free evdev devices\n");
return -ENFILE;
}
/*分配evdev*/
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
INIT_LIST_HEAD(&evdev->client_list); //初始化client_list-->用来连接客户端client
spin_lock_init(&evdev->client_lock); //初始化链表锁-->互斥访问client_list,防止并发
mutex_init(&evdev->mutex); //初始化evdev防止并发访问
init_waitqueue_head(&evdev->wait); //初始化等待队列
dev_set_name(&evdev->dev, "event%d", minor); //设置evdev->dev的名字-->event%d
evdev->exist = true; //设置evdev存在标志
evdev->minor = minor; //设置evdev次设备号
/*将handler驱动 和 input_dev设备用handle连接起来*/
evdev->handle.dev = input_get_device(dev);
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
evdev->handle.private = evdev; //设置handle.private数据
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); //设置evdev->dev的设备号--主设备号13,用于创建设备文件
evdev->dev.class = &input_class; //设置设备类-->属于input_class类
evdev->dev.parent = &dev->dev;
evdev->dev.release = evdev_free;
/********前面Linux驱动模型探究--3(device)*************/
device_initialize(&evdev->dev); //初始化设备
/*input_register_handle - register a new input handle
*handle: handle to register*/
error = input_register_handle(&evdev->handle); //注册handle,和input_dev和handler建立连接
error = evdev_install_chrdev(evdev);
error = device_add(&evdev->dev); //注册evdev , 生成设备文件(event%d)
return 0;
}