1.输入子系统学习-struct input_dev-2023.02

内核版本:4.4.194

平台相关:rk3399

目前主要是看的触摸屏的代码

目录

一、include/linux/input.h(struct_input_dev)

二、结构体的注释部分(百度翻译)

三、Documentation/input/event-codes.txt(百度翻译)

四、Documentation/input/input.txt(百度翻译)

五、Documentation/input/input-programming.txt(百度翻译)


一、include/linux/input.h(struct_input_dev)

struct input_dev {
	const char *name;
	const char *phys;
	const char *uniq;
	struct input_id id;

	unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];

	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 hint_events_per_packet;

	unsigned int keycodemax;
	unsigned int keycodesize;
	void *keycode;

	int (*setkeycode)(struct input_dev *dev,
			  const struct input_keymap_entry *ke,
			  unsigned int *old_keycode);
	int (*getkeycode)(struct input_dev *dev,
			  struct input_keymap_entry *ke);

	struct ff_device *ff;

	unsigned int repeat_key;
	struct timer_list timer;

	int rep[REP_CNT];

	struct input_mt *mt;

	struct input_absinfo *absinfo;

	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 (*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 __rcu *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;

	unsigned int num_vals;
	unsigned int max_vals;
	struct input_value *vals;

	bool devres_managed;
};

二、结构体的注释部分(百度翻译)

/**
 * 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)          //设备的id(struct input_id)
 * @propbit: bitmap of device properties and quirks    //设备特性的位图
 * @evbit: bitmap of types of events supported by the device (EV_KEY,       //设备支持的事件类型位图(EV_KEY,EV_REL等)
 *    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                //设备上存在的led位图
 * @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                      //设备上存在的开关位图
 * @hint_events_per_packet: average number of events generated by the     
 *    device in a packet (between EV_SYN/SYN_REPORT events). Used by
 *    event handlers to estimate size of the buffer needed to hold
 *    events.                                                                                //设备在数据包中生成的事件的平均数量(EV_SYN/SYN_REPORT事件之间)。由事件处理程序用于估计保存事件所需的缓冲区大小。
 * @keycodemax: size of keycode table                                //键码表的大小
 * @keycodesize: size of elements in keycode table              //keycode表中元素的大小
 * @keycode: map of scancodes to keycodes for this device      //此设备的扫描码到键码的映射
 * @getkeycode: optional legacy method to retrieve current keymap.    //用于检索当前keymap的可选遗留方法。
 * @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                                               //用于更改当前关键点映射的可选方法,用于实现稀疏关键点映射。如果未提供,将使用默认机制。在保持event_lock时调用该方法,因此不能休眠
 * @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       //软件自动重复计时器
 * @rep: current values for autorepeat parameters (delay, rate)    //自动重复参数的当前值(延迟、速率)
 * @mt: pointer to multitouch state                   //指向多点触摸状态的指针
 * @absinfo: array of &struct input_absinfo elements holding information
 *    about absolute axes (current value, min, max, flat, fuzz,
 *    resolution)                                           //保存绝对轴信息的&struct input_absinfo元素数组(当前值、最小值、最大值、平坦值、模糊值、分辨率)
 * @key: reflects current state of device's keys/buttons     //反映设备按键/按钮的当前状态
 * @led: reflects current state of device's LEDs               //反映设备led的当前状态
 * @snd: reflects current state of sound effects              //反映当前音效状态
 * @sw: reflects current state of device's switches           //反映设备开关的当前状态
 * @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.)                        //当第一个用户调用input_open_device()时,就会调用此方法。驱动程序必须准备好设备以开始生成事件(启动轮询线程、请求IRQ、提交URB等)
 * @close: this method is called when the very last user calls
 *    input_close_device().                                              //当最后一个用户调用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                //发送到设备的事件的事件处理程序,如EV_LED或EV_SND。设备应执行请求的操作(打开LED、播放声音等)。这个调用受@event_lock保护,不得休眠
 * @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     //当前已抓取设备的输入句柄(通过EVIOCGRAB ioctl)。当手柄抓取设备时,它将成为来自该设备的所有输入事件的唯一接收者
 * @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.    //当输入核心接收并处理设备的新事件时(在input_event()中),将使用此自旋锁。在设备注册到输入核心后,访问和/或修改设备参数(如keymap或absmin、absmax、absfuzz等)的代码必须使用此锁。
 * @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                                               //存储打开此设备的用户数(输入处理程序)。它由input_open_device()和input_close_device()使用,以确保dev->open()仅在第一个用户打开设备时调用,dev->close()在最后一个用户关闭设备时调用
 * @going_away: marks devices that are in a middle of unregistering and
 *    causes input_open_device*() fail with -ENODEV.        //标记正在注销的设备,并导致input_open_device*()失败,返回-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        //与设备关联的输入句柄列表。访问列表时,必须持有dev->mutex
 * @node: used to place the device onto input_dev_list    //用于将设备放置到input_dev_list中
 * @num_vals: number of values queued in the current frame    //当前帧中排队的值数
 * @max_vals: maximum number of values queued in a frame   //帧中排队的最大值数
 * @vals: array of values queued in the current frame      //当前帧中排队的值数组
 * @devres_managed: indicates that devices is managed with devres framework
 *    and needs not be explicitly unregistered or freed.     //表示设备是用devres框架管理的,不需要显式注销或释放。
 */


三、Documentation/input/event-codes.txt(百度翻译)

The input protocol uses a map of types and codes to express input device values to userspace. This document describes the types and codes and how and when they may be used.
输入协议使用类型和代码的映射来向用户空间表示输入设备值。本文件描述了类型和代码,以及它们的使用方式和时间。

 A single hardware event generates multiple input events. Each input event contains the new value of a single data item. A special event type, EV_SYN, is used to separate input events into packets of input data changes occurring at the same moment in time. In the following, the term "event" refers to a single input event encompassing a type, code, and value.

单个硬件事件生成多个输入事件。每个输入事件都包含单个数据项的新值。一种特殊的事件类型EV_SYN用于将输入事件分离为在同一时刻发生的输入数据变化包。在下文中,术语“事件”是指包含类型、代码和值的单个输入事件。

 The input protocol is a stateful protocol. Events are emitted only when values of event codes have changed. However, the state is maintained within the Linux input subsystem; drivers do not need to maintain the state and may attempt to emit unchanged values without harm. Userspace may obtain the current state of event code values using the EVIOCG* ioctls defined in linux/input.h. The event reports supported by a device are also provided by sysfs in class/input/event*/device/capabilities/, and the properties of a device are provided in class/input/event*/device/properties.
 
输入协议是有状态协议。仅当事件代码的值发生更改时才会发出事件。但是,该状态在Linux输入子系统中保持;驱动程序不需要保持状态,并且可以尝试在没有损害的情况下发出不变的值。用户空间可以使用linux/input.h 中定义的EVIOCG*ioctls 获取事件代码值的当前状态。设备支持的事件报告也由class/input/event*/device/capabilities/中的sysfs提供,设备的属性在class/infut/event*/device/属性中提供。


一、Event types: 
 =========== 
 Event types are groupings of codes under a logical input construct. Each type has a set of applicable codes to be used in generating events. See the Codes section for details on valid codes for each type.
 事件类型是逻辑输入构造下的代码分组。每种类型都有一组用于生成事件的适用代码。有关每种类型的有效代码的详细信息,请参阅代码部分。

 *1. EV_SYN:
  - Used as markers to separate events. Events may be separated in time or in space, such as with the multitouch protocol.
 -用作分隔事件的标记。事件可以在时间或空间上分离,例如使用多点触摸协议。
 *2. EV_KEY:
  - Used to describe state changes of keyboards, buttons, or other key-like devices.
 -用于描述键盘、按钮或其他类似按键的设备的状态变化。
 *3. EV_REL:
  - Used to describe relative axis value changes, e.g. moving the mouse 5 units to the left.
 -用于描述相对轴值的变化,例如将鼠标向左移动5个单位。
 *4. EV_ABS:
  - Used to describe absolute axis value changes, e.g. describing the coordinates of a touch on a touchscreen.
 -用于描述绝对轴值变化,例如描述触摸屏上触摸的坐标。
 *5. EV_MSC:
  - Used to describe miscellaneous input data that do not fit into other types.
 -用于描述不适合其他类型的杂项输入数据。 
 *6. EV_SW:
  - Used to describe binary state input switches.
  -用于描述二进制状态输入开关。
 *7. EV_LED:
  - Used to turn LEDs on devices on and off.
  -用于打开和关闭设备上的LED。
 *8. EV_SND:
  - Used to output sound to devices.
  -用于向设备输出声音。
 *9. EV_REP:
  - Used for autorepeating devices.
  -用于自动重复装置。
 *10. EV_FF:
  - Used to send force feedback commands to an input device.
  -用于向输入设备发送力反馈命令。
 *11. EV_PWR:
  - A special type for power button and switch input.
  -电源按钮和开关输入的特殊类型。
 *12. EV_FF_STATUS:
  - Used to receive force feedback device status.
  -用于接收力反馈装置状态。
 

 **************************
