- 3D-Druck Einstieg und Tipps         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 33

Thema: C/C++ lib für Sonderzeichenkombinationen (F1-12, +shift, alt, ctrl) als Scancode

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    HaWe
    Gast
    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 14:12 Uhr) Grund: per code tags nachformatiert

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    28.03.2016
    Beiträge
    8
    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

  3. #3
    HaWe
    Gast
    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?

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    28.03.2016
    Beiträge
    8
    Die Doku dazu ist hauptsächlich als simpler Text verfügbar und auch nicht gerade Umfangreich, da das ohne lib kaum jemand benutzt.

    https://www.kernel.org/doc/Documentation/input/

    input und input-programming dürften interessant sein.

    - - - Aktualisiert - - -

    Die Doku dazu ist hauptsächlich als simpler Text verfügbar und auch nicht gerade Umfangreich, da das ohne lib kaum jemand benutzt.

    https://www.kernel.org/doc/Documentation/input/

    input und input-programming dürften interessant sein.

  5. #5
    HaWe
    Gast
    nun, hmm, da bräuchte ich jetzt tatkräftige Hilfe von jemandem mit richtig viel Kenne, wie man das jetzt zur Problemlösung einsetzt ...

  6. #6
    HaWe
    Gast
    hallo, super, das Programm läuft!
    es werden jetzt in 1 Zeile alle modifier plus die gedrückte "echte" Taste angezeigt.

    Was hältst du davon, wenn man daraus einen eigenen Scancode generiert?

    einfache Taste, Bereich 0...255, so wie jetzt bereits ausgegeben.

    Modifier:
    shift (links oder rechts, egal): = 1*1024
    ctrl (links oder rechts, egal): = 2*1024
    alt (links): = 4*1024
    altgr (==ctrl+alt) : = 6*1024

    diese werden dann zum Rest der gedrückten Tasten dazu addiert.

    dann könnte man eine Funktion schreiben, die ausschließlich diesen Scancode berechnet und in einer globalen Variablen speichert.

    Dazu könnte ich ein paar Konstanten entwerfen wie z.B.
    Code:
    #define F1     59
    #define F2     60
    #define F3     61
    ...
    
    #define F1_shft     59+1024
    #define F2_shft     60+1024
    #define F3_shft     61+1024
    ...
    
    #define F1_ctrl     59+2048
    #define F2_ctrl     60+2048
    #define F3_ctrl     61+2048
    ...
    
    #define F1_alt      59+4092
    #define F2_alt      60+4092
    #define F3_alt      61+4092
    ...
    usw


    Code:
    // global)
    volatile int _kbscode_=0;
    
    
    void  getkbscancode() {
       int modkeycode = 0; 
       //...
       // hier jetzt deine Abfrage auf Druck ohne Wiederholung, 
       // dann modkeycode berechnen wie oben aus Summe aus
       // shift (links oder rechts, egal): = 1*1024
       // ctrl (links oder rechts, egal):  = 2*1024
       // alt (links oder rechts, egal):  = 4*1024
    
      _kbscode_ = ev[1].code + modkeycode  // hier jetzt die Sondertasten als Vielfache von 1024 dazuaddieren
    }
    sodass man die kbstates abfragen kann per
    Code:
    if(_kbscode_==F1) {...}
    else
    //...
    else
    if(_kbscode_==F3_alt) {...}
    ...
    else
    if(_kbscode_==F1_shiftalt) {...}
    //alternativ)
    if(_kbscode_==F1 +1024+4048) {...}
    usw...

    Die Frage wäre, ob man dann einen eigenen Task dafür spendiert, der ausschließlich void getkbscancode() wiederholt aufruft und so automatisch als keypress-Watcher funktioniert.
    Alternativ könnte man diese Funktion auch in jedem anderen, bereits laufenden Task aufrufen, quasi als zusätzliche Unterfunktion.

    zwischenstadium:

    Code:
    // Compile with: g++ -o /var/scripte/tastaturtest1 /var/scripte/tastaturtest1.c  -L/usr/local/lib -lpthread
    // /var/scripte/tastaturtest1
    // 05.04.2016 - peterfido
    // variant 06.04.2016 - hawe
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdint.h>
    #include <sys/sysinfo.h>
    #include <time.h>
    #include <linux/input.h>
    #include <pthread.h>
    #include <errno.h>
    #include <termios.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <sys/select.h>
    
    int ziffer=0;
    int beenden=2;
    int zeit=0;
    int shiftl=0;
    int shiftr=0;
    int shift =0;
    int strgl=0;
    int strgr=0;
    int strg=0;
    int capsl=0;
    int alt=0;
    int altgr=0;
    int windows=0;
    int kontext=0;
    int keybscan=0;
    
    int modscode;
    volatile int _kbscode_ ;
    
    
    void* thread1Go(void *)
    {
        int _TASKS_ACTIVE_=0;
        struct input_event ev[64];
        int fd, rd, value, size = sizeof (struct input_event);
    
        if ((fd = open ("/dev/input/event0", O_RDONLY)) == -1){
            printf ("Fehler mit Tastatur");
        }else{
            _TASKS_ACTIVE_=1;
        }
    
    
        struct input_event event;
        while (_TASKS_ACTIVE_) {
                 
            if ((rd = read (fd, ev, size * 64)) < size)
              printf ("Fehler mit Tastatur");
           
            if (ev[1].type != EV_KEY) continue;
            if (ev[1].value==0){         //Taste losgelassen
                    switch (ev[1].code) {
                        case 42: shiftl=0; break;
                        case 54: shiftr=0; break;
                        case 29: strgl=0; break;
                        case 97: strgr=0; break;
                        case 56: alt=0; break;
                        case 125: windows=0; break;
                        case 100: altgr=0; break;
                        case 127: kontext=0; break;
                    }
            }else{
                if (ev[1].value==1){            //==1 für nur einen Druck ohne Wiederholung. >=1 für Erkennung von gedrückt gehaltener Taste
                     modscode = 0;
                     switch (ev[1].code) {
                        case 42: shiftl=1;  break;
                        case 54: shiftr=1;   break;
                        case 29: strgl=1;   break;
                        case 97: strgr=1;  break;
                        case 56: alt=1;  break;
                        case 125: windows=1;   break;
                        case 100: altgr=1; modscode+=(2048+4096); break;
                        case 127: kontext=1; break;
                        
                        
    // Ab hier 'normale Tasten'
                       
                        //case 1: beenden=0; _TASKS_ACTIVE_=0; break; //ESC
                        default: keybscan=ev[1].code;// Scancode ablegen
                        
                        if(shiftl || shiftr ) modscode+=1024;   
                        if(strgl  || strgr  ) modscode+=2048;  
                        if(alt)   modscode+=4096;  
                        if(altgr) modscode+=(2048+4096);  
                                        
                        
                        _kbscode_= keybscan + modscode;
                        printf("SHIFTL: %2d, SHIFTR: %2d, STRGL: %2d, STRGR: %2d; ",shiftl,shiftr,strgl,strgr);
                        printf("Typ: %2d; Wert: %2d; Code: %2d scancode=%6d \n",ev[1].type,ev[1].value,ev[1].code, _kbscode_ );
                        break;
                    }
                }
            }
        }
        beenden=0;
        pthread_exit((void *) 0);
    }
    
    int main()
    {
        pthread_t thread1;
        struct  sched_param  param;
       
    
        if(pthread_create(&thread1, NULL, thread1Go, NULL) != 0)
        {
          fprintf(stderr, "Fehler bei Tastatur......\n");
          exit(0);
        }     
       
        param.sched_priority = 20;
        pthread_setschedparam(thread1, SCHED_RR, &param);
       
        beenden=1;
       
        while (beenden > 0)
            {     sleep(1);
                zeit++;
                if (zeit==30)
                {
                    zeit=0;
                    printf("Wieder 30 Sekunden um.\n");
                }
        }
        usleep(50);
        printf("***********Ende************\n");
        return 0;
    }
    was hältst du davon?



    ps, Tipp für dich:
    Ich habe mir sagen lassen, pthread verlinkt man besser per -pthread statt mit -lpthread.

    You should really use -pthread rather than -lpthread as as well as including the library it also sets any other options (which usually on linux means setting -D_REENTRANT as well). So yes, if you use -lpthread then you need -D_REENTRANT otherwise things could go wrong.

    Fragen an dich:
    1) was verlinkt eigentlich -L/usr/local/lib ?
    2) was ist "kontext" und "windows" ?
    Geändert von HaWe (06.04.2016 um 15:11 Uhr)

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Hallo,

    L/usr/local/lib gibt noch einen Pfad hinzu, wo der Compiler nach den Libs suchen kann. Evtl. ist es bei g++ gar nicht nötig. Windows ist die Windows-Taste zwischen STRG+Alt und Kontext die Kontextmenütaste zwischen AltGr und STRG auf meiner Tastatur.

    Sicher kann man einen eigenen Scancode erstellen. Das kommt auf den Anwendungsfall an. Bei freien Texteingaben ist es einzeln besser, da man die Buchstaben nur einmal abfragt und dann, ob Shift gedrückt ist. Möchte man einen Flipper programmieren, sind separate SHIFTs von Vorteil. Werden STRG UND SHIFT plus eine Taste gedrückt, passt es nicht mehr. Ist eine Makrotastatur vorhanden, empfiehlt es sich noch einen 'Tastaturpuffer' zu integrieren.

    In zwei Projekten von mir sind als Bedienung je eine 10er Tastatur dran. Da brauche ich jede Taste inklusive der NumLock Taste.

    Je nach Tastatur kann man mehrere Tasten gleichzeitig zuverlässig drücken. Gamer-Tastaturen lassen da normal mehr zu als 08/15 Tastaturen. Es lässt sich prinzipiell auch jede andere Taste als Modifiertaste nutzen. Und so z.B. für Codeeingaben auch die Drück- und Loslasssequenzen auswerten.

    Aktuell brauche ich es nicht. Das wär was für die nächsten langen Winterabende (oder einen davon).

    Meine Anfänge damit habe ich mit einer PS/2 Tastatur an einem Atmega gemacht. Da kann man dann auch die LEDs der Tastatur ansteuern. Da aber PS/2 bei den IR-Tastaturen und den 10er Tastaturen nicht so gängig ist, habe ich die Tastaturabfrage auf den Raspi ausgelagert.

    Das mit den (l)pthread teste ich mal aus. Der von mir gefundene Beispielcode im Netz damals hatte es so gemacht.

    Edit: AltGr durch STRG und Alt zu ersetzen klappt oft. Ist aber ein anderer Code. Windows z.B. reicht es nicht AltGr und Entf zu drücken
    Geändert von peterfido (06.04.2016 um 15:47 Uhr)
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  8. #8
    HaWe
    Gast
    ah ja, jetzt hab ischs verstanden mit kontext und windows, hatte ich überlesen.

    ps,
    2 Zeilen werden offenbar nicht benötigt:

    struct input_event event;
    und

    if (ev[1].type != EV_KEY) continue;

    oder?
    Geändert von HaWe (06.04.2016 um 18:30 Uhr)

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Hallo,

    auf den ersten Blick sieht es so aus, dass event sich da tatsächlich eingeschlichen hat. Das if schließt aus, dass bei einem 'falschen' Ereignistyp der Rest des Codes durchlaufen wird. Tritt kein Ereignis auf, ist der Typ 0 und dann würde ohne die Abfrage der Rest des Codes durchlaufen werden. So war zumindest der Gedanke. GeDebuggt habe ich nicht, ob es nach der Änderung des Codes noch notwendig ist.

    Ansonsten melde ich mich erstmal ab, da ich eine Zeit lang offline sein werde.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  10. #10
    HaWe
    Gast
    alles klar, auf jeden Fall nochmal vielen, vielen Dank, ich kann damit jetzt schon super arbeiten!


    - - - Aktualisiert - - -

    habs hingekriegt!
    die Scanfunktion läuft jetzt in nem eigenen Funktions-Wrap!

    Perfekt! Hilft mir jetzt super toll!

    Code:
    // Compile with: g++ -o /var/scripte/tastaturtest1 /var/scripte/tastaturtest1.c  -L/usr/local/lib -lpthread
    // /var/scripte/tastaturtest1
    // 05.04.2016 - peterfido
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdint.h>
    #include <sys/sysinfo.h>
    #include <time.h>
    #include <linux/input.h>
    #include <pthread.h>
    #include <errno.h>
    #include <termios.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <sys/select.h>
    
    int ziffer=0;
    int beenden=2;
    int zeit=0;
    int shiftl=0;
    int shiftr=0;
    int strgl=0;
    int strgr=0;
    int capsl=0;
    int alt=0;
    int altgr=0;
    int windows=0;
    int kontext=0;
    int keybscan=0;
    
    int modscode;
    volatile int _kbscode_ ;
    
    // keyboard dev
    int    fkbd;
    char * kbdin = "/dev/input/event0";
    struct input_event ev[64];
    
    
    int _TASKS_ACTIVE_= 1;    
        
    
    
    int getkbscancode() {
    	int  rd,  size = sizeof (struct input_event);
    	
    	if ((rd = read (fkbd, ev, size * 64)) < size)
              printf ("Fehler mit Tastatur");
           
            if (ev[1].type != EV_KEY) return 0;
            
            if (ev[1].value==0){         //Taste losgelassen
                    switch (ev[1].code) {
                        case 42: shiftl=0; break;
                        case 54: shiftr=0; break;
                        case 29: strgl=0; break;
                        case 97: strgr=0; break;
                        case 56: alt=0; break;
                        case 125: windows=0; break;
                        case 100: altgr=0; break;
                        case 127: kontext=0; break;
                    }
            }
            else
            {
                if (ev[1].value==1){            
    				 //==1 für nur einen Druck ohne Wiederholung. >=1 für Erkennung von gedrückt gehaltener Taste
                     modscode = 0;
                     switch (ev[1].code) {
                        case 42: shiftl=1;  break;
                        case 54: shiftr=1;   break;
                        case 29: strgl=1;   break;
                        case 97: strgr=1;  break;
                        case 56: alt=1;  break;
                        case 125: windows=1;   break;
                        case 100: altgr=1; modscode+=(2048+4096); break;
                        case 127: kontext=1; break;
                        
                        
                        // Ab hier 'normale Tasten'                   
                        default: keybscan=ev[1].code;// Scancode ablegen
                        
                        if(shiftl || shiftr ) modscode+=1024;   
                        if(strgl  || strgr  ) modscode+=2048;  
                        if(alt)   modscode+=4096;  
                        if(altgr) modscode+=(2048+4096);  
                        if(windows)   modscode+=8192;  
                        if(kontext)   modscode+=16384;  
                                        
                        if(keybscan>0) {
                           _kbscode_= keybscan + modscode;
                           return keybscan;
                        }
    		    else
    		    return 0 ;
                        //break;
                    }
                }
            }
            return 0 ;
    }
    
    void* thread6Go(void *)
    {
        
    
        while (_TASKS_ACTIVE_) {
             
             if(getkbscancode()) { 
                printf("\nSHIFTL: %2d, SHIFTR: %2d, STRGL: %2d, STRGR: %2d; ",shiftl,shiftr,strgl,strgr);
                printf("Typ: %2d; Wert: %2d; Code: %2d scancode=%6d \n",ev[1].type,ev[1].value,ev[1].code, _kbscode_ );            
             }
        }
        beenden=0;
        pthread_exit((void *) 0);
    }
    
    int main()
    {
        pthread_t thread6;
        struct  sched_param  param;
        
        
        if ((fkbd = open (kbdin, O_RDONLY)) == -1){
            printf ("Fehler mit Tastatur");
        }
      
       
    
        if(pthread_create(&thread6, NULL, thread6Go, NULL) != 0)
        {
          fprintf(stderr, "Fehler bei Tastatur......\n");
          exit(0);
        }     
       
        param.sched_priority = 20;
        pthread_setschedparam(thread6, SCHED_RR, &param);
       
        beenden=1;
       
        while (beenden > 0)
            {     sleep(1);
                zeit++;
                if (zeit==30)
                {
                    zeit=0;
                    printf("Wieder 30 Sekunden um.\n");
                }
        }
        usleep(50);
        printf("***********Ende************\n");
        return 0;
    }
    Geändert von HaWe (07.04.2016 um 08:52 Uhr)

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Antworten: 10
    Letzter Beitrag: 01.11.2017, 12:53
  2. Neue Atmega "A" und "PA" Typen
    Von AVR168 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 07.05.2012, 16:47
  3. Antworten: 2
    Letzter Beitrag: 15.06.2011, 21:18
  4. "Lichtverfolgung" in "TV-Remote" einbaue
    Von fabqu im Forum Robby RP6
    Antworten: 3
    Letzter Beitrag: 04.01.2011, 10:14
  5. "Soft-Reset?" und "Finger-Interrupt?"
    Von trapperjohn im Forum Asuro
    Antworten: 8
    Letzter Beitrag: 10.06.2008, 23:02

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress