Simulate keyboard typing programmatically in c

Asked

Viewed 984 times

3

The problem: I need my C program to write like a keyboard. When I open google, for example, and click on the search field I would like to keep showing several 'a'. As if the key was pressed on the keyboard.

Extra context: I’m making a bluetooth adapter for a super nintendo controller. I read the control commands with a microcontroller MSP430F5529 and send the result via bluetooth (HC-05) pro notebook. On the notebook, I have a C program that reads characters that arrive in the /dev/rfcomm0 file and printes them. I need this printf() to be recognized by Snes9x.

Code to illustrate:

I have followed that line, and failed

FILE * fp;
char input;

fp = fopen("/dev/rfcomm0", "rb");

while(1) {
  input = fgetc(fp);
  fputc(input, stdin);
  //printf("%c", input);
}
  • You can’t write on stdin yours, but if you have a pipe open and someone on the other side reading, just write on it

2 answers

3


Assuming your keyboard is on /dev/input/event3, follows a code capable of "simulating" the typing of the command ls -al followed by a enter:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <sys/time.h>
#include <stdint.h>

#define KEYBOARD_DEVICE_PATH  "/dev/input/event3"

int simularTecla( uint16_t tecla )
{
    int fd = -1;
    struct input_event k;

    /* Obtem um descritor para o dispositivo (teclado) */
    fd = open( KEYBOARD_DEVICE_PATH, O_WRONLY | O_NONBLOCK );

    if( fd < 0 )
        return -1;

    /* Toma controle exclusivo do teclado */
    if(ioctl( fd, EVIOCGRAB, 1 ))
        return -1;

    /* Pressionando Tecla */
    k.type = EV_KEY;
    k.value = 1;
    k.code = tecla;
    gettimeofday( &k.time, NULL );
    write( fd, &k, sizeof(struct input_event) );

    /* Soltando Tecla */
    k.type = EV_KEY;
    k.value = 0;
    k.code = tecla;
    gettimeofday( &k.time, NULL );
    write( fd, &k, sizeof(struct input_event) );

    /* Liberando controle do teclado */
    ioctl( fd, EVIOCGRAB, 0 );

    /* Fechando descritor para o dispositivo (teclado) */
    close(fd);

    /* Sucesso*/
    return 0;
}


int main( void )
{
    /* Sequencia de teclas */
    uint16_t teclas[] = { KEY_L, KEY_S, KEY_SPACE, KEY_MINUS, KEY_A, KEY_L, KEY_ENTER };
    unsigned int count =  sizeof(teclas) / sizeof(teclas[0]);
    unsigned int i = 0;

    /* Simula sequencia de teclas */
    for( i = 0; i < count; i++ )
        simularTecla( teclas[i] );

    return 0;
}

Compiling:

$ gcc kbdsim.c -o kbdsim

Testing (as root):

# ./kbdsim
ls -al
# ls -al
total 32
drwxr-xr-x   2 root root  4096 Oct 27 02:18 .
drwxrwxrwt. 30 root root 12288 Oct 27 02:18 ..
-rwxr-xr-x   1 root root  8760 Oct 27 02:18 kbdsim
-rw-r--r--   1 root root  1287 Oct 27 02:18 kbdsim.c

With a small modification in the main(), you can simulate activation of the key A once every second 100 times in a row:

int main( void )
{
    for( i = 0; i < 100; i++ )
    {
        simularTecla( KEY_A );
        sleep(1)
    }

    return 0;
}

The mapping with the code of each key can be found here.

  • The code is working. Put the keys only appear after I press them 4 times. Then 4 'a' or 4 'b' appear. I wanted to make it work key to key, but I don’t know how.

-1

FILE* controlador, snes;
char input;

controlador = fopen("/dev/rfcomm0", "rb");
snes = fopen("/dev/snes9x", "a");

while(controlador) {
     input = fgetc(controlador);
     if(snes)
         fputc(input, snes);

}
  • snes should not have been opened with w or a to allow writing?

  • very well observed

Browser other questions tagged

You are not signed in. Login or sign up in order to post.