二、以下是详细介绍:
 Event codes: 

 =========== 
 Event codes define the precise type of event.
 事件代码定义事件的精确类型。
2.1 EV_SYN
 ---------- 
 EV_SYN event values are undefined. Their usage is defined only by when they are sent in the evdev event stream.
  EV_SYN事件值未定义。它们的用法仅由在evdev事件流中发送时定义。

 2.1.1 SYN_REPORT:
  - Used to synchronize and separate events into packets of input data changes occurring at the same moment in time. For example, motion of a mouse may set the REL_X and REL_Y values for one motion, then emit a SYN_REPORT. The next motion will emit more REL_X and REL_Y values and send another SYN_REPORT.
-用于将事件同步并分离为在同一时刻发生的输入数据更改包。例如,鼠标的运动可以为一个运动设置REL_X和REL_Y值,然后发出SYN_REPORT。下一个动作将发出更多REL_X和REL_Y值,并发送另一个SYN_REPORT。

 2.1.2 SYN_CONFIG:
  - TBD
  -待定
 2.1.3 SYN_MT_REPORT:
  - Used to synchronize and separate touch events. See the multi-touch-protocol.txt document for more information.
  -用于同步和分离触摸事件。有关详细信息,请参阅multitouch-protocol.txt文档。

 2.1.4 SYN_DROPPED:
  - Used to indicate buffer overrun in the evdev client's event queue. Client should ignore all events up to and including next SYN_REPORT event and query the device (using EVIOCG* ioctls) to obtain its current state.
  -用于指示evdev客户端事件队列中的缓冲区溢出。客户端应忽略直到下一个SYN_REPORT事件的所有事件,并查询设备(使用EVIOCG*ioctls)以获取其当前状态。

2.2 EV_KEY
 ---------- 
 EV_KEY events take the form KEY_<name> or BTN_<name>. For example, KEY_A is used to represent the 'A' key on a keyboard. When a key is depressed, an event with the key's code is emitted with value 1. When the key is released, an event is emitted with value 0. Some hardware send events when a key is repeated. These events have a value of 2. In general, KEY_<name> is used for keyboard keys, and BTN_<name> is used for other types of momentary switch events.
 
EV_KEY事件的形式为KEY_<name>或BTN_<name>。例如,KEY_A用于表示键盘上的“A”键。按下键时,将发出一个带有键代码的事件,值为1。释放密钥时,将发出一个值为0的事件。某些硬件在重复按键时发送事件。这些事件的值为2。通常,KEY_<name>用于键盘键,BTN_<name>则用于其他类型的瞬时开关事件。


 A few EV_KEY codes have special meanings:
 2.2.1 BTN_TOOL_<name>:
  - These codes are used in conjunction with input trackpads, tablets, and touchscreens. These devices may be used with fingers, pens, or other tools. When an event occurs and a tool is used, the corresponding BTN_TOOL_<name> code should be set to a value of 1. When the tool is no longer interacting with the input device, the BTN_TOOL_<name> code should be reset to 0. All trackpads, tablets, and touchscreens should use at least one BTN_TOOL_<name> code when events are generated.
 -这些代码与输入轨迹板、平板电脑和触摸屏一起使用。这些设备可以与手指、笔或其他工具一起使用。当发生事件并使用工具时,相应的BTN_tool_<name>代码应设置为值1。当工具不再与输入设备交互时,BTN_tool_<name>代码应重置为0。生成事件时,所有轨迹板、平板电脑和触摸屏应至少使用一个BTN_TOOL_<name>代码。

 2.2.2 BTN_TOUCH: BTN_TOUCH is used for touch contact. While an input tool is determined to be within meaningful physical contact, the value of this property must be set to 1. Meaningful physical contact may mean any contact, or it may mean contact conditioned by an implementation defined property. For example, a touchpad may set the value to 1 only when the touch pressure rises above a certain value. BTN_TOUCH may be combined with BTN_TOOL_<name> codes. For example, a pen tablet may set BTN_TOOL_PEN to 1 and BTN_TOUCH to 0 while the pen is hovering over but not touching the tablet surface.
BTN_TOUCH用于触摸接触。当确定输入工具处于有意义的物理接触中时,此属性的值必须设置为1。有意义的物理接触可能意味着任何接触,也可能意味着由实现定义的属性限制的接触。例如,触摸板可以仅在触摸压力升高到某个值以上时将该值设置为1。BTN_TOUCH可以与BTN_TOUL_<name>代码组合。例如,当笔悬停在平板电脑表面但不接触平板电脑表面时,笔平板电脑可以将BTN_TOOL_pen设置为1,将BTN_TOUCH设置为0。

 Note: For appropriate function of the legacy mousedev emulation driver,BTN_TOUCH must be the first evdev code emitted in a synchronization frame.
注意:对于传统mousedev仿真驱动程序的适当功能,BTN_TOUCH必须是同步帧中发出的第一个evdev代码。

 Note: Historically a touch device with BTN_TOOL_FINGER and BTN_TOUCH was interpreted as a touchpad by userspace, while a similar device without BTN_TOOL_FINGER was interpreted as a touchscreen. For backwards compatibility with current userspace it is recommended to follow this distinction. In the future, this distinction will be deprecated and the device properties ioctl EVIOCGPROP, defined in linux/input.h, will be used to convey the device type.

注:历史上,带有BTN_TOOL_FINGER和BTN_TOUCH的触摸设备被用户空间解释为触摸板,而没有BTN_TOOL_FINGER的类似设备被解释为触摸屏。为了与当前用户空间向后兼容,建议遵循此区别。将来,这种区别将被弃用,linux/input.h 中定义的设备属性 ioctl EVIOCGPROP 将用于表示设备类型。

 2.2.3 BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP:
  - These codes denote one, two, three, and four finger interaction on a trackpad or touchscreen. For example, if the user uses two fingers and moves them on the touchpad in an effort to scroll content on screen, BTN_TOOL_DOUBLETAP should be set to value 1 for the duration of the motion. Note that all BTN_TOOL_<name> codes and the BTN_TOUCH code are orthogonal in purpose. A trackpad event generated by finger touches should generate events for one code from each group. At most only one of these BTN_TOOL_<name> codes should have a value of 1 during any synchronization frame.
-这些代码表示一个、两个、三个和四个手指在触摸板或触摸屏上的交互。例如,如果用户使用两个手指并在触摸板上移动它们以在屏幕上滚动内容,则BTN_TOOL_DOUBLETAP应在运动持续时间内设置为值1。注意,所有BTN_TOOL_<name>码和BTN_TOUCH码在目的上是正交的。手指触摸生成的轨迹板事件应该为每个组中的一个代码生成事件。在任何同步帧期间,这些BTN_TOOL_<name>代码中最多只有一个代码的值应为1。

 Note: Historically some drivers emitted multiple of the finger count codes with a value of 1 in the same synchronization frame. This usage is deprecated.
注意:历史上,一些驱动器在同一同步帧中发出多个值为1的手指计数代码。此用法已弃用。

 Note: In multitouch drivers, the input_mt_report_finger_count() function should be used to emit these codes. Please see multi-touch-protocol.txt for details.
注意:在多点触摸驱动程序中,应该使用input_mt_report_finger_count()函数来发出这些代码。有关详细信息,请参阅multitouch-protocol.txt。 

