LINUX.ORG.RU

Эмуляция нажатия клавиши на клавиатуре

 , , ,


0

3

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

Я подумал в сторону /dev/input/event*, но тут две неприятности:

1. в сети нагуглил только примеры кейлогеров, т.е. RDONLY

2.

# file /dev/input/event0 
/dev/input/event0: character special (13/64)
# cat /dev/input/event0 
cat: /dev/input/event0: No such device

И так с любым event*

target ядро (ровесник мамонтов) - 2.4.32

★★★★★

Насколько я понимаю архитектуру (менее чем никак), с юзерспейса эмулировать клавиатуру напрямую нельзя (разве что только через модуль ядра). Можно писать в /dev/tty* , а если в tty запущены иксы - тогда через xdotool/libxdo. Т.е. надо определять запущены иксы в активном tty или нет.

mtk
()
Ответ на: uinput от Deleted

Нема

# ls /dev/input/uinput
ls: /dev/input/uinput: No such file or directory
# ls /dev/uinput
ls: /dev/uinput: No such file or directory
# ls -1R /dev/ | grep uinput
#
Stil ★★★★★
() автор топика
Последнее исправление: Stil (всего исправлений: 1)
Ответ на: комментарий от mtk

xdotool/libxdo

по крайней мере первое шлет ввод средствами иксов, через XEvent или что-нить типа XTest, а мне нужна клавиатура, а не события иксов

/dev/tty*

посмотрю, хотя это, похоже, не то

разве что только через модуль ядра

самый очевидный вариант, но я убьюсь писать модуль ведра, еще и под 2.4.32

Stil ★★★★★
() автор топика
Ответ на: комментарий от m0rph

возвращает 0, и lsmod | grep uinput показывает, что модуль загружен, но файлов в /dev все равно нет

Stil ★★★★★
() автор топика
Ответ на: комментарий от Stil

файлов в /dev все равно нет

у тебя там udev или всё-таки devfsd? Если последнее - есть мнение что ноды устройств надо создавать вручную. Какой у них major и minor для передачи mknod - хз, надо курить модуль...

Pinkbyte ★★★★★
()
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: uinput от Deleted

Спасибо, не знал.

kim-roader ★★
()

Итого

uinput действительно решил проблему

Предыстория: на таргете в иксах есть баг - раскладка в иксах не переключается до первого события от хардварной клавы, т.е. если использовать только виртуальную клавиатуру на всех этапах, включая логин скрин, то раскладка в иксах не переключается в принципе, не через XkbLockGroup, ни через XTestFakeKeyEvent, ни через XSendEvent, ни через апплет на панели DE... А работать ОС должна, в том числе и совсем без хардварной клавиатуры, и раскладка при этом должна переключаться...

Теперь по решению: модуль на таргете по умолчанию не загружался и файл в /dev тоже не создавался, поэтому в XSetup было добавлено:

modprobe uinput
if [[ ! -c /dev/input/uinput ]] ; then
    mknod /dev/input/uinput c 10 223
fi
sleep 0.5
hwkbdhook

где hwkbdhook - почти полная копипаста этого

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>

int main(void)
{
    int fd;
    struct uinput_user_dev uidev;
    struct input_event ev;

    fd = open("/dev/input/uinput", O_WRONLY | O_NONBLOCK);
    if (fd < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ open /dev/input/uinput : %d : %s",
                e, strerror(e));
        exit(EXIT_FAILURE);
    }
    if (ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ ioctl UI_SET_EVBIT EV_KEY : %d : %s",
                e, strerror(e));
        exit(EXIT_FAILURE);
    }
    if (ioctl(fd, UI_SET_KEYBIT, KEY_ESC) < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ ioctl UI_SET_KEYBIT KEY_ESC : %d : %s",
                e, strerror(e));
        exit(EXIT_FAILURE);
    }

    bzero(&uidev, sizeof(uidev));
    snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "tmp-input");
    uidev.idbus = BUS_USB;
    uidev.idvendor  = 0x1;
    uidev.idproduct = 0x1;
    uidev.idversion = 1;
    if (write(fd, &uidev, sizeof(uidev)) < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ write uidev : %d : %s", e, strerror(e));
        exit(EXIT_FAILURE);
    }
    if(ioctl(fd, UI_DEV_CREATE) < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ ioctl UI_DEV_CREATE : %d : %s",
                e, strerror(e));
        exit(EXIT_FAILURE);
    }

    bzero(&ev, sizeof(struct input_event));
    ev.type = EV_KEY;
    ev.code = KEY_ESC;
    ev.value = 1;
    if (write(fd, &ev, sizeof(struct input_event)) < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ write EV_KEY KEY_ESC 1 : %d : %s",
                e, strerror(e));
        exit(EXIT_FAILURE);
    }

    usleep(200);

    memset(&ev, 0, sizeof(struct input_event));
    ev.type = EV_KEY;
    ev.code = KEY_ESC;
    ev.value = 0;
    if (write(fd, &ev, sizeof(struct input_event)) < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ write EV_KEY KEY_ESC 0 : %d : %s",
                e, strerror(e));
    }

    usleep(200);

    if (ioctl(fd, UI_DEV_DESTROY) < 0) {
        const int e = errno;
        fprintf(stderr, "fail @ ioctl UI_DEV_DESTROY : %d : %s",
                e, strerror(e));
    }

    close(fd);

    return EXIT_SUCCESS;
}

Господа mironov_ivan и m0rph, благодарю за пинки в нужную сторону

Stil ★★★★★
() автор топика
Ответ на: комментарий от fluorite

спасибо, учту на будующее :)

Stil ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.