libpayload/keyboard: Revise keyboard_cmd() error handling
Even if we are careful, it's still possible that we read spurious data from the keyboard, e.g. keystrokes. Namely, when we send the reset/disable command, there is a race before the command is pro- cessed. So we should always process data from the keyboard in a loop. We break it, when an ACK (0xfa) or a NAK (0xfe) is received, and warn on unexpected data unless it might be due to the mentioned race. This also gives us the opportunity to use command-specific timeouts which we take from Linux: 1s for the keyboard self-test (as there are keyboards that perform the test before acking the command) and 200ms for all other commands. Change-Id: I60a2643a8ff4b9231c63bf970c8749c97c7d8926 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/c/coreboot/+/47083 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
f651022df3
commit
a160d93dda
|
@ -28,6 +28,7 @@
|
|||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <keycodes.h>
|
||||
#include <libpayload-config.h>
|
||||
|
@ -173,9 +174,33 @@ static struct layout_maps keyboard_layouts[] = {
|
|||
|
||||
static bool keyboard_cmd(unsigned char cmd)
|
||||
{
|
||||
const uint64_t timeout_us = cmd == I8042_KBCMD_RESET ? 1*1000*1000 : 200*1000;
|
||||
const uint64_t start_time = timer_us(0);
|
||||
|
||||
i8042_write_data(cmd);
|
||||
|
||||
return i8042_wait_read_ps2() == 0xfa;
|
||||
do {
|
||||
if (!i8042_data_ready_ps2()) {
|
||||
udelay(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint8_t data = i8042_read_data_ps2();
|
||||
switch (data) {
|
||||
case 0xfa:
|
||||
return true;
|
||||
case 0xfe:
|
||||
return false;
|
||||
default:
|
||||
/* Warn only if we already disabled keyboard input. */
|
||||
if (cmd != I8042_KBCMD_DEFAULT_DIS)
|
||||
printf("WARNING: Keyboard sent spurious 0x%02x.\n", data);
|
||||
break;
|
||||
}
|
||||
} while (timer_us(start_time) < timeout_us);
|
||||
|
||||
printf("ERROR: Keyboard command timed out.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool keyboard_havechar(void)
|
||||
|
|
Loading…
Reference in New Issue