2.3 EV_REL: ---------- 
 EV_REL events describe relative changes in a property. For example, a mouse may move to the left by a certain number of units, but its absolute position in space is unknown. If the absolute position is known, EV_ABS codes should be used instead of EV_REL codes.
 EV_REL事件描述属性中的相对更改。例如,鼠标可能向左移动一定数量的单位,但其在空间中的绝对位置是未知的。如果绝对位置已知,则应使用EV_ABS代码而不是EV_REL代码。
 A few EV_REL codes have special meanings:
2.3.1 REL_WHEEL, REL_HWHEEL:
  - These codes are used for vertical and horizontal scroll wheels, respectively.
  -这些代码分别用于垂直和水平滚轮。
2.4 EV_ABS: ---------- 
 EV_ABS events describe absolute changes in a property. For example, a touchpad may emit coordinates for a touch location.
 EV_ABS事件描述属性中的绝对更改。例如,触摸板可以发出触摸位置的坐标。
 A few EV_ABS codes have special meanings:
 2.4.1 ABS_DISTANCE:
  - Used to describe the distance of a tool from an interaction surface. This event should only be emitted while the tool is hovering, meaning in close proximity of the device and while the value of the BTN_TOUCH code is 0. If the input device may be used freely in three dimensions, consider ABS_Z instead.
  -用于描述工具与交互表面的距离。仅当工具悬停时,即在设备附近且BTN_TOUCH代码值为0时,才会发出此事件。如果输入设备可以在三维中自由使用,请考虑ABS_Z。

 2.4.2 ABS_MT_<name>:
  - Used to describe multitouch input events. Please see multi-touch-protocol.txt for details.
  -用于描述多点触摸输入事件。有关详细信息,请参阅multitouch-protocol.txt。
2.5 EV_SW: ---------- 
 EV_SW events describe stateful binary switches. For example, the SW_LID code is used to denote when a laptop lid is closed.
 EV_SW事件描述有状态二进制开关。例如,SW_LID代码用于表示笔记本电脑盖何时关闭。
 Upon binding to a device or resuming from suspend, a driver must report the current switch state. This ensures that the device, kernel, and userspace state is in sync.
 绑定到设备或从挂起状态恢复时,驱动程序必须报告当前开关状态。这确保了设备、内核和用户空间状态同步。

 Upon resume, if the switch state is the same as before suspend, then the input subsystem will filter out the duplicate switch state reports. The driver does not need to keep the state of the switch at any time.
 恢复后,如果切换后的状态与挂起前相同,则输入子系统将过滤掉重复的切换状态报告。驱动无需随时保持开关的状态。
 
2.6 EV_MSC: ---------- 
 EV_MSC events are used for input and output events that do not fall under other categories.
  EV_MSC事件用于不属于其他类别的输入和输出事件。

 A few EV_MSC codes have special meaning:
 2.6.1 MSC_TIMESTAMP:
  - Used to report the number of microseconds since the last reset. This event should be coded as an uint32 value, which is allowed to wrap around with no special consequence. It is assumed that the time difference between two consecutive events is reliable on a reasonable time scale (hours). A reset to zero can happen, in which case the time since the last event is unknown.  If the device does not provide this information, the driver must not provide it to user space.
-用于报告自上次重置以来的微秒数。这个事件应该被编码为uint32值,它被允许在没有特殊后果的情况下回环。假设两个连续事件之间的时间差在合理的时间尺度(小时)上是可靠的。可能会重置为零,在这种情况下,自上次事件以来的时间未知。如果设备不提供此信息,则驱动不得将其提供给用户空间。

2.7 EV_LED: ---------- 
 EV_LED events are used for input and output to set and query the state of various LEDs on devices.
 EV_LED事件用于输入和输出,以设置和查询设备上各种LED的状态。
2.8 EV_REP: ---------- 
 EV_REP events are used for specifying autorepeating events.
 EV_REP事件用于指定自动重复事件。
2.9 EV_SND: ---------- 
 EV_SND events are used for sending sound commands to simple sound output devices.
 EV_SND事件用于向简单声音输出设备发送声音命令。
2.10 EV_FF: ---------- 
 EV_FF events are used to initialize a force feedback capable device and to cause such device to feedback.
 EV_FF事件用于初始化具有力反馈功能的设备,并使该设备进行反馈。
2.11 EV_PWR: ---------- 
 EV_PWR events are a special type of event used specifically for power management. Its usage is not well defined. To be addressed later.
 EV_PWR事件是专门用于电源管理的特殊类型的事件。它的用法没有很好的定义。稍后讨论。


三、Device properties: (设备属性)
 ================= 
 Normally, userspace sets up an input device based on the data it emits, i.e., the event types. In the case of two devices emitting the same event types, additional information can be provided in the form of device properties.
 如果两个设备发出相同的事件类型,可以以设备属性的形式提供附加信息。
3.1 INPUT_PROP_DIRECT + INPUT_PROP_POINTER: 
 -------------------------------------- 
 The INPUT_PROP_DIRECT property indicates that device coordinates should be directly mapped to screen coordinates (not taking into account trivial transformations, such as scaling, flipping and rotating). Non-direct input devices require non-trivial transformation, such as absolute to relative transformation for touchpads. Typical direct input devices: touchscreens, drawing tablets; non-direct devices: touchpads, mice.
3.1.1 INPUT_PROP_DIRECT 属性表示设备坐标应直接映射到屏幕坐标(不考虑缩放、翻转和旋转等细微变换)。非直接输入设备需要一些的转换,例如触摸板的绝对到相对转换。典型的直接输入设备:触摸屏、绘图板;非直接设备:触摸板、鼠标。

 The INPUT_PROP_POINTER property indicates that the device is not transposed on the screen and thus requires use of an on-screen pointer to trace user's movements.  Typical pointer devices: touchpads, tablets, mice; non-pointer device: touchscreen.
INPUT_PROP_POINTER属性表示设备未在屏幕上换位,因此需要使用屏幕指针来跟踪用户的移动。典型的指针设备:触摸板、平板电脑、鼠标;非指针设备:触摸屏。

 If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is considered undefined and the device type should be deduced in the traditional way, using emitted event types.
 如果未设置INPUT_PROP_DIRECT或INPUT_PROP_POINTER,则认为该属性未定义,应使用发出的事件类型以传统方式推断设备类型。


3.2 INPUT_PROP_BUTTONPAD: 
 -------------------- 
 For touchpads where the button is placed beneath the surface, such that pressing down on the pad causes a button click, this property should be set. Common in clickpad notebooks and macbooks from 2009 and onwards.
 对于按钮位于表面下方的触摸板,按下触摸板会导致按钮单击,应设置此属性。从2009年起,常见于点击板笔记本和macbook。

 Originally, the buttonpad property was coded into the bcm5974 driver version field under the name integrated button. For backwards compatibility, both methods need to be checked in userspace.
最初,buttonpad属性被编码到名为integrated button的bcm5974 驱动程序版本字段中。 为了向后兼容 ,需要在用户空间中 检查这两种方法。

3.3 INPUT_PROP_SEMI_MT: 
 ------------------ 
 Some touchpads, most common between 2008 and 2011, can detect the presence of multiple contacts without resolving the individual positions; only the number of contacts and a rectangular shape is known. For such touchpads, the semi-mt property should be set.
 2008年至2011年间最常见的一些触摸板可以检测多个触点的存在,而无需解析各个位置;只有接触的数量和矩形形状是已知的。对于此类触摸板,应设置semi-mt属性。
 Depending on the device, the rectangle may enclose all touches, like a bounding box, or just some of them, for instance the two most recent touches. The diversity makes the rectangle of limited use, but some gestures can normally be extracted from it.
 根据设备的不同,矩形可能会包围所有触摸,比如边界框,或者只是其中的一些,例如最近的两次触摸。多样性使得矩形的用途有限,但通常可以从中提取一些手势。
 If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT device.
 如果未设置INPUT_PROP_SEMI_MT,则假定该设备为真正的MT设备。

