User avatar
Mikumiku747
Posts: 17
Joined: Fri Nov 01, 2013 10:54 am
Location: Sydney Australia

Simple C keyboard emulation

Sat Sep 27, 2014 3:25 am

Hello everyone,
I'd like to know if any library or set of libraries exists to emulate keyboard presses on the command line. I'd like to hook the GPIO pins up to buttons to play game with AdvanceMame, so I was going to write a C program to run in the background that takes inputs on the GPIO and corresponds them to keyboard presses. But the problem is, I can't find a simple way to emulate the keyboard.

I've tried using python and evdev, but I don't understand it that well, and it also tends to use too much CPU and not keep up. I had a look at uInput. but it was unclear how it worked to me, so if somebody could explain that, that would be helpful as well.

Just for extra info, I'm using the wiringPi library for IO and I also have one of those 2.8" TFT screens attatched to my pi, so the solution needs to not interfere with the i2C pins as well as pins 18 and 25. Just some limitations to keep in mind.

Hope to get some help soon. ;)
Thanks,
Mikumiku747 :)


Have a look at my portable pi:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=40&t=59903&p=447601#p447601

User avatar
PeterO
Posts: 6095
Joined: Sun Jul 22, 2012 4:14 pm

Re: Simple C keyboard emulation

Sat Sep 27, 2014 7:22 am

I've not got time now for a detailed reply, but I'm pretty sure you can write keyboard event structures into the files in /dev/input/by-id.

Structures and symbols are defined in /usr/include/linux/input.h

PeterO

PS: I'm not sure this classes as "simple" though :-)
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
Mikumiku747
Posts: 17
Joined: Fri Nov 01, 2013 10:54 am
Location: Sydney Australia

Re: Simple C keyboard emulation

Sat Sep 27, 2014 10:20 am

PeterO,

As you suspect, from my point of view, your answer wasn't very simple for me to understand. I think I get that /dev/input/event# devices are input devices and you're saying that I can use C to inject events into them. Beyond that, however, I have no idea what I'm doing :'(

I've really only got a hobbyist level understanding of Linux, and Although I'm new to C, I've messed around with arduino and java, so I think I've got a decent understanding of it. From what you say, I need to open the input device as a file and write a special event to it that I generate beforehand? Like you said, a more detailed answer would be nice.

However, thanks for pointing me in the right direction, this is a great start.
Thanks,
Mikumiku747 :)


Have a look at my portable pi:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=40&t=59903&p=447601#p447601

User avatar
mahjongg
Forum Moderator
Forum Moderator
Posts: 13973
Joined: Sun Mar 11, 2012 12:19 am
Location: South Holland, The Netherlands

Re: Simple C keyboard emulation

Sat Sep 27, 2014 11:37 am

moved to gaming, as it seems to belong there, as there are several threads there discussing this topic, and its not programming language dependent, but is a matter of stuffing keyboard events into the keyboard event queue.

User avatar
Mikumiku747
Posts: 17
Joined: Fri Nov 01, 2013 10:54 am
Location: Sydney Australia

Re: Simple C keyboard emulation

Sat Sep 27, 2014 11:58 am

mahjongg wrote:moved to gaming, as it seems to belong there, as there are several threads there discussing this topic, and its not programming language dependent, but is a matter of stuffing keyboard events into the keyboard event queue.
Thanks, I'll keep that in mind next time. :)
Thanks,
Mikumiku747 :)


Have a look at my portable pi:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=40&t=59903&p=447601#p447601

User avatar
PeterO
Posts: 6095
Joined: Sun Jul 22, 2012 4:14 pm

Re: Simple C keyboard emulation

Sun Sep 28, 2014 9:26 am

Running this code will put the string "ls\n" into the input buffer.
"ls\n" will then be in the input stream ready to be read by the shell when this code exits and will produce a directory list.

Code: Select all

/* Demo of how to emulate key presses 
(C) P.J.Onion 2014
No Warantee of any kind.  
Running this may cause the destruction
of the universe!  You have been warned !
*/



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


bool pressKeys( void )
{
    static int keyboardFd = -1;
    int rd,n;
    bool ret = false;

    DIR *dirp;
    struct dirent *dp;
    regex_t kbd;

    char fullPath[1024];
    static char *dirName = "/dev/input/by-id";
    
    int result;
    struct input_event forcedKey;


    // Send ls<ret>
    uint16_t keys[] = {KEY_L,KEY_S,KEY_ENTER,0}; 
    int index;

    /* Find the device with a name ending in "event-kbd" */

    if(regcomp(&kbd,"event-kbd",0)!=0)
    {
        printf("regcomp for kbd failed\n");
        return false;

    }
    if ((dirp = opendir(dirName)) == NULL) {
        perror("couldn't open '/dev/input/by-id'");
        return false;
    }


    do {
        errno = 0;
        if ((dp = readdir(dirp)) != NULL) 
        {
            printf("readdir (%s)\n",dp->d_name);
            if(regexec (&kbd, dp->d_name, 0, NULL, 0) == 0)
            {
                printf("match for the kbd = %s\n",dp->d_name);
                sprintf(fullPath,"%s/%s",dirName,dp->d_name);
                keyboardFd = open(fullPath,O_WRONLY | O_NONBLOCK);
                printf("%s Fd = %d\n",fullPath,keyboardFd);
                printf("Getting exclusive access: ");
                result = ioctl(keyboardFd, EVIOCGRAB, 1);
                printf("%s\n", (result == 0) ? "SUCCESS" : "FAILURE");

            }


        }
    } while (dp != NULL);

    closedir(dirp);


    regfree(&kbd);


    /* Now write some key press and key release events to the device */


    index = 0;
    while(keys[index] != 0)
    {
    
        forcedKey.type = EV_KEY;
        forcedKey.value = 1;    // Press
        forcedKey.code = keys[index];
        gettimeofday(&forcedKey.time,NULL);
            
        n = write(keyboardFd,&forcedKey,sizeof(struct input_event));
        printf("n=%d\n",n);

        forcedKey.type = EV_KEY;
        forcedKey.value = 0 ;   // Release
        forcedKey.code = keys[index];
        gettimeofday(&forcedKey.time,NULL);       
             
        n = write(keyboardFd,&forcedKey,sizeof(struct input_event));
        printf("n=%d\n",n);
    
        index += 1;
    }

    close(keyboardFd);

    return(true);

}




int main(int argc,char **argv)
{
    pressKeys();
    return(1);
}

Just compile with "gcc -o keyPress keyPress.c" and run with "./keyPress"

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

pocketvj
Posts: 3
Joined: Wed Mar 11, 2015 9:24 am

Re: Simple C keyboard emulation

Wed Mar 11, 2015 10:15 am

I tried your code. Thanks.

However, for an openframeworks application, for which I'm creating a remote app, I need to create a fake keyboard in

Code: Select all

/dev/input/by-path/
since the program is looking for a keyboard in this particular path.

I also tried to fake a keyboard with this solution: http://www.fsays.eu/Blogging/Blog/Details/23
but it puts an

Code: Select all

event0
into
/dev/input/
I found your code which nearly does what i need,
unluckily it does not work if no input device is connected to the pi,
can you help me on that?

Return to “Gaming”