1

I am using Ubuntu 14.04, and I am setting up a virtual keyboard in c, which requires uinput to work.

My program is supposed to send the key 'a' to terminal, as it would when I would press the 'a' key on the keyboard.

Here's my source code:

int main()
{
int uinp_fd;
int i;

/********** Open uinput file section. **********************/

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

if(uinp_fd < 0)
{

    printf("Unable to open /dev/uinput\n");
    return -1;
}

else printf("Can open /dev/uinput\n");

/********* Setup input device structure section: ***********/

memset(&uinp,0,sizeof(uinp));

snprintf(uinp.name, UINPUT_MAX_NAME_SIZE, "The C Keyboard");
uinp.id.bustype = BUS_USB;  
uinp.id.version = 1;
uinp.id.vendor = 0x1234;
uinp.id.product = 0xfedc;

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


/****** Setup the uinput keyboard device section: **********/

ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
ioctl(uinp_fd, UI_SET_EVBIT, EV_SYN);
ioctl(uinp_fd, UI_SET_EVBIT, EV_REP);

ioctl(uinp_fd, UI_SET_KEYBIT, KEY_A);

if (ioctl(uinp_fd, UI_DEV_CREATE, NULL) < 0)
{
    printf("Unable to create UINPUT device.\n");
    return -1;
}

/*********** Send keypress events to kernel: ***************/

memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);

event.type = EV_KEY;
event.code = KEY_A;
event.value = 1;
write(uinp_fd, &event, sizeof(event));



event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(uinp_fd, &event, sizeof(event));

/************** Release keypress event: *******************/

memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);

event.type = EV_KEY;
event.code = KEY_A;
event.value = 0;
write(uinp_fd, &event, sizeof(event));

event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(uinp_fd, &event, sizeof(event));

/*** Destroy keyboard device and close the Uinput device: **/

ioctl(uinp_fd, UI_DEV_DESTROY);
close(uinp_fd);

return 0;

}

My program however, doesn't do anything. It merely prints out:

Can open /dev/uinput

and thats it...

What am I doing wrong? Thank you for the help!

Jara
  • 23
  • 3
  • 1
    After open fails, your error message should contain the value of errno. That will give you some clue as to WHY the open failed. Additionally, this link (http://thiemonge.org/getting-started-with-uinput ) indicates your open() should use O_NONBLOCK not O_NDELAY. – TonyB Feb 27 '16 at 06:25
  • But my open doesn't fail. The program just doesn't do what it is meant to do. Why? – Jara Feb 27 '16 at 06:40
  • Sorry, I miss-read the message... but you should read the link provided above ... it does include some sample code too... – TonyB Feb 27 '16 at 06:43
  • That's where I got started with uinput actually! LOL! Thanks. But yea. Right now, I am kinda puzzled at this. The thing is. I have created a rule to allow access to uinput, but does that also mean that my program should somehow be executed with reference to it. I am at the moment just saving the program in home directory and executing it from there. Is this the cause? Or is it that keying in 'a' just doesn't do anything at kernel level; I would expect it to type out the letter 'a' at terminal. How can this be done? What am I doing wrong with the program really? – Jara Feb 27 '16 at 07:02
  • @TonyB and the sample program provided there also doesn't do anything when run! So why is that? – Jara Feb 27 '16 at 07:12
  • @Jara Did you succeed ? I write something similar. It's working on fedora 24 but not on ubuntu 16.04. – Erwan Douaille Jul 18 '16 at 14:38

1 Answers1

0

I've seen many answers like this: https://stackoverflow.com/a/40742162/6340338 saying that you should sleep(1) after executing ioctl(uinp_fd, UI_DEV_CREATE).