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.

> # 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;

Reply via email to