3.4 INPUT_PROP_TOPBUTTONPAD: 
 ----------------------- 
 Some laptops, most notably the Lenovo *40 series provide a trackstick device but do not have physical buttons associated with the trackstick device. Instead, the top area of the touchpad is marked to show visual/haptic areas for left, middle, right buttons intended to be used with the trackstick.
 一些笔记本电脑,尤其是Lenovo*40系列,提供了一个跟踪棒设备,但没有与跟踪棒设备关联的物理按钮。相反,触摸板的顶部区域被标记为显示用于轨迹杆的左、中、右按钮的视觉/触觉区域。

 If INPUT_PROP_TOPBUTTONPAD is set, userspace should emulate buttons accordingly. This property does not affect kernel behavior. The kernel does not provide button emulation for such devices but treats them as any other INPUT_PROP_BUTTONPAD device.
如果设置了INPUT_PROP_TOPBUTTONPAD,则用户空间应相应地模拟按钮。此属性不影响内核行为。内核不为此类设备提供按钮模拟,而是将其视为任何其他INPUT_PROP_BUTTONPAD设备。

 INPUT_PROP_ACCELEROMETER ------------------------- 
 Directional axes on this device (absolute and/or relative x, y, z) represent accelerometer data. All other axes retain their meaning. A device must not mix regular directional axes and accelerometer axes on the same event node.
此设备上的方向轴(绝对和/或相对x、y、z) 表示加速计数据。 所有其他轴线保留其含义。 设备不得在同一事件节点上混合常规方向轴和加速计轴。
 

四、Guidelines: (指导意见)
 ========== 
 The guidelines below ensure proper single-touch and multi-finger functionality. For multi-touch functionality, see the multi-touch-protocol.txt document for more information.
 以下指导原则确保正确的单触和多指功能。有关多点触摸功能的详细信息,请参阅multitouch-protocol.txt文档。
4.1 Mice: (鼠标) 
 ---------- 
 REL_{X,Y} must be reported when the mouse moves. BTN_LEFT must be used to report the primary button press. BTN_{MIDDLE,RIGHT,4,5,etc.} should be used to report further buttons of the device. REL_WHEEL and REL_HWHEEL should be used to report scroll wheel events where available.
当鼠标移动时,必须报告REL_{X,Y}。BTN_LEFT必须用于报告主按钮按下。BTN_{中、右、4、5等}应用于报告设备的其他按钮。REL_WHEEL和REL_HWHEEL应用于报告可用的滚轮事件。


4.2 Touchscreens: (触摸屏)
 ---------- 
 ABS_{X,Y} must be reported with the location of the touch. BTN_TOUCH must be used to report when a touch is active on the screen. BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch contact. BTN_TOOL_<name> events should be reported where possible.
 ABS_{X,Y}必须报告触摸位置。BTN_TOUCH必须用于报告屏幕上的触摸何时激活。BTN_{鼠标、左、中、右}不得报告为触摸接触的结果。如果可能,应报告BTN_TOOL_<name>事件。
 For new hardware, INPUT_PROP_DIRECT should be set.
 对于新硬件,应设置INPUT_PROP_DIRECT。
 
4.3 Trackpads: (触摸板)
 ---------- 
 Legacy trackpads that only provide relative position information must report events like mice described above.
 仅提供相对位置信息的传统轨迹板必须报告上述鼠标等事件。
 Trackpads that provide absolute touch position must report ABS_{X,Y} for the location of the touch. BTN_TOUCH should be used to report when a touch is active on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should be used to report the number of touches active on the trackpad.
 提供绝对触摸位置的触摸板必须报告ABS_{X,Y}触摸位置。BTN_TOUCH应用于报告触摸板上的触摸何时激活。如果多指支持可用,则应使用BTN_TOOL_<name>报告触摸板上活动的触摸次数。
 For new hardware, INPUT_PROP_POINTER should be set.
 对于新硬件,应设置INPUT_PROP_POINTER。
 
4.4 Tablets: (画板)
 ---------- 
 BTN_TOOL_<name> events must be reported when a stylus or other tool is active on the tablet. ABS_{X,Y} must be reported with the location of the tool. BTN_TOUCH should be used to report when the tool is in contact with the tablet. BTN_{STYLUS,STYLUS2} should be used to report buttons on the tool itself. Any button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}. BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use meaningful buttons, like BTN_FORWARD, unless the button is labeled for that purpose on the device.
 平板电脑:当手写笔或其他工具在平板电脑上处于活动状态时,必须报告BTN_TOOL_<name>事件。ABS_{X,Y}必须与工具位置一起报告。BTN_TOUCH应用于报告工具何时与平板电脑接触。BTN_{STYLUS,STYLUS2}应用于报告工具本身上的按钮。除BTN_{MOUSE,LEFT}外,平板电脑上的按钮可以使用任何按钮。BTN_{0,1,2等}是用于未标记按钮的良好通用代码。不要使用有意义的按钮,如BTN_FORWARD,除非该按钮在设备上为此目的标记。
 For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set.
对于新硬件,应设置INPUT_PROP_DIRECT和INPUT_PROP_POINTER。


 

四、Documentation/input/input.txt(百度翻译)

主要是应用部分的介绍

              Linux Input drivers v1.0
           (c) 1999-2001 Vojtech Pavlik <vojtech@ucw.cz>
                 Sponsored by SuSE 
----------------------------------------------------------------------------
 0. Disclaimer   //免责声明
 ~~~~~~~~~~~~~
  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
该程序是免费软件;您可以根据自由软件基金会发布的GNU通用公共许可证条款重新分发和/或修改它; 许可证的版本2或(由您选择)任何更高版本。


  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
分发此程序是希望它有用,但没有任何保证;甚至没有适销性或特定用途适用性的隐含保证。有关详细信息,请参阅GNU通用公共许可证。


  You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
你应该已经收到了GNU通用公共许可证的副本以及这个程序;如果没有,请写信给自由软件基金会股份有限公司,地址:59 Temple Place,Suite 330,Boston,MA 02111-1307 USA


  Should you need to contact me, the author, you can do so either by e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
如果您需要联系我,作者,您可以通过电子邮件将您的信息发送到<vojtech@ucw.cz>,或通过纸质邮件:Vojtech Pavlik,Simunkova 1594,布拉格8,18200捷克共和国


  For your convenience, the GNU General Public License version 2 is included in the package: See the file COPYING.
为方便起见,GNU通用公共许可证版本2包含在软件包中:请参阅文件COPYING。

 1. Introduction   //1.引言
 ~~~~~~~~~~~~~~~
  This is a collection of drivers that is designed to support all input devices under Linux. While it is currently used only on for USB input devices, future use (say 2.5/2.6) is expected to expand to replace most of the existing input system, which is why it lives in drivers/input/ instead of drivers/usb/.
这是一组驱动程序,旨在支持Linux下的所有输入设备。虽然它目前仅用于USB输入设备,但未来的用途(如2.5/2.6)预计将扩大,以取代大多数现有的输入系统,这就是为什么它使用drivers/input/而不是drivers/USB/。


  The centre of the input drivers is the input module, which must be loaded before any other of the input modules - it serves as a way of communication between two groups of modules:

输入驱动程序的中心是输入模块,它必须在任何其他输入模块之前加载-它是两组模块之间的通信方式:

 1.1 Device drivers   //1.1设备驱动程序
 ~~~~~~~~~~~~~~~~~~
  These modules talk to the hardware (for example via USB), and provide events (keystrokes, mouse movements) to the input module.
这些模块与硬件通信(例如通过USB),并向输入模块提供事件(按键、鼠标移动)。


 1.2 Event handlers   1.2事件处理程序
 ~~~~~~~~~~~~~~~~~~
  These modules get events from input and pass them where needed via various interfaces - keystrokes to the kernel, mouse movements via a simulated PS/2 interface to GPM and X and so on.
这些模块从输入中获取事件,并通过各种接口将它们传递到需要的地方——按键到内核,鼠标通过模拟PS/2接口移动到GPM和X等等。


 2. Simple Usage   //2.简单用法
 ~~~~~~~~~~~~~~~
  For the most usual configuration, with one USB mouse and one USB keyboard, you'll have to load the following modules (or have them built in to the kernel):
