ventana una tipos teclas teclado tecla studio sistemas sintaxis salidas salida rapidas por perifericos para ordenes operativos metodo manejo lista imagenes gestor gestion fisico entradas entrada ejemplos dispositivos developer consola completa comandos cerrar bloques basicos atajos administrador administracion abreviado c linux keyboard-events modifier-key

una - tecla ctrl en android



Acceso a las teclas desde el dispositivo de entrada de Linux (1)

Abra el dispositivo de entrada,

#include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <linux/input.h> #include <string.h> #include <stdio.h> static const char *const evval[3] = { "RELEASED", "PRESSED ", "REPEATED" }; int main(void) { const char *dev = "/dev/input/by-path/platform-i8042-serio-0-event-kbd"; struct input_event ev; ssize_t n; int fd; fd = open(dev, O_RDONLY); if (fd == -1) { fprintf(stderr, "Cannot open %s: %s./n", dev, strerror(errno)); return EXIT_FAILURE; }

y luego leer los eventos del teclado desde el dispositivo:

while (1) { n = read(fd, &ev, sizeof ev); if (n == (ssize_t)-1) { if (errno == EINTR) continue; else break; } else if (n != sizeof ev) { errno = EIO; break; }

El fragmento de código anterior se desprende del bucle si se produce algún error, o si el espacio de usuario recibe solo una estructura de eventos parcial (lo que no debería ocurrir, pero podría ocurrir en algunos núcleos futuros / con errores). Es posible que desee utilizar un bucle de lectura más robusto; Personalmente estaría satisfecho al reemplazar la última break con continue , de modo que las estructuras de eventos parciales se ignoren.

Luego puede examinar la estructura del evento ev para ver qué ocurrió y finalizar el programa:

if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2) printf("%s 0x%04x (%d)/n", evval[ev.value], (int)ev.code, (int)ev.code); } fflush(stdout); fprintf(stderr, "%s./n", strerror(errno)); return EXIT_FAILURE; }

Para una pulsación de tecla,

  • ev.time : hora del evento ( struct timeval type)

  • ev.type : EV_KEY

  • ev.code : KEY_* , identificador de clave; vea la lista completa en /usr/include/linux/input.h

  • ev.value : 0 si suelta la tecla, 1 si presiona la tecla, 2 si presiona automáticamente la tecla

Consulte Documentation/input/input.txt en las fuentes del kernel de Linux para obtener más detalles.

Las constantes nombradas en /usr/include/linux/input.h son bastante estables, ya que es una interfaz de espacio de usuario de kernel, y los desarrolladores del kernel hacen un gran esfuerzo para mantener la compatibilidad. (Es decir, puede esperar que haya nuevos códigos de vez en cuando, pero los códigos existentes rara vez cambian).

Lo que estoy tratando de hacer

Por lo tanto, he estado tratando de acceder a la entrada del teclado en Linux. Específicamente, necesito poder acceder a las pulsaciones de las teclas modificadoras sin presionar otras teclas. Además, quiero poder hacer esto sin un sistema X en ejecución.

Así que, en definitiva, mis requerimientos son estos:

  • Funciona en linux
  • No necesita X11
  • Puede recuperar la tecla modificadora sin que se presione ninguna otra tecla
    • Esto incluye las siguientes teclas:
      • Cambio
      • Controlar
      • Alt
    • Todo lo que necesito es un simple 0 = not pressed , 1 = currently pressed para avisarme si la tecla se mantiene presionada cuando se comprueba el teclado

Configuración de mi computadora

Mi máquina normal de Linux está en un camión hacia mi nuevo apartamento; Entonces, solo tengo un Macbook Air para trabajar en este momento. Por lo tanto, estoy ejecutando Linux en una máquina virtual para probar esto.

Máquina Virtual en VirtualBox

  • SO: Linux Mint 16
  • Entorno de escritorio: XFCE

Todo lo de abajo fue hecho en este ambiente. He intentado con X en ejecución y en uno de los otros ttys.

