[Concept,17/17] efi: mouse: Scale the pointer to the display

Message ID 20251006232236.2091941-18-sjg@u-boot.org
State New
Headers
Series expo: Complete mouse operation in the EFI app |

Commit Message

Simon Glass Oct. 6, 2025, 11:21 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/input/efi_mouse.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)
  

Patch

diff --git a/drivers/input/efi_mouse.c b/drivers/input/efi_mouse.c
index 53976bf9e22..e9870e119a0 100644
--- a/drivers/input/efi_mouse.c
+++ b/drivers/input/efi_mouse.c
@@ -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)