Was ich versuche zu tun
Also habe ich versucht, unter Linux auf Tastatureingaben zuzugreifen. Insbesondere muss ich in der Lage sein, auf Modifikatortastendrücke zuzugreifen ohne andere Tasten gedrückt werden. Außerdem möchte ich das können ohne ein laufendes X-System.
Also, kurz gesagt, meine Anforderungen sind diese:
- Funktioniert unter Linux
- Benötigt kein X11
- Kann Modifikatortastendruck abrufen ohne alle anderen Tasten gedrückt werden
- Dazu gehören folgende Schlüssel:
- Wechsel
- Kontrolle
- Alt
- Alles, was ich brauche, ist ein einfaches
0 = not pressed
,1 = currently pressed
um mich wissen zu lassen, ob die Taste gedrückt gehalten wird, wenn die Tastatur überprüft wird
- Dazu gehören folgende Schlüssel:
Mein Computer-Setup
Meine normale Linux-Maschine steht auf einem Lastwagen in Richtung meiner neuen Wohnung; Also habe ich im Moment nur ein Macbook Air, mit dem ich arbeiten kann. Daher führe ich Linux in einer VM aus, um dies zu testen.
Virtuelle Maschine in VirtualBox
- Betriebssystem: Linux Mint 16
- Desktop-Umgebung: XFCE
Alles unten wurde in dieser Umgebung gemacht. Ich habe es sowohl mit laufendem X als auch in einem der anderen ttys versucht.
Meine Gedanken
Ich werde das ändern, wenn mich jemand korrigieren kann.
Ich habe ziemlich viel gelesen, um festzustellen, dass Bibliotheken auf höherer Ebene diese Art von Funktionalität nicht bieten. Zusatztasten werden zusammen mit anderen Tasten verwendet, um einen alternativen Tastencode bereitzustellen. Der Zugriff auf die Modifikatortasten selbst über eine High-Level-Bibliothek in Linux ist nicht so einfach. Oder besser gesagt, ich habe unter Linux keine High-Level-API dafür gefunden.
ich dachte libtermkey wäre die Antwort, aber es scheint die Shift-Modifikatortaste nicht besser zu unterstützen als das normale Abrufen von Tastenanschlägen. Ich bin mir auch nicht sicher, ob es ohne X funktioniert.
Während ich mit libtermkey arbeitete (bevor ich merkte, dass es in Fällen wie Shift-Return keine Verschiebung bekam), plante ich, einen Daemon zu schreiben, der ausgeführt wird, um Tastaturereignisse zu sammeln. Laufende Kopien des Daemon-Programms würden einfach Anfragen nach Tastaturdaten weiterleiten und als Antwort Tastaturdaten erhalten. Ich könnte dieses Setup verwenden, um etwas immer im Hintergrund laufen zu lassen, falls ich den Schlüsselcodestatus zu bestimmten Zeiten nicht überprüfen kann (muss Schlüsselcodes erhalten, wenn sie passieren).
Unten sind meine zwei Versuche, ein Programm zu schreiben, das vom Linux-Tastaturgerät lesen kann. Ich habe auch meinen kleinen Check beigefügt, um sicherzustellen, dass ich das richtige Gerät habe.
Versuch Nr. 1
Ich habe versucht, direkt auf das Tastaturgerät zuzugreifen, aber es treten Probleme auf. Ich habe den Vorschlag hier ausprobiert, der in einem anderen Stack Overflow-Thread ist. Es gab mir einen Segmentierungsfehler; Also habe ich es von fopen auf open geändert:
// ...
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);
// ...
Während es keinen Segmentierungsfehler gab, gab es keinen Hinweis auf einen Tastendruck (nicht nur Modifikatortasten). Ich habe dies getestet mit:
./foo && echo "TRUE" || echo "FALSE"
Ich habe das ziemlich häufig verwendet, um auf erfolgreiche Rückgabecodes von Befehlen zu testen. Also, ich weiß, das ist in Ordnung. Ich habe auch den Schlüssel (immer 0) und die Maske (0100) zur Überprüfung ausgegeben. Es scheint einfach nichts zu erkennen.
Versuch Nr. 2
Von hier aus dachte ich, ich würde einen etwas anderen Ansatz versuchen. Ich wollte herausfinden, was ich falsch mache. Folgend Dies Seite mit einem Ausschnitt, der das Ausdrucken von Schlüsselcodes demonstriert, habe ich das in ein Programm gebündelt:
#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;
}
Früher hatte ich die Größe auf 16 Bytes statt 128 Bytes. Ich sollte ehrlich gesagt etwas mehr Zeit damit verbringen, ioctl und EVIOCGKEY zu verstehen. Ich weiß nur, dass es angeblich Bits bestimmten Tasten zuordnet, um Drücken oder ähnliches anzuzeigen (korrigiert mich, wenn ich falsch liege, bitte!).
Ich hatte anfangs auch keine Schleife und hielt einfach verschiedene Tasten gedrückt, um zu sehen, ob ein Tastencode angezeigt wurde. Ich habe nichts erhalten; Also dachte ich, eine Schleife könnte die Überprüfung einfacher machen, falls etwas übersehen wird.
Woher weiß ich, dass das Eingabegerät das richtige ist?
Ich habe es durch Laufen getestet cat
auf dem Eingabegerät. Speziell:
$ sudo cat /dev/input/by-path/platform-i8042-serio-0-event-kbd
Garbage ASCII wurde bei Tastendruck und -freigabe an mein Terminal gesendet, beginnend mit der Eingabetaste (Enter), als ich die Ausgabe mit cat begann. Ich weiß auch, dass dies mit Modifikatortasten wie Umschalttaste, Steuerung, Funktion und sogar Apples Befehlstaste auf meinem Macbook, auf dem eine Linux-VM ausgeführt wird, gut zu funktionieren scheint. Die Ausgabe erschien, wenn eine Taste gedrückt wurde, begann schnell von nachfolgenden Signalen zu erscheinen, die durch Gedrückthalten der Taste gesendet wurden, und gab mehr Daten aus, wenn eine Taste losgelassen wurde.
Also, obwohl mein Ansatz vielleicht nicht der richtige ist (ich bin bereit zu hören irgendein Alternative), scheint das Gerät das zu bieten, was ich brauche.
Außerdem weiß ich, dass auf diesem Gerät nur ein Link läuft, der auf /dev/input/event2 zeigt:
$ ls -l /dev/input/by-path/platform-i8042-serio-0-event-kbd
Ich habe beide oben genannten Programme mit /dev/input/event2 ausprobiert und keine Daten erhalten. Das Ausführen von cat auf /dev/input/event2 lieferte die gleiche Ausgabe wie mit dem Link.
Kurzer Tipp (ich habe keine wirkliche Antwort): Sie können den Statuscode des vorherigen Befehls in bash mit drucken
echo $?
. Könnte Tipparbeit sparen. 🙂– Luser Drog
6. Januar 2014 um 5:46 Uhr
Wusste das nicht. Vielen Dank!
– Senkwich
6. Januar 2014 um 6:38 Uhr