J'ai essayé de créer un correctif approprié pour ce bogue. C'est un problème dans le noyau plutôt qu'au niveau du clavier, bien que l'on puisse dire que le clavier se comporte d'une manière étrange. Quoi qu'il en soit, le correctif est soumis à la liste d'entrée Linux pour examen, mais il n'y a pas encore de commentaires à ce sujet.
Cela devrait résoudre le problème mentionné ici avec le QPAD MK-85, mais le même problème existe avec Corsair K70, Gigabyte Osmium et d'autres claviers similaires. Si vous avez un clavier qui a le bogue, ce serait bien que vous puissiez tester le patch. Si vous le testez, faites-moi savoir si cela fonctionne et aussi quel clavier vous avez, il est également important de savoir quelle version de langue vous utilisez, les claviers américains et non américains se comporteront différemment. Notez que la touche barre oblique inverse sur les claviers américains aura d'autres étiquettes sur d'autres versions du clavier.
Voici le mail de linux-input avec le patch :
http://article.gmane.org/gmane.linux.kernel.input/37583
D'accord, j'ai réussi à mettre en place un hack qui résout le problème. Je l'écrirai ici au cas où quelqu'un tomberait sur le même problème.
Tout d'abord, si vous n'êtes pas intéressé à peaufiner la source du noyau, vous pouvez avoir une autre option :http://kbd-mangler.sourceforge.net/ - Je ne l'ai pas testé, mais la description semble plutôt prometteuse. Il vous permet de modifier l'entrée avant qu'elle ne soit transmise au système.
Ma solution était d'éditer le fichier drivers/hid/hid-input.c. Au début du fichier, j'ai ajouté trois nouvelles définitions de variables ;
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
Trouver la fonction
void hidinput_hid_event
Au bas de cette fonction se trouve
input_event(input, usage->type, usage->code, value);
L'entrée est le contrôleur, le type fait référence au type d'événement (1 est une pression sur une touche.. 2 est un mouvement de la souris ?), code est le code de la touche et la valeur est soit 0 pour enfoncé et 1 pour enfoncé.
À chaque pression de touche, le système HID parcourt 4 fois toutes les touches du clavier. Pourquoi le fait-il 4 fois, je ne sais pas, mais 4 correspond au nombre d'appuis supplémentaires sur les touches que j'ai obtenus avec ma clé problématique. Sur la première boucle, la touche enfoncée a la valeur 0, sur la deuxième valeur 1, et sur les troisième et quatrième à nouveau la valeur 0.
La solution consistait à modifier cette fonction afin qu'elle ne permette pas d'appuyer à nouveau sur la touche problématique lorsque d'autres touches sont enfoncées OU dans les 4 boucles de la touche d'origine. Ceci a été réalisé par le code suivant (Ai-je mentionné que je n'avais pas codé en C depuis au moins une décennie ? Désolé)
/* 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);
Si vous implémentez cela, vous souhaiterez peut-être supprimer les instructions printk une fois que vous aurez vérifié que cela fonctionne comme prévu. Ils sont juste là pour aider au débogage.