[coreboot-gerrit] New patch to review for coreboot: libpayload-x86: Add PS2 mouse driver

Patrick Rudolph (siro@das-labor.org) gerrit at coreboot.org
Mon Mar 6 18:51:55 CET 2017


Patrick Rudolph (siro at das-labor.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18597

-gerrit

commit b14b6ac06692bc8c118fa6989d5a8ec7f902a2da
Author: Patrick Rudolph <siro at das-labor.org>
Date:   Mon Feb 6 15:26:58 2017 +0100

    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>
---
 payloads/libpayload/Kconfig                |  10 +-
 payloads/libpayload/drivers/Makefile.inc   |   1 +
 payloads/libpayload/drivers/i8042/mouse.c  | 281 +++++++++++++++++++++++++++++
 payloads/libpayload/drivers/mouse_cursor.c |   6 +-
 payloads/libpayload/include/libpayload.h   |   9 +
 5 files changed, 304 insertions(+), 3 deletions(-)

diff --git a/payloads/libpayload/Kconfig b/payloads/libpayload/Kconfig
index 26f4967..a6255cc 100644
--- a/payloads/libpayload/Kconfig
+++ b/payloads/libpayload/Kconfig
@@ -315,11 +315,18 @@ config COREBOOT_VIDEO_CONSOLE
 
 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
@@ -351,6 +358,7 @@ config NVRAM
 
 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 b874efe..12ceda5 100644
--- a/payloads/libpayload/drivers/Makefile.inc
+++ b/payloads/libpayload/drivers/Makefile.inc
@@ -39,6 +39,7 @@ libc-$(CONFIG_LP_IPQ806X_SERIAL_CONSOLE) += serial/ipq806x.c serial/serial.c
 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..8da3d2c
--- /dev/null
+++ b/payloads/libpayload/drivers/i8042/mouse.c
@@ -0,0 +1,281 @@
+/*
+ * 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, 0);
+
+	i8042_write_input(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)
+{
+	/* 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;
+
+	i8042_wait_read_aux();
+
+	return 1;
+}
+
+/** Try to detect Microsoft Explorer mouse */
+static u8 mouse_is_intellimouse_explorer(void)
+{
+	/* 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;
+
+	i8042_wait_read_aux();
+
+	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_data_get_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;
+
+	/* Initialized keyboard controller. */
+	if (!i8042_probe() || !i8042_has_aux())
+		return;
+
+	/* Empty mouse buffer. */
+	while (i8042_data_ready_aux())
+		i8042_data_get_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, 0);
+	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)
+		return;
+
+	/* Empty keyboard buffer */
+	while (i8042_data_ready_aux())
+		i8042_data_get_aux();
+
+	/* Disable mouse. */
+	i8042_cmd(0xa7, 0);
+
+	initialized = 0;
+}
diff --git a/payloads/libpayload/drivers/mouse_cursor.c b/payloads/libpayload/drivers/mouse_cursor.c
index 73985ff..50220c6 100644
--- a/payloads/libpayload/drivers/mouse_cursor.c
+++ b/payloads/libpayload/drivers/mouse_cursor.c
@@ -59,7 +59,9 @@ void mouse_cursor_add_input_driver(struct mouse_cursor_input_driver *in)
 /** 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;
@@ -141,7 +143,7 @@ void mouse_cursor_get_rel(int *x, int *y, int *z)
  */
 void mouse_cursor_get_buttons(u32 *buttons)
 {
-	mouse_poll();
+	mouse_cursor_poll();
 
 	if (buttons)
 		*buttons = mouse_buttons;
diff --git a/payloads/libpayload/include/libpayload.h b/payloads/libpayload/include/libpayload.h
index a44eedd..27ec436 100644
--- a/payloads/libpayload/include/libpayload.h
+++ b/payloads/libpayload/include/libpayload.h
@@ -200,6 +200,15 @@ int i8042_wait_read_aux(void);
 /** @} */
 
 /**
+ * @defgroup i8042 PS2 Mouse functions
+ * @ingroup input
+ * @{
+ */
+void i8042_mouse_init(void);
+void i8042_mouse_disconnect(void);
+/** @} */
+
+/**
  * @defgroup serial Serial functions
  * @ingroup input
  * @{



More information about the coreboot-gerrit mailing list