input 设备的一些概念

 input 设备用 input_dev 来表示。

每一种类型的事件都在input_dev.evbit中用一位来表示,构成一个位图,如果某一位为1,表示支持该事件,如果该位为0,表示不支持该事件。

1. 事件类型 由 input_dev ->evbit 来表示, 可以有如下一些类型:

/*
 * Event types
 */

#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
#define EV_SND            0x12
#define EV_REP            0x14
#define EV_FF            0x15
#define EV_PWR            0x16
#define EV_FF_STATUS        0x17
#define EV_MAX            0x1f
#define EV_CNT            (EV_MAX+1)
确定设备能力和特性

对于一些设备,也许知道设备的身份信息就足够了,因为它允许你根据设备的使用情况处理设备的任何 case

但是这总做法的尺度不好,比如,你有一个设备仅有一个滑轮,你想使能处理滑轮的 handler,但是你并不想在 code里列出每个带有滑轮的鼠标的 vendor/product信息。

为此, event interface允许你对于某个设备确定有哪些功能和特性。

Event interface支持的feature types有:

    EV_SYN:    //同步事件
    EV_KEY: absolute binary results, such as keys and buttons.   //键盘,按键事件
    EV_REL: relative results, such as the axes on a mouse.      //相对坐标事件
    EV_ABS: absolute integer results, such as the axes on a joystick or for a tablet.  //绝对坐标事件,如touch 就是产生坐标事件
    EV_MSC: miscellaneous uses that didn't fit anywhere else.   //其他事件
    EV_LED: LEDs and similar indications.           //LED
    EV_SND: sound output, such as buzzers.  //音频事件
    EV_REP: enables autorepeat of keys in the input core.  //repeat事件
    EV_FF: sends force-feedback effects to a device.  //力反馈事件
    EV_FF_STATUS: device reporting of force-feedback effects back to the host.   //力反馈状态事件
    EV_PWR: power management events   //电源管理时间
这些仅仅是 type features ,每个 type feature 包含了很大范围的不同的个体 feature

例如, EV_REL type区别了 x轴, y轴, z轴,横轮,竖轮。同样, EV_KEY type包含了成千上百个 keys buttons

2. 使用 EVIOCGBIT()  ioctl可以获取设备的能力和特性,它告知你设备是否有 key或者 button

EVIOCGBIT()  ioctl处理 4个参数 ( ioctl(fd, EVIOCGBIT(ev_type, max_bytes), bitfield))

ev_type是返回的 type feature 0是个特殊 case,表示返回设备支持的所有的 type features)。

max_bytes表示返回的最大字节数。

bitfield域是指向保存结果的内存指针。

return value表示保存结果的实际字节数,如果调用失败,则返回负值。

下面展现了其使用示例,可以用来测试/dev/input/event* 设备节点支持哪些type feature

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <linux/input.h>

#define BITS_PER_LONG 32
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)

static int test_bit(int nr, const volatile unsigned long *addr)
{
    return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
}

int main(int argc, char ** argv)
{
	int fd;
	unsigned long *evtype_b = malloc(sizeof(int));
	int yalv;

	if ((fd = open(argv[1], O_RDONLY)) < 0) {
		perror("evdev open");
		exit(1);
	}

	memset(evtype_b, 0, sizeof(evtype_b));

	if (ioctl(fd, EVIOCGBIT(0, EV_MAX), evtype_b) < 0) {
		perror("evdev ioctl");
	}

	printf("Supported event types:\n");

	for (yalv = 0; yalv < EV_MAX; yalv++) {
		if (test_bit(yalv, evtype_b)) {
			/* the bit is set in the event types list */
			printf(" Event type 0x%02x ", yalv);

			switch (yalv) {
				case EV_SYN :
					printf(" (Synch Events)\n");
					break;
				case EV_KEY :
					printf(" (Keys or Buttons)\n");
					break;
				case EV_REL :
					printf(" (Relative Axes)\n");
					break;
				case EV_ABS :
					printf(" (Absolute Axes)\n");
					break;
				case EV_MSC :
					printf(" (Miscellaneous)\n");
					break;
				case EV_LED :
					printf(" (LEDs)\n");
					break;
				case EV_SND :
					printf(" (Sounds)\n");
					break;
				case EV_REP :
					printf(" (Repeat)\n");
					break;
				case EV_FF :
				case EV_FF_STATUS:
					printf(" (Force Feedback)\n");
					break;
				case EV_PWR:
					printf(" (Power Management)\n");
					break;
				default:
					printf(" (Unknown: 0x%04hx)\n", yalv);
			}
		}
	}
	close(fd);
}

这个例子使用了 evtype_bit掩码EV_MAX(在 <linux/input.h>里定义),觉得 bit array需要多少内存。

ioctl提交后,由 event layer填充 bit array

我们测试 bit array里的每一个 bit,来确定设备支持哪些 feature type

所有的设备都支持 EV_SYNC,该 bit input core来设置。

下面是运行结果的样例:

如果是 keyboard, 则

Supported event types:
  Event type 0x00  (Synchronization Events)
  Event type 0x01  (Keys or Buttons)
  Event type 0x11  (LEDs)
  Event type 0x14  (Repeat
如果是 mouse ,则
Supported event types:
  Event type 0x00  (Synchronization Events)
  Event type 0x01  (Keys or Buttons)
  Event type 0x02  (Relative Axes)
3. 对于具体的一个事件,比如坐标事件,可以设置它支持的属性.

例如你可以只支持坐标事件中的X坐标,你也可以像代码中贴出的,支持X,Y,Z轴。
更形象的地说,

set_bit(EV_ABS, idev->evbit);

set_bit(ABS_X, idev->absbit);
set_bit(ABS_Y, idev->absbit);
set_bit(ABS_Z, idev->absbit);
是一种总分的关系. evbit 是总表示支持绝对坐标时间,absbit 是分,表示支持X,Y,Z轴的绝对坐标时间。

ABS事件可以有如下一些属性:

/*
 * 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_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_MAX			0x3f
#define ABS_CNT			(ABS_MAX+1)
4. 这些内容其实在input_dev 结构里都有体现:

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, int scancode, int keycode);
	int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);

	struct ff_device *ff;

	unsigned int repeat_key;
	struct timer_list timer;

	int sync;

	int abs[ABS_MAX + 1];
	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_MAX + 1];
	int absmin[ABS_MAX + 1];
	int absfuzz[ABS_MAX + 1];
	int absflat[ABS_MAX + 1];
	int absres[ABS_MAX + 1];

	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;
	struct input_handle *filter;

	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;
};
#define to_input_dev(d) container_of(d, struct input_dev, dev)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值