input子系统学习笔记

输入设备(按键、键盘、触摸屏、鼠标)是典型的字符设备,工作机理是底层
在按键、触摸等动作发生时产生一个中断(或驱动timer定时查询),然后CPU
通过SPI、I2C或外部存储器总线读取键值,坐标等数据。
输入核心层提供了底层输入设备驱动程序所需的API,如分配/释放一个输入设备
输入子系统由输入子系统核心层( Input Core ),驱动层和事件处理层(Event Handler)三部份组成。一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 input driver -> Input core -> Event handler -> userspace 到达用户空间传给应用程序
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
input_allocate_device()返回的是1个input_dev的结构体,此结构体用于表征1个输入设备
注册/注销输入设备用的接口
input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
报告输入事件的接口,指定type, code, value
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
input通用数据结构
1. input_dev是input设备基本的设备结构,每个input驱动程序必须分配初始化这样一个结构
path:include/linux/input.h
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_slot *mt;
 int mtsize;
 int slot;
 int trkid;
 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;
 bool sync;
 struct device dev;
 struct list_head h_list;
 struct list_head node;
};
/**
 * 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 array of struct input_mt_slot holding current values
 * of tracked contacts
 * @mtsize: number of MT slots the device uses
 * @slot: MT slot currently being transmitted
 * @trkid: stores MT tracking ID for the current contact
 * @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.
 * @sync: set to %true when there were no new events since last EV_SYN
 * @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
 */
2. input_event 驱动层向input子系统核心报告事件的函数。
void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value);
path:linux/input.h 这个文件定义了event事件的结构体,API和标准按键的编码等;
struct input_event {
    struct timeval time;  //按键时间
    __u16 type; //事件类型
    __u16 code; //要模拟成什么按键
    __s32 value;//是按下还是释放
};
type,指事件类型,常见的事件类型有:
EV_KEY, 按键事件,如键盘的按键(按下哪个键),鼠标的左键右键(是非击下)等;
EV_REL, 相对坐标,主要是指鼠标的移动事件(相对位移 轨迹等);
EV_ABS, 绝对坐标,主要指触摸屏的移动事件
code:事件的代码.
如果事件的类型代码是EV_ABS,该代码code为设备事件代码“Absolute axes”绝对轴:
#define ABS_X   0x00
#define ABS_Y   0x01
#define ABS_Z   0x02
#define ABS_RX   0x03
#define ABS_RY   0x04
#define ABS_RZ   0x05
#define ABS_THROTTLE  0x06
#define ABS_RUDDER  0x07
#define ABS_WHEEL  0x08
#define ABS_GAS   0x09
#define ABS_BRAKE  0x0a
#define ABS_HAT0X  0x10
#define ABS_HAT0Y  0x11
#define ABS_HAT1X  0x12
#define ABS_HAT1Y  0x13
#define ABS_HAT2X  0x14
#define ABS_HAT2Y  0x15
#define ABS_HAT3X  0x16
#define ABS_HAT3Y  0x17
#define ABS_PRESSURE  0x18
#define ABS_DISTANCE  0x19
#define ABS_TILT_X  0x1a
#define ABS_TILT_Y  0x1b
#define ABS_TOOL_WIDTH  0x1c
#define ABS_VOLUME  0x20
#define ABS_MISC  0x28
#define ABS_MT_SLOT  0x2f /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
#define ABS_MT_BLOB_ID  0x38 /* Group a set of packets as a blob */
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
#define ABS_MT_PRESSURE  0x3a /* Pressure on contact area */
#define ABS_MT_DISTANCE  0x3b /* Contact hover distance */
#ifdef __KERNEL__
/* Implementation details, userspace should not care about these */
#define ABS_MT_FIRST  ABS_MT_TOUCH_MAJOR
#define ABS_MT_LAST  ABS_MT_DISTANCE
#endif
#define ABS_MAX   0x3f
#define ABS_CNT   (ABS_MAX+1)
value:事件的值.如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0;如果事件的类型代码是EV_REL,value的正数值和负数值分别代表两个不同方向的值.
3. 分配并初始化input_dev
input_allocate_device()

4. 向内核注册一个input设备
input_register_device()
5. input驱动流程
1)定义input设备结构
struct input_dev *input;
2)分配并初始化input_dev接构
input = input_allocate_device();
input->name = "gpio-keys";
input->phys = "gpio-keys/input0";
input->id.bustype = BUS_HOST;
input->id.vendor  = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
3) 记录本设备对于哪些事件感兴趣(对其进行处理)input_set_capability();
定义/drivers/input/input.c
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
input_set_capability(input, EV_KEY, 101);

4)向内核注册一个input设备
input_register_device(input);

5)记录按键状态
int state = (gpio_get_value((S3C64XX_GPN(0)) ? 1 : 0) ^ 1 ;

6)汇报输入事件
input_event(input, EV_KEY, 101, !!state);

7)等待输入事件处理完成
input_sync(input);

8)注销一个input设备
input_unregister_device(input);
在内核自带的文档Documentation/input/input-programming.txt中。有一个使用input子系统的例子,并附带相应的说明

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

suvine

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

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

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

打赏作者

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

抵扣说明:

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

余额充值