uhidev allows a child device to claim all reports by calling *_match functions with the report id set to UHIDEV_CLAIM_ALLREPORTID.
umt needs this because it has to access 3 reports which has worked okay up until now because devices with umt and a ukbd have usually presented them on separate uhidev devices. However, on a new Surface Type Cover device, someone reported that these devices are on the same uhidev meaning if umt attaches, the ukbd device can't. To remedy this, probe devices with UHIDEV_CLAIM_MULTIPLE_REPORTID instead and include an array in the uhidev_attach_arg the size of the available reports. Devices wanting to claim multiple reports just set the indexes in the array to 1 that it wants to claim and uhidev will reserve those, but still probe other devices with each specific unclaimed id. umt is modified to do its report finding in its match function so it can claim just the specific reports it needs. Index: dev/usb/uhidev.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uhidev.c,v retrieving revision 1.89 diff -u -p -u -p -r1.89 uhidev.c --- dev/usb/uhidev.c 15 Feb 2021 11:26:00 -0000 1.89 +++ dev/usb/uhidev.c 5 Mar 2021 14:51:09 -0000 @@ -250,21 +250,27 @@ uhidev_attach(struct device *parent, str uha.uaa = uaa; uha.parent = sc; - uha.reportid = UHIDEV_CLAIM_ALLREPORTID; + uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID; + uha.nreports = nrepid; + uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO); - /* Look for a driver claiming all report IDs first. */ + /* Look for a driver claiming multiple report IDs first. */ dev = config_found_sm(self, &uha, NULL, uhidevsubmatch); if (dev != NULL) { for (repid = 0; repid < nrepid; repid++) { /* * Could already be assigned by uhidev_set_report_dev(). */ - if (sc->sc_subdevs[repid] == NULL) + if (sc->sc_subdevs[repid] != NULL) + continue; + + if (uha.claimed[repid]) sc->sc_subdevs[repid] = (struct uhidev *)dev; } - return; } + free(uha.claimed, M_TEMP, nrepid); + for (repid = 0; repid < nrepid; repid++) { DPRINTF(("%s: try repid=%d\n", __func__, repid)); if (hid_report_size(desc, size, hid_input, repid) == 0 && @@ -355,7 +361,7 @@ uhidevprint(void *aux, const char *pnp) if (pnp) printf("uhid at %s", pnp); - if (uha->reportid != 0 && uha->reportid != UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid != 0 && uha->reportid != UHIDEV_CLAIM_MULTIPLE_REPORTID) printf(" reportid %d", uha->reportid); return (UNCONF); } Index: dev/usb/umt.c =================================================================== RCS file: /cvs/src/sys/dev/usb/umt.c,v retrieving revision 1.2 diff -u -p -u -p -r1.2 umt.c --- dev/usb/umt.c 23 Aug 2020 11:08:02 -0000 1.2 +++ dev/usb/umt.c 5 Mar 2021 14:51:09 -0000 @@ -61,8 +61,8 @@ const struct wsmouse_accessops umt_acces }; int umt_match(struct device *, void *, void *); -int umt_find_winptp_reports(struct uhidev_softc *, void *, int, - struct umt_softc *); +int umt_find_winptp_reports(struct uhidev_softc *, void *, int, int *, + int *, int *); void umt_attach(struct device *, struct device *, void *); int umt_hidev_get_report(struct device *, int, int, void *, int); int umt_hidev_set_report(struct device *, int, int, void *, int); @@ -83,13 +83,19 @@ int umt_match(struct device *parent, void *match, void *aux) { struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; + int input = 0, conf = 0, cap = 0; int size; void *desc; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) { + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) { uhidev_get_report_desc(uha->parent, &desc, &size); - if (umt_find_winptp_reports(uha->parent, desc, size, NULL)) + if (umt_find_winptp_reports(uha->parent, desc, size, &input, + &conf, &cap)) { + uha->claimed[input] = 1; + uha->claimed[conf] = 1; + uha->claimed[cap] = 1; return (UMATCH_DEVCLASS_DEVSUBCLASS); + } } return (UMATCH_NONE); @@ -97,16 +103,17 @@ umt_match(struct device *parent, void *m int umt_find_winptp_reports(struct uhidev_softc *parent, void *desc, int size, - struct umt_softc *sc) + int *input, int *config, int *cap) { int repid; - int input = 0, conf = 0, cap = 0; + int finput = 0, fconf = 0, fcap = 0; - if (sc != NULL) { - sc->sc_rep_input = -1; - sc->sc_rep_config = -1; - sc->sc_rep_cap = -1; - } + if (input != NULL) + *input = -1; + if (config != NULL) + *config = -1; + if (cap != NULL) + *cap = -1; for (repid = 0; repid < parent->sc_nrepid; repid++) { if (hid_report_size(desc, size, hid_input, repid) == 0 && @@ -116,26 +123,26 @@ umt_find_winptp_reports(struct uhidev_so if (hid_is_collection(desc, size, repid, HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHPAD))) { - input = 1; - if (sc != NULL && sc->sc_rep_input == -1) - sc->sc_rep_input = repid; + finput = 1; + if (input != NULL && *input == -1) + *input = repid; } else if (hid_is_collection(desc, size, repid, HID_USAGE2(HUP_DIGITIZERS, HUD_CONFIG))) { - conf = 1; - if (sc != NULL && sc->sc_rep_config == -1) - sc->sc_rep_config = repid; + fconf = 1; + if (config != NULL && *config == -1) + *config = repid; } /* capabilities report could be anywhere */ if (hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX), repid, hid_feature, NULL, NULL)) { - cap = 1; - if (sc != NULL && sc->sc_rep_cap == -1) - sc->sc_rep_cap = repid; + fcap = 1; + if (cap != NULL && *cap == -1) + *cap = repid; } } - return (conf && input && cap); + return (fconf && finput && fcap); } void @@ -153,7 +160,8 @@ umt_attach(struct device *parent, struct usbd_set_idle(uha->parent->sc_udev, uha->parent->sc_ifaceno, 0, 0); uhidev_get_report_desc(uha->parent, &desc, &size); - umt_find_winptp_reports(uha->parent, desc, size, sc); + umt_find_winptp_reports(uha->parent, desc, size, &sc->sc_rep_input, + &sc->sc_rep_config, &sc->sc_rep_cap); memset(mt, 0, sizeof(sc->sc_mt)); Index: dev/usb/fido.c =================================================================== RCS file: /cvs/src/sys/dev/usb/fido.c,v retrieving revision 1.2 diff -u -p -u -p -r1.2 fido.c --- dev/usb/fido.c 18 Dec 2019 05:09:53 -0000 1.2 +++ dev/usb/fido.c 5 Mar 2021 14:51:08 -0000 @@ -63,7 +63,7 @@ fido_match(struct device *parent, void * void *desc; int ret = UMATCH_NONE; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (ret); /* Find the FIDO usage page and U2F collection */ Index: dev/usb/ucycom.c =================================================================== RCS file: /cvs/src/sys/dev/usb/ucycom.c,v retrieving revision 1.38 diff -u -p -u -p -r1.38 ucycom.c --- dev/usb/ucycom.c 25 Feb 2020 10:03:39 -0000 1.38 +++ dev/usb/ucycom.c 5 Mar 2021 14:51:09 -0000 @@ -165,7 +165,7 @@ ucycom_match(struct device *parent, void { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); return (usb_lookup(ucycom_devs, uha->uaa->vendor, uha->uaa->product) != NULL ? Index: dev/usb/ugold.c =================================================================== RCS file: /cvs/src/sys/dev/usb/ugold.c,v retrieving revision 1.15 diff -u -p -u -p -r1.15 ugold.c --- dev/usb/ugold.c 17 Aug 2020 04:26:57 -0000 1.15 +++ dev/usb/ugold.c 5 Mar 2021 14:51:09 -0000 @@ -110,7 +110,7 @@ ugold_match(struct device *parent, void int size; void *desc; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); if (usb_lookup(ugold_devs, uha->uaa->vendor, uha->uaa->product) == NULL) Index: dev/usb/uhid.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uhid.c,v retrieving revision 1.83 diff -u -p -u -p -r1.83 uhid.c --- dev/usb/uhid.c 29 Jan 2021 16:59:41 -0000 1.83 +++ dev/usb/uhid.c 5 Mar 2021 14:51:09 -0000 @@ -115,7 +115,7 @@ uhid_match(struct device *parent, void * { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); return (UMATCH_IFACECLASS_GENERIC); Index: dev/usb/uhidev.h =================================================================== RCS file: /cvs/src/sys/dev/usb/uhidev.h,v retrieving revision 1.27 diff -u -p -u -p -r1.27 uhidev.h --- dev/usb/uhidev.h 11 Feb 2021 06:55:10 -0000 1.27 +++ dev/usb/uhidev.h 5 Mar 2021 14:51:09 -0000 @@ -81,7 +81,9 @@ struct uhidev_attach_arg { struct usb_attach_arg *uaa; struct uhidev_softc *parent; uint8_t reportid; -#define UHIDEV_CLAIM_ALLREPORTID 255 +#define UHIDEV_CLAIM_MULTIPLE_REPORTID 255 + uint8_t nreports; + uint8_t *claimed; }; int uhidev_report_type_conv(int); Index: dev/usb/ujoy.c =================================================================== RCS file: /cvs/src/sys/dev/usb/ujoy.c,v retrieving revision 1.1 diff -u -p -u -p -r1.1 ujoy.c --- dev/usb/ujoy.c 23 Jan 2021 05:08:36 -0000 1.1 +++ dev/usb/ujoy.c 5 Mar 2021 14:51:09 -0000 @@ -104,7 +104,7 @@ ujoy_match(struct device *parent, void * void *desc; int ret = UMATCH_NONE; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (ret); /* Find the general usage page and gamecontroller collections */ Index: dev/usb/uoaklux.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uoaklux.c,v retrieving revision 1.13 diff -u -p -u -p -r1.13 uoaklux.c --- dev/usb/uoaklux.c 8 Apr 2017 02:57:25 -0000 1.13 +++ dev/usb/uoaklux.c 5 Mar 2021 14:51:09 -0000 @@ -107,7 +107,7 @@ uoaklux_match(struct device *parent, voi { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); if (uoaklux_lookup(uha->uaa->vendor, uha->uaa->product) == NULL) Index: dev/usb/uoakrh.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uoakrh.c,v retrieving revision 1.15 diff -u -p -u -p -r1.15 uoakrh.c --- dev/usb/uoakrh.c 8 Apr 2017 02:57:25 -0000 1.15 +++ dev/usb/uoakrh.c 5 Mar 2021 14:51:09 -0000 @@ -110,7 +110,7 @@ uoakrh_match(struct device *parent, void { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); if (uoakrh_lookup(uha->uaa->vendor, uha->uaa->product) == NULL) Index: dev/usb/uoakv.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uoakv.c,v retrieving revision 1.13 diff -u -p -u -p -r1.13 uoakv.c --- dev/usb/uoakv.c 8 Apr 2017 02:57:25 -0000 1.13 +++ dev/usb/uoakv.c 5 Mar 2021 14:51:09 -0000 @@ -110,7 +110,7 @@ uoakv_match(struct device *parent, void { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); if (uoakv_lookup(uha->uaa->vendor, uha->uaa->product) == NULL) Index: dev/usb/upd.c =================================================================== RCS file: /cvs/src/sys/dev/usb/upd.c,v retrieving revision 1.28 diff -u -p -u -p -r1.28 upd.c --- dev/usb/upd.c 29 Jan 2021 16:59:41 -0000 1.28 +++ dev/usb/upd.c 5 Mar 2021 14:51:10 -0000 @@ -155,7 +155,7 @@ upd_match(struct device *parent, void *m int ret = UMATCH_NONE; int i; - if (uha->reportid != UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid != UHIDEV_CLAIM_MULTIPLE_REPORTID) return (ret); DPRINTF(("upd: vendor=0x%04x, product=0x%04x\n", uha->uaa->vendor, Index: dev/usb/uslhcom.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uslhcom.c,v retrieving revision 1.6 diff -u -p -u -p -r1.6 uslhcom.c --- dev/usb/uslhcom.c 8 Apr 2017 02:57:25 -0000 1.6 +++ dev/usb/uslhcom.c 5 Mar 2021 14:51:10 -0000 @@ -115,7 +115,7 @@ uslhcom_match(struct device *parent, voi struct uhidev_attach_arg *uha = aux; /* use all report IDs */ - if (uha->reportid != UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid != UHIDEV_CLAIM_MULTIPLE_REPORTID) return UMATCH_NONE; return (usb_lookup(uslhcom_devs, Index: dev/usb/uthum.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uthum.c,v retrieving revision 1.34 diff -u -p -u -p -r1.34 uthum.c --- dev/usb/uthum.c 14 Feb 2020 14:55:30 -0000 1.34 +++ dev/usb/uthum.c 5 Mar 2021 14:51:10 -0000 @@ -167,7 +167,7 @@ uthum_match(struct device *parent, void { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); if (uthum_lookup(uha->uaa->vendor, uha->uaa->product) == NULL) Index: dev/usb/utrh.c =================================================================== RCS file: /cvs/src/sys/dev/usb/utrh.c,v retrieving revision 1.23 diff -u -p -u -p -r1.23 utrh.c --- dev/usb/utrh.c 25 Feb 2020 10:03:39 -0000 1.23 +++ dev/usb/utrh.c 5 Mar 2021 14:51:10 -0000 @@ -93,7 +93,7 @@ utrh_match(struct device *parent, void * { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); return (usb_lookup(utrh_devs, uha->uaa->vendor, uha->uaa->product) != NULL ? Index: dev/usb/utwitch.c =================================================================== RCS file: /cvs/src/sys/dev/usb/utwitch.c,v retrieving revision 1.20 diff -u -p -u -p -r1.20 utwitch.c --- dev/usb/utwitch.c 25 Feb 2020 10:03:39 -0000 1.20 +++ dev/usb/utwitch.c 5 Mar 2021 14:51:10 -0000 @@ -107,7 +107,7 @@ utwitch_match(struct device *parent, voi { struct uhidev_attach_arg *uha = aux; - if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) + if (uha->reportid == UHIDEV_CLAIM_MULTIPLE_REPORTID) return (UMATCH_NONE); return (usb_lookup(utwitch_devs, uha->uaa->vendor, uha->uaa->product) != NULL ?