Instead of always following up "power on" with a "reset", only
authortobhe <tobhe@openbsd.org>
Fri, 18 Oct 2024 12:53:49 +0000 (12:53 +0000)
committertobhe <tobhe@openbsd.org>
Fri, 18 Oct 2024 12:53:49 +0000 (12:53 +0000)
send a single reset during attach.  We have discovered that some
devices such as the built-in keyboard on the Thinkpad T14s Gen 6
don't like getting more than one reset sent or they become
unresponsive.

This has been in snaps for a while and hasn't caused any major
regressions so we are confident the extra reset is not needed on
most hardware.

feedback from kettenis@
ok deraadt@ mlarkin@

sys/dev/i2c/ihidev.c

index 4e65a4b..de0c29b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ihidev.c,v 1.32 2024/08/19 09:26:58 kettenis Exp $ */
+/* $OpenBSD: ihidev.c,v 1.33 2024/10/18 12:53:49 tobhe Exp $ */
 /*
  * HID-over-i2c driver
  *
@@ -67,6 +67,7 @@ int   ihidev_activate(struct device *, int);
 
 int    ihidev_hid_command(struct ihidev_softc *, int, void *);
 int    ihidev_intr(void *);
+int    ihidev_poweron(struct ihidev_softc *);
 int    ihidev_reset(struct ihidev_softc *);
 int    ihidev_hid_desc_parse(struct ihidev_softc *);
 
@@ -248,7 +249,7 @@ ihidev_activate(struct device *self, int act)
                            sc->sc_dev.dv_xname);
                break;
        case DVACT_WAKEUP:
-               ihidev_reset(sc);
+               ihidev_poweron(sc);
                sc->sc_dying = 0;
                if (sc->sc_poll && timeout_initialized(&sc->sc_timer))
                        timeout_add(&sc->sc_timer, 2000);
@@ -525,7 +526,7 @@ ihidev_hid_command(struct ihidev_softc *sc, int hidcmd, void *arg)
 }
 
 int
-ihidev_reset(struct ihidev_softc *sc)
+ihidev_poweron(struct ihidev_softc *sc)
 {
        DPRINTF(("%s: resetting\n", sc->sc_dev.dv_xname));
 
@@ -536,6 +537,16 @@ ihidev_reset(struct ihidev_softc *sc)
 
        ihidev_sleep(sc, 100);
 
+       return 0;
+}
+
+
+int
+ihidev_reset(struct ihidev_softc *sc)
+{
+       if (ihidev_poweron(sc))
+               return (1);
+
        if (ihidev_hid_command(sc, I2C_HID_CMD_RESET, 0)) {
                printf("%s: failed to reset hardware\n", sc->sc_dev.dv_xname);
 
@@ -784,7 +795,7 @@ ihidev_open(struct ihidev *scd)
                return (0);
 
        /* power on */
-       ihidev_reset(sc);
+       ihidev_poweron(sc);
 
        if (sc->sc_poll) {
                if (!timeout_initialized(&sc->sc_timer))