efi: mouse: Scale the pointer to the display

If a display is provided to the mouse uclass, use it to scale the coords
returned by the absolute-pointer protocol.

Series-to: concept
Series-cc: heinrich
Cover-letter:
expo: Complete mouse operation in the EFI app
This series includes various improvements which allow the mouse to be
used when running as an EFI app.

In particular:
- support for the absolute-pointer protocol, since this provides better
  integration when running under QEMU
- input tweaks to improve performance under QEMU

It also includes some x86-specific fixes for i8042 and MTRRs.

Finally, a new --bootcmd option is added to the build-qemu script to
allow passing a boot command to U-Boot.

This series is part F
END

Signed-off-by: Simon Glass <sjg@chromium.org>
Series-links: 1:48
Series-version: 2
This commit is contained in:
Simon Glass
2025-10-06 07:28:13 -06:00
parent 8ba4a7e611
commit 99479f5b7c

View File

@@ -13,6 +13,7 @@
#include <efi_api.h>
#include <log.h>
#include <mouse.h>
#include <video.h>
/* Maximum coordinate value for mouse position */
#define MOUSE_MAX_COORD 0xffff
@@ -49,12 +50,14 @@ struct efi_mouse_priv {
* get_abs_pointer() - Handle absolute pointer input
*
* @priv: Private data
* @uc_priv: Uclass-private data
* @rel_x: Returns relative X movement
* @rel_y: Returns relative Y movement
* @new_buttons: Returns button state
* Return: 0 if OK, -EAGAIN if no event, -ve on error
*/
static int get_abs_pointer(struct efi_mouse_priv *priv, int *rel_x,
static int get_abs_pointer(struct efi_mouse_priv *priv,
struct mouse_uc_priv *uc_priv, int *rel_x,
int *rel_y, int *new_buttons)
{
struct efi_absolute_pointer_state state;
@@ -83,8 +86,28 @@ static int get_abs_pointer(struct efi_mouse_priv *priv, int *rel_x,
log_debug("abs: rel_x=%d, rel_y=%d\n", *rel_x, *rel_y);
}
priv->abs_last = state;
priv->x = state.current_x;
priv->y = state.current_y;
/* Update absolute position - scale to video display if available */
if (uc_priv->video_dev && priv->abs->mode) {
struct efi_absolute_pointer_mode *mode = priv->abs->mode;
u64 x_range = mode->abs_max_x - mode->abs_min_x;
u64 y_range = mode->abs_max_y - mode->abs_min_y;
if (x_range > 0 && y_range > 0) {
log_debug("abs: unscaled x=%llx y=%llx\n",
state.current_x, state.current_y);
priv->x = ((state.current_x - mode->abs_min_x) *
uc_priv->video_width) / x_range;
priv->y = ((state.current_y - mode->abs_min_y) *
uc_priv->video_height) / y_range;
} else {
priv->x = state.current_x;
priv->y = state.current_y;
}
} else {
priv->x = state.current_x;
priv->y = state.current_y;
}
/* Extract button state */
*new_buttons = state.active_buttons & 0x3; /* Left and right buttons */
@@ -219,6 +242,7 @@ static int get_button_event(struct efi_mouse_priv *priv, int new_buttons,
static int efi_mouse_get_event(struct udevice *dev, struct mouse_event *event)
{
struct mouse_uc_priv *uc_priv = dev_get_uclass_priv(dev);
struct efi_mouse_priv *priv = dev_get_priv(dev);
struct mouse_motion *motion;
int new_buttons;
@@ -230,7 +254,8 @@ static int efi_mouse_get_event(struct udevice *dev, struct mouse_event *event)
* so we poll directly
*/
if (priv->use_absolute)
ret = get_abs_pointer(priv, &rel_x, &rel_y, &new_buttons);
ret = get_abs_pointer(priv, uc_priv, &rel_x, &rel_y,
&new_buttons);
else
ret = get_rel_pointer(priv, &rel_x, &rel_y, &new_buttons);
if (ret)