diff --git a/repos/os/src/drivers/input/spec/ps2/x86/i8042.h b/repos/os/src/drivers/input/spec/ps2/x86/i8042.h index 5ed7196db5..155912093e 100644 --- a/repos/os/src/drivers/input/spec/ps2/x86/i8042.h +++ b/repos/os/src/drivers/input/spec/ps2/x86/i8042.h @@ -75,11 +75,17 @@ class I8042 enum Return { + RET_INVALID = 0x23, /* arbitrary value */ RET_TEST_OK = 0x55, RET_KBD_TEST_OK = 0x00, RET_AUX_TEST_OK = 0x00, }; + /* + * Maximal number of attempts to read from port + */ + enum { MAX_ATTEMPTS = 4096 }; + class _Channel : public Serial_interface, public Genode::Ring_buffer { @@ -115,8 +121,21 @@ class I8042 unsigned char read() { - while (empty()) + unsigned attempts = MAX_ATTEMPTS; + while (empty() && attempts > 0) { flush_read(); + attempts--; + } + + /* + * We can savely return zero at this point because it only + * matters while the driver is initializing (see various reset() + * functions). + */ + if (attempts == 0) { + PERR("Failed to read from port"); + return 0; + } return get(); } @@ -184,7 +203,16 @@ class I8042 */ unsigned char _wait_data() { - while (!_output_buffer_full()); + unsigned attempts = MAX_ATTEMPTS; + + while (!_output_buffer_full() && attempts > 0) + attempts--; + + if (attempts == 0) { + PERR("No data available"); + return RET_INVALID; + } + return _data(); }