Re: imt/hidmt: work better with dual touchpad/trackstick devices

2020-07-02 Thread Dave Voutila


joshua stein writes:

> I have confirmation that these fix the touchpad and trackstick on
> one Dell laptop and I'd like more testing to make sure they don't
> break other laptops.

Seems to be fine on my Lenovo x270.

pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
wsmouse1 at pms0 mux 0
pms0: Synaptics clickpad, firmware 8.2, 0x1e2b1 0x943300 0x330340 0xf408a3 
0x12e800

Trackpad and trackpoint working as they did previously.

--
-Dave Voutila



imt/hidmt: work better with dual touchpad/trackstick devices

2020-07-02 Thread joshua stein
On some laptops that have a Windows Precision Touchpad (imt) but 
also have a trackstick, imt was claiming all report ids of the 
ihidev device preventing the trackstick from attaching as a separate 
mouse (ims) device.  (This probably doesn't affect Thinkpads because 
their trackstick attaches as a legacy pms device.)

Also, some touchpads don't have the "maximum number of contacts" or 
"button type" usages, so we can use some reasonable defaults here 
rather than failing to attach.

I have confirmation that these fix the touchpad and trackstick on 
one Dell laptop and I'd like more testing to make sure they don't 
break other laptops.


diff --git sys/dev/hid/hidmt.c sys/dev/hid/hidmt.c
index 532da1b6627..8033c9cf446 100644
--- sys/dev/hid/hidmt.c
+++ sys/dev/hid/hidmt.c
@@ -138,31 +138,29 @@ hidmt_setup(struct device *self, struct hidmt *mt, void 
*desc, int dlen)
}
 
/* find maximum number of contacts being reported per input report */
-   if (!hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX),
+   mt->sc_num_contacts = HIDMT_MAX_CONTACTS;
+   if (hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX),
mt->sc_rep_cap, hid_feature, , NULL)) {
-   printf("\n%s: can't find maximum contacts\n", self->dv_xname);
-   return 1;
-   }
-
-   d = hid_get_udata(rep, capsize, );
-   if (d > HIDMT_MAX_CONTACTS) {
-   printf("\n%s: contacts %d > max %d\n", self->dv_xname, d,
-   HIDMT_MAX_CONTACTS);
-   return 1;
+   d = hid_get_udata(rep, capsize, );
+   if (d > HIDMT_MAX_CONTACTS)
+   printf("\n%s: contacts %d > max %d\n", self->dv_xname,
+   d, HIDMT_MAX_CONTACTS);
+   else
+   mt->sc_num_contacts = d;
}
-   else
-   mt->sc_num_contacts = d;
 
/* find whether this is a clickpad or not */
-   if (!hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS, HUD_BUTTON_TYPE),
+   if (hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS, HUD_BUTTON_TYPE),
mt->sc_rep_cap, hid_feature, , NULL)) {
-   printf("\n%s: can't find button type\n", self->dv_xname);
-   return 1;
+   d = hid_get_udata(rep, capsize, );
+   mt->sc_clickpad = (d == 0);
+   } else {
+   /* if there's not a 2nd button, this is probably a clickpad */
+   if (!hid_locate(desc, dlen, HID_USAGE2(HUP_BUTTON, 2),
+   mt->sc_rep_input, hid_input, , NULL))
+   mt->sc_clickpad = 1;
}
 
-   d = hid_get_udata(rep, capsize, );
-   mt->sc_clickpad = (d == 0);
-
/*
 * Walk HID descriptor and store usages we care about to know what to
 * pluck out of input reports.
diff --git sys/dev/i2c/ihidev.c sys/dev/i2c/ihidev.c
index 4c63eb5bae2..789a2300a3f 100644
--- sys/dev/i2c/ihidev.c
+++ sys/dev/i2c/ihidev.c
@@ -173,17 +173,22 @@ ihidev_attach(struct device *parent, struct device *self, 
void *aux)
iha.iaa = ia;
iha.parent = sc;
 
-   /* Look for a driver claiming all report IDs first. */
-   iha.reportid = IHIDEV_CLAIM_ALLREPORTID;
+   /* Look for a driver claiming multiple report IDs first. */
+   iha.reportid = IHIDEV_CLAIM_MULTIPLEID;
+   iha.nclaims = 0;
dev = config_found_sm((struct device *)sc, , NULL,
ihidev_submatch);
if (dev != NULL) {
-   for (repid = 0; repid < sc->sc_nrepid; repid++)
-   sc->sc_subdevs[repid] = (struct ihidev *)dev;
-   return;
+   for (repid = 0; repid < iha.nclaims; repid++) {
+   sc->sc_subdevs[iha.claims[repid]] =
+   (struct ihidev *)dev;
+   }
}
 
for (repid = 0; repid < sc->sc_nrepid; repid++) {
+   if (sc->sc_subdevs[repid] != NULL)
+   continue;
+
if (hid_report_size(sc->sc_report, sc->sc_reportlen, hid_input,
repid) == 0 &&
hid_report_size(sc->sc_report, sc->sc_reportlen,
@@ -748,7 +753,7 @@ ihidev_print(void *aux, const char *pnp)
if (pnp)
printf("hid at %s", pnp);
 
-   if (iha->reportid != 0 && iha->reportid != IHIDEV_CLAIM_ALLREPORTID)
+   if (iha->reportid != 0)
printf(" reportid %d", iha->reportid);
 
return (UNCONF);
diff --git sys/dev/i2c/ihidev.h sys/dev/i2c/ihidev.h
index dde7cef5ab5..ad1f7ce83b8 100644
--- sys/dev/i2c/ihidev.h
+++ sys/dev/i2c/ihidev.h
@@ -112,7 +112,9 @@ struct ihidev_attach_arg {
struct i2c_attach_args  *iaa;
struct ihidev_softc *parent;
uint8_t  reportid;
-#defineIHIDEV_CLAIM_ALLREPORTID255
+   uint8_t  claims[16];
+   uint8_t  nclaims;
+#define