您的位置:首页 > 其它

input输入子系统讲解

2011-06-16 09:29 253 查看
Linux的input子系统提供了输入设备的驱动框架,比如鼠标、键盘、触摸屏等就属于输入设备。Linux中关于input子系统的文档在Documentation/input目录,input的核心代码在input.c和input.h中。

input_handle, input_handler, input_dev
input_handle, input_handler, input_dev是input子系统中最重要的3个数据结构。

(1)input_handler用于上层应用获取输入事件。上层应用打开输入设备的设备节点,然后对节点进行读写操作以获得鼠标移动信息,或者键盘信息等等。这里对设备节点的文件操作函数就是由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
* @filter: similar to @event; separates normal event handlers from
*	"filters".
* @match: called after comparing device's id with handler's id_table
*	to perform fine-grained matching between device and handler
* @connect: called when attaching a handler to an input device
* @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
* @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
* @h_list: list of input handles associated with the handler
* @node: for placing the driver onto 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.
*
* The very same structure is used to implement input filters. Input core
* allows filters to run first and will not pass event to regular handlers
* if any of the filters indicate that the event should be filtered (by
* returning %true from their filter() method).
*
* 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);
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*match)(struct input_handler *handler, struct input_dev *dev);
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;

struct list_head	h_list;
struct list_head	node;
};


(2)input_dev代表的是具体的设备,比如鼠标、键盘等等。
对于一台Linux电脑,可能会连着多个鼠标、多个键盘。每一个鼠标都能控制光标的运动,每一个键盘也都能正常使用。这在input子系统中,体现为一个input_handle关联多个input_dev,能够同时从多个input_dev获取输入消息。与此同时,linux中可能会有多个device节点同时与一个input具体设备关联,这样,应用程序通过任何一个设备节点,都可以获得例如鼠标、键盘等具体设备的输入信息。所以,input_dev和input_handler之间是多对多的关联关系,而这些关联就是由input_handle表示。
]/**
* struct input_dev - represents an input device
* @name: name of the device
* @phys: physical path to the device in the system hierarchy
* @uniq: unique identification code for the device (if device has it)
* @id: id of the device (struct input_id)
* @evbit: bitmap of types of events supported by the device (EV_KEY,
*	EV_REL, etc.)
* @keybit: bitmap of keys/buttons this device has
* @relbit: bitmap of relative axes for the device
* @absbit: bitmap of absolute axes for the device
* @mscbit: bitmap of miscellaneous events supported by the device
* @ledbit: bitmap of leds present on the device
* @sndbit: bitmap of sound effects supported by the device
* @ffbit: bitmap of force feedback effects supported by the device
* @swbit: bitmap of switches present on the device
* @keycodemax: size of keycode table
* @keycodesize: size of elements in keycode table
* @keycode: map of scancodes to keycodes for this device
* @setkeycode: optional method to alter current keymap, used to implement
*	sparse keymaps. If not supplied default mechanism will be used.
*	The method is being called while holding event_lock and thus must
*	not sleep
* @getkeycode: optional method to retrieve current keymap. If not supplied
*	default mechanism will be used. The method is being called while
*	holding event_lock and thus must not sleep
* @ff: force feedback structure associated with the device if device
*	supports force feedback effects
* @repeat_key: stores key code of the last key pressed; used to implement
*	software autorepeat
* @timer: timer for software autorepeat
* @sync: set to 1 when there were no new events since last EV_SYNC
* @abs: current values for reports from absolute axes
* @rep: current values for autorepeat parameters (delay, rate)
* @key: reflects current state of device's keys/buttons
* @led: reflects current state of device's LEDs
* @snd: reflects current state of sound effects
* @sw: reflects current state of device's switches
* @absmax: maximum values for events coming from absolute axes
* @absmin: minimum values for events coming from absolute axes
* @absfuzz: describes noisiness for axes
* @absflat: size of the center flat position (used by joydev)
* @absres: resolution used for events coming form absolute axes
* @open: this method is called when the very first user calls
*	input_open_device(). The driver must prepare the device
*	to start generating events (start polling thread,
*	request an IRQ, submit URB, etc.)
* @close: this method is called when the very last user calls
*	input_close_device().
* @flush: purges the device. Most commonly used to get rid of force
*	feedback effects loaded into the device when disconnecting
*	from it
* @event: event handler for events sent _to_ the device, like EV_LED
*	or EV_SND. The device is expected to carry out the requested
*	action (turn on a LED, play sound, etc.) The call is protected
*	by @event_lock and must not sleep
* @grab: input handle that currently has the device grabbed (via
*	EVIOCGRAB ioctl). When a handle grabs a device it becomes sole
*	recipient for all input events coming from the device
* @event_lock: this spinlock is is taken when input core receives
*	and processes a new event for the device (in input_event()).
*	Code that accesses and/or modifies parameters of a device
*	(such as keymap or absmin, absmax, absfuzz, etc.) after device
*	has been registered with input core must take this lock.
* @mutex: serializes calls to open(), close() and flush() methods
* @users: stores number of users (input handlers) that opened this
*	device. It is used by input_open_device() and input_close_device()
*	to make sure that dev->open() is only called when the first
*	user opens device and dev->close() is called when the very
*	last user closes the device
* @going_away: marks devices that are in a middle of unregistering and
*	causes input_open_device*() fail with -ENODEV.
* @dev: driver model's view of this device
* @h_list: list of input handles associated with the device. When
*	accessing the list dev->mutex must be held
* @node: used to place the device onto input_dev_list
*/
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_id id;

unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev,
unsigned int scancode, unsigned int keycode);
int (*getkeycode)(struct input_dev *dev,
unsigned int scancode, unsigned int *keycode);

struct ff_device *ff;

unsigned int repeat_key;
struct timer_list timer;

int sync;

int abs[ABS_CNT];
int rep[REP_MAX + 1];

unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];

int absmax[ABS_CNT];
int absmin[ABS_CNT];
int absfuzz[ABS_CNT];
int absflat[ABS_CNT];
int absres[ABS_CNT];

int (*open)(struct input_dev *dev);
void (*close)(struct input_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;
bool going_away;

struct device dev;

struct list_head	h_list;
struct list_head	node;
};


(3)handler与dev之间关联的建立
首先看看input_handle的结构体成员:
]/**
* struct input_handle - links input device with an input handler
* @private: handler-specific data
* @open: counter showing whether the handle is 'open', i.e. should deliver
*	events from its device
* @name: name given to the handle by handler that created it
* @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;

struct input_dev *dev;
struct input_handler *handler;

struct list_head	d_node;
struct list_head	h_node;
};

input_handle中包含一个input_dev的指针和一个input_handler的指针,所以能建立handler和dev之间的一个一对一的关联。在input_handler中,有一个链表h_list,指向和这个handler关联的所有input_handle,通过这些handle就可以找到与handler关联的所有dev。同样的,在input_dev中,也有一个链表h_list,指向与dev关联的所有input_handle,通过这些handle可以找到与dev相关的所有handler。通过这两个链表和input_handle,input_handler和input_dev之间建立了一个复杂的网状结构。

那么,input_handler和input_dev之间建立关联的规则是什么?即在什么情况下需要建立关联,什么时候不需要建立关联?这就需要handler和dev之间有一个匹配机制。

input_handler中有两个指针,id_table和blacklist,其中blacklist是黑名单,凡是与之匹配的dev都将被强制过滤;而与id_table中任意一项匹配的dev才能与handler建立关联。
-------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: