[coreboot-gerrit] Change in coreboot[master]: libpayload-x86: Add PS2 mouse driver

Philipp Deppenwiese (Code Review) gerrit at coreboot.org
Tue May 15 14:02:36 CEST 2018


Philipp Deppenwiese has submitted this change and it was merged. ( https://review.coreboot.org/18597 )

Change subject: libpayload-x86: Add PS2 mouse driver
......................................................................

libpayload-x86: Add PS2 mouse driver

Make use of i8042 driver to add PS2 mouse driver support.

Tested on Lenovot T500.
The touchpad can be used to drive the mouse cursor.

Change-Id: I4be9c74467596b94d64dfa510824d8722108fe9c
Signed-off-by: Patrick Rudolph <siro at das-labor.org>
Reviewed-on: https://review.coreboot.org/18597
Tested-by: build bot (Jenkins) <no-reply at coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi at google.com>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki at gmail.com>
---
M payloads/libpayload/Kconfig
M payloads/libpayload/drivers/Makefile.inc
A payloads/libpayload/drivers/i8042/mouse.c
M payloads/libpayload/drivers/mouse_cursor.c
M payloads/libpayload/include/libpayload.h
5 files changed, 314 insertions(+), 2 deletions(-)

Approvals:
  build bot (Jenkins): Verified
  Patrick Georgi: Looks good to me, approved
  Philipp Deppenwiese: Looks good to me, approved



diff --git a/payloads/libpayload/Kconfig b/payloads/libpayload/Kconfig
index d4d76bb..e482e93 100644
--- a/payloads/libpayload/Kconfig
+++ b/payloads/libpayload/Kconfig
@@ -331,11 +331,18 @@
 
 config PC_I8042
 	bool "A common PC i8042 driver"
-	default y if PC_KEYBOARD
+	default y if PC_KEYBOARD || PC_MOUSE
 	default n
 	help
 	  To be used by PC_KEYBOARD and PC_MOUSE.
 
+config PC_MOUSE
+	bool "Allow input from a PC mouse"
+	default y if ARCH_X86 # uses IO
+	default n
+	help
+	  PS/2 mouse driver on top of PC_I8042.
+
 config PC_KEYBOARD
 	bool "Allow input from a PC keyboard"
 	default y if ARCH_X86 # uses IO
@@ -367,6 +374,7 @@
 
 config MOUSE_CURSOR
 	bool "Support for mouse cursor handling"
+	default y if PC_MOUSE
 	default n
 	help
 	  Provides a common interface for various mouse cursor drivers.
diff --git a/payloads/libpayload/drivers/Makefile.inc b/payloads/libpayload/drivers/Makefile.inc
index 6eb9f0c..2d70856 100644
--- a/payloads/libpayload/drivers/Makefile.inc
+++ b/payloads/libpayload/drivers/Makefile.inc
@@ -39,6 +39,7 @@
 libc-$(CONFIG_LP_IPQ40XX_SERIAL_CONSOLE) += serial/ipq40xx.c serial/serial.c
 libc-$(CONFIG_LP_BG4CD_SERIAL_CONSOLE) += serial/bg4cd.c serial/serial.c
 libc-$(CONFIG_LP_PC_KEYBOARD) += i8042/keyboard.c
+libc-$(CONFIG_LP_PC_MOUSE) += i8042/mouse.c
 libc-$(CONFIG_LP_PC_I8042) += i8042/i8042.c
 
 libc-$(CONFIG_LP_CBMEM_CONSOLE) += cbmem_console.c
diff --git a/payloads/libpayload/drivers/i8042/mouse.c b/payloads/libpayload/drivers/i8042/mouse.c
new file mode 100644
index 0000000..21096d1
--- /dev/null
+++ b/payloads/libpayload/drivers/i8042/mouse.c
@@ -0,0 +1,292 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2017 Patrick Rudolph <siro at das-labor.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libpayload-config.h>
+#include <libpayload.h>
+
+static int x_axis;
+static int y_axis;
+static int z_axis;
+static u32 buttons;
+static u8 is_intellimouse;
+static u8 is_explorer_intellimouse;
+static u8 initialized;
+static unsigned char mouse_buf[4];
+static unsigned char mouse_buf_idx;
+
+static u8 mouse_cmd(unsigned char cmd)
+{
+	i8042_cmd(0xd4);
+
+	i8042_write_data(cmd);
+
+	return i8042_wait_read_aux() == 0xfa;
+}
+
+static u8 mouse_cmd_data(u8 cmd, u8 val)
+{
+	if (!mouse_cmd(cmd))
+		return 0;
+
+	return mouse_cmd(val);
+}
+
+/** Try to detect Microsoft Intelli mouse */
+static u8 mouse_is_intellimouse(void)
+{
+	/* Silence mouse. */
+	if (!mouse_cmd(0xf5))
+		return 0;
+
+	/* Set standard. */
+	if (!mouse_cmd(0xf6))
+		return 0;
+
+	/* Magic sequence. */
+	if (!mouse_cmd_data(0xf3, 0xc8))
+		return 0;
+	if (!mouse_cmd_data(0xf3, 0x64))
+		return 0;
+	if (!mouse_cmd_data(0xf3, 0x50))
+		return 0;
+
+	/* Get mouse id */
+	if (!mouse_cmd(0xf2))
+		return 0;
+
+	if (i8042_wait_read_aux() != 0x03)
+		return 0;
+
+	return 1;
+}
+
+/** Try to detect Microsoft Explorer mouse */
+static u8 mouse_is_intellimouse_explorer(void)
+{
+	/* Silence mouse. */
+	if (!mouse_cmd(0xf5))
+		return 0;
+
+	/* Set standard. */
+	if (!mouse_cmd(0xf6))
+		return 0;
+
+	/* Magic sequence. */
+	if (!mouse_cmd_data(0xf3, 0xc8))
+		return 0;
+	if (!mouse_cmd_data(0xf3, 0xc8))
+		return 0;
+	if (!mouse_cmd_data(0xf3, 0x50))
+		return 0;
+
+	/* Get mouse id */
+	if (!mouse_cmd(0xf2))
+		return 0;
+
+	if (i8042_wait_read_aux() != 4)
+		return 0;
+
+	return 1;
+}
+
+/** Decode temporary buffer
+ * Sanity check to prevent out of order decode.
+ * Decode PS/2 data.
+ * Supported devices:
+ *  Generic 3 button mouse
+ *  Microsoft Intelli mouse
+ *  Microsoft Explorer mouse
+ */
+static void mouse_decode(void)
+{
+	/* Buffer full check and sanity check */
+	if (is_intellimouse) {
+		if (mouse_buf_idx < 4)
+			return;
+		if ((mouse_buf[3] & 0x10) != (mouse_buf[3] & 0x08)) {
+			mouse_buf_idx = 0;
+			return;
+		}
+	} else if (is_explorer_intellimouse) {
+		if (mouse_buf_idx < 4)
+			return;
+		if (mouse_buf[3] & 0xc0) {
+			mouse_buf_idx = 0;
+			return;
+		}
+	} else {
+		if (mouse_buf_idx < 3)
+			return;
+	}
+
+	/* Common protocol */
+	x_axis += mouse_buf[1] ? mouse_buf[1] - ((mouse_buf[0] << 4) & 0x100) : 0;
+	y_axis += mouse_buf[2] ? ((mouse_buf[0] << 3) & 0x100) - mouse_buf[2] : 0;
+	buttons = mouse_buf[0] & 0x7;
+
+	/* Extended protocol */
+	if (is_intellimouse) {
+		z_axis += (mouse_buf[3] & 0x7) - (mouse_buf[3] & 0x08) ? 8 : 0;
+	} else if (is_explorer_intellimouse) {
+		z_axis += (mouse_buf[3] & 0x7) - (mouse_buf[3] & 0x08) ? 8 : 0;
+		buttons = (mouse_buf[0] & 0x7) | (mouse_buf[3] & 0x30) >> 1;
+	}
+
+	mouse_buf_idx = 0;
+}
+
+/** Insert data into internal temporary buffer. */
+static void insert_buf(unsigned char c)
+{
+	/* Validate input:
+	 * First byte shall have bit 3 set ! */
+	if (!mouse_buf_idx && !(c & 8))
+		return;
+
+	mouse_buf[mouse_buf_idx++] = c;
+}
+
+/** Probe i8042 for new aux data and try to decode it. */
+static void mouse_sample(void)
+{
+	if (!initialized)
+		return;
+
+	while (i8042_data_ready_aux()) {
+		insert_buf(i8042_read_data_aux());
+		mouse_decode();
+	}
+}
+
+/** Mouse cursor interface method
+ * Return and reset internal state.
+ */
+static void mouse_state(int *x, int *y, int *z, u32 *b)
+{
+	if (!initialized)
+		return;
+
+	mouse_sample();
+
+	if (x) {
+		*x = x_axis;
+		x_axis = 0;
+	}
+	if (y) {
+		*y = y_axis;
+		y_axis = 0;
+	}
+	if (z) {
+		*z = z_axis;
+		z_axis = 0;
+	}
+	if (b)
+		*b = buttons;
+}
+
+static struct mouse_cursor_input_driver curs = {
+	.get_state = mouse_state,
+	.input_type = CURSOR_INPUT_TYPE_PS2,
+};
+
+/** Probe for PS/2 mouse */
+void i8042_mouse_init(void)
+{
+	int ret;
+
+	/**
+	 * Initialize keyboard controller.
+	 * Might fail in case no AUX port or firmware disabled the AUX port.
+	 */
+	if (!i8042_probe() || !i8042_has_aux())
+		return;
+
+	/* Empty mouse buffer. */
+	while (i8042_data_ready_aux())
+		i8042_read_data_aux();
+
+	/* Enable mouse.
+	 * Documentation is unclear at this point.
+	 * Some recommend to wait for response, some claim there's none.
+	 * No response on Lenovo H8 EC.
+	 * Ignore it ... */
+	ret = i8042_cmd(0xa8);
+	if (ret == -1)
+		return;
+
+	/* Silence mouse. */
+	if (!mouse_cmd(0xf5))
+		return;
+
+	/* Read mouse id. */
+	if (!mouse_cmd(0xf2))
+		return;
+
+	ret = i8042_wait_read_aux();
+	if (ret)
+		return;
+
+	/* Get and enable features (scroll wheel and 5 buttons) */
+	is_intellimouse = mouse_is_intellimouse();
+	is_explorer_intellimouse = mouse_is_intellimouse_explorer();
+
+	/* Set defaults. */
+	if (!mouse_cmd(0xf6))
+		return;
+
+	/* Enable data transmission. */
+	if (!mouse_cmd(0xf4))
+		return;
+
+	initialized = 1;
+
+	/* Register mouse cursor driver */
+	mouse_cursor_add_input_driver(&curs);
+}
+
+/* Disable PS/2 mouse. */
+void i8042_mouse_disconnect(void)
+{
+	/* If 0x64 returns 0xff, then we have no keyboard
+	 * controller */
+	if (inb(0x64) == 0xFF || !initialized)
+		return;
+
+	/* Empty keyboard buffer */
+	while (i8042_data_ready_aux())
+		i8042_read_data_aux();
+
+	/* Disable mouse. */
+	i8042_cmd(0xa7);
+
+	initialized = 0;
+
+	/* Release keyboard controller driver */
+	i8042_close();
+}
diff --git a/payloads/libpayload/drivers/mouse_cursor.c b/payloads/libpayload/drivers/mouse_cursor.c
index 781845c..40c8934 100644
--- a/payloads/libpayload/drivers/mouse_cursor.c
+++ b/payloads/libpayload/drivers/mouse_cursor.c
@@ -60,7 +60,9 @@
 /** Init enabled mouse cursor drivers */
 void mouse_cursor_init(void)
 {
-/* FIXME */
+#if IS_ENABLED(CONFIG_LP_PC_MOUSE)
+	i8042_mouse_init();
+#endif
 }
 
 static u32 mouse_buttons;
diff --git a/payloads/libpayload/include/libpayload.h b/payloads/libpayload/include/libpayload.h
index 96cc5f8..c6b9447 100644
--- a/payloads/libpayload/include/libpayload.h
+++ b/payloads/libpayload/include/libpayload.h
@@ -204,6 +204,15 @@
 /** @} */
 
 /**
+ * @defgroup i8042 PS2 Mouse functions
+ * @ingroup input
+ * @{
+ */
+void i8042_mouse_init(void);
+void i8042_mouse_disconnect(void);
+/** @} */
+
+/**
  * @defgroup serial Serial functions
  * @ingroup input
  * @{

-- 
To view, visit https://review.coreboot.org/18597
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I4be9c74467596b94d64dfa510824d8722108fe9c
Gerrit-Change-Number: 18597
Gerrit-PatchSet: 8
Gerrit-Owner: Patrick Rudolph <siro at das-labor.org>
Gerrit-Reviewer: Julius Werner <jwerner at chromium.org>
Gerrit-Reviewer: Martin Roth <martinroth at google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi at google.com>
Gerrit-Reviewer: Patrick Rudolph <patrick.rudolph at 9elements.com>
Gerrit-Reviewer: Patrick Rudolph <siro at das-labor.org>
Gerrit-Reviewer: Paul Menzel <paulepanter at users.sourceforge.net>
Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki at gmail.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply at coreboot.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180515/3847cab5/attachment.html>


More information about the coreboot-gerrit mailing list