tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

RE: Reboot resistant USB bug



Speaking as a USB host-stack person: it's a bad idea to assume that a device
has not changed after a reboot of the system. 

Also, some descriptor-gets will normally fail, and it's important to pass
the failure to the caller.  So I believe that your fix will have unforeseen
side-effects.

It is unfortunately true that the accepted test plan for many USB devices
is:

* plug into Windows
* does it work? 
  * ship it

This means that host stacks have to emulate the Windows enumeration system
precisely in order to maximize compatibility.

Does this device work properly under Windows? If so, you can perhaps ask
someone to get you a bus trace of the Windows enumeration and compare to
NetBSD. 

--Terry

-----Original Message-----
From: tech-kern-owner%NetBSD.org@localhost <tech-kern-owner%NetBSD.org@localhost> On Behalf Of
Emmanuel Dreyfus
Sent: Tuesday, October 16, 2018 08:27
To: Emmanuel Dreyfus <manu%netbsd.org@localhost>
Cc: tech-kern%netbsd.org@localhost
Subject: Re: Reboot resistant USB bug

On Thu, Oct 11, 2018 at 02:11:22PM +0000, Emmanuel Dreyfus wrote:
> On both netbsd-8 and -current, I have a problem with USB devices that
> get stuck in a non-functionning state even after a reboot.

I investigated a lot: in my example, the pn533 chip seems to corrupts
its USB config, interface and endpoint descriptors. They contain 
garbage, and on reboot the kernel cannot figure enough  about the 
device, and disable the USB port.

But if I detect the condition in usbd_get_desc() and inject
fake descriptors (see below), the device is correctly attached
on reboot, and it works again. Is it an acceptable workaround?

usbd_status
usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void
*desc)
{
        usb_device_request_t req;
        usbd_status err;

        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

        DPRINTFN(3,"type=%jd, index=%jd, len=%jd", type, index, len, 0);

        req.bmRequestType = UT_READ_DEVICE;
        req.bRequest = UR_GET_DESCRIPTOR;
        USETW2(req.wValue, type, index);
        USETW(req.wIndex, 0);
        USETW(req.wLength, len);
        err = usbd_do_request(dev, &req, desc);

        /*
         * Attempt to fake the descriptor if it fails sanity check
         */
        if (err == USBD_NORMAL_COMPLETION) {
                usb_descriptor_t *d = desc;

                if (d->bDescriptorType != type || d->bLength > len)
                        err = usbd_get_desc_fake(dev, type, index, len,
desc);
        }

        return err;
}


-- 
Emmanuel Dreyfus
manu%netbsd.org@localhost



Home | Main Index | Thread Index | Old Index