From f31b43ced9cf4cbf056e9d8aceb4fa40a73e00cd Mon Sep 17 00:00:00 2001 From: jcs Date: Mon, 8 Mar 2021 14:35:57 +0000 Subject: [PATCH] Allow uhidev child devices to claim selective report ids There may be multiple matching devices on a single uhidev device but the first device that responds to UHIDEV_CLAIM_ALLREPORTID will block the others from attaching. Change this to UHIDEV_CLAIM_MULTIPLE_REPORTID and require any devices wanting some/all report ids to fill in the claimed array in uhidev_attach_arg with just the reports it needs. uhidev can then run match routines for other drivers with the available report ids. ok anton --- sys/dev/usb/fido.c | 4 ++-- sys/dev/usb/ucycom.c | 4 ++-- sys/dev/usb/ugold.c | 4 ++-- sys/dev/usb/uhid.c | 4 ++-- sys/dev/usb/uhidev.c | 19 ++++++++++----- sys/dev/usb/uhidev.h | 6 +++-- sys/dev/usb/ujoy.c | 4 ++-- sys/dev/usb/umt.c | 54 +++++++++++++++++++++++++------------------ sys/dev/usb/uoaklux.c | 4 ++-- sys/dev/usb/uoakrh.c | 4 ++-- sys/dev/usb/uoakv.c | 4 ++-- sys/dev/usb/upd.c | 4 ++-- sys/dev/usb/uslhcom.c | 4 ++-- sys/dev/usb/uthum.c | 4 ++-- sys/dev/usb/utrh.c | 4 ++-- sys/dev/usb/utwitch.c | 4 ++-- 16 files changed, 74 insertions(+), 57 deletions(-) diff --git a/sys/dev/usb/fido.c b/sys/dev/usb/fido.c index 77bd9b12175..c6d846aaa84 100644 --- a/sys/dev/usb/fido.c +++ b/sys/dev/usb/fido.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fido.c,v 1.2 2019/12/18 05:09:53 deraadt Exp $ */ +/* $OpenBSD: fido.c,v 1.3 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2019 Reyk Floeter @@ -63,7 +63,7 @@ fido_match(struct device *parent, void *match, void *aux) 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 */ diff --git a/sys/dev/usb/ucycom.c b/sys/dev/usb/ucycom.c index ca6d6e9c6b2..ca8636f0a7f 100644 --- a/sys/dev/usb/ucycom.c +++ b/sys/dev/usb/ucycom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ucycom.c,v 1.38 2020/02/25 10:03:39 mpi Exp $ */ +/* $OpenBSD: ucycom.c,v 1.39 2021/03/08 14:35:57 jcs Exp $ */ /* $NetBSD: ucycom.c,v 1.3 2005/08/05 07:27:47 skrll Exp $ */ /* @@ -165,7 +165,7 @@ ucycom_match(struct device *parent, void *match, void *aux) { 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 ? diff --git a/sys/dev/usb/ugold.c b/sys/dev/usb/ugold.c index bc2d84ca42e..c939966760e 100644 --- a/sys/dev/usb/ugold.c +++ b/sys/dev/usb/ugold.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ugold.c,v 1.15 2020/08/17 04:26:57 gnezdo Exp $ */ +/* $OpenBSD: ugold.c,v 1.16 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2013 Takayoshi SASANO @@ -110,7 +110,7 @@ ugold_match(struct device *parent, void *match, void *aux) 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) diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c index ba21e8cf96f..085c1523ccf 100644 --- a/sys/dev/usb/uhid.c +++ b/sys/dev/usb/uhid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhid.c,v 1.83 2021/01/29 16:59:41 sthen Exp $ */ +/* $OpenBSD: uhid.c,v 1.84 2021/03/08 14:35:57 jcs Exp $ */ /* $NetBSD: uhid.c,v 1.57 2003/03/11 16:44:00 augustss Exp $ */ /* @@ -115,7 +115,7 @@ uhid_match(struct device *parent, void *match, void *aux) { 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); diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c index 24b7841d837..d777cfb6e45 100644 --- a/sys/dev/usb/uhidev.c +++ b/sys/dev/usb/uhidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhidev.c,v 1.89 2021/02/15 11:26:00 mglocker Exp $ */ +/* $OpenBSD: uhidev.c,v 1.90 2021/03/08 14:35:57 jcs Exp $ */ /* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */ /* @@ -250,21 +250,28 @@ uhidev_attach(struct device *parent, struct device *self, void *aux) 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); + uha.claimed = NULL; + 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 +362,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); } diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h index 7cce36f515d..cb83045084c 100644 --- a/sys/dev/usb/uhidev.h +++ b/sys/dev/usb/uhidev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uhidev.h,v 1.27 2021/02/11 06:55:10 anton Exp $ */ +/* $OpenBSD: uhidev.h,v 1.28 2021/03/08 14:35:57 jcs Exp $ */ /* $NetBSD: uhidev.h,v 1.3 2002/10/08 09:56:17 dan Exp $ */ /* @@ -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); diff --git a/sys/dev/usb/ujoy.c b/sys/dev/usb/ujoy.c index 18a35d737b9..ca461e5969a 100644 --- a/sys/dev/usb/ujoy.c +++ b/sys/dev/usb/ujoy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ujoy.c,v 1.1 2021/01/23 05:08:36 thfr Exp $ */ +/* $OpenBSD: ujoy.c,v 1.2 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2021 Thomas Frohwein @@ -104,7 +104,7 @@ ujoy_match(struct device *parent, void *match, void *aux) 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 */ diff --git a/sys/dev/usb/umt.c b/sys/dev/usb/umt.c index 863781f2659..a3fd5ce9c28 100644 --- a/sys/dev/usb/umt.c +++ b/sys/dev/usb/umt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: umt.c,v 1.2 2020/08/23 11:08:02 mglocker Exp $ */ +/* $OpenBSD: umt.c,v 1.3 2021/03/08 14:35:57 jcs Exp $ */ /* * USB multitouch touchpad driver for devices conforming to * Windows Precision Touchpad standard @@ -61,8 +61,8 @@ const struct wsmouse_accessops umt_accessops = { }; 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 *match, void *aux) 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_softc *parent, void *desc, int size, 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 device *self, void *aux) 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)); diff --git a/sys/dev/usb/uoaklux.c b/sys/dev/usb/uoaklux.c index 3932b139a51..c97bdf57285 100644 --- a/sys/dev/usb/uoaklux.c +++ b/sys/dev/usb/uoaklux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uoaklux.c,v 1.13 2017/04/08 02:57:25 deraadt Exp $ */ +/* $OpenBSD: uoaklux.c,v 1.14 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2012 Yojiro UO @@ -107,7 +107,7 @@ uoaklux_match(struct device *parent, void *match, void *aux) { 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) diff --git a/sys/dev/usb/uoakrh.c b/sys/dev/usb/uoakrh.c index 66a030409de..1e1e49a426c 100644 --- a/sys/dev/usb/uoakrh.c +++ b/sys/dev/usb/uoakrh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uoakrh.c,v 1.15 2017/04/08 02:57:25 deraadt Exp $ */ +/* $OpenBSD: uoakrh.c,v 1.16 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2012 Yojiro UO @@ -110,7 +110,7 @@ uoakrh_match(struct device *parent, void *match, void *aux) { 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) diff --git a/sys/dev/usb/uoakv.c b/sys/dev/usb/uoakv.c index a8cdb734001..2963e47da0d 100644 --- a/sys/dev/usb/uoakv.c +++ b/sys/dev/usb/uoakv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uoakv.c,v 1.13 2017/04/08 02:57:25 deraadt Exp $ */ +/* $OpenBSD: uoakv.c,v 1.14 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2012 Yojiro UO @@ -110,7 +110,7 @@ uoakv_match(struct device *parent, void *match, void *aux) { 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) diff --git a/sys/dev/usb/upd.c b/sys/dev/usb/upd.c index 50cc25af08f..ad65b77718b 100644 --- a/sys/dev/usb/upd.c +++ b/sys/dev/usb/upd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: upd.c,v 1.28 2021/01/29 16:59:41 sthen Exp $ */ +/* $OpenBSD: upd.c,v 1.29 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2015 David Higgs @@ -155,7 +155,7 @@ upd_match(struct device *parent, void *match, void *aux) 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, diff --git a/sys/dev/usb/uslhcom.c b/sys/dev/usb/uslhcom.c index 39db391aecd..15291aae645 100644 --- a/sys/dev/usb/uslhcom.c +++ b/sys/dev/usb/uslhcom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uslhcom.c,v 1.6 2017/04/08 02:57:25 deraadt Exp $ */ +/* $OpenBSD: uslhcom.c,v 1.7 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2015 SASANO Takayoshi @@ -115,7 +115,7 @@ uslhcom_match(struct device *parent, void *match, void *aux) 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, diff --git a/sys/dev/usb/uthum.c b/sys/dev/usb/uthum.c index 601abdc64ab..d368472c19a 100644 --- a/sys/dev/usb/uthum.c +++ b/sys/dev/usb/uthum.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthum.c,v 1.34 2020/02/14 14:55:30 mpi Exp $ */ +/* $OpenBSD: uthum.c,v 1.35 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2009, 2010 Yojiro UO @@ -167,7 +167,7 @@ uthum_match(struct device *parent, void *match, void *aux) { 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) diff --git a/sys/dev/usb/utrh.c b/sys/dev/usb/utrh.c index cd6f43c06d9..c74ca0746ca 100644 --- a/sys/dev/usb/utrh.c +++ b/sys/dev/usb/utrh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utrh.c,v 1.23 2020/02/25 10:03:39 mpi Exp $ */ +/* $OpenBSD: utrh.c,v 1.24 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2009 Yojiro UO @@ -93,7 +93,7 @@ utrh_match(struct device *parent, void *match, void *aux) { 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 ? diff --git a/sys/dev/usb/utwitch.c b/sys/dev/usb/utwitch.c index cc8396a21dd..a7a5479700f 100644 --- a/sys/dev/usb/utwitch.c +++ b/sys/dev/usb/utwitch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utwitch.c,v 1.20 2020/02/25 10:03:39 mpi Exp $ */ +/* $OpenBSD: utwitch.c,v 1.21 2021/03/08 14:35:57 jcs Exp $ */ /* * Copyright (c) 2010 Yojiro UO @@ -107,7 +107,7 @@ utwitch_match(struct device *parent, void *match, void *aux) { 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 ? -- 2.20.1