[Concept,09/17] sandbox: Provide a test for the mouse uclass

Message ID 20250915104705.937780-9-sjg@u-boot.org
State New
Headers
Series mouse: Provide some support for using a mouse |

Commit Message

Simon Glass Sept. 15, 2025, 10:46 a.m. UTC
  From: Simon Glass <sjg@chromium.org>

Provide a few simple tests for two methods available in the mouse
uclass.

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

 arch/sandbox/include/asm/test.h | 17 ++++++
 drivers/input/sandbox_mouse.c   | 49 +++++++++++++++++
 test/dm/Makefile                |  1 +
 test/dm/mouse.c                 | 96 +++++++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+)
 create mode 100644 test/dm/mouse.c
  

Patch

diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 4df39fac1da..499db42804c 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -11,6 +11,7 @@ 
 #include <pci_ids.h>
 
 struct unit_test_state;
+struct mouse_event;
 
 /* The sandbox driver always permits an I2C device with this address */
 #define SANDBOX_I2C_TEST_ADDR		0x59
@@ -361,4 +362,20 @@  bool sandbox_sf_bootdev_enabled(void);
  */
 void sandbox_sf_set_enable_bootdevs(bool enable);
 
+/**
+ * sandbox_mouse_set_test_mode() - Enable/disable test mode for sandbox mouse
+ *
+ * @dev: Mouse device
+ * @test_mode: true to enable test mode, false to use SDL
+ */
+void sandbox_mouse_set_test_mode(struct udevice *dev, bool test_mode);
+
+/**
+ * sandbox_mouse_inject() - Inject a mouse event for testing
+ *
+ * @dev: Mouse device (must be in test mode)
+ * @event: Event to inject
+ */
+void sandbox_mouse_inject(struct udevice *dev, struct mouse_event *event);
+
 #endif
diff --git a/drivers/input/sandbox_mouse.c b/drivers/input/sandbox_mouse.c
index 4aedf0fdf2d..ba271242b1a 100644
--- a/drivers/input/sandbox_mouse.c
+++ b/drivers/input/sandbox_mouse.c
@@ -8,11 +8,29 @@ 
 #include <mouse.h>
 #include <asm/sdl.h>
 
