I'm trying to do a virtual keyboard with uinput on Debian Stretch, that i could feed with strings, like "Toto !", and the keyboard would write this string. However, I'm stuck with the conversion from C char to keycodes handled by the keyboard. I'm not using the Macros defined in event-codes.h because I want my solution to work on the locale of the computer, and the macros are defined around an US Keyboard.
Here's the device created using uinput :
int setup_uinput_device(){
/* Temporary variable */
int i=0;
/* Open the input device */
uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
if (fcntl(uinp_fd, F_GETFD) == -1)
{
printf("Unable to open /dev/uinput\n");
return -1;
}
memset(&uinp,0,sizeof(uinp)); /* Intialize the uInput device to NULL */
strncpy(uinp.name, "Custom Keyboard", UINPUT_MAX_NAME_SIZE);
uinp.id.bustype = BUS_USB;
// Setup the uinput device
ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
ioctl(uinp_fd, UI_SET_EVBIT, EV_REL);
ioctl(uinp_fd, UI_SET_EVBIT, EV_REP);
for (i=0; i < 256; i++) {
ioctl(uinp_fd, UI_SET_KEYBIT, i);
}
/* Create input device into input sub-system */
write(uinp_fd, &uinp, sizeof(uinp));
if (ioctl(uinp_fd, UI_DEV_CREATE))
{
printf("Unable to create UINPUT device.\n");
return -1;
}
return 0;
}
I've already tried solutions using the X11 library, as depicted in this link : Convert ASCII character to x11 keycode Unfortunately, the keyboard i've managed to create using uinput takes differents keycodes than the ones X11 uses. (I think my keyboard takes the same keycodes that I can get with using the dumpkeys command). It's surely possible to convert X11 keycodes into (kernel ?) keycodes that my keyboard correctly inteprets, but I'd like to keep the numbers of dependencies low.
I'm now trying to use EVIOCGKEYCODE as depicted in linux.h, but I have difficulties to understand how it works, and I think it does the inverse of what I really want.
Here's an example :
int main(int argc, char *argv[]) {
setup_uinput_device();
struct input_keymap_entry mapping;
int i =0;
/* Set the max value at 130 just for the purpose of testing */
for (i=0; i<130; i++) {
mapping.scancode[0] = i;
if(ioctl(fd, EVIOCGKEYCODE_V2, mapping)) {
perror("evdev ioctl");
}
printf("Scancode= %d, Keycode = %d\n",
mapping.scancode[0], mapping.keycode);
}
/* Simple function to destroy the device */
destroy_uinput_device();
return 0;
}
I get the following error : "evdev ioctl: Invalid argument". I've read somewhere that it's an old method used with PS2 keyboard, so it's probably one of the many reasons it's not working.
The last solution I consider is to parse the result of dumpkeys in a table or a map that I could use later, but I think I will get performance issues, and I don't want to recreate something that perhaps already exists.
Any Idea ?