使用 ARMv8 程序集和 Uinput 模拟击键

Posted

技术标签:

【中文标题】使用 ARMv8 程序集和 Uinput 模拟击键【英文标题】:Emulating a keystroke using ARMv8 assembly and Uinput 【发布时间】:2018-07-22 08:42:20 【问题描述】:

2018 年 7 月 23 日更新:

我有 uinput 的 C 代码实现如下:

#include <linux/uinput.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h> 
#include <string.h>
void emit(int fd, int type, int code, int val)

   struct input_event ie;

   ie.type = type;
   ie.code = code;
   ie.value = val;
   /* timestamp values below are ignored */
   ie.time.tv_sec = 0;
   ie.time.tv_usec = 0;

   write(fd, &ie, sizeof(ie));


int main(void)

   struct uinput_setup usetup;

   int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);


   /*
    * The ioctls below will enable the device that is about to be
    * created, to pass key events, in this case the space key.
    */
   ioctl(fd, UI_SET_EVBIT, EV_KEY);
   ioctl(fd, UI_SET_KEYBIT, KEY_W);

   memset(&usetup, 0, sizeof(usetup));
   usetup.id.bustype = BUS_USB;
   usetup.id.vendor = 0x1234; /* sample vendor */
   usetup.id.product = 0x5678; /* sample product */
   strcpy(usetup.name, "Example device");

   ioctl(fd, UI_DEV_SETUP, &usetup);
   ioctl(fd, UI_DEV_CREATE);

   /*
    * On UI_DEV_CREATE the kernel will create the device node for this
    * device. We are inserting a pause here so that userspace has time
    * to detect, initialize the new device, and can start listening to
    * the event, otherwise it will not notice the event we are about
    * to send. This pause is only needed in our example code!
    */
   sleep(1);
   while(1)
   /* Key press, report the event, send key release, and report again */
   emit(fd, EV_KEY, KEY_W, 1);

    
   /*
    * Give userspace some time to read the events before we destroy the
    * device with UI_DEV_DESTOY.
    */
   sleep(1);

   ioctl(fd, UI_DEV_DESTROY);
   close(fd);

   return 0;

但是好像没有输出


旧帖 07/22/2018 我已经在这个项目上工作了一段时间,并在这里找到了解决我的一些错误的帮助。

我有工作 ARM 汇编代码,它从我的树莓派 3 的 GPIO 中获取按钮输入,我需要最后一件事来最终让它一劳永逸。

我需要找到某种方法让系统认为按钮按下了某个键,这样游戏就可以将输入解释为游戏代码中的击键。或者更好的是只有一个简单的屏幕,我可以在屏幕上移动一个像素。我发现很难找到 ARM 语言的帮助。

我的代码如下:

//data Section

         .data
         .align    4
Intro:   .asciz    "Raspberry Pi - Blinking led test inassembly\n"
ErrMsg:  .asciz    "Setup didn't work... Aborting...\n"
TestMsg: .asciz    "Test stuff\n"
Up:      .asciz    "Up pressed"
Left:    .asciz    "Left Pressed"
Down:    .asciz    "Down Pressed"
Right:   .asciz    "Right pressed"
Pause:   .asciz    "Pause pressed"
Quit:    .asciz    "Quit pressed"
Pressed: .asciz    "button pressed"

// WiringPi pin values
pinUp:   .int      15
pinLeft: .int    3
pinDown: .int    0
pinRight:.int    7
pinPau:  .int    16
pinQu:   .int    2
i:       .int    10
Compr:   .int    1
INPUT    =       0

//Code section

    .text
    .global main
    .extern printf
    .extern scanf
    .extern wiringPiSetup
    .extern delay
    .extern digitalRead
    .extern pinMode

main:   push    ip, lr
// printf message
    ldr r0, =Intro
    bl  printf

//Check for setup error
    bl  wiringPiSetup
    mov r1,#-1
    cmp r0, r1
    bne init
    ldr r0, =ErrMsg
    bl  printf
    b   done
init:
    //Set all pins to input
    ldr r0, =pinUp
    ldr r0, [r0]
    mov r1, #INPUT
    bl  pinMode

    ldr r0, =pinLeft
    ldr r0, [r0]
    mov r1, #INPUT
    bl  pinMode

    ldr r0, =pinDown
    ldr r0, [r0]
    mov r1, #INPUT
    bl  pinMode

    ldr r0, =pinRight
    ldr r0, [r0]
    mov r1, #INPUT
    bl  pinMode

    ldr r0, =pinPau
    ldr r0, [r0]
    mov r1, #INPUT
    bl  pinMode

    ldr r0, =pinQu
    ldr r0, [r0]
    mov r1, #INPUT
    bl  pinMode

    b while 
while:

    //Digital Read
    ldr r0, =pinUp
    ldr r0, [r0]
    bl digitalRead
    cmp r0, #1
    beq msg


    ldr r0, =pinLeft
    ldr r0, [r0]
    bl digitalRead
    cmp r0, #1
    beq msgleft


    ldr r0, =pinDown
    ldr r0, [r0]
    bl digitalRead
    cmp r0, #1
    beq msgdown

    ldr r0, =pinRight
    ldr r0, [r0]
    bl digitalRead
    cmp r0, #1
    beq msgRight

    ldr r0, =pinPau
    ldr r0, [r0]
    bl digitalRead
    cmp r0, #1
    beq msgpause

    ldr r0, =pinQu
    ldr r0, [r0]
    bl digitalRead
    cmp r0, #1
    beq msgquit

    b while         // Loop back

// Messages for input
msg:
    ldr r0, =Up
    bl printf
    b  while

msgleft:
    ldr r0, =Left
    bl printf
    b  while

msgRight:
    ldr r0, =Right
    bl printf
    b while
msgdown:
    ldr r0, =Down
    bl printf
    b while
msgpause:
    ldr r0, =Pause
    bl printf
    b while
msgquit:
    ldr r0, =Quit
    bl printf
    b while

done:   

    pop ip,pc

任何帮助将不胜感激

【问题讨论】:

【参考方案1】:

要为所有 Linux 程序注入按键,您需要使用 uinput interface。

打开/dev/input/uinput/dev/uinput,使用ioctl 调用对其进行配置,然后编写输入事件结构。

【讨论】:

@ Timothy Baldwin 我对此完全陌生,所以我不知道要更改什么或 ioctl 调用做什么。我知道这是输入输出控制,但其他方面我什么都没有。 您是否点击了我提供给文档的链接?你有什么不明白的? 好的,我对你所说的有了更好的理解。我查看了链接,现在正在尝试实现它。我认为我拥有的代码应该连续按“w”,但它似乎不起作用。我正在运行一个游戏来测试输入。我会用新的 C 代码更新问题

以上是关于使用 ARMv8 程序集和 Uinput 模拟击键的主要内容,如果未能解决你的问题,请参考以下文章

在 macOS Sierra 中使用 Quartz 事件模拟击键

从 Winforms 应用程序发送全局击键/伪造全局热键

如何使用 C# 模拟 CTRL+V 击键(粘贴)

使用 C# 模拟键盘

如何修复“忽略的击键”

VB通过user32模拟击键