legionus / kbd

Mirror of https://git.kernel.org/pub/scm/linux/kernel/git/legion/kbd.git
https://kbd-project.org
Other
84 stars 41 forks source link

function `codetoksym` not working for letters #71

Closed pmkap closed 2 years ago

pmkap commented 2 years ago

https://github.com/legionus/kbd/blob/master/src/libkeymap/ksyms.c#L196:

if (KTYP(code) == KT_LETTER)               // This is 11
    code = K(KT_LATIN, KVAL(code));     // (0<<8) | KVAL(code) = KVAL(code)

if (KTYP(code) > KT_LATIN)                    // Now KTYP(KVAL(code)) is 0 for all letters and get_sym is never called
    return get_sym(ctx, KTYP(code), KVAL(code));

Is changing the value of code intenional?

legionus commented 2 years ago

This change was a very long time ago (2009)[1]. As far as I remember these changes are based on debian changes[2]. So in answer to your question, I would say yes.

[1] https://github.com/legionus/kbd/commit/8fbabd72bedcfe40f947a3f2ffda8ce5d833da95 [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=251550#192

pmkap commented 2 years ago

Thank you for your answer. I made a minimal example for what is not working for me.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <keymap.h>

int main() {
    struct lk_ctx *ctx = lk_init();
    if (!ctx) {
        exit(EXIT_FAILURE);
    }

    int fd = open("/dev/tty0" , O_RDONLY);
    lk_kernel_keymap(ctx, fd);

    for (int i = 1; i <= 25; i++) {
        int code = lk_get_key(ctx, 0, i);
        const char *ksym = lk_code_to_ksym(ctx, code);
        printf("%d %s\n", i, ksym);
    }
}

Prints (null) instead of letters:

1 Escape
2 one
3 two
4 three
5 four
6 five
7 six
8 seven
9 eight
10 nine
11 zero
12 minus
13 equal
14 Delete
15 Tab
16 (null)
17 (null)
18 (null)
19 (null)
20 (null)
21 (null)
22 (null)
23 (null)
24 (null)
25 (null)
legionus commented 2 years ago

Ah! Now I understand why you asked this question. The lk_code_to_ksym returns NULL if no ksym is found for this code. This is done because post-processing often differs. Here is an example of such usage:

https://github.com/legionus/kbd/blob/9e085eda2f018298fea75cb6b7a45ba7aaef1b76/src/libkeymap/dump.c#L283-L305

I won't argue if you say it's not intuitive. I will also not argue if you say that you need a function in the API that would give a pointer to a string always if there was no error.

pmkap commented 2 years ago

So q, Q, w, W etc. are not ksyms?

legionus commented 2 years ago

@pmkap The kernel knows nothing about ksyms. А ksym is an abstraction used by kbd. А ksym is the text representation of code like a cent, caron, etc. The q does not require a special representation.

I suspect you were expecting the string "q" as the result of lk_code_to_ksym. Right ?

pmkap commented 2 years ago

@legionus Yes that's what I expected. The way I understood it so far is that the kernel only knows about the events defined here: https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h , and kdb decides what to do with these events according to a keymap.

legionus commented 2 years ago

@pmkap kernel keymaps work in the different way than xkb. All work happens inside the kernel and kbd cannot affect it in any way. loadkeys loads a 256x256 table into the kernel, by which the kernel determines which character should be output to the terminal for keycode. Once the table is loaded, kbd does not take part in processing keycodes or input events.

pmkap commented 2 years ago

Ah I understand a lot better now. Thank you for your help and explanations.

I hope it is ok if I ask one last question: When getting the first (resp. second) column of the 256x256 matrix, why do the codes for a-zA-Z not correspond to ASCII values like the others but range from 2881 to 2938.

When using dumpkeys -l to 'get all available actions' like stated in keymaps(5), the codes for a-zA-z do match with ascii values.

legionus commented 2 years ago

Ah I understand a lot better now. Thank you for your help and explanations. I hope it is ok if I ask one last question:

Absolutely ok. I'm glad to answer your questions.

When getting the first (resp. second) column of the 256x256 matrix, why do the codes for a-zA-Z not correspond to ASCII values like the others but range from 2881 to 2938.

@pmkap Can you give me an example of who you do that?

When using dumpkeys -l to 'get all available actions' like stated in keymaps(5), the codes for a-zA-z do match with ascii values.

pmkap commented 2 years ago

@legionus of course:

#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <keymap.h>

int main() {
    struct lk_ctx *ctx = lk_init();
    if (!ctx) {
        exit(EXIT_FAILURE);
    }

    int fd = open("/dev/tty0" , O_RDONLY);
    lk_kernel_keymap(ctx, fd);

    // 41 entries of the first column (plain)
    for (int i = 1; i <= 41; i++) {
        int code = lk_get_key(ctx, 0, i);
        const char *ksym = lk_code_to_ksym(ctx, code);
        printf("event: %d, code: %d, ksym: %s\n", i, code, ksym);
    }
}

output:

event: 1, code: 27, ksym: Escape
event: 2, code: 49, ksym: one
event: 3, code: 50, ksym: two
event: 4, code: 51, ksym: three
event: 5, code: 52, ksym: four
event: 6, code: 53, ksym: five
event: 7, code: 54, ksym: six
event: 8, code: 55, ksym: seven
event: 9, code: 56, ksym: eight
event: 10, code: 57, ksym: nine
event: 11, code: 48, ksym: zero
event: 12, code: 45, ksym: minus
event: 13, code: 61, ksym: equal
event: 14, code: 127, ksym: Delete
event: 15, code: 9, ksym: Tab
event: 16, code: 2929, ksym: (null)
event: 17, code: 2935, ksym: (null)
event: 18, code: 2917, ksym: (null)
event: 19, code: 2930, ksym: (null)
event: 20, code: 2932, ksym: (null)
event: 21, code: 2937, ksym: (null)
event: 22, code: 2933, ksym: (null)
event: 23, code: 2921, ksym: (null)
event: 24, code: 2927, ksym: (null)
event: 25, code: 2928, ksym: (null)
event: 26, code: 91, ksym: bracketleft
event: 27, code: 93, ksym: bracketright
event: 28, code: 513, ksym: Return
event: 29, code: 1794, ksym: Control
event: 30, code: 2913, ksym: (null)
event: 31, code: 2931, ksym: (null)
event: 32, code: 2916, ksym: (null)
event: 33, code: 2918, ksym: (null)
event: 34, code: 2919, ksym: (null)
event: 35, code: 2920, ksym: (null)
event: 36, code: 2922, ksym: (null)
event: 37, code: 2923, ksym: (null)
event: 38, code: 2924, ksym: (null)
event: 39, code: 59, ksym: semicolon
event: 40, code: 39, ksym: apostrophe
event: 41, code: 96, ksym: grave

Looking at the output, codes correspond to ASCII values except letters are ~2900.

legionus commented 2 years ago

I hope it is ok if I ask one last question: When getting the first (resp. second) column of the 256x256 matrix, why do the codes for a-zA-Z not correspond to ASCII values like the others but range from 2881 to 2938.

When using dumpkeys -l to 'get all available actions' like stated in keymaps(5), the codes for a-zA-z do match with ascii values.

If I understand the question correctly, then the codes that are stored in the table in the kernel are "encoded". You may have already seen this code:

https://github.com/legionus/kbd/blob/9e085eda2f018298fea75cb6b7a45ba7aaef1b76/src/libkeymap/ksyms.c#L380-L424

I hope that I have answered your question.

pmkap commented 2 years ago

Yes, everything is clear now. Thanks for your help. I close this now.