对于最常见的配置,使用一个USB鼠标和一个USB键盘,您必须加载以下模块(或将其内置到内核中):

  
    input    //输入
    mousedev   //鼠标控制器
    keybdev    //按键按钮
    usbcore    //usb核
    uhci_hcd or ohci_hcd or ehci_hcd   //uhci_hcd、ohci_hcd或ehci_hcd
    usbhid     //usb hid(人机接口设备)

  After this, the USB keyboard will work straight away, and the USB mouse will be available as a character device on major 13, minor 63:
  在这之后,USB键盘将立即工作,USB鼠标将作为主要13、次要63的字符设备:

    crw-r--r--   1 root     root      13,  63 Mar 28 22:45 mice

  This device has to be created.   //必须创建此设备。
  The commands to create it by hand are:   //手动创建它的命令有:

    cd /dev
    mkdir input
    mknod input/mice c 13 63

  After that you have to point GPM (the textmode mouse cut&paste tool) and XFree to this device to use it - GPM should be called like:
  之后,您必须将GPM(文本模式鼠标剪切和粘贴工具)和XFree指向该设备才能使用它-GPM应该被称为:

    gpm -t ps2 -m /dev/input/mice

  And in X:

    Section "Pointer"
        Protocol    "ImPS/2"
        Device      "/dev/input/mice"
        ZAxisMapping 4 5
    EndSection

  When you do all of the above, you can use your USB mouse and keyboard.
  完成以上所有操作后,您可以使用USB鼠标和键盘。


 3. Detailed Description   //3.详细说明
 ~~~~~~~~~~~~~~~~~~~~~~~ 
 3.1 Device drivers    //3.1设备驱动程序
 ~~~~~~~~~~~~~~~~~~
  Device drivers are the modules that generate events. The events are however not useful without being handled, so you also will need to use some of the modules from section 3.2.
  设备驱动程序是生成事件的模块。然而,这些事件在未处理的情况下是没有用处的,因此您还需要使用第3.2节中的一些模块。

 3.1.1 usbhid 
 ~~~~~~~~~~~~
  usbhid is the largest and most complex driver of the whole suite. It handles all HID devices, and because there is a very wide variety of them, and because the USB HID specification isn't simple, it needs to be this big.

  usbhid是整个套件中最大、最复杂的驱动程序。它处理所有的HID设备,因为它们的种类非常多,而且USB HID规范不简单,所以它需要这么大。

  Currently, it handles USB mice, joysticks, gamepads, steering wheels keyboards, trackballs and digitizers.
  目前,它处理USB鼠标、操纵杆、游戏手柄、方向盘键盘、轨迹球和数字转换器。

 However, USB uses HID also for monitor controls, speaker controls, UPSs, LCDs and many other purposes.
 然而,USB也将HID用于监视器控制、扬声器控制、UPS、LCD和许多其他用途。

 The monitor and speaker controls should be easy to add to the hid/input interface, but for the UPSs and LCDs it doesn't make much sense. For this, the hiddev interface was designed. See Documentation/hid/hiddev.txt for more information about it.
显示器和扬声器控件应该很容易添加到隐藏/输入界面,但对于UPS和LCD来说,这没有多大意义。为此,设计了hiddev接口。有关它的详细信息,请参阅Documentation/hid/hiddev.txt。


  The usage of the usbhid module is very simple, it takes no parameters, detects everything automatically and when a HID device is inserted, it detects it appropriately.
usbhid模块的使用非常简单,它不需要任何参数,自动检测所有内容,当插入HID设备时,它会适当地检测到它。


  However, because the devices vary wildly, you might happen to have a device that doesn't work well. In that case #define DEBUG at the beginning of hid-core.c and send me the syslog traces.
然而,由于设备千差万别,您可能碰巧有一个设备无法正常工作。在这种情况下,#在hid-core.c的开头定义DEBUG,并向我发送syslog跟踪。

 3.1.2 usbmouse   //3.1.2 usb鼠标
 ~~~~~~~~~~~~~~
  For embedded systems, for mice with broken HID descriptors and just any other use when the big usbhid wouldn't be a good choice, there is the usbmouse driver. It handles USB mice only. It uses a simpler HIDBP protocol. This also means the mice must support this simpler protocol. Not all do. If you don't have any strong reason to use this module, use usbhid instead.
对于嵌入式系统,对于具有损坏的HID描述符的鼠标,以及当大型usbhid不是一个好选择时的任何其他用途,都有usbmouse驱动程序。它只处理USB鼠标。它使用更简单的HIDBP协议。这也意味着小鼠必须支持这种更简单的方案。并非所有人都这么做。如果您没有充分的理由使用此模块,请改用usbhid。

 3.1.3 usbkbd  //3.1.3 usb键盘
 ~~~~~~~~~~~~
  Much like usbmouse, this module talks to keyboards with a simplified HIDBP protocol. It's smaller, but doesn't support any extra special keys. Use usbhid instead if there isn't any special reason to use this.
与usbmouse非常类似,该模块使用简化的HIDBP协议与键盘进行对话。它更小,但不支持任何额外的特殊键。如果没有任何特殊的理由使用,请改用usbhid。

 3.1.4 wacom   //3.1.4 wacom公司
 ~~~~~~~~~~~
  This is a driver for Wacom Graphire and Intuos tablets. Not for Wacom PenPartner, that one is handled by the HID driver. Although the Intuos and Graphire tablets claim that they are HID tablets as well, they are not and thus need this specific driver.
这是Wacom Graphire和Intuos平板电脑的驱动程序。不适用于Wacom PenPartner,它由HID驱动程序处理。尽管Intuos和Graphire平板电脑声称它们也是HID平板电脑,但它们不是,因此需要这个特定的驱动程序。


 3.1.5 iforce 
 ~~~~~~~~~~~~
  A driver for I-Force joysticks and wheels, both over USB and RS232.  It includes ForceFeedback support now, even though Immersion Corp. considers the protocol a trade secret and won't disclose a word about it. 
I-Force操纵杆和轮子的驱动程序,通过USB和RS232。它现在包括ForceFeedback支持,尽管Immersion Corp.认为该协议是商业秘密,不会透露任何信息。

 3.2 Event handlers   //3.2事件处理程序
 ~~~~~~~~~~~~~~~~~~
  Event handlers distribute the events from the devices to userland and kernel, as needed.
事件处理程序根据需要将事件从设备分发到用户区域和内核。

 3.2.1 keybdev   3.2.1键盘设备
 ~~~~~~~~~~~~~
  keybdev is currently a rather ugly hack that translates the input events into architecture-specific keyboard raw mode (Xlated AT Set2 on x86), and passes them into the handle_scancode function of the keyboard.c module. This works well enough on all architectures that keybdev can generate rawmode on, other architectures can be added to it.
keybdev目前是一个相当丑陋的黑客,它将输入事件转换为特定于体系结构的键盘原始模式(x86上的Xlated AT Set2),并将它们传递到keyboard.c模块的handle_scancode函数中。这在keybdev可以在其上生成rawmode的所有架构上都非常有效,其他架构也可以添加到其中。


  The right way would be to pass the events to keyboard.c directly, best if keyboard.c would itself be an event handler. This is done in the input patch, available on the webpage mentioned below. 
正确的方法是将事件直接传递给keyboard.c,最好是keyboard-c本身是一个事件处理程序。这是在下面提到的网页上提供的输入补丁中完成的。

 3.2.2 mousedev  //3.2.2鼠标设备
 ~~~~~~~~~~~~~~
  mousedev is also a hack to make programs that use mouse input work. It takes events from either mice or digitizers/tablets and makes a PS/2-style (a la /dev/psaux) mouse device available to the userland. Ideally, the programs could use a more reasonable interface, for example evdev
