From patchwork Tue Oct 7 17:05:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 565 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1759856832; bh=CfU92ZuDPd40ZzSNRM0wZ09S45ewO+3cELRCDcUGg54=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=HfnK1e8aIa5Ea1S1f+HGgd+ovemwuujcWMEC8d55R/1fwvVa3l3lT4tEDtzmvUmpr jdvwjbkeNLOYSmmBcnggGGknIWiMtds2JnTJOWMZeLxiwdSHX+xTYVOGERZpWgJaiv 3zwVbJgTxurh/6qF05iGy4uq7aSg/+RnHcoJxDiyye3GaNSkWUOTSPnuhXdMGFVuXU nHvUQ9CVttEOrUS7E/SO8h+vTXTQablWZoIaY1gLmD73BwJRxq2oBJ+M7uMg1J+uJ7 mbDZZuCTnhmnm7bSpUKRpvRSlcCoysapoPZTNCRvcRb63PO9ko5AUqF638qELscwJL VOk32F84Dzl9w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id D40AC67ECE for ; Tue, 7 Oct 2025 11:07:12 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id epC6RgTZg4WR for ; Tue, 7 Oct 2025 11:07:12 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1759856830; bh=CfU92ZuDPd40ZzSNRM0wZ09S45ewO+3cELRCDcUGg54=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=d7BDEiZFDj4HD+i81ERB/zzH9CtWvndouB5+gLzRDCfN0CuTZcpe0fhiYzQgeRlTD 9LVAb8VhPRGmdI/5EJn7pq6ran6Ko2eT0Fj+QBqHsYmS+8NOCuA+dQOqSAgShO16LQ y18HK7CHjVUd72/C8db4cInR2msA1l15uhhWzokExM7PgF47ZxT0Ikk4klFBNHUyZg LGK5vAx3rnjiwAbfIXzUym9GH4GgQl86iV5xIzOa0cOUJWfGn1BcRtbOfr9oPinf5v 4haJwwgzvhUzS1LdO7bwTvRQnX4KeF1X1PsZYWoQOdBKcUyVZpObQLZEjrcUhfY544 uDu468x0L5s7g== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CB60467FF9 for ; Tue, 7 Oct 2025 11:07:10 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1759856828; bh=wk7Jztn04Mo72YoNYoYaoYqv3zY1ZQowbeBwOoI8V/Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XO4N5Z1P5znW9nWtS3CRf2gVAoqTz0GACZ6j4+7zqPW3V18h1og0l2Q3sxAmrP5pK WmxsRCDw+hfLtRl6fMWiATcRuzsh/mo2wxrd4GM3ct+7GFK79ZB7SGmEIvVVD2YEAG nzEa8YfIdo+kh08+DRgsX0m9hR/b9eIdNWZhmub46hG6iBeH+BZhm/OdkOiHQ9c+lL LLJWyqQ00HOnfhtP7nK01Y5UoimDkLKfANfETne/u6QhPBtb0cbA74aMYSUHOmII0y 2txreaqwdpqn/rwVEWxccHPKWJX6movk8E+ktql2nz/vUTG/CIw3Xe/YK1IfKif+1m E/Xmo0kv73bUg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DB83967F71; Tue, 7 Oct 2025 11:07:08 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 4T78eoelDYB3; Tue, 7 Oct 2025 11:07:08 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1759856826; bh=RhCdNd/ZvvSbau5uXX4k1RpXkFHBB766fOa4bxMSA+k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T4+9zRsMLpIISy/uJP8rlAyzlydDgcndlfvQBG/Eryia8NkGBtyG60ChG4OOjowU9 OOywLRpWhSBOAUt/ZxfQo2wbymlL7i06pPc5pLO51i2WD3iqjm1RUh7xMPU20bMaIc OfxpMJ9Oos9VuA3Zm6OjRECOhEuN4B9SyWXfZtKi/oLfgf7JmbmE+uYd1Vo4+mENCt xXNpuQWGT/cBN+jsGR4cgC7U/P7jMBfeNbzZuZDYmxIQqaqLMDL7R//9kdct5SjQlD n7xPzT9sPoFYw5EI98zVvsoJF2NywyIzuevk0NNFBIqn+g5KWNI+5I0OqxnrxrxRrl o+Ms2kdbAq8JQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id E6A8767F1E; Tue, 7 Oct 2025 11:07:05 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Tue, 7 Oct 2025 11:05:33 -0600 Message-ID: <20251007170549.541981-20-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251007170549.541981-1-sjg@u-boot.org> References: <20251007170549.541981-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: ZBHQXXL2HNSQ2YPAAM3VXVGCAIMSFWUN X-Message-ID-Hash: ZBHQXXL2HNSQ2YPAAM3VXVGCAIMSFWUN X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH v2 19/20] efi: mouse: Add support for an absolute pointer List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass The absolute-pointer protocol is useful particularly with QEMU since it allows the position to be consistent between the host and the guest. Add support for this new protocol and use it in preference to the simple one, when both are available. Signed-off-by: Simon Glass --- (no changes since v1) drivers/input/efi_mouse.c | 134 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 7 deletions(-) diff --git a/drivers/input/efi_mouse.c b/drivers/input/efi_mouse.c index ced8672085c..b82a26c9885 100644 --- a/drivers/input/efi_mouse.c +++ b/drivers/input/efi_mouse.c @@ -21,8 +21,11 @@ * struct efi_mouse_priv - Private data for EFI mouse driver * * @simple: Simple pointer protocol (relative movement) + * @abs: Absolute pointer protocol (absolute position) * @simple_last: Last simple pointer state + * @abs_last: Last absolute pointer state * @has_last_state: True if we have a previous state for delta calculation + * @use_absolute: True to use absolute pointer, false for simple/relative * @x: Current X position * @y: Current Y position * @buttons: Current button state @@ -31,14 +34,64 @@ */ struct efi_mouse_priv { struct efi_simple_pointer_protocol *simple; + struct efi_absolute_pointer_protocol *abs; struct efi_simple_pointer_state simple_last; + struct efi_absolute_pointer_state abs_last; bool has_last_state; + bool use_absolute; int x, y; int buttons; int old_buttons; struct efi_event *timer_event; }; +/** + * get_abs_pointer() - Handle absolute pointer input + * + * @priv: 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, + int *rel_y, int *new_buttons) +{ + struct efi_absolute_pointer_state state; + efi_status_t ret; + + /* Debug: check structure size and alignment */ + log_debug("State struct size: %zu, address: %p\n", sizeof(state), + &state); + + ret = priv->abs->get_state(priv->abs, &state); + if (ret == EFI_NOT_READY) + return -EAGAIN; + if (ret) { + log_debug("abs: get_state failed (ret=0x%lx)\n", ret); + return -EIO; + } + + /* Always log the state values to see what we're getting */ + log_debug("abs: X=%llu Y=%llu Buttons=0x%x\n", state.current_x, + state.current_y, state.active_buttons); + + /* Calculate relative movement */ + if (priv->has_last_state) { + *rel_x = (int)(state.current_x - priv->abs_last.current_x); + *rel_y = (int)(state.current_y - priv->abs_last.current_y); + 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; + + /* Extract button state */ + *new_buttons = state.active_buttons & 0x3; /* Left and right buttons */ + + return 0; +} + /** * get_rel_pointer() - Handle relative pointer input * @@ -172,8 +225,14 @@ static int efi_mouse_get_event(struct udevice *dev, struct mouse_event *event) int rel_x, rel_y; int ret; - /* Get current pointer state */ - ret = get_rel_pointer(priv, &rel_x, &rel_y, &new_buttons); + /* + * Get current pointer state. Under QEMU, EFI pointer-events are broken + * so we poll directly + */ + if (priv->use_absolute) + ret = get_abs_pointer(priv, &rel_x, &rel_y, &new_buttons); + else + ret = get_rel_pointer(priv, &rel_x, &rel_y, &new_buttons); if (ret) return ret; @@ -202,6 +261,47 @@ static int efi_mouse_get_event(struct udevice *dev, struct mouse_event *event) return 0; } +/** + * setup_abs_pointer() - Set up absolute pointer protocol + * + * @priv: Private data + * Return: 0 if OK, -ve on error + */ +static int setup_abs_pointer(struct efi_mouse_priv *priv) +{ + struct efi_boot_services *boot = efi_get_boot(); + efi_handle_t *handles; + efi_uintn_t num_handles; + efi_status_t ret; + + ret = boot->locate_handle_buffer(BY_PROTOCOL, + &efi_guid_absolute_pointer, + NULL, &num_handles, &handles); + if (ret) + return -ENODEV; + + log_debug("Found %zu absolute pointer device(s) guid %pU\n", + num_handles, &efi_guid_absolute_pointer); + + /* Use the first absolute pointer device */ + ret = boot->open_protocol(handles[0], &efi_guid_absolute_pointer, + (void **)&priv->abs, + efi_get_parent_image(), NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret) { + log_debug("Cannot open absolute pointer protocol (ret=0x%lx)\n", + ret); + efi_free_pool(handles); + return -EIO; + } + + priv->use_absolute = true; + log_debug("Using absolute pointer protocol\n"); + efi_free_pool(handles); + + return 0; +} + /** * setup_simple_pointer() - Set up simple pointer protocol * @@ -235,6 +335,7 @@ static int setup_simple_pointer(struct efi_mouse_priv *priv) return -EIO; } + priv->use_absolute = false; log_debug("Using simple pointer protocol\n"); efi_free_pool(handles); @@ -247,13 +348,17 @@ static int efi_mouse_probe(struct udevice *dev) struct efi_boot_services *boot = efi_get_boot(); efi_status_t ret; - if (setup_simple_pointer(priv)) + /* Try absolute pointer first, then fall back to simple pointer */ + if (setup_abs_pointer(priv) && setup_simple_pointer(priv)) return -ENODEV; /* Reset the pointer device */ - ret = priv->simple->reset(priv->simple, false); - if (ret != EFI_SUCCESS) { - log_warning("Failed to reset EFI pointer device\n"); + if (priv->use_absolute) + ret = priv->abs->reset(priv->abs, true); + else + ret = priv->simple->reset(priv->simple, true); + if (ret) { + log_warning("Failed to reset device (err=0x%lx)\n", ret); /* Continue anyway - some devices might not support reset */ } @@ -275,7 +380,22 @@ static int efi_mouse_probe(struct udevice *dev) } } - log_info("EFI mouse initialized\n"); + /* Test protocol validity */ + if (priv->use_absolute && priv->abs->mode) { + struct efi_absolute_pointer_mode *mode = priv->abs->mode; + + log_debug("absolute mouse mode: x %llx-%llx y %llx-%llx\n", + mode->abs_min_x, mode->abs_max_x, + mode->abs_min_y, mode->abs_max_y); + log_debug("absolute mouse wait_for_input event: %p\n", + priv->abs->wait_for_input); + } else if (!priv->use_absolute && priv->simple) { + log_debug("simple mouse wait_for_input event: %p\n", + priv->simple->wait_for_input); + } + + log_debug("initialized (%s protocol)\n", + priv->use_absolute ? "absolute" : "simple"); return 0; }