Uinput是一个虚拟的设备,使得可以在用户控件处理input设备,一般来讲uinput设备文件存在于/dev/input或者/dev/input/uinput目录中。
uinput的使用
一. 创建合适的uinput设备
1.打开uinput设备
so easy, 在linux中,一切都是文件,所以按照通常的做法就是使用系统调用open()来打开uinput设备就可以啦, 不过要注意open()的第二个参数哦, 也就是打开的模式。
2.uinput的配置
打开设备以后我们需要告诉input子系统我们想要使用input event 的哪种type,这些type可以查看/usr/include/linux/input.h,
具有代表性的就是一下三种
#define EV_KEY :代表按键的按下与释放事件
#define EV_REL :代表相对坐标事件,一般就是鼠标啦
#define EV_ABS : 代表绝对坐标事件,一般是触摸屏
那么如何配置 uinput 呢,那就是使用ioctl()啦, ioctl()是个很棒的系统调用,大家可以深入的研究一下。
我们使用UI_SET_EVBIT作为我们想进行的配置项,并使用以上三个define作为我们想要的事件类型,例如我们可以用如下语句是能按键的按下释放事件
ioctl(fd, UI_SET_EVBIT, EV_KEY)
仅仅这样还不够,我们还需要告诉input子系统,哪些键值可以被送到input子系统:
ioctl(fd, UI_SET_EVBIT, KEY_D)
如果是针对触摸屏进行配置的话,那就是这个样子的:
ioctl(fd, UI_SET_EVBIT, EV_ABS)
ioctl(fd, UI_SET_EVBIT, ABS_X)
ioctl(fd, UI_SET_EVBIT, ABS_Y)
3. 配置struct uinput_user_dev
第二步完成了最基本的配置,接下来我们需要向设备写入一个叫做 struct uinput_user_dev 的结构体,该结构体在/usr/include/linux/uinput.h中定义,如下
#define UINPUT_MAX_NAME_SIZE 80
struct uinput_user_dev {
char name[UINPUT_MAX_NAME_SIZE]; //用户定义的uinput设备的名字
struct input_id id; //用于描述设备的总线类型、厂商ID、产品ID和版本
__u32 ff_effects_max;
__s32 absmax[ABS_CNT]; //定义最大的绝对坐标值,在进行触摸屏的配置时应该使用
__s32 absmin[ABS_CNT]; //定义最小的绝对坐标值,在进行触摸屏的配置时应该使用
__s32 absfuzz[ABS_CNT];
__s32 absflat[ABS_CNT];
};
我们可以这样填充这个结构体
struct uinput_user_dev iudev;
snprintf(iudev.name, UINPUT_MAX_NAME_SIZE, ''uinput_name");
iudev.id.bustype = BUS_USB;
iudev.id.vendor = 0x1234;
iudev.id.product = 0xfedc;
iudev.id.version = 1;
然后写入到设备中:
write(fd, &iudev, sizeof(iudev));
4. 创建出我们的uinput设备
到目前为止我们完成了对uinput的配置,但是还是不能使用,因为我们并没有申请创建这个设备。创建uinput需要以下语句
ioctl(fd, UI_DEV_CREATE)
OK, 以后我们就可以通过描述符 fd 来对uinput设备进行访问啦。
二. 将事件注入到input子系统中
为了完成这个操作我们需要使用一个结构体: struct input_event, 他有三个成员:
type :事件类型, EV_REL, EV_KEY, EV_ABS
code:键值或者坐标,可以使用 KEY_D 或者 ABS_X...
value:对于按键来讲 1 表示按下 0 表示释放, 如果是鼠标的话,则代表移动的数
例子:
按键:
struct input_event ev;
ev.type = EV_KEY;
ev.code = KEY_D;
ev.value = 1;
ret = write(fd, &ev, sizeof(ev));
触摸屏:
struct input_event ev[2];
ev[0].type = EV_ABS;
ev[0].code = ABS_X;
ev[0].value = 1023;
ev[1].type = EV_ABS;
ev[1].code = ABS_X;
ev[1].value = 102;
ret = write(fd, ev, sizeof(ev));
三. 销毁uinput设备
ret = ioctl(fd, UI_DEV_DESTROY);
PS:
本文中的触摸屏只是使用EV_ABS的其中一个例子而已,不要固话思维。