mousedev也是一种使使用鼠标输入的程序工作的黑客。它从鼠标或数字转换器/平板电脑中获取事件,并为用户提供PS/2风格(la/dev/psaux) 鼠标设备。理想情况下, 程序可以使用更合理的接口,例如evdev

  Mousedev devices in /dev/input (as shown above) are:
  /dev/input中的鼠标设备(如上所示)包括:

    crw-r--r--   1 root     root      13,  32 Mar 28 22:45 mouse0
    crw-r--r--   1 root     root      13,  33 Mar 29 00:41 mouse1
    crw-r--r--   1 root     root      13,  34 Mar 29 00:41 mouse2
    crw-r--r--   1 root     root      13,  35 Apr  1 10:50 mouse3
    ...
    ...
    crw-r--r--   1 root     root      13,  62 Apr  1 10:50 mouse30
    crw-r--r--   1 root     root      13,  63 Apr  1 10:50 mice
 Each 'mouse' device is assigned to a single mouse or digitizer, except the last one - 'mice'. This single character device is shared by all mice and digitizers, and even if none are connected, the device is present.  This is useful for hotplugging USB mice, so that programs can open the device even when no mice are present.

每个“鼠标”设备都分配给一个鼠标或数字转换器,除了最后一个“鼠标”。所有鼠标和数字转换器都共享这个单字符设备,即使没有连接,该设备也存在。这对于热插拔USB鼠标非常有用,这样即使没有鼠标,程序也可以打开设备。

  CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are the size of your screen (in pixels) in XFree86. This is needed if you want to use your digitizer in X, because its movement is sent to X via a virtual PS/2 mouse and thus needs to be scaled accordingly. These values won't be used if you use a mouse only.

内核配置中的CONFIG_INPUT_MOUSEDEV_SCREN_[XY]是XFree86中屏幕的大小(以像素为单位)。如果您想在X中使用数字化仪,这是需要的,因为它的移动是通过虚拟PS/2鼠标发送到X的,因此需要相应地缩放。如果仅使用鼠标,则不会使用这些值。

  Mousedev will generate either PS/2, ImPS/2 (Microsoft IntelliMouse) or ExplorerPS/2 (IntelliMouse Explorer) protocols, depending on what the program reading the data wishes. You can set GPM and X to any of these. You'll need ImPS/2 if you want to make use of a wheel on a USB mouse and ExplorerPS/2 if you want to use extra (up to 5) buttons. 
Mousedev将生成PS/2、ImPS/2(Microsoft IntelliMouse)或ExplorerPS/2(IntelliMouse Explorer)协议,具体取决于读取数据的程序的愿望。您可以将GPM和X设置为任何一个。如果您想使用USB鼠标上的滚轮,则需要ImPS/2;如果您想额外使用(最多5个)按钮,则需要ExplorerPS/2。

 3.2.3 joydev   //3.2.3操纵手柄
 ~~~~~~~~~~~~
  Joydev implements v0.x and v1.x Linux joystick api, much like drivers/char/joystick/joystick.c used to in earlier versions. See joystick-api.txt in the Documentation subdirectory for details.  As soon as any joystick is connected, it can be accessed in /dev/input on: 
Joydev实现了v0.x和v1.x Linux操纵杆api,非常类似于早期版本中使用的drivers/car/jonger/jonger.c。有关详细信息,请参阅Documentation子目录中的joystick-api.txt。一旦连接了任何操纵杆,就可以在/dev/input中访问:

    crw-r--r--   1 root     root      13,   0 Apr  1 10:50 js0
    crw-r--r--   1 root     root      13,   1 Apr  1 10:50 js1
    crw-r--r--   1 root     root      13,   2 Apr  1 10:50 js2
    crw-r--r--   1 root     root      13,   3 Apr  1 10:50 js3
    ...
 And so on up to js31.
 3.2.4 evdev   //3.2.4电子设备
 ~~~~~~~~~~~
  evdev is the generic input event interface. It passes the events generated in the kernel straight to the program, with timestamps. The API is still evolving, but should be usable now. It's described in section 5. 
evdev是通用的输入事件接口。它将内核中生成的事件直接传递给程序,并带有时间戳。API仍在发展,但现在应该可以使用了。第5节对此进行了描述。
  This should be the way for GPM and X to get keyboard and mouse events. It allows for multihead in X without any specific multihead kernel support. The event codes are the same on all architectures and are hardware independent.
这应该是GPM和X获取键盘和鼠标事件的方式。它允许X中的多头,而不需要任何特定的多头内核支持。事件代码在所有架构上都是相同的,并且与硬件无关。
  The devices are in /dev/input:
设备位于/dev/input中:
    crw-r--r--   1 root     root      13,  64 Apr  1 10:49 event0
    crw-r--r--   1 root     root      13,  65 Apr  1 10:50 event1
    crw-r--r--   1 root     root      13,  66 Apr  1 10:50 event2
    crw-r--r--   1 root     root      13,  67 Apr  1 10:50 event3
    ...
 And so on up to event31.

 4. Verifying if it works   //4.验证是否有效
 ~~~~~~~~~~~~~~~~~~~~~~~~
  Typing a couple keys on the keyboard should be enough to check that a USB keyboard works and is correctly connected to the kernel keyboard driver. 
在键盘上键入几个键应该足以检查USB键盘是否正常工作,是否正确连接到内核键盘驱动程序。
  Doing a "cat /dev/input/mouse0" (c, 13, 32) will verify that a mouse is also emulated; characters should appear if you move it.
执行“cat/dev/input/mouse0”(c,13,32)将验证是否也模拟了鼠标;如果移动它,应该会出现字符。
  You can test the joystick emulation with the 'jstest' utility, available in the joystick package (see Documentation/input/joystick.txt).
您可以使用“jstest”实用程序测试游戏杆仿真,该实用程序在游戏杆软件包中提供(请参阅Documentation/input/joystick.txt)。
  You can test the event devices with the 'evtest' utility available in the LinuxConsole project CVS archive (see the URL below).
您可以使用LinuxConsole项目CVS存档中提供的“evtest”实用程序测试事件设备(请参阅下面的URL)。


 5. Event interface  5.事件接口
 ~~~~~~~~~~~~~~~~~~
  Should you want to add event device support into any application (X, gpm, svgalib ...) I <vojtech@ucw.cz> will be happy to provide you any help I can. Here goes a description of the current state of things, which is going to be extended, but not changed incompatibly as time goes:
如果您想在任何应用程序中添加事件设备支持(X、gpm、svgalib…)<vojtech@ucw.cz>我会很乐意为您提供任何帮助。下面是对事物当前状态的描述,它将被扩展,但不会随着时间的推移而发生不兼容的变化:
  You can use blocking and nonblocking reads, also select() on the /dev/input/eventX devices, and you'll always get a whole number of input events on a read. Their layout is:
 您可以使用阻塞和非阻塞读取,也可以在/dev/input/eventX设备上使用select()函数, 这样每次读取都会得到大量的输入事件。其布局如下:
 struct input_event {
    struct timeval time;
    unsigned short type;
    unsigned short code;
    unsigned int value; 
    };

  'time' is the timestamp, it returns the time at which the event happened. Type is for example EV_REL for relative moment, EV_KEY for a keypress or release. More types are defined in include/linux/input.h.
“time”是时间戳,它返回事件发生的时间。例如,EV_REL表示相对力矩,EV_KEY表示按键或释放。include/linux/input.h中定义了更多类型。
  'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete list is in include/linux/input.h.
“code”是事件代码,例如REL_X或KEY_BACKSPACE,同样完整的列表在include/linux/input.h中。
  'value' is the value the event carries. Either a relative change for EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat.
“value”是事件携带的值。EV_REL的相对变化,EV_ABS(操纵杆…)的绝对新值,或EV_KEY的0表示释放,1表示按键,2表示自动重复。


 

五、Documentation/input/input-programming.txt(百度翻译)

输入设备驱动编程示例。

Programming input drivers
~~~~~~~~~~~~~~~~~~~~~~~~~

1. Creating an input device driver   //创建一个输入设备驱动
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.0 The simplest example   //1.0 一个简单的例子
~~~~~~~~~~~~~~~~~~~~~~~~

Here comes a very simple example of an input device driver. The device has just one button and the button is accessible at i/o port BUTTON_PORT. When pressed or released a BUTTON_IRQ happens. The driver could look like:
下面是输入设备驱动程序的一个非常简单的示例。该设备只有一个按钮,可通过i/o端口button_port 访问该按钮。 按下或松开按钮时,BUTTON_IRQ(按键中断)发生。驱动程序可能看起来像:


#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>

