The 8042 emulation found on Chromebooks does not support the RESET command,
authormiod <miod@openbsd.org>
Sun, 13 Aug 2023 21:54:02 +0000 (21:54 +0000)
committermiod <miod@openbsd.org>
Sun, 13 Aug 2023 21:54:02 +0000 (21:54 +0000)
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.

sys/dev/pckbc/pckbd.c
sys/dev/pckbc/pckbdreg.h

index 71ccf51..50d523f 100644 (file)
@@ -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.
index 6848f48..7acd4eb 100644 (file)
@@ -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 */