Hallo,
mit Tastaturen unter Linux kenne ich mich nicht so aus. Du musst die Linux Doku finden, die die entsprechnenden Dinge beschreibt, wie hier das Windows Gegenstück:
https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
hallo,
wer kennt eine C/C++ lib für Sonderzeichenkombinationen (F1-12, +shift, alt, ctrl), um sie als Art "scancode" von der Tastatur zu lesen?
es soll so ähnlich funktionieren wie mit getch() / getchar(), nur dass nicht ein ASCII Zeichen gelesen werden soll, sondern ein einzigarteiger "Scancode" für die Tastenkombi (also keine Folge von einzelnen chars), z.B.
64031 für F1
65031 für ctrl+F1
66031 für shift+F1
...
usw,
praktischerweise auch
27 für ESC und
65 für 'A' etc,
um sie einfach abfragen und behandeln zu können, wie hier im Pseudocode:
Code:int32_t i=getkeycode(); if(i==27) {...} // ESC: return NULL, terminate program (quit) else if(i==64031) {...} // F1: switch openVG window 1 else if(i==64032) {...} // F2: switch openVG window 2 else if(i==64033) {...} // F3: switch openVG window 3 else if(i==63001) {...} // ctrl + : zoom in else if(i==63002) {...} // ctrl - : zoom out else if(i==64111) {...} // cur_up: move slow forward else if(i==64112) {...} // cur_dn: move slow reverse else if(i==66111) {...} // shift+cur_up: move fast forward else if(i==66112) {...} // shift+cur_dn: move fast reverse else if(i==64113) {...} // cur_left: turn slow left else if(i==64114) {...} // cur_right: turn slow right else if(i==66113) {...} // shift+cur_left: turn strong left else if(i==66114) {...} // shift+cur_right: turn strong right else if(i==65113) {...} // ctrl+cur_left: spin left else if(i==65114) {...} // ctrl+cur_right: spin right else if(i==64120) {...} // end: stop move, coast else if(i==65120) {...} // ctrl+end: stop move, brake ...
Man bräuchte dazu allerdings auch eine Tabelle als Übersicht, um die Zeichen nachschlagen zu können:
wo gibt's sowas, nach 40 Jahren C und Unix/Linux ?Code:key plain shift ctrl alt shift+ctrl ctrl+alt shift+alt shift+ctrl+alt Home Insert Delete End Pgup PgDn F1 F2 F3 ... cur_up cur_dn cur_left cur_right ... A B C ... a b c ...
Geändert von HaWe (04.04.2016 um 22:15 Uhr)
Hallo,
mit Tastaturen unter Linux kenne ich mich nicht so aus. Du musst die Linux Doku finden, die die entsprechnenden Dinge beschreibt, wie hier das Windows Gegenstück:
https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
Hallo,
Die Frage ist jetzt auf welcher Ebene du ansetzen willst?
Ganz früher haben Tastaturcontroller direkt den ASCII-Code der Tasten geliefert. Das brauchte dann aber für jede Tastenanordnung (Sprache) einen anderen Controller. STRG und SHFT wurden nur intern verwendet. An Computer wurden Terminals angeschlossen, Einheiten aus Tastatur und Bildschirm. Für die Codierung von z.B. Coursor-Tasten, welche in ASCII nicht vorgesehen sind, hatte jeder Terminal-Hersteller eine eigene Lösung. Wie auch für die Steuerbefehle ans Terminal.
Sehr verbreitet waren die DEC VT100 Terminals, woraus sich dann auch eine ANSI-Norm für Terminals entwickelte.
IBM hat dann beim PC die Tasten einfach durchnummeriert. Jede Taste setzt dann ein Signal beim Drücken und eines beim loslassen ab (Scancode).
Im PC war dann ein Tastaturtreiber, welcher aus den Scancodes dann die entsprechenden ASCII-Werte erzeugt und die speziellen Tasten wie STRG, SHFT usw. auswertet.
Für Sondertasten gibt es keine definierte ASCII-Codes, also wurden für sie zwei Zeichen erzeugt.
Da liegt halt der Hund begraben!wo gibt's sowas, nach 40 Jahren C und Unix/Linux ?
Den IBM-PC gibt es erst seit 35 Jahren und Unix kam erst später auf den IBM-PC.
Unix war zuerst auf Grossrechnern vorhanden, weshalb es unter Unix/Linux deshalb heute immer noch eine Menge Treiber für Terminals gibt oder Treiber welche eines der Terminals simulieren.
MfG Peter(TOO)
Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?
Ich glaube mit Terminal hat Peter das richtige Stichwort genannt.
getch() und Verwandte setzen wahrscheinlich auf den Terminal-Funktionen auf. Man muss also mindestens auf diese Ebene herunter. Es gibt da auch einen raw Modus, möglicherweise liefert der das gesuchte. Das alles ist verwandt mit den Funktionen zur UART-Programmierung, das ist für Unix alles das selbe, genau wie Peter schon sagt. Früher hingen alle Textterminals an seriellen Schnittstellen.
Noch tiefer kommt man wohl nur mit raw input, das geht irgendwie mit Sachen aus den /dev/... Verzeichnissen. Hab ich noch nie gemacht.
im Prinzip ist mir die Ebene egal, ich lese die Tastatur in einer Art pthread "keyboard watcher task" - bisher wird nur die Taste ESC überwacht für einen program abort, aber nun sollen auch andere Tasten überwacht werden, insbesondere Sondertasten:
*arrrgs* wieder kein Code Tag!!!kbhit habe ich als conio-mimic hierraus:Code:void* thread1Go(void *) // medium priority: keyboard + heartbeat monitoring { int c; // keyboard key while(_TASKS_ACTIVE_) { c=0; if (kbhit()) { // <<<<<<<<<<<<<<<<<< c = getchar(); if( c==27 ) { // ESC to quit program printf("\n\n ESC pressed - program terminated by user \n"); _TASKS_ACTIVE_=0; // semaphore to stop all tasks printf("\n wait for tasks to join main()... \n\n"); return NULL; } } //... ***SNIP*** delay(50); } return NULL; }
Code:#ifndef RPICONIO_H #define RPICONIO_H #include <stdbool.h> #include <stdio.h> #include <string.h> #include <termio.h> #include <unistd.h> bool kbhit(void) { struct termios original; tcgetattr(STDIN_FILENO, &original); struct termios term; memcpy(&term, &original, sizeof(term)); term.c_lflag &= ~ICANON; tcsetattr(STDIN_FILENO, TCSANOW, &term); int characters_buffered = 0; ioctl(STDIN_FILENO, FIONREAD, &characters_buffered); tcsetattr(STDIN_FILENO, TCSANOW, &original); bool pressed = (characters_buffered != 0); return pressed; } //... ***SNIP*** #endif
über wiederholtes getchar() Auslesen ginge es zwar prinzipiell, aber F1 liefert 3 Zechen im keyb-Puffer (27,79,80) und shift-F1 wohl sogar 6, was ein Unding wäre, das über eine extra state machine verarbeiten zu wollen - für alle 102x7 möglichen key+modifier-Kombis.
Also wird eine Art "Scancode" gebraucht, so wie es das schon früher bei Turbo Pascal und Turbo C optional, zusätzlich zu readkey oder getchar gab.
Geändert von HaWe (05.04.2016 um 11:55 Uhr)
Shift-F1 ist eine Kombination, ich denke bei 3 für eine Einzelne ist Schluss. Kombinationen muss man immer nach dem Puffer verarbeiten. Ausser man nutzt eine library wie ncurses, welche ich persönlich gern nutze. Sehr einfache Struktur und mit ein paar Zeilen Ergebnisse.über wiederholtes getchar() Auslesen ginge es zwar prinzipiell, aber F1 liefert 3 Zechen im keyb-Puffer (27,79,80) und shift-F1 wohl sogar 6, was ein Unding wäre, das über eine extra state machine verarbeiten zu wollen - für alle 102x7 möglichen key+modifier-Kombis.
So aufwendig ist das ohne eine Library auch nicht... Pseudocode:
Code:uint8_t c, len; int ret; c = get_scancode(); len = lookup_len(c); // tabelle/array mit möglichen längen (1-3) array_rcv[0] = c; // erstes/einzelnes zeichen speichern if(len > 1) { ret = get_more(array[1], array[2], len); // empfange len mehr zeichen, return = empfangene zeichen // etwas tun }
ncurses nutzt eine eigenes Terminal-Window mit eigener print-Funktion
mvaddstr
und mit einem ziemlichen Initialisierungs-Overhead
initscr();
raw();
noecho();
keypad(stdscr, TRUE);
und mit Eigenschaften, die std-printf()-Ausgaben "verzerren", so wird z.B. nach \n kein carriage return ausgeführt. Mehrmals einen string mit \n ausgeben lässt ihn daher mit Treppenstufen-Versatz in die nächste Zeile nach rechts rutschen, nicht untereinander ab Anfang jeder Zeile.
Außerdem kann ncurses - zumindest per Testcode - z.B. kein shift+F1 anzeigen. Von daher ist also einerseits nicht mehr standardconform, und zum anderen auch noch von sehr eingeschränktem Nutzungsumfang.
für ncurses hatte ich mal diesen testcode ausprobiert:
Code:#include <ncurses.h> int main( void ) { /* Initialize ncurses */ initscr(); const char *str; int ch; /* Switch of echoing and enable keypad */ raw(); noecho(); keypad(stdscr, TRUE); mvaddstr( LINES-1, 0, "Press keys, 'q' to quit" ); /* Loop until user hits 'q' to quit */ while( (ch = getch()) != 'q' ) { switch( ch ) { case KEY_F(1): str = "F1 key"; break; case KEY_F(2): str = "F2 key"; break; case KEY_F(3): str = "F3 key"; break; case KEY_F(4): str = "F4 key"; break; case 'a' ... 'z': str = "Lower case letter"; break; case 'A' ... 'Z': str = "Upper case letter"; break; case '0' ... '9': str = "Digit"; break; case KEY_UP: str = "KEY_UP"; break; case KEY_DOWN: str = "KEY_DOWN"; break; case KEY_LEFT: str = "KEY_LEFT"; break; case KEY_RIGHT: str = "KEY_RIGHT"; break; case KEY_HOME: str = "KEY_HOME"; break; case KEY_END: str = "KEY_END"; } //mvaddstr( LINES-1, 0, str ); printf("%s\n", str); clrtoeol(); } /* Clean up after ourselves */ endwin(); return 0; }
Einen (wünschenswerten) Pseudocode hatte ich ja bereits selber skizziert, zu Erläuterungszwecken.
Was ich aber jetzt brauche, ist kein Pseudocode, sondern echten Code, zusammen mit einer Liste aller möglichen denkbaren modifier-Kombis, damit man nicht das Rad neu erfinden muss.
**arrrgs** und schon wieder keine Code Tags hier vorhanden...Code:key plain shift ctrl alt shift+ctrl ctrl+alt shift+alt shift+ctrl+alt Home Insert Delete End Pgup PgDn F1 F2 F3 ... cur_up cur_dn cur_left cur_right ... A B C ...
"Das Rad nicht neu erfinden" gilt übrigens auch für meine gesuchte Funktion, ich denke, das müsste es nach 40 Jahren UNIX/Linux sicher schon längst geben.
- - - Aktualisiert - - -
pps,
für BIOS/MSDOS etc gabs das ja, gelistet z.B. hier
http://flint.cs.yale.edu/cs422/doc/a...pdf/APNDXC.PDF
(Appendices Page 1353)
so etwas bräuchte ich nun für Linux als Art "getscancode()" etc.
Geändert von HaWe (05.04.2016 um 15:12 Uhr) Grund: per code tags nachformatiert
Hmm... Die Modifier-Tasten sind eben nur Modifier und ich kenne da keinen anderen Weg. Vielleicht hilft dir das ja weiter, um alles Steuerzeichen direkt zu bekommen:
https://www.daniweb.com/programming/...g-gcc-compiler
- - - Aktualisiert - - -
Hmm... Die Modifier-Tasten sind eben nur Modifier und ich kenne da keinen anderen Weg. Vielleicht hilft dir das ja weiter, um alles Steuerzeichen direkt zu bekommen:
https://www.daniweb.com/programming/software-development/threads/147540/how-can-we-get-scan-code-in-c-using-gcc-compiler
das ist die oben von mir skizzierte kaskadierte Methode.
Für F1 muss man dazu hintereinander 27, dann 79, dann 80 auslesen, um es als F1 zu identifizieren, und für shift-F1 nochmal 3 chars zusätzlich.
Dann denk mal drüber nach, welche Verrenkungen nötig sind, um ein ctr+shift+F1 von einem ctr+shift+F2 oder einem alt+ctrl+F2 oder einem shift+ctrl+alt+F1 oder shift+ctrl+alt+F2 zu unterscheiden....
Das bringt doch wie gesagt nichts.
Was man bräuchte, wäre der Scancode, was eher dem gleichkommt, was die Keyboard-Hardware selber produziert, nicht das, was das Linux-Terminal daraus macht.
wie könnte man z.B.
/dev/input/*
auslesen?
Und wo findet man die zugehörige Tasten-Kombinationen-Tabelle?
Lesezeichen