#include <asm/irq.h>
#include <asm/io.h>

static struct input_dev *button_dev;

//中断处理函数
static irqreturn_t button_interrupt(int irq, void *dummy)
{
    input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);  //向内核上报按键值,inb读回一个字节
    input_sync(button_dev);   //发送同步信号
    return IRQ_HANDLED;
}

//按键初始化
static int __init button_init(void)
{
    int error;
    //注册中断
    if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
                return -EBUSY;
        }

    button_dev = input_allocate_device();  //分配输入设备结构体空间
    if (!button_dev) {
        printk(KERN_ERR "button.c: Not enough memory\n");
        error = -ENOMEM;
        goto err_free_irq;
    }

    button_dev->evbit[0] = BIT_MASK(EV_KEY);
    button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);   //设置上报键值

    error = input_register_device(button_dev);  //注册输入设备
    if (error) {
        printk(KERN_ERR "button.c: Failed to register device\n");
        goto err_free_dev;
    }

    return 0;
//出错处理
 err_free_dev:
    input_free_device(button_dev);
 err_free_irq:
    free_irq(BUTTON_IRQ, button_interrupt);
    return error;
}


//驱动卸载执行,去初始化
static void __exit button_exit(void)
{
    input_unregister_device(button_dev);   //注销输入设备
    free_irq(BUTTON_IRQ, button_interrupt);  //释放中断
}

module_init(button_init);
module_exit(button_exit);


1.1 What the example does    //例子做了什么?
~~~~~~~~~~~~~~~~~~~~~~~~~

First it has to include the <linux/input.h> file, which interfaces to the input subsystem. This provides all the definitions needed.
首先,它必须包含<linux/input.h>文件,该文件与输入子系统接口。这提供了所需的所有定义。

 In the _init function, which is called either upon module load or when booting the kernel, it grabs the required resources (it should also check for the presence of the device).
在_init函数中,该函数在模块加载时或启动内核时调用,它获取所需的资源(还应检查设备的存在)。

 Then it allocates a new input device structure with input_allocate_device() and sets up input bitfields. This way the device driver tells the other parts of the input systems what it is - what events can be generated or accepted by this input device. Our example device can only generate EV_KEY type events, and from those only BTN_0 event code. Thus we only set these two bits. We could have used
然后,它使用input_allocate_device()分配一个新的输入设备结构,并设置输入位字段。这样,设备驱动程序告诉输入系统的其他部分它是什么——这个输入设备可以生成或接受什么事件。我们的示例设备只能生成EV_KEY类型的事件,并且只能生成BTN_0事件代码。因此,我们只设置这两个位。我们可以用

    set_bit(EV_KEY, button_dev.evbit);
    set_bit(BTN_0, button_dev.keybit);

as well, but with more than single bits the first approach tends to be
shorter.
但是对于多于单个比特的情况,第一种方法往往更短。
Then the example driver registers the input device structure by calling
然后,示例驱动程序通过调用


    input_register_device(&button_dev);

This adds the button_dev structure to linked lists of the input driver and calls device handler modules _connect functions to tell them a new input device has appeared. input_register_device() may sleep and therefore must not be called from an interrupt or with a spinlock held.
这会将button_dev结构添加到输入驱动程序的链接列表中,并调用设备处理程序模块_connect函数,告诉它们出现了新的输入设备。input_register_device()可能会休眠,因此不能从中断或持有自旋锁的情况下调用。

While in use, the only used function of the driver is
在使用过程中,驱动程序唯一使用的功能是
    button_interrupt()

which upon every interrupt from the button checks its state and reports it
via the
该按钮在每次中断时检查其状态并通过
    input_report_key()

call to the input system. There is no need to check whether the interrupt routine isn't reporting two same value events (press, press for example) to the input system, because the input_report_* functions check that themselves.
调用输入系统。无需检查中断例程是否没有向输入系统报告两个相同值的事件(例如,按下),因为input_report_*函数会自行检查。
Then there is the

    input_sync()

call to tell those who receive the events that we've sent a complete report. This doesn't seem important in the one button case, but is quite important for for example mouse movement, where you don't want the X and Y values to be interpreted separately, because that'd result in a different movement.
调用这个函数告诉那些收到事件的人,我们已经发送了一份完整的报告。这在单按钮情况下似乎并不重要,但对于例如鼠标移动来说非常重要,因为您不希望X和Y值被单独解释,因为这会导致不同的移动。


1.2 dev->open() and dev->close()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In case the driver has to repeatedly poll the device, because it doesn't have an interrupt coming from it and the polling is too expensive to be done all the time, or if the device uses a valuable resource (eg. interrupt), it can use the open and close callback to know when it can stop polling or release the interrupt and when it must resume polling or grab the interrupt again. To do that, we would add this to our example driver:
如果驱动程序必须重复轮询设备,因为它没有来自它的中断,并且轮询太昂贵,无法一直进行,或者如果设备使用了宝贵的资源(例如中断),它可以使用打开和关闭回调来知道何时可以停止轮询或释放中断,何时必须恢复轮询或再次获取中断。为此,我们将在示例驱动程序中添加以下内容:

static int button_open(struct input_dev *dev)
{
    if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
                return -EBUSY;
        }

        return 0;
}

static void button_close(struct input_dev *dev)
{
        free_irq(IRQ_AMIGA_VERTB, button_interrupt);
}

static int __init button_init(void)
{
    ...
    button_dev->open = button_open;
    button_dev->close = button_close;
    ...
}

Note that input core keeps track of number of users for the device and makes sure that dev->open() is called only when the first user connects to the device and that dev->close() is called when the very last user disconnects. Calls to both callbacks are serialized.
请注意,input core会跟踪设备的用户数量,并确保只有当第一个用户连接到设备时才调用dev->open(),而当最后一个用户断开连接时,才会调用dev->close()。对两个回调的调用都是序列化的。


The open() callback should return a 0 in case of success or any nonzero value
in case of failure. The close() callback (which is void) must always succeed.
如果成功,open()回调应返回0,如果失败,则返回任何非零值。close()回调(为空)必须始终成功。

1.3 Basic event types   //基本事件类型
~~~~~~~~~~~~~~~~~~~~~

The most simple event type is EV_KEY, which is used for keys and buttons.
It's reported to the input system via:
最简单的事件类型是EV_KEY,用于键和按钮。
通过以下方式向输入系统报告:
    input_report_key(struct input_dev *dev, int code, int value)

See linux/input.h for the allowable values of code (from 0 to KEY_MAX). Value is interpreted as a truth value, ie any nonzero value means key pressed, zero value means key released. The input code generates events only in case the value is different from before.
有关代码的允许值(从0到KEY_MAX),请参见linux/input.h。值被解释为真值,即任何非零值表示按键按下,零值表示按键释放。输入代码仅在值与之前不同的情况下生成事件。


In addition to EV_KEY, there are two more basic event types: EV_REL and EV_ABS. They are used for relative and absolute values supplied by the device. A relative value may be for example a mouse movement in the X axis. The mouse reports it as a relative difference from the last position, because it doesn't have any absolute coordinate system to work in. Absolute events are namely for joysticks and digitizers - devices that do work in an absolute coordinate systems.
除了EV_KEY之外,还有两种更基本的事件类型:EV_REL和EV_ABS。它们用于设备提供的相对值和绝对值。相对值可以是例如鼠标在X轴上的移动。鼠标将其报告为与上一个位置的相对差异,因为它没有任何绝对坐标系。绝对事件是指操纵杆和数字转换器-在绝对坐标系中工作的设备。


Having the device report EV_REL buttons is as simple as with EV_KEY, simply
set the corresponding bits and call the
让设备报告EV_REL按钮与EV_KEY一样简单,只需设置相应的位并调用
    input_report_rel(struct input_dev *dev, int code, int value)

function. Events are generated only for nonzero value.
函数。仅为非零值生成事件。
However EV_ABS requires a little special care. Before calling input_register_device, you have to fill additional fields in the input_dev struct for each absolute axis your device has. If our button device had also the ABS_X axis:
然而,EV_ABS需要特别注意。在调用input_register_device之前,必须在input_dev结构中为设备的每个绝对轴填充其他字段。如果我们的按钮设备也具有ABS_X轴:
    button_dev.absmin[ABS_X] = 0;
    button_dev.absmax[ABS_X] = 255;
    button_dev.absfuzz[ABS_X] = 4;
    button_dev.absflat[ABS_X] = 8;

