tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[PATCH] Fix for PS2 on Chromebook



On at least some Chromebooks PS/2 reset command generates no response and we end up reading garbage and disabling keyboard support altogether even though that controller otherwise works fine. Linux issues reset but ignores the reply and relies on getid instead. So does Haiku. FreeBSD assumes that all coreboot systems have PS/2 which is wrong as it supports some MacBooks as well. No idea what windows does but keyboard works there.
[PATCH] pckbd fix for chromebook

---
 sys/dev/pckbport/pckbd.c    | 44 ++++++++++++++++++++++++++++++++++++-
 sys/dev/pckbport/pckbdreg.h |  1 +
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/sys/dev/pckbport/pckbd.c b/sys/dev/pckbport/pckbd.c
index 01c925ee4..829d09d10 100644
--- a/sys/dev/pckbport/pckbd.c
+++ b/sys/dev/pckbport/pckbd.c
@@ -300,8 +300,29 @@ pckbd_resume(device_t dv, const pmf_qual_t *qual)
 }
 
 /*
- * these are both bad jokes
+ * these are three bad jokes
  */
+static int check_keyboard_by_id(struct pckbport_attach_args *pa) {
+	u_char cmd[1], resp[2];
+	int res;
+
+	cmd[0] = KBC_GETID;
+	res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 0);
+	if (res) {
+		printf("getid failed with %d\n", res);
+		return (0);
+	}
+
+	if (resp[0] != 0xab && resp[0] != 0xac &&  /* Regular and NCD Sun keyboards */
+	    resp[0] != 0x2b && resp[0] != 0x5d &&  /* Trust keyboard, raw and translated */
+	    resp[0] != 0x60 && resp[0] != 0x47) { /* NMB SGI keyboard, raw and translated */
+		printf("getid returned 0x%x\n", resp[0]);
+		return (0);
+	}
+
+	return (1);
+}
+
 int
 pckbdprobe(device_t parent, cfdata_t cf, void *aux)
 {
@@ -327,6 +348,20 @@ pckbdprobe(device_t parent, cfdata_t cf, void *aux)
 	res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
 	if (res) {
 		aprint_debug("pckbdprobe: reset error %d\n", res);
+
+		/*
+		 * On Chromebooks reset fails but otherwise controller works fine.
+		 * Check keyboard IDs similar to Linux and Haiku.
+		 * FreeBSD's approach here is to skip probing if
+		 * coreboot is detected which is suboptimal as coreboot
+		 * also supports some mac models which have no PC controller
+		 */
+		if (check_keyboard_by_id(pa)) {
+			if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
+				return 0;
+			return (2);
+		}
+
 		/*
 		 * There is probably no keyboard connected.
 		 * Let the probe succeed if the keyboard is used
@@ -336,6 +371,13 @@ pckbdprobe(device_t parent, cfdata_t cf, void *aux)
 	}
 	if (resp[0] != KBR_RSTDONE) {
 		printf("pckbdprobe: reset response 0x%x\n", resp[0]);
+
+		if (check_keyboard_by_id(pa)) {
+			if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
+				return 0;
+			return (2);
+		}
+
 		return 0;
 	}
 
diff --git a/sys/dev/pckbport/pckbdreg.h b/sys/dev/pckbport/pckbdreg.h
index e848ea659..b23a2aa84 100644
--- a/sys/dev/pckbport/pckbdreg.h
+++ b/sys/dev/pckbport/pckbdreg.h
@@ -11,6 +11,7 @@
 #define	KBC_DISABLE	0xF5	/* as per KBC_SETDEFAULT, but also disable key scanning */
 #define	KBC_ENABLE	0xF4	/* enable key scanning */
 #define	KBC_TYPEMATIC	0xF3	/* set typematic rate and delay */
+#define	KBC_GETID	0xF2	/* get keyboard ID */
 #define	KBC_SETTABLE	0xF0	/* set scancode translation table */
 #define	KBC_MODEIND	0xED	/* set mode indicators (i.e. LEDs) */
 #define	KBC_ECHO	0xEE	/* request an echo from the keyboard */
-- 
2.40.1



Home | Main Index | Thread Index | Old Index