Linux 有自己的 input 子系统,可以统一管理鼠标和键盘事件。

如果想模拟键盘事件,但是系统没有键盘设备该如何是好?

基于输入子系统实现的 input 可以方便的在用户空间模拟鼠标和键盘事件。

也可以自己做一个字符设备接收用户输入,根据输入,投递 input 事件。

还有一种方式就是直接往evnent 里写入数据,都可以达到控制鼠标键盘的功能。---没有键盘设备的话,向哪一个event里面写?

好文:

http://blog.chinaunix.net/uid-23381466-id-3883164.html

https://blog.csdn.net/neiloid/article/details/7893732

相关书籍:

https://blog.csdn.net/huaweimember/article/details/51001672

http://baijiahao.baidu.com/s?id=1601404998850288910&wfr=spider&for=pc


weekend 探索成功, 使用uinput驱动来实现 linux系统用户空间模拟按键事件:

    这几篇真是太棒了!:

http://sipgreen.iteye.com/blog/1774676

    http://sipgreen.iteye.com/blog/1774676

    http://blog.sina.com.cn/s/blog_602f87700100llew.html

    https://www.cnblogs.com/myblesh/articles/2367648.html

    https://www.cnblogs.com/myblesh/articles/2367648.html

   https://www.kernel.org/doc/html/v4.12/input/uinput.html ----linux官网上关于uinput模块的介绍

  首先在内核中添加uinput模块(也可以将这个模块直接编译进内核里面),然后使用wriet系统函数向文件中写入键盘事件!

linux2.6.x内核提供了uinput驱动,它可以帮助用户将数据(包括用户输入的键盘或者鼠标或者触摸板数据)注入到Linux内核,这对于编写用户自定义的输入设备的应用程序是非常有用。

驱动程序使用/dev/uinput的设备,将数据发送到内核空间,内核将数据发送到X-Windows或者shell终端。此功能可用于所有涉及图形用户的输入。

uinput驱动在许多linux内核里均被配置为可加载的模块,你可以通过$ modprobe uinput 命令加载luinput驱动。

$ lsmod 命令列出linux系统已经加载的所有驱动。你应该可以看到“uinput”驱动也在这个列表中。但是如果你是在kernel里把uinput设置成编译进内核,而不是编译成模块的话,那么你通过lsmod是看不到uinput模块的。但你在/dev下会看到uinput的设备结点。后面你可以直接打开此结点来向uinput发送数据。

相关头文件:

#include <sys/types.h>  #include <sys/stat.h>  #include <fcntl.h>  #include <linux/input.h>  #include <linux/uinput.h>  #include <sys/time.h>  #include <unistd.h>  #include <errno.h> 

step1:打开uinput设备并设置设备参数:

uinp_fd = open(“/dev/uinput”,O_WRONLY|O_NDELAY);

If(uinp_fd < 0){

printf(“unable to open /dev/uinput\n”);//也有可能在/dev/input/uniput

Return -1;

}

成功打开/dev/uinput设备之后,需要通过驱动的ioctl函数(点击打开链接)来配置uinput设备的参数,包括鼠标参数、键盘参数等,即设置Input Device关心或者说会产生的消息:

ioctl(uinp_fd ,UI_SET_EVBIT,EV_KEY); //设置设备所支持的动作,#defineEV_KEY 0x01 // 按下键

