On Wed, Nov 03, 2021 at 09:43:54AM +0100, Damien Couderc wrote:
> Le 03/11/2021 à 07:44, Anton Lindqvist a écrit :
> > Hi,
> > In an attempt to fix a bug related to upd(4) I discovered that the
> > pseudo report id UHIDEV_CLAIM_MULTIPLE_REPORTID is conflicting with an
> > actual report id. The previous fix, reverted by now, avoided the
> > conflict by incrementing the pseudo report id was not a good idea
> > since a report id is expected to be represented using a single unsigned
> > byte elsewhere in the usb stack.
> >
> > Here's a second attempt. Report id zero is according to the USB HID
> > specification reserved and should not be used. We can define
> > UHIDEV_CLAIM_MULTIPLE_REPORTID as zero removing the need to use a larger
> > integer type than the existing uint8_t for the report id. Another
> > correction is also needed. Some descriptors only supports a single
> > report and the report id is in this case optional. Internally, uhidev
> > uses report id zero for such devices. It's therefore of importance to
> > not perform a claim multiple report ids attachment on such devices as
> > there's only one report id to claim.
> >
> > Testing would be much appreciated.
> >
> > Comments? OK?
> >
> > diff --git sys/dev/usb/uhidev.c sys/dev/usb/uhidev.c
> > index 5fe2f702e21..f5cc5984b59 100644
> > --- sys/dev/usb/uhidev.c
> > +++ sys/dev/usb/uhidev.c
> > @@ -247,29 +247,36 @@ uhidev_attach(struct device *parent, struct device
> > *self, void *aux)
> > sc->sc_isize += (nrepid != 1); /* one byte for the report ID */
> > DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize));
> > + memset(&uha, 0, sizeof(uha));
> > uha.uaa = uaa;
> > uha.parent = sc;
> > - uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
> > - uha.nreports = nrepid;
> > - uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
> > /* 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)
> > - continue;
> > -
> > - if (uha.claimed[repid])
> > + if (nrepid > 1) {
> > + uha.reportid = UHIDEV_CLAIM_MULTIPLE_REPORTID;
> > + uha.nreports = nrepid;
> > + uha.claimed = malloc(nrepid, M_TEMP, M_WAITOK|M_ZERO);
> > +
> > + 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)
> > + continue;
> > +
> > + if (!uha.claimed[repid])
> > + continue;
> > sc->sc_subdevs[repid] = (struct uhidev *)dev;
> > + }
> > }
> > - }
> > - free(uha.claimed, M_TEMP, nrepid);
> > - uha.claimed = NULL;
> > + free(uha.claimed, M_TEMP, nrepid);
> > + uha.nreports = 0;
> > + uha.claimed = NULL;
> > + }
> > for (repid = 0; repid < nrepid; repid++) {
> > DPRINTF(("%s: try repid=%d\n", __func__, repid));
> > diff --git sys/dev/usb/uhidev.h sys/dev/usb/uhidev.h
> > index 6ce75b1f49d..9ae85e1ab9f 100644
> > --- sys/dev/usb/uhidev.h
> > +++ sys/dev/usb/uhidev.h
> > @@ -81,8 +81,8 @@ struct uhidev_attach_arg {
> > struct usb_attach_arg *uaa;
> > struct uhidev_softc *parent;
> > uint8_t reportid;
> > -#define UHIDEV_CLAIM_MULTIPLE_REPORTID 255
> > - uint8_t nreports;
> > +#define UHIDEV_CLAIM_MULTIPLE_REPORTID 0
> > + u_int nreports;
> > uint8_t *claimed;
> > };
>
> Hi,
>
> It works flawlessly for me and unplugging is fine too.
Thanks, committed.