Or, you can just say:

    input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);

This setting would be appropriate for a joystick X axis, with the minimum of 0, maximum of 255 (which the joystick *must* be able to reach, no problem if it sometimes reports more, but it must be able to always reach the min and max values), with noise in the data up to +- 4, and with a center flat position of size 8.

此设置适用于操纵杆X轴,最小值为0,最大值为255(操纵杆*必须*能够达到,如果有时报告更多,则没有问题,但必须始终能够达到最小值和最大值),数据中的噪声高达+-4,中心平面位置大小为8。


If you don't need absfuzz and absflat, you can set them to zero, which mean that the thing is precise and always returns to exactly the center position (if it has any).
如果你不需要absfuzz和absflat,你可以将它们设置为零,这意味着这个东西是精确的,并且总是精确地返回到中心位置(如果有)。


1.4 BITS_TO_LONGS(), BIT_WORD(), BIT_MASK()
~~~~~~~~~~~~~~~~~~~~~~~~~~

These three macros from bitops.h help some bitfield computations:
bitops.h中的这三个宏有助于一些位域计算
    BITS_TO_LONGS(x) - returns the length of a bitfield array in longs for x bits  返回x位的位字段数组的长度(以longs为单位)
    BIT_WORD(x)     - returns the index in the array in longs for bit x  返回数组中位x的索引(以longs为单位)
    BIT_MASK(x)     - returns the index in a long for bit x  返回位x的长整型索引

1.5 The id* and name fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The dev->name should be set before registering the input device by the input device driver. It's a string like 'Generic button device' containing a user friendly name of the device.
在输入设备驱动程序注册输入设备之前,应该设置dev->name。它是一个类似“通用按钮设备”的字符串,包含设备的用户友好名称。


The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device ID of the device. The bus IDs are defined in input.h. The vendor and device ids are defined in pci_ids.h, usb_ids.h and similar include files. These fields should be set by the input device driver before registering it.
id*字段包含设备的总线id(PCI、USB…)、供应商id和设备id。总线ID在input.h中定义。供应商和设备ID在pci_IDs.h、usb_IDs.h和类似的include文件中定义。这些字段应在注册之前由输入设备驱动程序设置。

The idtype field can be used for specific information for the input device
driver.
idtype字段可用于输入设备驱动程序的特定信息。

The id and name fields can be passed to userland via the evdev interface.
id和name字段可以通过evdev接口传递给userland。

1.6 The keycode, keycodemax, keycodesize fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

These three fields should be used by input devices that have dense keymaps. The keycode is an array used to map from scancodes to input system keycodes. The keycode max should contain the size of the array and keycodesize the size of each entry in it (in bytes).
这三个字段应由具有密集键映射的输入设备使用。键码是用于从扫描码映射到输入系统键码的数组。keycodemax应该包含数组的大小,keycodesize包含其中每个条目的大小(以字节为单位)。

Userspace can query and alter current scancode to keycode mappings using EVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface. When a device has all 3 aforementioned fields filled in, the driver may rely on kernel's default implementation of setting and querying keycode mappings.
用户空间可以使用相应evdev接口上的EVIOCGKEYCODE和EVIOCSKEYCODE ioctl查询和更改当前扫描码到键码的映射。当一个设备填写了前面提到的所有3个字段时,驱动程序可能依赖于内核设置和查询键码映射的默认实现。


1.7 dev->getkeycode() and dev->setkeycode()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getkeycode() and setkeycode() callbacks allow drivers to override default keycode/keycodesize/keycodemax mapping mechanism provided by input core and implement sparse keycode maps.
getkeycode()和setkeycode()回调允许驱动程序重写输入内核提供的默认keycode/keycodesize/keycodemax映射机制,并实现稀疏的keycode映射。


1.8 Key autorepeat
~~~~~~~~~~~~~~~~~~

... is simple. It is handled by the input.c module. Hardware autorepeat is not used, because it's not present in many devices and even where it is present, it is broken sometimes (at keyboards: Toshiba notebooks). To enable autorepeat for your device, just set EV_REP in dev->evbit. All will be handled by the input system.
…很简单。它由input.c模块处理。不使用硬件自动重印,因为它在许多设备中都不存在,即使在存在的地方,它有时也会损坏(在键盘上:东芝笔记本电脑)。要为设备启用自动重拍,只需在dev->evbit中设置EV_REP。所有这些都将由输入系统处理。

1.9 Other event types, handling output events  其他事件类型,处理输出事件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The other event types up to now are:

EV_LED - used for the keyboard LEDs.   //用于键盘led
EV_SND - used for keyboard beeps.      //用于键盘蜂鸣器

They are very similar to for example key events, but they go in the other direction - from the system to the input device driver. If your input device driver can handle these events, it has to set the respective bits in evbit, *and* also the callback routine:
它们与例如按键事件非常相似,但它们的方向相反-从系统到输入设备驱动程序。如果您的输入设备驱动程序可以处理这些事件,则必须在evbit、*and*以及回调例程中设置相应的位:

    button_dev->event = button_event;

int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
{
    if (type == EV_SND && code == SND_BELL) {
        outb(value, BUTTON_BELL);
        return 0;
    }
    return -1;
}

This callback routine can be called from an interrupt or a BH (although that
isn't a rule), and thus must not sleep, and must not take too long to finish.
这个回调例程可以从中断或BH中调用(虽然这不是规则),因此不能休眠,也不能花费太长时间来完成。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这段代码是一个在输入子系统中使用的ADC按键驱动程序的轮询函数。下面是每行代码的功能: 1. `static void adc_keys_poll(struct input_polled_dev *dev)`:声明一个名为 `adc_keys_poll` 的静态函数,它接受一个指向 `input_polled_dev` 结构体的指针作为参数,并且没有返回值。 2. `struct adc_keys_state st = dev->private;`:声明一个名为 `st` 的 `adc_keys_state` 结构体变量,并将其初始化为指向 `input_polled_dev` 结构体的 `private` 成员。 3. `int i, value, ret; u32 diff, closest = 0xffffffff; int keycode = 0;`:声明一些变量,包括整型变量 `i`、`value`、`ret`、`keycode`,无符号整型变量 `diff` 和 `closest`。其中 `closest` 被初始化为最大可能的值。 4. `ret = iio_read_channel_processed(st->channel, &value);`:使用 `iio_read_channel_processed` 函数读取 ADC 通道的值,并将结果存储在 `value` 变量中。读取成功时,返回值为 0,否则为负数。 5. `if (unlikely(ret < 0)) { / Forcibly release key if any was pressed */ value = st->keyup_voltage; }`:如果读取 ADC 通道的值失败,将 `value` 设置为 `st->keyup_voltage`,并且强制释放任何已经按下的键。 6. `else { for (i = 0; i < st->num_keys; i++) { diff = abs(st->map[i].voltage - value); if (diff < closest) { closest = diff; keycode = st->map[i].keycode; } } }`:如果读取 ADC 通道的值成功,那么遍历 `st->map` 数组中的所有键,找到最接近 `value` 值的那个键,并将其对应的键码存储在 `keycode` 变量中。 7. `if (abs(st->keyup_voltage - value) < closest) keycode = 0;`:如果 `st->keyup_voltage` 与 `value` 的差值比最接近的键的差值还小,那么将 `keycode` 设置为 0,表示没有键被按下。 8. `if (st->last_key && st->last_key != keycode) input_report_key(dev->input, st->last_key, 0);`:如果之前有键被按下,且上一次按下的键与当前按下的键不同,那么向输入子系统报告上一次按下的键已经释放。 9. `if (keycode) input_report_key(dev->input, keycode, 1);`:如果当前有键被按下,那么向输入子系统报告该键已经按下。 10. `input_sync(dev->input);`:向输入子系统报告输入事件已经处理完毕。 11. `st->last_key = keycode;`:将 `keycode` 的值存储到 `st->last_key` 变量中,以便在下一次轮询时使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大智兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值