Reputation: 111
Example code:
#include <stdio.h>
#include <stdlib.h>
#include <linux/keyboard.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
int
main(int argc, char **argv) {
struct kbentry ke;
ke.kb_table = (unsigned char)atoi(argv[1]);
ke.kb_index = (unsigned char)atoi(argv[2]);
ioclt(0, KDGKBENT, &ke);
printf("keycode %u = %04x\n", ke.kb_index, ke.kb_value);
return 0;
}
When I try to get the value of a keycode using e.g. the code above, KDGKBENT returns strange values. It adds a '0B' to ASCII characters: 0x0B61 for 'a' instead of 0x0061, 0x0B41 for 'A' instead of 0x0041.
I cannot find any answer regarding to what this happens on the internet.
I only found the same question, without any answer there: https://www.unix.com/unix-for-advanced-and-expert-users/178627-questions-about-linux-console-keyboard-driver-translation-tables.html
Those values in 0x0Bxx do not appear when running dumpkeys -l (alphabet has normal ASCII values), nor in this list: https://wiki.linuxquestions.org/wiki/List_of_keysyms
Why does this happen? And how am I supposed to get a proper conversion?
Actually, looking carefully at dumpkeys tables, the alphabet keys symbols are '+a', '+A' etc. i.e. they are Caps Lock conditioned to change their case. Could be the explanation behind '0x0B' but I need to find a confirmation about this theory.
Upvotes: 1
Views: 104
Reputation: 748
I also had this problem, so I decided to check why dumpkeys work but my code doesn't and while looking through the source code I found this fragment of code (src/libkeymap/keysyms.c:195):
if (KTYP(code) == KT_LETTER)
code = K(KT_LATIN, KVAL(code));
where code is the ke.kb_value
from
struct kbentry ke;
ke.kb_table = 0; // no modifiers
ke.kb_index = 16; // q in en-us layout
ke.kb_value = 0;
ioctl(fd, KDGKBENT, (unsigned long)&ke);
It checks for letter keys and converts them to their latin version (by changing the KTYP
from KT_LETTER
to KT_LATIN
).
It solved the issue for me
Upvotes: 0