`
sipgreen
  • 浏览: 25291 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

linux在用户程序中如何向操作系统发送按键事件

 
阅读更多

 转自:http://blog.csdn.net/xiangpengmeng/article/details/6396589

 考虑到很多人也可能都需要这些类似的功能, 尤其是搞嵌入式的, 我解决这个问题的思路也是从android系统中借鉴的,这个功能需要首先在内核中添加uinput模块, 大家也可以将这个模块直接编译进内核里面, 编译内核大家都熟悉, 我就不在说了, 都是整天配置编译的人啊。。。

 

下面两个文件直接取自我们一个使用手机远程控制系统, 下面是代码, 代码中已经有了注释, 不在解释了, 希望以上代码会对你有所帮助。

/**
 * @file  The file is using for (>>> function<<<)
 * @author imxiangpeng
 * @time  
 *
 * Copyright (C) imxiangpeng@gmail.com, Inc. All Rights Reserved.
 * Written by imxiangpeng@gmail.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */
#ifndef RCBOARDMOUSE_H
#define RCBOARDMOUSE_H
#include <string.h>
#include <stdio.h>
#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>
static void kbdms_open_dev();
static int kbdms_init_dev(char *dev);
extern void kbdms_close_dev(void); /* you can call the function explicitly if you no need the function anymore*/
/* only the following functions which you can called, we initialise the device when you call the following function firstly */
/* key_code: referce to linux/input.h
   is_pressed_or_release: 1 if the key is pressed , 0 :release
   注意按键有按下,就必然会有释放,如果没有释放,再次调用按下函数是没有反映的
*/
extern void kbdms_send_button_event(unsigned short key_code, int is_pressed_or_release);
/* is_rel:1--relative move, else--absolutely
   if you want to send left or right mouse button , please call kbdms_send_button_event
*/
//extern void kbdms_send_mouse_move_events(unsigned short is_rel, unsigned short pos_x, unsigned short pos_y);
extern void kbdms_send_mouse_move_events(unsigned short is_rel, short pos_x, short pos_y);
extern void kbdms_send_wheel_events(short wheel_value);
#endif  /* RCBOARDMOUSE_H */

 

/**
 * @file  The file is using for (>>> function<<<)
 * @author imxiangpeng
 * @time  
 *
 * Copyright (C) imxiangpeng@gmail.com, Inc. All Rights Reserved.
 * Written by imxiangpeng@gmail.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */
 
#include "rcboardmouse.h"
static int uinput_fd = -1;
static struct uinput_user_dev uinput;
static struct input_event event;
static void kbdms_open_dev(){
  int ret = -1;
  ret = kbdms_init_dev("/dev/uinput");
  if(ret < 0){
    ret = kbdms_init_dev("/dev/input/uinput");
    if(ret < 0){
      printf("call kbdms_open_dev failure/n");
      return;
    }
  }
}
static int kbdms_init_dev(char *dev){
  int i = 0;
  if(dev == NULL){
    printf("The device is null/n");
    return -1;
  }
  uinput_fd = open(dev, O_WRONLY | O_NDELAY);
  if(uinput_fd < 0){
    perror("open uinput device failure:");
    return -1;
  }
  memset(&uinput, 0, sizeof(uinput));
  strncpy(uinput.name,"xiangpeng's virtual device",UINPUT_MAX_NAME_SIZE);
  uinput.id.version = 4;
  uinput.id.bustype = BUS_USB;
  ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY);
  ioctl(uinput_fd, UI_SET_EVBIT, EV_REL);
  ioctl(uinput_fd, UI_SET_RELBIT, REL_X);
  ioctl(uinput_fd, UI_SET_RELBIT, REL_Y);
  ioctl(uinput_fd, UI_SET_RELBIT, REL_WHEEL);
  
  for(i = 0; i < 256; i++){
    ioctl(uinput_fd, UI_SET_KEYBIT, i);
  } /* end for */
  ioctl(uinput_fd, UI_SET_KEYBIT, BTN_MOUSE);
  ioctl(uinput_fd, UI_SET_KEYBIT, BTN_TOUCH);
  ioctl(uinput_fd, UI_SET_KEYBIT, BTN_LEFT);
  ioctl(uinput_fd, UI_SET_KEYBIT, BTN_MIDDLE);
  ioctl(uinput_fd, UI_SET_KEYBIT, BTN_RIGHT);
  ioctl(uinput_fd, UI_SET_KEYBIT, BTN_FORWARD);
  ioctl(uinput_fd, UI_SET_KEYBIT, BTN_BACK);
  /* Create input device into input sub-system */
  write(uinput_fd, &uinput, sizeof(uinput));
  if(ioctl(uinput_fd, UI_DEV_CREATE)){
    perror("create uinput device");
    return -1;
  }
  return 0;                     /* success */
  
} /* end init_uinput_dev function */
/* is_rel:1--relative move, else--absolutely
   which_button_pressed: 0--no button press, 1--left button press, 2--right button press 3--middle button press
   
 */
void kbdms_send_mouse_move_events(unsigned short is_rel, short pos_x, short pos_y){
  if(uinput_fd <= 0){
    
    printf("RC : %s please call dbdms_init_dev first/n",__FUNCTION__);
    kbdms_open_dev();
    if(uinput_fd <= 0)
      return;
  }
  /* Move pointer to (0,0) location */
  memset(&event, 0, sizeof(event));
  gettimeofday(&event.time, NULL);
  event.type = (is_rel == 1)?EV_REL:EV_ABS;
  event.code = (is_rel == 1)?REL_X:ABS_X;
  event.value = pos_x;
  write(uinput_fd, &event, sizeof(event));  
  event.type = EV_SYN;
  event.code = SYN_REPORT;
  event.value = 0;
  write(uinput_fd, &event, sizeof(event));
  memset(&event, 0, sizeof(event));
  gettimeofday(&event.time, NULL);
  event.type = (is_rel == 1)?EV_REL:EV_ABS;
  event.code = (is_rel == 1)?REL_Y:ABS_Y;
  event.value = pos_y;
  write(uinput_fd, &event, sizeof(event));
  /* 鼠标点击事件我们也通过 kbdms_send_button_event 来发送*/
  
} /* end send_click_events function */
/* key_code: referce to linux/input.h
   is_pressed_or_release: 1 if the key is pressed , 0 :release
 */
void kbdms_send_button_event(unsigned short key_code, int is_pressed_or_release){
  
  if(uinput_fd <= 0){
    printf("RC : %s please call dbdms_init_dev first/n",__FUNCTION__);
    kbdms_open_dev();
    if(uinput_fd <= 0)
      return;
  }
  /* report button click --press event */
  
  memset(&event, 0, sizeof(event));
  gettimeofday(&event.time, NULL);
  event.type = EV_KEY;
  event.code = key_code;
  event.value = is_pressed_or_release;
  write(uinput_fd, &event, sizeof(event));
  event.type = EV_SYN;
  event.code = SYN_REPORT;
  event.value = 0;
  write(uinput_fd, &event, sizeof(event));
  
}
void kbdms_send_wheel_events(short wheel_value){
  if(uinput_fd <= 0){
    printf("RC : %s please call dbdms_init_dev first/n",__FUNCTION__);
    kbdms_open_dev();    
    if(uinput_fd <= 0)
      return;
   
  }
  /* Move pointer to (0,0) location */
  memset(&event, 0, sizeof(event));
  gettimeofday(&event.time, NULL);
  event.type = EV_REL;
  event.code = REL_WHEEL;
  event.value = wheel_value;
  write(uinput_fd, &event, sizeof(event));  
  event.type = EV_SYN;
  event.code = SYN_REPORT;
  event.value = 0;
  write(uinput_fd, &event, sizeof(event));
  
} /* end send_click_events function */
void kbdms_close_dev(void){
  if(uinput_fd > 0){
    ioctl(uinput_fd, UI_DEV_DESTROY);
    close(uinput_fd);
  }
}
#if 0                           /* using for test all the functions */
int main(int argc, char **argv){
  if(argc <2){
    printf("Please specified the uinput device path/n");
    return -1;
  }
  printf("The device is :%s/n",argv[1]);
  if(kbdms_init_dev(argv[1]) < 0){
    printf("Call init_uinput_dev failure/n");
    return -1;
  }
  
  while(1){
    printf("we will send a click and a button event/n");
    //send_click_events();
    kbdms_send_button_event(KEY_LEFT, 1);
    kbdms_send_button_event(KEY_LEFT, 0);
    sleep(3);
    kbdms_send_button_event(KEY_DOWN,1);
    kbdms_send_button_event(KEY_DOWN,0);
    sleep(2);
    kbdms_send_button_event(KEY_DOWN,1);
    kbdms_send_button_event(KEY_DOWN,0);
    sleep(2);
    printf("we will call kbdms_send_wheel_events/n");
    kbdms_send_wheel_events(10);
    printf("We will wheel back up/n");
    sleep(2);
    
    kbdms_send_wheel_events(-10);
  }
  kbdms_close_dev();
  return 0;
}
#endif

 希望以上代码会对你有所帮助, 如果有什么疑问也可以给我发邮件, 邮件地址在每个文件的头部

当然, 本人计算机都是自学的, 如果各位看着在编程风格和代码书写上如果有什么不足, 希望大家可以提出来

 

 

分享到:
评论

相关推荐

    嵌入式Linux应用程序开发标准教程(第2版全)

    1.1.2 Linux作为嵌入式操作系统的优势 1.1.3 Linux发行版本 1.1.4 如何学习Linux 1.2 Linux安装 1.2.1 基础概念 1.2.2 硬件需求 1.2.3 安装准备 1.3 Linux文件及文件系统 1.3.1 文件类型及文件属性 1.3.2 文件系统...

    《计算机操作系统》期末复习指导

    对考试很有帮助的.......... ...UNIX或Linux操作系统中文件系统的主要特点 (1)操作系统文件的目录组织是一个树形结构,从根结点到叶子称为文件的全路径名,文件可以由其全路径名唯一确定...

    Linux指令一周通 (技术图书大系).azw3

    3.22 mcd指令:在MS-DOS文件系统中切换工作目录 3.23 mdeltree指令:删除MS-DOS 目录/文件 3.24 mdu指令:显示MS-DOS目录所占用的磁盘空间 3.25 mformat指令:对MS-DOS文件系统的磁盘进行格式化 3.26 mkbootdisk指令...

    嵌入式系统/ARM技术中的I2C总线在Linux系统中的驱动设计

    针对S3C2410微处理器和键盘扫描管理器件,深入讨论如何在嵌入式操作系统ARM Linux中实现ZLG7290的驱动。  2 I2C总线  I2C总线是器件间串行传输总线,以其规范和带I2C接口的外围器件获得广泛应用。S3C2410处理器...

    Windows和Linux上的钩子和模拟键盘事件-python

    在单独的线程中自动捕获事件,不会阻塞主程序。 经过测试和记录。 不会破坏重音死键(我在看着你,pyHook)。 可通过项目鼠标(pip install mouse)获得鼠标支持。 用法 安装 PyPI 包: pip install keyboard ...

    仿红帽子操作系统Shell

    一款模仿Linux操作系统红帽子(RedHat)的shell编程示例,基本的桌面菜单,开始菜单,任务栏菜单,托盘菜单,右键弹出菜单都做的栩栩如生,是一个完整漂亮的外壳程序。对于一些商用软件完全可以修改后套用形成一个漂亮...

    易语言程序免安装版下载

    操作系统界面功能支持库(shell.fne)中的“执行()”命令增加一个参数“窗口显示方式”,作用与核心库“运行()”命令的同名参数一致。 6. 数据库操作支持库增加读写长整数字段的功能,但受限于系统接口暂不能读写...

    安卓课程设计-手机通讯录系统全解.doc

    它包括 操作系统、用户界面和应用程序 ——移动电话工作所需的全部软件,而且不存在任何以往阻碍移动产业创新的专有权障碍 。谷歌与开放手机联盟合作开发了 Android,这个联盟由包括中国移动、摩托罗拉、高通、宏达...

    vc++ 应用源码包_1

    内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...

    新版Android开发教程.rar

    � Android 更像一款桌面环境为 Java 的 Linux 操作系统。有助于 Google 实现其 " 随时随地为每个人提供信 息 " 的企业战略。 HTC HTC HTC HTC Dream/G1 Dream/G1 Dream/G1 Dream/G1 具体配置 硬件 3.17 英寸 HVGA ...

    vc++ 应用源码包_2

    内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...

    vc++ 应用源码包_6

    内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...

    Linux高级bash编程

    文件信息:对包含在变量中的文件列表进行操作 10-4. 在for循环中操作文件 10-5. 在for循环中省略[list] 10-6. 使用命令替换来产生for循环的[list] 10-7. 对于二进制文件的一个grep替换 10-8. 列出系统上的所有用户 ...

    vc++ 应用源码包_3

    内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...

    vc++ 应用源码包_5

    内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...

    vc++ 开发实例源码包

    内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...

    VICREO-Listener

    安装下载适合您的操作系统的软件包,然后在要控制的计算机(主机)上启动该程序。 在客户端计算机(您要从其发送命令的客户端计算机)上,将TCP字符串从主机发送到正确的IP地址,并发送到端口10001(或将端口更改为...

    c语言编写单片机技巧

    C语言是一种结构化程序设计语言,它支持当前程序设计中广泛采用的由顶向下结构化程序设计技术。此外,C语言程序具有完善的模块程序结构,从而为软件开发中采用模块化程序设计方法提供了有力的保障。因此,使用C语言...

    Magic ARM 2410

    4.3.4 启动Linux 操作系统...................170 4.4 Linux 启动参数的设定方法 ................171 4.4.1 ZLG/BOOT 的运行过程..............171 4.4.2 Linux 启动参数的含义 ................172 4.4.3 ...

    adb1.0.26包含fastboot.exe

    注意这个状态并不能标识 Android 系统已经完全启动和可操作,在设备启动过程中设备实例就可连接到 adb,但启动完毕后系统才处于可操作状态。 no device —— 没有设备/模拟器连接。 以上输出显示当前已经连接了...

Global site tag (gtag.js) - Google Analytics