summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2023-08-13 21:54:03 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2023-08-13 21:54:03 +0000
commit3b436d19a3102c59581652341324dc311adf6d51 (patch)
treea6c5573a867b752c47cba4d73a6dc04544337b7b
parent6dcc1dc9608e156057d20730b30158371388a251 (diff)
The 8042 emulation found on Chromebooks does not support the RESET command,
for no good reason, and causes pckbc not to attach. However, sending a `get keyboard id' works, so this can be used as a second check to give those fawlty pieces of hardware a chance to work. Based on a diff submitted by, and tested by, Vladimir 'phcoder' Serbinenko.
-rw-r--r--sys/dev/pckbc/pckbd.c40
-rw-r--r--sys/dev/pckbc/pckbdreg.h3
2 files changed, 35 insertions, 8 deletions
diff --git a/sys/dev/pckbc/pckbd.c b/sys/dev/pckbc/pckbd.c
index 71ccf514758..50d523f395a 100644
--- a/sys/dev/pckbc/pckbd.c
+++ b/sys/dev/pckbc/pckbd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pckbd.c,v 1.50 2023/07/25 10:00:44 miod Exp $ */
+/* $OpenBSD: pckbd.c,v 1.51 2023/08/13 21:54:02 miod Exp $ */
/* $NetBSD: pckbd.c,v 1.24 2000/06/05 22:20:57 sommerfeld Exp $ */
/*-
@@ -344,7 +344,7 @@ pckbdprobe(struct device *parent, void *match, void *aux)
{
struct cfdata *cf = match;
struct pckbc_attach_args *pa = aux;
- u_char cmd[1], resp[1];
+ u_char cmd[1], resp[2];
int res;
/*
@@ -363,10 +363,40 @@ pckbdprobe(struct device *parent, void *match, void *aux)
/* Reset the keyboard. */
cmd[0] = KBC_RESET;
res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
- if (res) {
+ if (res != 0) {
#ifdef DEBUG
printf("pckbdprobe: reset error %d\n", res);
#endif
+ } else if (resp[0] != KBR_RSTDONE) {
+#ifdef DEBUG
+ printf("pckbdprobe: reset response 0x%x\n", resp[0]);
+#endif
+ res = EINVAL;
+ }
+#if defined(__i386__) || defined(__amd64__)
+ if (res) {
+ /*
+ * The 8042 emulation on Chromebooks fails the reset
+ * command but otherwise appears to work correctly.
+ * Try a "get ID" command to give it a second chance.
+ */
+ cmd[0] = KBC_GETID;
+ res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot,
+ cmd, 1, 2, resp, 0);
+ if (res != 0) {
+#ifdef DEBUG
+ printf("pckbdprobe: getid error %d\n", res);
+#endif
+ } else if (resp[0] != 0xab || resp[1] != 0x83) {
+#ifdef DEBUG
+ printf("pckbdprobe: unexpected id 0x%x/0x%x\n",
+ resp[0], resp[1]);
+#endif
+ res = EINVAL;
+ }
+ }
+#endif
+ if (res) {
/*
* There is probably no keyboard connected.
* Let the probe succeed if the keyboard is used
@@ -387,10 +417,6 @@ pckbdprobe(struct device *parent, void *match, void *aux)
#endif
return (pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0);
}
- if (resp[0] != KBR_RSTDONE) {
- printf("pckbdprobe: reset response 0x%x\n", resp[0]);
- return (0);
- }
/*
* Some keyboards seem to leave a second ack byte after the reset.
diff --git a/sys/dev/pckbc/pckbdreg.h b/sys/dev/pckbc/pckbdreg.h
index 6848f48f817..7acd4eb1703 100644
--- a/sys/dev/pckbc/pckbdreg.h
+++ b/sys/dev/pckbc/pckbdreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pckbdreg.h,v 1.2 2003/10/22 09:44:22 jmc Exp $ */
+/* $OpenBSD: pckbdreg.h,v 1.3 2023/08/13 21:54:02 miod Exp $ */
/* $NetBSD: pckbdreg.h,v 1.2 1998/04/07 13:43:16 hannken Exp $ */
/*
@@ -12,6 +12,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 (not supported on AT kbd) */
#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 */