Mis pensamientos

Lo alteraré si alguien me puede corregir.

He leído bastante para darme cuenta de que las bibliotecas de nivel superior no proporcionan este tipo de funcionalidad. Las teclas modificadoras se utilizan con otras teclas para proporcionar un código de tecla alternativo. Acceder a las claves modificadoras a través de una biblioteca de alto nivel en Linux no es tan fácil. O, mejor dicho, no he encontrado una API de alto nivel para esto en Linux.

Pensé que la respuesta sería libtermkey , pero no parece admitir la tecla modificadora Shift mejor que la recuperación de pulsaciones de tecla normal. Tampoco estoy seguro de si funciona sin X.

Mientras trabajaba con libtermkey (antes de darme cuenta de que no había cambios en casos como Shift-Return), planeaba escribir un demonio que se ejecutaría para recopilar eventos de teclado. Ejecutar copias del programa daemon simplemente canalizaría las solicitudes de datos del teclado y recibiría los datos del teclado en respuesta. Podría usar esta configuración para tener algo siempre ejecutándose en segundo plano, en caso de que no pueda verificar los estados de los códigos clave en momentos específicos (se deben recibir los códigos clave a medida que ocurren).

A continuación están mis dos intentos de escribir un programa que puede leer desde el dispositivo de teclado Linux. También he incluido mi pequeño cheque para asegurarme de que tenía el dispositivo correcto.

Intento # 1

He intentado acceder al dispositivo del teclado directamente, pero tengo problemas. He intentado la sugerencia here que está en otro hilo de desbordamiento de pila. Me dio una falla de segmentación; Así que, lo cambié de fopen para abrir:

// ... 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); // ...

Si bien no hubo falla de segmentación, no hubo ningún indicador de pulsación de tecla (no solo teclas modificadoras). He probado esto utilizando:

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

He usado eso para probar códigos de retorno exitosos de comandos bastante; Entonces, sé que está bien. También he enviado la clave (siempre 0) y la máscara (0100) para verificar. Simplemente no parece detectar nada.

Intento # 2

Desde aquí, pensé en probar un enfoque ligeramente diferente. Quería averiguar qué estaba haciendo mal. Siguiendo this página que proporciona un fragmento de código que muestra la impresión de los códigos clave, lo integré en un programa:

#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; }

Anteriormente, tenía el tamaño de 16 bytes en lugar de 128 bytes. Sinceramente, debería dedicar un poco más de tiempo a comprender ioctl y EVIOCGKEY. Solo sé que supuestamente asigna bits a teclas específicas para indicar pulsaciones, o algo así (¡ corríjame si me equivoco, por favor! ).

Al principio, tampoco tenía un bucle y simplemente presionaba varias teclas para ver si aparecía un código clave. No recibí nada; por lo tanto, pensé que un bucle podría hacer que la verificación fuera más fácil de probar en caso de que algo se perdiera

Cómo sé que el dispositivo de entrada es el correcto

Lo probé ejecutando cat en el dispositivo de entrada. Específicamente:

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

El ASCII de basura se envió a mi terminal al presionar y liberar eventos de teclas que comienzan con la tecla de retorno (ingresar) cuando comencé la salida usando cat. También sé que esto parece funcionar bien con las teclas modificadoras como cambio, control, función e incluso la tecla de comando de Apple en mi Macbook que ejecuta una VM de Linux. La salida apareció cuando se presionó una tecla, comenzó a aparecer rápidamente de las señales posteriores enviadas al mantener presionada la tecla y generó más datos cuando se soltó una tecla.

Entonces, si bien mi enfoque puede no ser el correcto (estoy dispuesto a escuchar cualquier alternativa), el dispositivo parece proporcionar lo que necesito.

Además, sé que este dispositivo es solo un enlace que apunta a / dev / input / event2 desde la ejecución:

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

He probado los dos programas anteriores con / dev / input / event2 y no recibí datos. La ejecución de cat en / dev / input / event2 proporcionó la misma salida que con el enlace.