Ich habe versucht, einen geeigneten Patch für diesen Fehler zu erstellen. Es ist eher ein Problem im Kernel als bei der Tastatur, obwohl argumentiert werden könnte, dass sich die Tastatur auf seltsame Weise verhält. Wie auch immer, der Patch wurde der Linux-Eingabeliste zur Überprüfung vorgelegt, aber es gibt noch keine Kommentare dazu.
Dies sollte das hier erwähnte Problem mit dem QPAD MK-85 beheben, aber das gleiche Problem besteht mit Corsair K70, Gigabyte Osmium und anderen ähnlichen Tastaturen. Wenn Sie eine Tastatur mit dem Fehler haben, wäre es großartig, wenn Sie den Patch testen könnten. Wenn Sie es testen, teilen Sie mir mit, ob es funktioniert und welche Tastatur Sie haben. Es ist auch wichtig, welche Sprachversion Sie verwenden. US- und Nicht-US-Tastaturen verhalten sich unterschiedlich. Beachten Sie, dass die Backslash-Taste auf US-Tastaturen auf anderen Versionen der Tastatur andere Beschriftungen hat.
Hier ist die Mail von linux-input mit dem Patch:
http://article.gmane.org/gmane.linux.kernel.input/37583
Okay, ich habe es geschafft, einen Hack zusammenzustellen, der das Problem löst. Ich werde es hier schreiben, falls jemand mit dem gleichen Problem stolpert.
Zunächst einmal, wenn Sie nicht daran interessiert sind, die Kernelquellen zu optimieren, haben Sie vielleicht eine andere Option:http://kbd-mangler.sourceforge.net/ - Ich habe es nicht getestet, aber die Beschreibung sieht ziemlich vielversprechend aus. Es ermöglicht Ihnen, Eingaben zu optimieren, bevor sie an das System weitergeleitet werden.
Meine Lösung bestand darin, die Datei drivers/hid/hid-input.c zu bearbeiten. Am Anfang der Datei habe ich drei neue Variablendefinitionen hinzugefügt;
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
Suchen Sie die Funktion
void hidinput_hid_event
Am Ende dieser Funktion steht
input_event(input, usage->type, usage->code, value);
Eingabe ist der Controller, Typ bezieht sich auf den Ereignistyp (1 ist Tastendruck.. 2 ist Mausbewegung?), Code ist der Tastencode und der Wert ist entweder 0 für gedrückt und 1 für gedrückt.
Bei jedem Tastendruck durchläuft das HID-System alle Tasten der Tastatur viermal. Warum es 4 Mal passiert, weiß ich nicht, aber 4 entspricht der Anzahl zusätzlicher Tastendrücke, die ich mit meiner problematischen Taste erhalten habe. Auf der ersten Schleife hat die gedrückte Taste den Wert 0, auf der zweiten den Wert 1 und auf der dritten und vierten wieder den Wert 0.
Die Lösung bestand darin, diese Funktion so zu modifizieren, dass die problematische Taste nicht erneut gedrückt werden kann, wenn andere Tasten gedrückt werden ODER innerhalb von 4 Schleifen des ursprünglichen Tastendrucks. Dies wurde durch den folgenden Code erreicht (Habe ich erwähnt, dass ich C seit mindestens einem Jahrzehnt nicht mehr codiert habe? Entschuldigung)
/* 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);
Wenn Sie dies implementieren, möchten Sie möglicherweise die printk-Anweisungen entfernen, sobald Sie überprüft haben, dass es wie beabsichtigt funktioniert. Sie sind nur da, um beim Debuggen zu helfen.