From patchwork Mon Oct 6 23:21:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 546 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=1759793029; bh=Dij1UJNZtN5XSsQTctH6OOfEycBFFfaCnxlULvvkAFc=; 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=uXHwzCRVerW+TpYKuWFDmABbpdM6k3+3bhFgyA44/JP1wUWOACU8Ez3PwJbpb0l6l sMOFFITkv8I2Jrnfl8ccospPSQHfSTYqgzjt31xvyH64tgNUPE2D1KZ2QZLDSJmdaZ uoezii+QVqTeh+Qsszo++7nL5jW9jNEEwk5lj0y+ciX/YYqByEPrRLgTWecGWEf5VQ tBPi9oT5NdacUClMpIdHRXdjbKKPaqUEqXtdcNgyo3jVoTsa5N4Sn7O/JZLUUfTgTf H1nPd8gHKoGr4oKXogr7b646W1mgp4B3+C4ufdeX58azOro3kbMnnvFlGqhhk4FMhv Z7Ke+vsrKm4Pw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id BF67C67F03 for ; Mon, 6 Oct 2025 17:23:49 -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 vpOwQ_ILcyT2 for ; Mon, 6 Oct 2025 17:23:49 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1759793028; bh=Dij1UJNZtN5XSsQTctH6OOfEycBFFfaCnxlULvvkAFc=; 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=gHKIVHAFgiS2uL7Dv3VgBO71t/EeqUYFDq8DJDfiBNDDZRSBQfQzEaCTijRSBsxKZ NRhZpN2rhwTPTkGTCyYUZsM88I8ckxFV14JA43qTOz6/Y3ESEi+e1W9a3yeN2a1x85 FjCElxukBaZ+d6MLRE97pEUnHCgJBIArN+q1QKmDwiIxy3EqJdTofyFVTsJ/WiEm0o wtXFNHHBt9HZmbAI9DKMGh5jqzlUOajmOptaaZsxGnnWi2yRTzWycGwRoFWfwt03wq WAOHQkvbWlDYDdf7eoIFwuPuxT6+65foG8Sy0fotWBUpyMZFqPVzBcnFwSfEjHZyAk i7ajRoe01bryw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B56CD67DB4 for ; Mon, 6 Oct 2025 17:23:48 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1759793027; bh=CsWMY8GgDDGgeu9PlErjEH2OV4I2ctDzzqDnFeCjmIE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nhia/k83qzQ4TAS4RFHzH1wUVPK/FokpFXaGqY4NOwOL1KLJ3DCZgMs+d5PD5ly/r 8txlKWbBYE77hYB+Ph7LPf2xu2NqdMzkq010tD5zRtRTE70A5v86QaXeG4W/42zk80 IRq24My4MwVFtit6Q5qRPIgib4JGj9zQiZjq0igBbUNg+N/Q81wpCFQG9FTw4PV0hZ S/kpxUeg5oYkqfkZDx+43ifi8AP7qPLnYHZ17Z9hkYxdy7NxjlrbiS2D9JQfp1g7PL H9vBaphm0YtFrINOrmd7oQqEy3QXQr0WQuPH7g7GfKjrwrLtzOnmfuxIyIUxxN6W7c FFhk9QB74vvHA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2182467F58; Mon, 6 Oct 2025 17:23:47 -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 pXMTGXyzMoyS; Mon, 6 Oct 2025 17:23:47 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1759793025; bh=p9dmF5P4O5H9NI9ORR6N/QT6VMtwo486LF6nlyf+vAA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vUNXOLpOpW5G9vWTLTOc8ZLbQOApj9Ol/OAPiahMFWuM5WRbYsMicR7XCvz6E6PkK EolFpgxV4r2C+b4+0CvzFlH6I7wdObHV6Xy4VBTtox3Vb0sp+P2QDSW+eCDKKbdaTk 2aRRJS6frn+X6V5nypG4rGilgsqSJal78no4wlw4f/XQWN7QuVMuSpIiLKdSjFIqh+ r/5EYl5IRdn+sN9TbS9mM9dmCl2W+5T8pU3LPrIGSyg9pvSZq09VTb5GQKmN99dphz LOyv3ciwrKd7aXyyiLyt9/y4YqNFoONnHJSmQ3szF0q2NWM92qRyTIgUZhgIdsLtuw jTr6JeajTog/A== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 4E06367AF3; Mon, 6 Oct 2025 17:23:45 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Mon, 6 Oct 2025 17:21:58 -0600 Message-ID: <20251006232236.2091941-17-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251006232236.2091941-1-sjg@u-boot.org> References: <20251006232236.2091941-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: Y5VNHXDSATVPIE3B6INFG3HJN7FQX3YI X-Message-ID-Hash: Y5VNHXDSATVPIE3B6INFG3HJN7FQX3YI 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 16/17] 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 --- 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 81c3fcb862e..53976bf9e22 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; }