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 ?

Reply via email to