ioctl(uinp_fd ,UI_SET_EVBIT,EV_REP); //设置设备所支持的动作,#defineEV_KEY 0x02 // 释放

   (//EV_KEY和EV_REP来告诉uinput驱动是包含键值的键盘事件。)

ioctl(uinp_fd , UI_SET_RELBIT, REL_X); //包含鼠标事件

ioctl(uinp_fd , UI_SET_RELBIT, REL_Y);

ioctl(uinp_fd , UI_SET_EVBIT, EV_ABS);

ioctl(uinp_fd , UI_SET_ABSBIT, ABS_X);

ioctl(uinp_fd , UI_SET_ABSBIT, ABS_Y);

ioctl(uinp_fd , UI_SET_ABSBIT, ABS_PRESSURE);

for(i = 0; i < 256; i++){//  ---------------------???????

ioctl(uinp_fd , UI_SET_KEYBIT, i);

}

setp2:创建设备并写入至input子系统

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( uinp_fd , &uinput, sizeof(uinput) );

ioctl(uinput_fd, UI_DEV_CREATE)

如果在代码中,上面的执行完成之后,马上执行下面的step3的话,会导致没有任何效果,我加掩饰100ms,好了!原因还未知!

step3: 自己构造input事件并写入

所有来自用户进程的事件都会通过结构体“struct input_event”(在/usr/include/linux/input.h中定义)传送给内核空间。

可以通过下面的代码产生键盘事件:

event.type = EV_KEY;

event.code = KEY_ENTER;

event.value = 1;//1表示按下,0表示抬起

gettimeofday(&event.time, NULL);

__u16 type; //类型,在下面有定义
__u16 code; //要模拟成什么按键

__s32 value;//是按下还是释放

write(uinp_fd, &event, sizeof(event));

event.type = EV_SYN;

event.code = SYN_REPORT;

event.value = 0;

gettimeofday(&event.time, NULL);

write(uinput_fd, &event, sizeof(event));//发送同步信号

上面的代码将要发送一个enter键给内核。该键值最终会通过内核发送给用户空间的应用程序。所有的按键定义在“/usr/include/linux/input.h”中;注意,当发送按键事件之后,要马上发送一个同步事件,否则内核不会马上处理你的按键事件!


my code as follows: 注意需要修改/dev/uinput文件的权限

  1. void testevent()
  2. {
  3. //int uinp_fd = open("/dev/uinput",O_WRONLY|O_NDELAY);O_RDWR
  4. int uinp_fd = open("/dev/uinput",O_RDWR);
  5. if (uinp_fd < 0){
  6. qDebug()<<"unable to open /dev/uinput";
  7. return;
  8. }
  9. if(ioctl(uinp_fd ,UI_SET_EVBIT,EV_KEY)<0) //设置设备所支持的动作,#defineEV_KEY 0x01 // 按下键
  10. {
  11. qDebug()<<"unable to set EV_KEY";
  12. return;
  13. }
  14. if(ioctl(uinp_fd ,UI_SET_EVBIT,EV_REP)<0) //设置设备所支持的动作,#defineEV_KEY 0x02 // 释放
  15. {
  16. qDebug()<<"unable to set EV_REP";
  17. return;
  18. }
  19. for(int i = 0; i < 256; i++){ //---------------------???????
  20. ioctl(uinp_fd , UI_SET_KEYBIT, i);
  21. }
  22. //创建设备并写入至input子系统
  23. struct uinput_user_dev uinput;
  24. memset(&uinput,0,sizeof(uinput));
  25. uinput.id.version = 4;
  26. uinput.id.bustype = BUS_USB;
  27. strncpy(uinput.name,"virtual device a",UINPUT_MAX_NAME_SIZE);
  28. int ret = write( uinp_fd , &uinput, sizeof(uinput) );
  29. if(ret<0)
  30. {
  31. qDebug()<<"unable to write(uinp_fd , &uinput, sizeof(uinput)";
  32. return;
  33. }
  34. int err = ioctl(uinp_fd, UI_DEV_CREATE);
  35. if(err < 0)
  36. {
  37. qDebug()<<"unable to creat device";
  38. return;
  39. }
  40. //construct input_event and send it
  41. struct input_event event;
  42. unsigned int key_code = KEY_TAB;
  43. usleep(100000);//important!!!!!!!!!!!!!!!!!!!!!!!!!! don't know why
  44. //unsigned int key_code = KEY_CAPSLOCK;
  45. event.type = EV_KEY;
  46. event.code = key_code;
  47. event.value = 1; //1 means pressed signal
  48. gettimeofday(&event.time, NULL);
  49. if (write(uinp_fd, &event, sizeof(event)) < 0) {
  50. qDebug()<<"unable to write key event";
  51. return;
  52. }
  53. gettimeofday(&event.time, NULL);
  54. event.value = 0;
  55. ////////////////send sync signal///////////////////////////////
  56. event.type = EV_SYN;
  57. event.code = SYN_REPORT;
  58. event.value = 0;
  59. gettimeofday(&event.time, NULL);
  60. if( write(uinp_fd, &event, sizeof(event))<0 )//发送同步信号
  61. {
  62. qDebug()<<"unable to write sync event";
  63. return;
  64. }
  65. close(uinp_fd);
  66. qDebug()<<"UmProg::testQevent() end:";
  67. return;
  68. }

linux udev学习:



linux系统下,在用户空间应用程序中模拟发送系统键盘事件的更多相关文章

  1. linux系统下的用户文件句柄数限制

    linux系统下的用户文件句柄数限制 文章来源:企鹅号 为什么要修改用户打开的文件数 系统默认单个进程可以打开1024个文件,对于一些应用如tomcat.oracle等,运行时经常open成千上万个文 ...

  2. 05 Linux系统下的用户以及用户权限管理(权限管理介绍、用户管理、常见命令介绍)

    这一节我们介绍Linux的用户以及权限管理的前半段,包括:1.权限管理介绍: 2.用户管理: 3.常见命令 权限管理介绍 权限管理: 为了访问计算机资源,我们需要对其进行授权才能访问,根据什么东西来进 ...

  3. (转)linux 系统下虚拟用户的作用

    原文:http://blog.csdn.net/luoshao20120430/article/details/16900653            http://blog.csdn.net/u01 ...

  4. 记录linux系统下所有用户的操作信息

    在日常运维中,我们需要清楚服务器上每个用户登录后都做了哪些操作,我们需要记录下每个用户的操作命令.下面的内容设置可以实现在Linux下所有用户,不管是远程还是本地登陆,在本机的所有操作都会记录下来,并 ...

  5. linux系统下root用户和普通用户的时区不一致

    1. 发现这个问题是在root下执行 date -R 和 普通用户下执行 date -R,发现时区不一致 2. 在一些linux机器下,发现是一致的 3. 什么原因呢?找了半天,最后发现 时区一致的机 ...

  6. Linux系统下C语言如何调用scalapack中的函数

    在并行计算中经常需要调用scalapck(并行化的lapack)函数库里面的函数进行编程,这里简单介绍在C语言如何调用scalapck中的矩阵向量乘的函数. 注意:scalapack中的函数是用for ...

  7. 在C#程序中模拟发送键盘按键消息

    using System.Runtime.InteropServices; 引入键盘事件函数 [DllImport("user32.dll")]public static exte ...

  8. linux系统下memcached启动正常但程序无法连接的问题解决

    在虚拟机linux安装好memcached之后,试着用java程序连接一下memcached的服务端,但却出现了以下错误 com.schooner.MemCached.SchoonerSockIOPo ...

  9. Linux系统下超级用户密码的修改

    1)重启系统:在虚拟机刚启动界面,不停地按上下键,停止系统的自动引导(界面底部有提示) 2) 按 e 进入编辑模式 3) 编辑内容如下:完成后按Ctrl+x    (具体编辑内容为下图:删除倒数第三行 ...

随机推荐

  1. GitHub中PR(Pull request)操作

    1. 贡献代码: 贡献代码,通俗的说,就是自己修改了代码,希望合并到别人的Repository(仓库)中.将自己的智慧贡献给开源社区.下面将详细讲解步骤 1.1 第一步:fork 在GitHub社区闲 ...

  2. NetworkX系列教程(10)-算法之一:最短路径问题

    小书匠Graph图论 重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定先把图 ...

  3. 数据结构实验之图论六:村村通公路【Prim算法】(SDUT 3362)

    题解:选点,选最小权的边,更新点权.可以手动自行找一遍怎么找到这个最小的生成树,随便选一个点放入我们选的集合中,然后看和这个点相连的点中,与那个点相连的那条边权值是最小的,选择之后,把相连的这个点一起 ...

  4. js 将网络图片格式转为base64 canvas 跨域

    function getBase64Image(img) { var canvas = document.createElement("canvas"); canvas.width ...

  5. Hadoop界的Hello World!

    Hadoop界的Hello World! 2019-05-20  19:50:09 应用平台:Eclipse+ubantu+hadoop包 注:例分析的形式给宝宝们解释一下,详细运行过程省略. 实例: ...

  6. IdentityServer4入门四:应用Implicit模式保护网站(上)

    我们先新增一个网站,名为“ClientMvc",也是asp.net core Web应用程序(模型视图控制器) 使用nuget安装以下引用 Microsoft.AspNetCore.Auth ...

  7. RESTful入门

    RESTful入门 1. REST简介 和RPC一样,都是目前比较主流的URL链接风格,也可以说是web服务的一种架构风格.REST全称Representational State Transfer, ...

  8. GCC与GDB使用

    GCC基本命令 gcc[选项][文件名] -E:仅执行编译预处理(.c->.i) -S:将c代码转换成汇编代码(.i->.s) -c:仅执行编译操作,不进行连接操作(.s->.o) ...

  9. node.js 简易聊天室

    效果图 首先开启server.js 打开服务器端,然后打开client.js,注册用户.打开一个注册一个用户,打开三个,注册三个用户. 接下来,小王发布一个广播消息,小李和小刘都收到了此消息. 接下来 ...

  10. python 将数据写入excel

    摘要链接: python第三方库——xlrd和xlwt操作Excel文件学习 :http://blog.csdn.net/wangkai_123456/article/details/50457284 ...