
From: Simon Glass <sjg@chromium.org> The EFI serial driver checks for keypresses but does not allow other events to be processed. For devices which have a USB keyboard, the USB message must be processed before any keys can emerge for the serial driver to pick up. Add a periodic timer to the list of events. This allows the keyboard to work on Qualcomm laptops, for example. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/serial/serial_efi.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c index 5733eaaf9d4..461c23e6cbc 100644 --- a/drivers/serial/serial_efi.c +++ b/drivers/serial/serial_efi.c @@ -19,7 +19,9 @@ struct serial_efi_priv { struct efi_simple_text_input_protocol *con_in; struct efi_simple_text_output_protocol *con_out; + struct efi_boot_services *boot; struct efi_input_key key; + struct efi_event *timer; bool have_key; }; @@ -33,10 +35,22 @@ int serial_efi_setbrg(struct udevice *dev, int baudrate) static int serial_efi_get_key(struct serial_efi_priv *priv) { - int ret; + struct efi_simple_text_input_protocol *cin = priv->con_in; + struct efi_event *events[2] = {cin->wait_for_key, priv->timer}; + efi_uintn_t index; + efi_status_t ret; if (priv->have_key) return 0; + + ret = priv->boot->wait_for_event(2, events, &index); + if (ret) { + log_err("wait_for_event() failed\n"); + return -EAGAIN; + } + if (index) + return -EAGAIN; + ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key); if (ret == EFI_NOT_READY) return -EAGAIN; @@ -133,9 +147,22 @@ static int serial_efi_probe(struct udevice *dev) { struct efi_system_table *table = efi_get_sys_table(); struct serial_efi_priv *priv = dev_get_priv(dev); + struct efi_boot_services *boot = efi_get_boot(); + efi_status_t ret; priv->con_in = table->con_in; priv->con_out = table->con_out; + priv->con_in->reset(priv->con_in, true); + priv->boot = boot; + + ret = boot->create_event(EVT_TIMER, TPL_APPLICATION, NULL, NULL, + &priv->timer); + if (ret) + return -ECOMM; + ret = boot->set_timer(priv->timer, EFI_TIMER_PERIODIC, + 1000 * 1000 / 100 /* 1ms in 100ns units */); + if (ret) + return -ECOMM; return 0; } -- 2.43.0