Tudo bem, consegui montar um hack que resolve o problema. Vou escrever aqui caso alguém tropeça com o mesmo problema.
Primeiro, se você não está interessado em mexer no código fonte do kernel, você pode ter outra opção: link - I não testei, mas a descrição parece bastante promissora. Permite ajustar a entrada antes de ser passada para o sistema.
Minha solução foi editar os drivers de arquivo / hid / hid-input.c. No início do arquivo, adicionei três novas definições de variáveis;
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
Encontre a função
void hidinput_hid_event
Na parte inferior desta função está
input_event(input, usage->type, usage->code, value);
A entrada é o controlador, o tipo refere-se ao tipo de evento (1 é o pressionamento da tecla .. 2 é o movimento do mouse?), o código é o código e o valor é 0 para pressionado e 1 para pressionado.
Em qualquer tecla, o sistema HID faz um loop 4 vezes em todas as teclas do teclado. Por que ele faz isso 4 vezes eu não sei, mas 4 corresponde à quantidade extra de pressionamentos de teclas que eu obtive com a minha chave problemática. No primeiro loop, a tecla pressionada tem valor 0, no segundo valor 1, e no terceiro e quarto novamente, valor 0.
A solução foi modificar esta função para que não permitisse que a tecla problemática fosse pressionada novamente quando outras teclas fossem pressionadas OU dentro de 4 voltas do pressionamento de tecla original. Isto foi conseguido com o seguinte código (eu mencionei que não codifiquei C por pelo menos uma década? Desculpe)
/* 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 você estiver implementando isso, talvez queira remover as instruções do printk depois de verificar se está funcionando conforme o esperado. Eles estão lá apenas para ajudar na depuração.