GNU/Linux >> Linux Esercitazione >  >> Linux

Un singolo tasto sulla tastiera produce ulteriori pressioni di tasti per ogni tasto premuto contemporaneamente

Ho provato a creare una patch adeguata per questo bug. È un problema nel kernel piuttosto che con la tastiera, anche se si potrebbe sostenere che la tastiera si comporti in modo strano. Ad ogni modo, la patch è stata inviata alla linux-input list per la revisione ma non ci sono ancora commenti su di essa.

Questo dovrebbe risolvere il problema menzionato qui con il QPAD MK-85, ma lo stesso problema esiste con Corsair K70, Gigabyte Osmium e altre tastiere simili. Se hai una tastiera che ha il bug, sarebbe fantastico che tu possa testare la patch. Se lo provi fammi sapere se funziona e anche che tastiera hai, è anche importante quale versione della lingua stai usando, le tastiere statunitensi e non statunitensi si comporteranno in modo diverso. Tieni presente che il tasto barra rovesciata sulle tastiere statunitensi avrà altre etichette su altre versioni della tastiera.

Ecco la mail da linux-input con la patch:

http://article.gmane.org/gmane.linux.kernel.input/37583


Bene, sono riuscito a mettere insieme un hack che risolve il problema. Lo scriverò qui nel caso in cui qualcuno si imbatta nello stesso problema.

Prima di tutto, se non sei interessato a modificare i sorgenti del kernel, potresti avere un'altra opzione:http://kbd-mangler.sourceforge.net/ - Non l'ho testato, ma la descrizione sembra piuttosto promettente. Ti consente di modificare l'input prima che venga passato al sistema.

La mia soluzione era modificare il file drivers/hid/hid-input.c. All'inizio del file ho aggiunto tre nuove definizioni di variabile;

static bool CODE43TRUE = 0; // If true, code43 has been pressed
static bool CODEXXTRUE = 0; // If true, any other key has been pressed
static int  CODESKIP = 0;   // Counter for skipping extra code43 events

Trova la funzione

void hidinput_hid_event

Alla fine di questa funzione c'è

input_event(input, usage->type, usage->code, value);

L'input è il controller, il tipo si riferisce al tipo di evento (1 è la pressione del tasto.. 2 è il movimento del mouse?), il codice è il codice della tastiera e il valore è 0 per premuto e 1 per premuto.

Ad ogni pressione di un tasto, il sistema HID scorre 4 volte tutti i tasti della tastiera. Perché lo fa 4 volte non lo so, ma 4 corrisponde alla quantità di pressioni di tasti extra che ho ottenuto con la mia chiave problematica. Al primo ciclo il tasto premuto ha valore 0, al secondo valore 1, e al terzo e quarto ancora valore 0.

La soluzione era modificare questa funzione in modo che non consentisse di premere nuovamente il tasto problematico quando vengono premuti altri tasti OPPURE entro 4 cicli dalla pressione del tasto originale. Ciò è stato ottenuto con il seguente codice (ho già detto che non ho codificato C per almeno un decennio? Mi dispiace)

/* report the usage code as scancode if the key status has changed */
if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
    input_event(input, EV_MSC, MSC_SCAN, usage->hid);

// NEW CODE STARTS HERE
if (usage->type == 1 && value == 1) // Keypress ahead
{
    if (usage->code == 43) { // Keypress is code 43
        if (CODE43TRUE == 0) {  // Key not yet pressed 
            CODE43TRUE = 1;
            printk(KERN_INFO "CODE43 SET TRUE\n");
        }
    else { // Key already pressed, so force value 1
        printk(KERN_INFO "CODE43 ALREADY TRUE SET VALUE 1\n");
        value = 0;
    }
}
else { // Some other key pressed, set XX true
    CODEXXTRUE = 1;
    printk(KERN_INFO "CODEXX SET TRUE\n");  
}
printk(KERN_INFO "Keypress type:%u code:%u value%d\n", (unsigned int) usage->type, (unsigned int) usage->code, (int) value);
}

if (usage->type == 1 && value == 0) { // Non-pressed key ahead
    if (usage->code == 43) { // If its a 43
        printk(KERN_INFO "43 call..\n");
        if (CODE43TRUE == 1) { // And 43 is fake pressed still
            if (CODEXXTRUE == 1 || CODESKIP < 4) { // If other buttons are pressed OR we are less than 5 ticks into the press..
                printk(KERN_INFO "FAKE PRESS 43. CODESKIP %d\n",CODESKIP);
                value = 0;
                CODESKIP ++;
            }
            else { // No other buttons pressed and over five ticks have passed
                printk(KERN_INFO "43 RELEASED\n");
                CODE43TRUE = 0;
                CODESKIP = 0;   
            }
        }
        // Reset the CODEXXTRUE (next time we get info about 43, we have looped through all the other keys so we know if something is pressed)
        CODEXXTRUE = 0;
    }   
}

// NEW CODE ENDS HERE
input_event(input, usage->type, usage->code, value);

Se lo stai implementando, potresti voler rimuovere le istruzioni printk dopo aver verificato che funziona come previsto. Sono lì solo per aiutare il debug.


Linux
  1. 3 modi per configurare SSH per la privacy

  2. Rileva se il tasto viene premuto dallo script?

  3. Ssh Mappa chiave pubblica-privata per il cliente?

  4. Equivalente/Alternativo per Alt+Punto in Mac

  5. Impostazione pipefail per un singolo comando con pipe

Come cercare strumenti di hacking extra su Kali

Rimappa i tasti della tastiera personalizzati in Linux - Tutorial

Usare "${a:-b}" per l'assegnazione di variabili negli script?

Il cloud hosting è una chiave scheletro IT per gli sviluppatori

Foglio grafico di Firefox per le scorciatoie da tastiera

Autorizzazioni per la chiave SSL?