On Wed, Feb 10, 2021 at 04:31:01PM +1300, Peter Kane wrote:
> On Wed, Feb 10, 2021 at 08:10:23AM +1300, Peter Kane wrote:
> > On Tue, Feb 09, 2021 at 08:29:08AM +0100, Anton Lindqvist wrote:
> > >
> > > Sorry about the regression. Could you try the following diff and send me
> > > the complete dmesg. I've also prepared an amd64 kernel with the patch
> > > applied:
> > >
>
> Hi Anton
>
> The patch applied cleanly for me and the mouse is working with the new
> kernel, plus console spam as for yours. My dmesg is below.
Great, the "spamming" is caused by UHIDPP_DEBUG being enabled. The last
diff introduced a bug which causes a panic once uhidpp is detached. The
following diff fixes that.
diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
index 9915b660d9d..dfc734aa4ea 100644
--- sys/dev/usb/uhidev.c
+++ sys/dev/usb/uhidev.c
@@ -273,11 +273,13 @@ uhidev_attach(struct device *parent, struct device *self,
void *aux)
hid_report_size(desc, size, hid_feature, repid) == 0)
continue;
+ /* Could already be assigned by uhidev_set_report_dev(). */
+ if (sc->sc_subdevs[repid] != NULL)
+ continue;
+
uha.reportid = repid;
dev = config_found_sm(self, &uha, uhidevprint, uhidevsubmatch);
- /* Could already be assigned by uhidev_set_report_dev(). */
- if (sc->sc_subdevs[repid] == NULL)
- sc->sc_subdevs[repid] = (struct uhidev *)dev;
+ sc->sc_subdevs[repid] = (struct uhidev *)dev;
}
}
@@ -1011,3 +1013,13 @@ uhidev_set_report_dev(struct uhidev_softc *sc, struct
uhidev *dev, int repid)
sc->sc_subdevs[repid] = dev;
return 0;
}
+
+int
+uhidev_unset_report_dev(struct uhidev_softc *sc, int repid)
+{
+ if (repid >= sc->sc_nrepid)
+ return EINVAL;
+
+ sc->sc_subdevs[repid] = NULL;
+ return 0;
+}
diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
index 5caba3d8304..85a44bf84a5 100644
--- sys/dev/usb/uhidev.h
+++ sys/dev/usb/uhidev.h
@@ -96,3 +96,4 @@ int uhidev_get_report_async(struct uhidev_softc *, int, int,
void *, int,
void *, void (*)(void *, int, void *, int));
usbd_status uhidev_write(struct uhidev_softc *, void *, int);
int uhidev_set_report_dev(struct uhidev_softc *, struct uhidev *, int);
+int uhidev_unset_report_dev(struct uhidev_softc *, int);
diff --git sys/dev/usb/uhidpp.c sys/dev/usb/uhidpp.c
index b041d86fecd..fe6550c78dd 100644
--- sys/dev/usb/uhidpp.c
+++ sys/dev/usb/uhidpp.c
@@ -281,7 +281,8 @@ uhidpp_match(struct device *parent, void *match, void *aux)
void *desc;
int descsiz, siz;
- if (uha->reportid != UHIDEV_CLAIM_ALLREPORTID)
+ if (uha->reportid != HIDPP_REPORT_ID_SHORT &&
+ uha->reportid != HIDPP_REPORT_ID_LONG)
return UMATCH_NONE;
if (usb_lookup(uhidpp_devs,
@@ -325,7 +326,7 @@ uhidpp_attach(struct device *parent, struct device *self,
void *aux)
error = uhidev_open(&sc->sc_hdev);
if (error) {
- printf(" error %d\n", error);
+ printf(" open error %d\n", error);
return;
}
@@ -338,10 +339,18 @@ uhidpp_attach(struct device *parent, struct device *self,
void *aux)
* in order to receive responses. Necessary as uhidev by default
* performs the wiring after the attach routine has returned.
*/
- uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
+ error = uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
HIDPP_REPORT_ID_SHORT);
- uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
+ if (error) {
+ printf(" short report error %d\n", error);
+ return;
+ }
+ error = uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
HIDPP_REPORT_ID_LONG);
+ if (error) {
+ printf(" long report error %d\n", error);
+ return;
+ }
/* Probe paired devices. */
for (i = 0; i < UHIDPP_NDEVICES; i++) {
@@ -408,6 +417,14 @@ uhidpp_detach(struct device *self, int flags)
sensor_detach(&sc->sc_sensdev,
&dev->d_battery.b_sens[j]);
}
+ /*
+ * Since this driver has multiple device handlers attached, remove all
+ * of them preventing the uhidev parent from calling this detach routine
+ * more than once.
+ */
+ uhidev_unset_report_dev(sc->sc_hdev.sc_parent, HIDPP_REPORT_ID_SHORT);
+ uhidev_unset_report_dev(sc->sc_hdev.sc_parent, HIDPP_REPORT_ID_LONG);
+
uhidev_close(&sc->sc_hdev);
return 0;