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-ow...@netbsd.org <tech-kern-ow...@netbsd.org> On Behalf Of Emmanuel Dreyfus Sent: Tuesday, October 16, 2018 08:27 To: Emmanuel Dreyfus <m...@netbsd.org> Cc: tech-kern@netbsd.org 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 m...@netbsd.org