On, at least, some Chromebook PS/2 protocol is implemented by EC rather than a real PS/2 controller. It works fine except for 2 things: * Unusual layout like multimedia keys instead of F* * Reset command returns garbage (usually last key) This patch attempts to handle later as it stops keyboard from being recognized at all. It works by checking getid if reset fails. How other OSes handle the situation: * Windows: no idea, but keyboard works * Linux. Check only getid results. Reset is done but it's results are ignored. * FreeBSD. Skips probing if firmware is determined to be coreboot and assumes presence of PS/2 keyboard. This is wrong e.g. coreboot supports some MacBooks and they use USB keyboard instead. * NetBSD shares the same code as OpenBSD AFAICT. Probably broken. * Haiku was broken and recently they accepted a similar path from me. Ref: https://review.haiku-os.org/c/haiku/+/6610
commit f52874fe02379d27785a67817e40d3115b42e5f4 Author: phcoder <phco...@qemu-obsd.my.domain> Date: Sun Jul 2 01:58:30 2023 +0200
Support chromebook ps2 keyboard diff --git a/sys/dev/pckbc/pckbd.c b/sys/dev/pckbc/pckbd.c index d81fd30f1..c9378ffa3 100644 --- a/sys/dev/pckbc/pckbd.c +++ b/sys/dev/pckbc/pckbd.c @@ -324,8 +324,29 @@ pckbd_is_console(pckbc_tag_t tag, pckbc_slot_t slot) } /* - * these are both bad jokes + * these are three bad jokes */ +static int check_keyboard_by_id(struct pckbc_attach_args *pa) { + u_char cmd[1], resp[2]; + int res; + + cmd[0] = KBC_GETID; + res = pckbc_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(struct device *parent, void *match, void *aux) { @@ -360,6 +381,17 @@ pckbdprobe(struct device *parent, void *match, void *aux) * as console input - it can be connected later. */ #if defined(__i386__) || defined(__amd64__) + /* + * 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)) { + return (2); + } + /* * However, on legacy-free PCs, there might really * be no PS/2 connector at all; in that case, do not @@ -376,6 +408,11 @@ pckbdprobe(struct device *parent, void *match, void *aux) } if (resp[0] != KBR_RSTDONE) { printf("pckbdprobe: reset response 0x%x\n", resp[0]); + + if (check_keyboard_by_id(pa)) { + return (2); + } + return (0); } diff --git a/sys/dev/pckbc/pckbdreg.h b/sys/dev/pckbc/pckbdreg.h index 6848f48f8..9ab1eca98 100644 --- a/sys/dev/pckbc/pckbdreg.h +++ b/sys/dev/pckbc/pckbdreg.h @@ -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 */ #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 */