Доступ к ключам с устройства ввода Linux

Что я пытаюсь сделать

Итак, я пытался получить доступ к вводу с клавиатуры в Linux. В частности, мне нужно иметь доступ к нажатию клавиш-модификаторовбез другие клавиши нажаты. Кроме того, я хочу быть в состоянии сделать этобез система X работает.

Итак, вкратце, мои требования таковы:

Работает на LinuxНе нужен X11Может получить модификатор нажатием клавишибез любые другие нажимаемые клавишиЭто включает в себя следующие ключи:сдвигконтрольAltВсе, что мне нужно, это простой0 = not pressed, 1 = currently pressed сообщить мне, удерживается ли клавиша при проверке клавиатурыНастройка моего компьютера

Моя обычная машина с Linux находится на грузовике в направлении моей новой квартиры; Итак, у меня есть только Macbook Air для работы прямо сейчас. Поэтому я запускаю Linux на виртуальной машине, чтобы проверить это.

Виртуальная машина в VirtualBox

ОС: Linux Mint 16Окружение рабочего стола: XFCE

Все ниже было сделано в этой среде. Я пробовал и с запущенным X, и с одним из других ttys.

Мои мысли

Я изменю это, если кто-то сможет исправить меня.

Я много читал, чтобы понять, что библиотеки более высокого уровня не предоставляют такую функциональность. Клавиши-модификаторы используются с другими клавишами для предоставления альтернативного кода клавиши. Получить доступ к самим ключам-модификаторам через библиотеку высокого уровня в Linux не так просто. Или, скорее, я не нашел высокоуровневого API для этого в Linux.

я думалlibtermkey было бы ответом, но он, кажется, не поддерживает клавишу-модификатор Shift лучше, чем обычное получение нажатия клавиши. Я также не уверен, работает ли он без X.

Работая с libtermkey (до того, как я понял, что в таких случаях, как Shift-Return, сдвиг не происходит), я планировал написать демон, который будет запускаться для сбора событий клавиатуры. Запуск копий программы-демона будет просто передавать запросы на данные клавиатуры и получать данные клавиатуры в ответ. Я мог бы использовать эту настройку, чтобы что-то всегда работало в фоновом режиме, в случае, если я не могу проверить статусы кода ключа в определенное время (должен быть получен код ключа в том виде, как он происходит).

Ниже приведены две мои попытки написать программу, которая может читать с клавиатуры устройства Linux. Я также включил свой маленький чек, чтобы убедиться, что у меня было правильное устройство.

Попытка № 1

Я попытался получить доступ к устройству клавиатуры напрямую, но у меня возникли проблемы. Я попробовал предложениеВот это находится в другом потоке переполнения стека. Это дало мне ошибку сегментации; Итак, я изменил его с fopen, чтобы открыть:

// ...

int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY);

char key_map[KEY_MAX/8 + 1];

memset(key_map, 0, sizeof(key_map));
ioctl(fd, EVIOCGKEY(sizeof key_map), key_map);

// ...

В то время как не было ошибки сегментации, не было никакого индикатора любого нажатия клавиши (не только клавиши модификатора). Я проверил это с помощью:

./foo && echo "TRUE" || echo "FALSE"

Я использовал это для проверки успешных кодов возврата команд; Итак, я знаю, что все в порядке. Я также вывел ключ (всегда 0) и маску (0100) для проверки. Кажется, он просто ничего не обнаруживает.

Попытка № 2

Отсюда я решил попробовать немного другой подход. Я хотел выяснить, что я делаю неправильно. Следующийэто На странице с фрагментом, демонстрирующим распечатку кодов ключей, я включил это в программу:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>

int main(int argc, char** argv) {
    uint8_t keys[128];
    int fd;

    fd = open("/dev/input/by-path/platform-i8042-serio-event-kbd", O_RDONLY);
    for (;;) {
        memset(keys, 0, 128);
        ioctl (fd, EVIOCGKEY(sizeof keys), keys);

        int i, j;
        for (i = 0; i < sizeof keys; i++)
            for (j = 0; j < 8; j++)
                if (keys[i] & (1 << j))
                    printf ("key code %d\n", (i*8) + j);
    }

    return 0;
}

Раньше у меня был размер до 16 байт вместо 128 байт. Я должен честно потратить немного больше времени на понимание ioctl и EVIOCGKEY. Я просто знаю, что он якобы отображает биты на определенные клавиши для указания нажатий или что-то в этом родепоправьте меня, если я ошибаюсь, пожалуйста!).

У меня также изначально не было цикла, и я просто удерживал различные клавиши, чтобы увидеть, появился ли код клавиши. Я ничего не получил; поэтому я подумал, что цикл может упростить проверку, если что-то пропущено.

Насколько я знаю, устройство ввода является правильным

Я проверил это, запустивcat на устройстве ввода. В частности:

$ sudo cat /dev/input/by-path/platform-i8042-serio-0-event-kbd

Мусор ASCII был отправлен на мой терминал при нажатии клавиши и отпускании событий, начиная с клавиши возврата (ввода), когда я начал вывод с помощью cat. Я также знаю, что это, кажется, работает нормально с клавишами-модификаторами, такими как shift, control, function и даже с клавишей Apple на моем Macbook, работающем под управлением виртуальной машины Linux. Вывод появлялся при нажатии клавиши, быстро начинал появляться из последующих сигналов, посылаемых при удерживании клавиши, и выводил больше данных при отпускании клавиши.

Так что, хотя мой подход не может быть правильным (я готов услышатьЛюбые альтернатива), устройство, кажется, обеспечивает то, что мне нужно.

Кроме того, я знаю, что это устройство - просто ссылка, указывающая на / dev / input / event2 от запуска:

$ ls -l /dev/input/by-path/platform-i8042-serio-0-event-kbd

Я пробовал обе программы выше с / dev / input / event2 и не получил данных. Запуск cat в / dev / input / event2 выдает тот же вывод, что и со ссылкой.

Ответы на вопрос(1)

Ваш ответ на вопрос