使用UInput模拟系统键盘鼠标动作
2017-05-23 20:49
302 查看
转自:http://blog.sina.com.cn/s/blog_602f87700100llew.html
在最近的项目中,Sam需要将设备数据解析后以系统键盘鼠标的消息发送出去。选用UInput(关于UInput Driver以及编译,( http://blog.sina.com.cn/s/blog_602f87700100liyk.html)。
当uinput driver已经insmod, 且node 已经建立后。即可使用它们传递系统输入设备消息。
1.打开UInput Device:
应用程序:
dev 为 UInput Node名:通常为/dev/uinput。
open(dev, O_WRONLY | O_NDELAY);
此时,在Kernel 层,对应的动作为:
参数inode对应的是 主设备为10,子设备为223的node(即位用户态的dev)
参数file对应打开的文件。
动作:
创建了newdev– uinput_device结构。
2.设置UInput Device:
ioctl(fd, UI_SET_EVBIT, EV_KEY);
此时,在Kernel 层,对应的动作为:
参数file对应打开的文件。
参数cmd 对应用户态ioctl参数2。UI_SET_EVBIT
参数arg对应用户态ioctl参数3。EV_KEY
动作:
2.1 将driver参数传递过来。
udev = file->private_data;
udev->dev 是个input_dev 类型数据。 此时,它未初始化。
如果udev->dev为空,则使用 uinput_allocate_device(udev);申请input_dev结构
具体到CMD=UI_SET_EVBIT
首先判断newdev->state为UIST_CREATED,则返回错误码。
这就说明:设置bit,需要在create input device 之前。
具体动作为:udev->dev->evbit 设为EV_KEY.
注意:此处input device的evbit:
一个是evbit.表示设备所支持的动作.
3.继续设置 Device:
同上。设置了Keybit等。
这里就是设置了Input Device关心或者说会产生的消息。
4.写入设备:
此时,在Kernel 层,对应的动作为:
此时Device status为UIST_NEW_DEVICE
并将udev->dev 这个input device 具体化。初始化该input_dev。
之后,改变状态:
5.创建Input Device:
注意,此处是创建了Input Device。而不是UInput Device。
ioctl(fd, UI_DEV_CREATE);
此时,在Kernel 层,对应的动作为:
6.向Input Device发送Event:
总结:
使用UInput的步骤为:
1. 打开设备。
2. 使用ioctl() 配置设备。
3. 使用write() 将input device信息设置好。
4. 使用ioctl(UI_DEV_CREATE)创建Input Device。(即使用write设置的)
5. 再使用write() 写入event.
UInput添加的Input Device在/proc的反应:
解释如下:
Bus=0003 Vendor=0000 Product=0000 Version=0004
这是在第一次write时设置的:
uinp.id.version = 4;
uinp.id.bustype = BUS_USB;
struct input_id {
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
};
EV=f
后记:
后来的工作中,Sam又看到Hi3716C中,如何使用Driver将红外遥控器模拟成一个Keyboard.
http://blog.sina.com.cn/s/blog_602f877001019wtx.html
其实原理非常类似. 都需要指出支持什么Type的Event.
注3:不同类型的Input Event:
也要指出每种Type的Event中又分别支持什么具体值.
然后才是创建Device.
在最近的项目中,Sam需要将设备数据解析后以系统键盘鼠标的消息发送出去。选用UInput(关于UInput Driver以及编译,( http://blog.sina.com.cn/s/blog_602f87700100liyk.html)。
当uinput driver已经insmod, 且node 已经建立后。即可使用它们传递系统输入设备消息。
1.打开UInput Device:
应用程序:
dev 为 UInput Node名:通常为/dev/uinput。
open(dev, O_WRONLY | O_NDELAY);
此时,在Kernel 层,对应的动作为:
static int uinput_open(struct inode *inode, struct file *file)
参数inode对应的是 主设备为10,子设备为223的node(即位用户态的dev)
参数file对应打开的文件。
动作:
创建了newdev– uinput_device结构。
newdev->state = UIST_NEW_DEVICE; file->private_data = newdev;
2.设置UInput Device:
ioctl(fd, UI_SET_EVBIT, EV_KEY);
此时,在Kernel 层,对应的动作为:
static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
参数file对应打开的文件。
参数cmd 对应用户态ioctl参数2。UI_SET_EVBIT
参数arg对应用户态ioctl参数3。EV_KEY
动作:
2.1 将driver参数传递过来。
udev = file->private_data;
udev->dev 是个input_dev 类型数据。 此时,它未初始化。
如果udev->dev为空,则使用 uinput_allocate_device(udev);申请input_dev结构
具体到CMD=UI_SET_EVBIT
uinput_set_bit(arg, evbit, EV_MAX);
首先判断newdev->state为UIST_CREATED,则返回错误码。
这就说明:设置bit,需要在create input device 之前。
具体动作为:udev->dev->evbit 设为EV_KEY.
注意:此处input device的evbit:
一个是evbit.表示设备所支持的动作.
#define EV_KEY 0x01 // 按键 #define EV_REL 0x02 // 释放
3.继续设置 Device:
ret = ioctl(fd, UI_SET_RELBIT, REL_X); //鼠标 ret = ioctl(fd, UI_SET_RELBIT, REL_Y); ret = ioctl(fd, UI_SET_EVBIT, EV_ABS); ret = ioctl(fd, UI_SET_ABSBIT, ABS_X); ret = ioctl(fd, UI_SET_ABSBIT, ABS_Y); ret = ioctl(fd, UI_SET_ABSBIT, ABS_PRESSURE);
同上。设置了Keybit等。
这里就是设置了Input Device关心或者说会产生的消息。
4.写入设备:
struct uinput_user_dev uinput; uinput.id.version = 4; uinput.id.bustype = BUS_USB; uinput.absmin[ABS_X] = 0; uinput.absmax[ABS_X] = 65535; //sam 把屏幕设为0-65535 uinput.absmin[ABS_Y] = 0; uinput.absmax[ABS_Y] = 65535; uinput.absmin[ABS_PRESSURE] = 0; uinput.absmax[ABS_PRESSURE] = 0xfff; ret = write(fd, &uinput, sizeof(uinput));
此时,在Kernel 层,对应的动作为:
此时Device status为UIST_NEW_DEVICE
并将udev->dev 这个input device 具体化。初始化该input_dev。
之后,改变状态:
udev->state = UIST_SETUP_COMPLETE;
5.创建Input Device:
注意,此处是创建了Input Device。而不是UInput Device。
ioctl(fd, UI_DEV_CREATE);
此时,在Kernel 层,对应的动作为:
input_register_device(udev->dev); //向子系统注册该设备,之后中断时input_event()向子系统报告事件 udev->state = UIST_CREATED;
6.向Input Device发送Event:
struct input_event event = {0}; gettimeofday(&event.time, NULL); event.type = EV_KEY; event.code = key; event.value = press ? 1:0; write(fd, &event, sizeof(event)); 此时,在Kernel 层,对应的动作为: static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 因为此时state为UIST_CREATED input_event(udev->dev, ev.type, ev.code, ev.value); 发送event.
总结:
使用UInput的步骤为:
1. 打开设备。
2. 使用ioctl() 配置设备。
3. 使用write() 将input device信息设置好。
4. 使用ioctl(UI_DEV_CREATE)创建Input Device。(即使用write设置的)
5. 再使用write() 写入event.
UInput添加的Input Device在/proc的反应:
#cat /proc/bus/input/device I: Bus=0003 Vendor=0000 Product=0000 Version=0004 N: Name="uinput" P: Phys= S: Sysfs=/class/input/input6 H: Handlers=event1 mouse1 B: EV=f B: KEY=400 0 670000 ffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff B: REL=3 B: ABS=1000003
解释如下:
Bus=0003 Vendor=0000 Product=0000 Version=0004
这是在第一次write时设置的:
uinp.id.version = 4;
uinp.id.bustype = BUS_USB;
struct input_id {
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
};
EV=f
后记:
后来的工作中,Sam又看到Hi3716C中,如何使用Driver将红外遥控器模拟成一个Keyboard.
http://blog.sina.com.cn/s/blog_602f877001019wtx.html
其实原理非常类似. 都需要指出支持什么Type的Event.
注3:不同类型的Input Event:
#define EV_SYN 0x00 表示设备支持所有的事件 #define EV_KEY 0x01 键盘或者按键,表示一个键码 #define EV_REL 0x02 鼠标设备,表示一个相对的光标位置结果 #define EV_ABS 0x03 手写板产生的值,其是一个绝对整数值 #define EV_MSC 0x04 其他类型 #define EV_LED 0x11 LED灯设备 #define EV_SND 0x12 蜂鸣器,输入声音 #define EV_REP 0x14 允许重复按键类型 #define EV_PWR 0x16 电源管理事件 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1)
也要指出每种Type的Event中又分别支持什么具体值.
然后才是创建Device.
相关文章推荐
- 使用UInput模拟系统键盘鼠标动作
- 使用UInput模拟系统键盘鼠标动作 UInput driver分析
- 使用UInput模拟系统键盘鼠标动作 UInput driver分析
- 使用UInput模拟系统键盘鼠标动作
- linux 虚拟输入设备(uinput)模拟鼠标和键盘的使用方法
- 使用SendInput模拟键盘和鼠标动作
- VFP调用API实现代码模拟鼠标.键盘动作
- 小熊鼠标键盘模拟工具 使用说明 及核心代码
- 使用JAVA Robot 扩展Webdriver 模拟键盘鼠标操作
- python之模拟鼠标键盘动作具体实现
- 用pywin32实现windows模拟鼠标及键盘动作
- 关于mac原生系列设备【Mac mini、iMac、MB】,系统启动时键盘、鼠标均不能使用的解决方案
- keybd_event和mouse_event完全彻底细致的模拟鼠标键盘所有动作
- keybd_event,mouse_event 模拟产生键盘事件、鼠标事件的使用
- 交互系统的构建之(二)Linux下鼠标和键盘的模拟控制
- 2011-7 模拟鼠标键盘动作
- 使用SWT模拟鼠标键盘事件
- C#中使用WinIO模拟键盘鼠标(转)
- 交互系统的构建之(二)Linux下鼠标和键盘的模拟控制
- 重装系统时,USB接口鼠标和键盘不能使用的解决办法