He intentado hacer un parche adecuado para este error. Es un problema del kernel más que del teclado, aunque se podría argumentar que el teclado se comporta de forma extraña. De todos modos, el parche se envía a la lista de entrada de Linux para su revisión, pero aún no hay comentarios al respecto.
Esto debería solucionar el problema mencionado aquí con el QPAD MK-85, pero el mismo problema existe con Corsair K70, Gigabyte Osmium y otros teclados similares. Si tiene un teclado que tiene el error, sería genial que pueda probar el parche. Si lo prueba, avíseme si funciona y también qué teclado tiene, también es importante qué versión de idioma está usando, los teclados estadounidenses y no estadounidenses se comportarán de manera diferente. Tenga en cuenta que la tecla de barra invertida en los teclados de EE. UU. tendrá otras etiquetas en otras versiones del teclado.
Aquí está el correo de linux-input con el parche:
http://article.gmane.org/gmane.linux.kernel.input/37583
Muy bien, logré armar un truco que resuelve el problema. Lo escribiré aquí en caso de que alguien tropiece con el mismo problema.
En primer lugar, si no está interesado en modificar el código fuente del kernel, es posible que tenga otra opción:http://kbd-mangler.sourceforge.net/ - No lo probé, pero la descripción parece bastante prometedora. Le permite ajustar la entrada antes de que se pase al sistema.
Mi solución fue editar el archivo drivers/hid/hid-input.c. Al principio del archivo agregué tres nuevas definiciones 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
Encuentra la función
void hidinput_hid_event
En la parte inferior de esta función está
input_event(input, usage->type, usage->code, value);
La entrada es el controlador, el tipo se refiere al tipo de evento (1 es presionar una tecla... ¿2 es mover el mouse?), el código es el código de tecla y el valor es 0 para presionar y 1 para presionar.
Con cualquier pulsación de tecla, el sistema HID recorre 4 veces todas las teclas del teclado. ¿Por qué lo hace 4 veces? No lo sé, pero 4 corresponde con la cantidad de pulsaciones de teclas adicionales que obtuve con mi tecla problemática. En el primer ciclo, la tecla presionada tiene el valor 0, en el segundo el valor 1, y en el tercero y cuarto nuevamente el valor 0.
La solución fue modificar esta función para que no permitiera presionar la tecla problemática nuevamente cuando se presionan otras teclas O dentro de los 4 bucles de la tecla original. Esto se logró con el siguiente código (¿Mencioné que no he codificado C durante al menos una década? Lo siento)
/* 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 está implementando esto, es posible que desee eliminar las declaraciones de printk una vez que haya verificado que funciona según lo previsto. Solo están ahí para ayudar con la depuración.