Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
sys/ihidev: quirk for Honor MagicBook's touchpad
To:
OpenBSD tech <tech@openbsd.org>
Date:
Mon, 06 Jan 2025 03:27:07 +0100

Download raw body.

Thread
tech@,

Here a quirk which is required for Honor MagicBook's touchpad to be read as
multioutch. This touchpad needs re-power command with sleep after report
description is read. Without waitng quite enough, almost the seconds, or
re-power command it reads only as:

        imt0 at ihidev1ihidev1: failed fetching report
        ims0 at ihidev1 reportid 1: 3 buttons, Z dir

but seems only on the cold boot. Otherwise with 1 seconds sleep and re-power
command, or on warm boot, it reads as:

        imt0 at ihidev1: touchpad, 5 contacts
        ims0 at ihidev1 reportid 1: 3 buttons, Z dir

Ok?

Index: sys/dev/i2c/ihidev.c
===================================================================
RCS file: /cvs/src/sys/dev/i2c/ihidev.c,v
diff -u -p -u -p -r1.35 ihidev.c
--- sys/dev/i2c/ihidev.c	6 Jan 2025 02:13:55 -0000	1.35
+++ sys/dev/i2c/ihidev.c	6 Jan 2025 02:18:27 -0000
@@ -76,6 +76,17 @@ int	ihidev_maxrepid(void *buf, int len);
 int	ihidev_print(void *aux, const char *pnp);
 int	ihidev_submatch(struct device *parent, void *cf, void *aux);
 
+#define IHIDEV_QUIRK_RE_POWER_ON	0x1
+
+const struct ihidev_quirks {
+	uint16_t		ihq_vid;
+	uint16_t		ihq_pid;
+	int			ihq_quirks;
+} ihidev_devs[] = {
+	/* HONOR MagicBook Art 14 Touchpad (QTEC0002) */
+	{ 0x35cc, 0x0104, IHIDEV_QUIRK_RE_POWER_ON },
+};
+
 const struct cfattach ihidev_ca = {
 	sizeof(struct ihidev_softc),
 	ihidev_match,
@@ -99,6 +110,25 @@ ihidev_match(struct device *parent, void
 	return (0);
 }
 
+int
+ihidev_quirks(struct ihidev_softc *sc)
+{
+	const struct ihidev_quirks	*q;
+	uint16_t			 vid, pid;
+	int 				 i, nent;
+
+	nent = nitems(ihidev_devs);
+
+	vid = letoh16(sc->hid_desc.wVendorID);
+	pid = letoh16(sc->hid_desc.wProductID);
+
+	for (i = 0, q = ihidev_devs; i < nent; i++, q++)
+		if (vid == q->ihq_vid && pid == q->ihq_pid)
+			return (q->ihq_quirks);
+
+	return (0);
+}
+
 void
 ihidev_attach(struct device *parent, struct device *self, void *aux)
 {
@@ -637,6 +667,23 @@ ihidev_hid_desc_parse(struct ihidev_soft
 		printf("%s: failed fetching HID report\n",
 		    sc->sc_dev.dv_xname);
 		return (1);
+	}
+
+	if (sc->sc_quirks & IHIDEV_QUIRK_RE_POWER_ON) {
+		if (ihidev_poweron(sc))
+			return (1);
+
+		/*
+		 * 7.2.8 states that a device shall not respond back
+		 * after receiving the power on command, and must ensure
+		 * that it transitions to power on state in less than 1
+		 * second. The ihidev_poweron function uses a shorter
+		 * sleep, sufficient for the ON-RESET sequence. Here,
+		 * however, it sleeps for the full second to accommodate
+		 * cold boot scenarios on affected devices.
+		 */
+
+		ihidev_sleep(sc, 1000);
 	}
 
 	return (0);
Index: sys/dev/i2c/ihidev.h
===================================================================
RCS file: /cvs/src/sys/dev/i2c/ihidev.h,v
diff -u -p -u -p -r1.9 ihidev.h
--- sys/dev/i2c/ihidev.h	3 Sep 2022 15:48:16 -0000	1.9
+++ sys/dev/i2c/ihidev.h	6 Jan 2025 02:18:27 -0000
@@ -93,6 +93,8 @@ struct ihidev_softc {
 	int		sc_fastpoll;
 	struct timeout	sc_timer;
 	int		sc_dying;
+
+	int		sc_quirks;
 };
 
 struct ihidev {


-- 
wbr, Kirill