欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 【Linux 驱动】IMX6ULL input驱动

【Linux 驱动】IMX6ULL input驱动

2024/10/24 16:31:47 来源:https://blog.csdn.net/weixin_47596351/article/details/140938142  浏览:    关键词:【Linux 驱动】IMX6ULL input驱动

1. input子系统介绍

input 子系统分为 input 驱动层、input 核心层、input 事件处理层,最终给用户空间提供可访问的设备节点。

  • 驱动层:输入设备的具体驱动程序,比如按键驱动程序,向内核层报告输入内容
  • 核心层:承上启下,为驱动层提供输入设备注册和操作接口。通知事件层对输入事件进行处理。
  • 事件层:主要和用户空间进行交互。

2. 重要结构体

2.1 struct input_dev

/*** 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)* @propbit: bitmap of device properties and quirks* @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* @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.* @keycodemax: size of keycode table* @keycodesize: size of elements in keycode table* @keycode: map of scancodes to keycodes for this device* @getkeycode: optional legacy method to retrieve current 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* @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)* @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* @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* @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.*/
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;
};
  • evbit 表示输入事件类型,比如同步事件、按键事件等
#define EV_SYN 0x00 /* 同步事件 */
#define EV_KEY 0x01 /* 按键事件 */
#define EV_REL 0x02 /* 相对坐标事件 */
#define EV_ABS 0x03 /* 绝对坐标事件 */
#define EV_MSC 0x04 /* 杂项(其他)事件 */
#define EV_SW 0x05 /* 开关事件 */
#define EV_LED 0x11 /* LED */
#define EV_SND 0x12 /* sound(声音) */
#define EV_REP 0x14 /* 重复事件 */
#define EV_FF 0x15 /* 压力事件 */
#define EV_PWR 0x16 /* 电源事件 */
#define EV_FF_STATUS 0x17 /* 压力状态事件 */
  • keybit、relbit 等等都是存放不同事件对应的值,比如keybit支持KEY_1、KEY_2等
#define KEY_RESERVED 0
#define KEY_ESC 1
#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5
#define KEY_5 6
#define KEY_6 7
#define KEY_7 8
#define KEY_8 9
#define KEY_9 10
#define KEY_0 11
......
#define BTN_TRIGGER_HAPPY39 0x2e6
#define BTN_TRIGGER_HAPPY40 0x2e7

2.2 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* @events: event sequence 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* @legacy_minors: set to %true by drivers using legacy minor ranges* @minor: beginning of range of 32 legacy 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);void (*events)(struct input_handle *handle,const struct input_value *vals, unsigned int count);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);bool legacy_minors;int minor;const char *name;const struct input_device_id *id_table;struct list_head	h_list;struct list_head	node;
};

2.3 设备获取、上报数据:struct input_event

/** The event structure itself*/struct input_event {struct timeval time;__u16 type;__u16 code;__s32 value;
};struct timeval {__kernel_time_t		tv_sec;		/* seconds */__kernel_suseconds_t	tv_usec;	/* microseconds */
};
  • time:事件发生时间
  • type:事件类型,EV_KEY、EV_ABS等
  • code:事件码,KEY_1、KEY_2等
  • value:值,比如 EV_KEY 事件中 value 就是按键值,表示按键有没有被按下,如果为 1 的话说明按键按下,如果为 0 的话说明按键没有被按下或者按键松开了

3. input 内部实现

  •  和platform总线驱动相似,左右两边依次比较,如果匹配,则调用input_handler结构体的connect函数

3.1 input 驱动编写流程

static int __init input_init(void)
{int err;err = class_register(&input_class);if (err) {pr_err("unable to register input_dev class\n");return err;}err = input_proc_init();if (err)goto fail1;err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),INPUT_MAX_CHAR_DEVICES, "input");if (err) {pr_err("unable to register char major %d", INPUT_MAJOR);goto fail2;}return 0;fail2:	input_proc_exit();fail1:	class_unregister(&input_class);return err;
}static void __exit input_exit(void)
{input_proc_exit();unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0),INPUT_MAX_CHAR_DEVICES);class_unregister(&input_class);
}subsys_initcall(input_init);
module_exit(input_exit);
  • 注册一个 input 类,这样系统启动以后就会在/sys/class 目录下有一个 input 子目录

  •  注册一个主设备号为INPUT_MAJOR(13)的字符驱动,后续在使用 input 子系统处理输入设备的时候就不需要去注册字符设备了,我们只需要向系统注册一个 input_device 即可

3.2 input_dev(ft5x06.c)注册过程

 3.3 struct input_handler(evdev.c)注册过程

3.4 input_register_device

 3.5 input_register_handler

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com