+struct sandbox_mouse_priv {
+	bool test_mode;
+	struct mouse_event test_event;
+	bool test_event_pending;
+};
+
 static int mouse_sandbox_get_event(struct udevice *dev,
 				   struct mouse_event *event)
 {
+	struct sandbox_mouse_priv *priv = dev_get_priv(dev);
 	int ret;
 
+	/* If in test mode, return test event if pending */
+	if (priv->test_mode) {
+		if (priv->test_event_pending) {
+			*event = priv->test_event;
+			priv->test_event_pending = false;
+			return 0;
+		} else {
+			return -EAGAIN;
+		}
+	}
+
 	ret = sandbox_sdl_get_mouse_event(event);
 
 	return ret;
@@ -27,9 +45,40 @@  static const struct udevice_id mouse_sandbox_ids[] = {
 	{ }
 };
 
+/**
+ * sandbox_mouse_set_test_mode() - Enable/disable test mode
+ *
+ * @dev: Mouse device
+ * @test_mode: true to enable test mode, false to use SDL
+ */
+void sandbox_mouse_set_test_mode(struct udevice *dev, bool test_mode)
+{
+	struct sandbox_mouse_priv *priv = dev_get_priv(dev);
+
+	priv->test_mode = test_mode;
+	priv->test_event_pending = false;
+}
+
+/**
+ * sandbox_mouse_inject() - Inject a mouse event for testing
+ *
+ * @dev: Mouse device (must be in test mode)
+ * @event: Event to inject
+ */
+void sandbox_mouse_inject(struct udevice *dev, struct mouse_event *event)
+{
+	struct sandbox_mouse_priv *priv = dev_get_priv(dev);
+
+	if (priv->test_mode) {
+		priv->test_event = *event;
+		priv->test_event_pending = true;
+	}
+}
+
 U_BOOT_DRIVER(mouse_sandbox) = {
 	.name	= "mouse_sandbox",
 	.id	= UCLASS_MOUSE,
 	.of_match = mouse_sandbox_ids,
 	.ops	= &mouse_sandbox_ops,
+	.priv_auto = sizeof(struct sandbox_mouse_priv),
 };
diff --git a/test/dm/Makefile b/test/dm/Makefile
index eab78d3ac4a..b38de3e12d0 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -68,6 +68,7 @@  obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o
 obj-$(CONFIG_MEMORY) += memory.o
 obj-$(CONFIG_MISC) += misc.o
 obj-$(CONFIG_DM_MMC) += mmc.o
+obj-$(CONFIG_MOUSE) += mouse.o
 obj-$(CONFIG_CMD_MUX) += mux-cmd.o
 obj-$(CONFIG_MULTIPLEXER) += mux-emul.o
 obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
diff --git a/test/dm/mouse.c b/test/dm/mouse.c
new file mode 100644
index 00000000000..f9c2e88c43a
--- /dev/null
+++ b/test/dm/mouse.c
@@ -0,0 +1,96 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for the driver model mouse API
+ *
+ * Copyright 2025 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <dm.h>
+#include <mouse.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include <asm/test.h>
+
+static int dm_test_mouse_basic(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_MOUSE, &dev));
+
+	/* put mouse in test mode */
+	sandbox_mouse_set_test_mode(dev, true);
+
+	return 0;
+}
+DM_TEST(dm_test_mouse_basic, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
+static int dm_test_mouse_motion(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct mouse_event event, inject;
+
+	ut_assertok(uclass_first_device_err(UCLASS_MOUSE, &dev));
+
+	/* put mouse in test mode */
+	sandbox_mouse_set_test_mode(dev, true);
+
+	/* inject a motion event */
+	inject.type = MOUSE_EV_MOTION;
+	inject.motion.state = 0;
+	inject.motion.x = 100;
+	inject.motion.y = 200;
+	inject.motion.xrel = 10;
+	inject.motion.yrel = 20;
+
+	sandbox_mouse_inject(dev, &inject);
+
+	/* get and verify the event */
+	ut_assertok(mouse_get_event(dev, &event));
+	ut_asserteq(MOUSE_EV_MOTION, event.type);
+	ut_asserteq(0, event.motion.state);
+	ut_asserteq(100, event.motion.x);
+	ut_asserteq(200, event.motion.y);
+	ut_asserteq(10, event.motion.xrel);
+	ut_asserteq(20, event.motion.yrel);
+
+	/* verify no more events are pending */
+	ut_asserteq(-EAGAIN, mouse_get_event(dev, &event));
+
+	return 0;
+}
+DM_TEST(dm_test_mouse_motion, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
+static int dm_test_mouse_button(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct mouse_event event, inject;
+
+	ut_assertok(uclass_first_device_err(UCLASS_MOUSE, &dev));
+
+	/* put mouse in test mode */
+	sandbox_mouse_set_test_mode(dev, true);
+
+	/* inject a button press event */
+	inject.type = MOUSE_EV_BUTTON;
+	inject.button.button = BUTTON_LEFT;
+	inject.button.press_state = BUTTON_PRESSED;
+	inject.button.clicks = 1;
+	inject.button.x = 150;
+	inject.button.y = 250;
+
+	sandbox_mouse_inject(dev, &inject);
+
+	/* get and verify the event */
+	ut_assertok(mouse_get_event(dev, &event));
+	ut_asserteq(MOUSE_EV_BUTTON, event.type);
+	ut_asserteq(BUTTON_LEFT, event.button.button);
+	ut_asserteq(BUTTON_PRESSED, event.button.press_state);
+	ut_asserteq(1, event.button.clicks);
+	ut_asserteq(150, event.button.x);
+	ut_asserteq(250, event.button.y);
+
+	return 0;
+}
+DM_TEST(dm_test_mouse_button, UTF_SCAN_PDATA | UTF_SCAN_FDT);