On Wed, Aug 26, 2020 at 11:27:21PM +0200, Marcus Glocker wrote:
> On Wed, 26 Aug 2020 19:20:26 +0000
> Mikolaj Kucharski <[email protected]> wrote:
>
> > On Wed, Aug 26, 2020 at 06:54:59PM +0000, Mikolaj Kucharski wrote:
> > > On Wed, Aug 26, 2020 at 06:45:28PM +0000, Mikolaj Kucharski wrote:
> > ...
> > > >
> > > > Do you have any theory why first control request is returning
> > > > wTotalLength=32 and second is returning wTotalLength=55? It also
> > > > seem that bNumInterface has different value between the runs.
> > >
> > > I ran more `scanimage -L` commands in a row and wTotalLength=32
> > > doesn't occur any more. As I'm remote to the machine and the
> > > printer I don't see it, but I imagine that printer/scanner goes to
> > > sleep after certain amount of time of inactivity.
> > >
> > > Maybe it's related that first call wakes up the printer/scanner and
> > > then wTotalLength=32. After that when printer/scanner is up all
> > > wTotalLength=55. I can test it again during a day tomorrow with
> > > hours of break in between of `scanimage -L` runs to see am I seeing
> > > more of this behaviour.
> > >
> >
> > Ok, so I waited 15+ minutes between scanimage -L, as I suspect that
> > would be enough time to get printer to sleep and yeah, I see again
> > wTotalLength=32:
>
> OK, this makes sense.
>
> Does this diff fix the issue?
> I'm hoping that we don't require a delay between the requests.
Yes, this diff does fix the issue. It works really well. I can confirm
this is related to the printer going to sleep-mode as that printer has
also web UI and there I can see status of the printer, for example page
says:
Sleeping...
or, when `scanimage -L` wakes up the printer it says:
Ready to Copy
Eco Mode 01
and this relates to wTotalLength 32 vs 55. After below diff all works
without panic and `scanimage -L` works reliably and scanning itself also
works.
I've also tested your diff against (kernel has disable ulpt applied):
# dmesg
...
ugen0 at uhub0 port 4 "Canon MG3200 series" rev 2.00/1.04 addr 2
# usbdevs -v
Controller /dev/usb0:
addr 01: 1022:0000 AMD, xHCI root hub
super speed, self powered, config 1, rev 1.00
driver: uhub0
addr 02: 04a9:1762 Canon, MG3200 series
high speed, self powered, config 1, rev 1.04, iSerial 860FE4
driver: ugen0
Controller /dev/usb1:
addr 01: 1022:0000 AMD, EHCI root hub
high speed, self powered, config 1, rev 1.00
driver: uhub1
addr 02: 0438:7900 Advanced Micro Devices, Hub
high speed, self powered, config 1, rev 0.18
driver: uhub2
# scanimage -L
device `pixma:04A91762_860FE4' is a CANON Canon PIXMA MG3200 Series
multi-function peripheral
That Canon MG3250 printer/scanner didn't had this issue, but I just
wanted to check is your diff also working on a device, which was working
before the change. All good here.
Thank you very much Marcus for fixing the problem!
> > # grep -F '/bsd' /var/log/messages | cut -b35- | head -n30
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 25
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 55
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 25
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 25
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 216
> > /bsd: 1:
> > /bsd: bLength=9
> > /bsd: bDescriptorType=2
> > /bsd: wTotalLength=32
> > /bsd: bNumInterface=1
> > /bsd: bConfigurationValue=1
> > /bsd: iConfiguration=0
> > /bsd: bmAttributes=0xc0
> > /bsd: bMaxPower=1
> > /bsd: 2:
> > /bsd: bLength=9
> > /bsd: bDescriptorType=2
> > /bsd: wTotalLength=55
> > /bsd: bNumInterface=2
> > /bsd: bConfigurationValue=1
> > /bsd: iConfiguration=0
> > /bsd: bmAttributes=0xc0
> > /bsd: bMaxPower=1
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 55
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 55
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 25
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 25
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 216
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 216
> > /bsd: USB_DEVICE_GET_FDESC wTotalLength free = 55
>
>
> Index: sys/dev/usb/usb_subr.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/usb_subr.c,v
> retrieving revision 1.151
> diff -u -p -u -p -r1.151 usb_subr.c
> --- sys/dev/usb/usb_subr.c 31 Jul 2020 10:49:33 -0000 1.151
> +++ sys/dev/usb/usb_subr.c 26 Aug 2020 21:25:31 -0000
> @@ -1366,6 +1366,7 @@ usbd_get_cdesc(struct usbd_device *dev,
> usb_config_descriptor_t *cdesc, *tdesc, cdescr;
> u_int len;
> usbd_status err;
> + int i;
>
> if (index == USB_CURRENT_CONFIG_INDEX) {
> tdesc = usbd_get_config_descriptor(dev);
> @@ -1378,11 +1379,23 @@ usbd_get_cdesc(struct usbd_device *dev,
> memcpy(cdesc, tdesc, len);
> DPRINTFN(5,("%s: current, len=%u\n", __func__, len));
> } else {
> - err = usbd_get_desc(dev, UDESC_CONFIG, index,
> - USB_CONFIG_DESCRIPTOR_SIZE, &cdescr);
> - if (err || cdescr.bDescriptorType != UDESC_CONFIG)
> - return (0);
> - len = UGETW(cdescr.wTotalLength);
> + /*
> + * Some devices return false configuration descriptor values
> + * on the first request, e.g. when they are in sleep mode.
> + * Therefore compare multiple request results; Two for sane
> + * values, three for initial false values.
> + */
> + for (len = 0, i = 0; i < 3; i++) {
> + err = usbd_get_desc(dev, UDESC_CONFIG, index,
> + USB_CONFIG_DESCRIPTOR_SIZE, &cdescr);
> + if (err || cdescr.bDescriptorType != UDESC_CONFIG)
> + return (0);
> + if (len == UGETW(cdescr.wTotalLength))
> + break;
> + len = UGETW(cdescr.wTotalLength);
> + }
> + if (i == 3)
> + return (NULL);
> DPRINTFN(5,("%s: index=%d, len=%u\n", __func__, index, len));
> if (lenp)
> *lenp = len;
--
Regards,
Mikolaj