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)