On Wed, 19 Aug 2020 12:02:23 +0200 Martin Pieuchot <m...@openbsd.org> wrote:
> On 18/08/20(Tue) 18:53, Marcus Glocker wrote: > > On Wed, 12 Aug 2020 21:39:15 +0200 > > Marcus Glocker <mar...@nazgul.ch> wrote: > > > > > jmc was so nice to send me his trouble device over to do some > > > further investigations. Just some updates on what I've noticed > > > today: > > > > > > - The issue isn't specific to xhci(4). I also see the same issue > > > on some of my ehci(4) machines when attaching this device. > > > > > > - It seems like the device gets in to an 'corrupted state' after > > > running a couple of control transfer against it. Initially they > > > work fine, with smaller and larger transfer sizes, and at one > > > point the device hangs up and doesn't recover until re-attaching > > > it. While on some ehci(4) machines the uhidev(4) attach works > > > fine, after running lsusb against the device, I see transfer > > > errors coming up again; On xhci(4) namely XHCI_CODE_TXERR. > > > > > > - Attaching an USB 2.0 hub doesn't make any difference, no matter > > > if attached to an xhci(4) or an ehci(4) controller. > > > > > > Not sure what is going wrong with this little beast ... > > > > OK, I give up :-) Following my summary report. > > > > This device seems to have issues with two control request types: > > > > - UR_GET_STATUS, not called for this device from the kernel in > > the default code path. But e.g. 'lsusb -v' will call it. > > > > - UR_SET_IDLE, as called in uhidev_attach(). > > > > UR_GET_STATUS will stall the device for good on *all* controller > > drivers. > > Does this also happen when the device attaches as ugen(4)? If yes > that would rules out concurrency issues that might happen when using > lsusb(1) while other transfers are in fly. To test you need to > disable the current attaching driver in ukc. Yes, it does also happen when attaching the device to ugen(4). But honestly, I was playing around yesterday evening a bit further with this device, and I noticed that the device also stalls with lsusb when I remove the get status and get report request in the lsusb code. Therefore I need to correct my statement, saying instead that *some* request in lsusb makes the device stall as well. What I just found in the lsusb ChangeLog: Added (somewhat dummy) Set_Protocol and Set_Idle requests to stream dumping setup. I'll try to confirm if the stall really happens there. At least that would be in line with our findings in the kernel. > > UR_SET_IDLE works only on ehci(4) - Don't ask me why. > > On all the other controller drivers the following UR_GET_REPORT > > request will fail, stalling the device as well. I tried all kind > > of things to get the UR_SET_IDLE request working on xhci(4), but > > without any luck. > > Does the device respond to GET_IDLE? No, same behaviour as for SET_IDLE, returns with USBD_STALLED. > It it a timing problem? How much time does the device need to be > idle? Does introducing a delay before and/or after usbd_set_idle() > change the behavior? I already tried 100ms delay before and after set idle, no change. > Did you try passing a non-0 duration parameter to the SET_IDLE > command? Yes, I also already tried with various non-0 duration parameters, no change. > Taking a step back, why does a uaudio(4) needs a UR_SET_IDLE? This > tells the device to only respond to IN interrupt transfers when new > events occur, right? Does all devices attaching to uhidev want this > behavior? I don't know since I was not involved in that code yet. Correct, that's what I did read in the HID specs as well. uhidev(4) does call set idle statically for all devices during attach. I was also questioning myself if that is the right thing, since for the uaudio(4) devices I own, it seems to make no difference when skipping the set idle request. > > The good news is that when we skip the UR_SET_IDLE request on > > xhci(4), the following UR_GET_REPORT request works, and isoc > > transfers also work perfectly fine. You can use the device for > > audio streaming. > > > > Therefore the only thing I can offer is a quirk to skip the > > UR_SET_IDLE request when attaching this device. On ehci(4) the > > device continues to work as before with this quirk. Therefore I > > didn't include any code to only apply the quirk on non-ehci > > controllers. > > > > I know it's not a nice solution, but at least it makes this device > > usable on xhci(4) while not impacting other things. > > Maybe it is a step towards a real solution. Should usbd_set_idle() > stay in uhidev(4) or, if it doesn't make sense for all devices, should > we move it in child drivers like ukbd(4), etc? I would also think that the set idle request is only required for keyboard, mouse, etc., but honestly I'm too less familiar with the HID specs. > > If anyone is OK with that and has no better idea how to fix it, I'm > > happy to commit. > > > > Cheers, > > Marcus > > > > > > Index: uhidev.c > > =================================================================== > > RCS file: /cvs/src/sys/dev/usb/uhidev.c,v > > retrieving revision 1.80 > > diff -u -p -u -p -r1.80 uhidev.c > > --- uhidev.c 31 Jul 2020 10:49:33 -0000 1.80 > > +++ uhidev.c 18 Aug 2020 13:36:13 -0000 > > @@ -151,7 +151,8 @@ uhidev_attach(struct device *parent, str > > sc->sc_ifaceno = uaa->ifaceno; > > id = usbd_get_interface_descriptor(sc->sc_iface); > > > > - usbd_set_idle(sc->sc_udev, sc->sc_ifaceno, 0, 0); > > + if (!(usbd_get_quirks(uaa->device)->uq_flags & > > UQ_NO_SET_IDLE)) > > + usbd_set_idle(sc->sc_udev, sc->sc_ifaceno, 0, 0); > > > > sc->sc_iep_addr = sc->sc_oep_addr = -1; > > for (i = 0; i < id->bNumEndpoints; i++) { > > Index: usb_quirks.c > > =================================================================== > > RCS file: /cvs/src/sys/dev/usb/usb_quirks.c,v > > retrieving revision 1.76 > > diff -u -p -u -p -r1.76 usb_quirks.c > > --- usb_quirks.c 5 Jan 2020 00:54:13 -0000 1.76 > > +++ usb_quirks.c 18 Aug 2020 13:36:13 -0000 > > @@ -52,6 +52,7 @@ const struct usbd_quirk_entry { > > u_int16_t bcdDevice; > > struct usbd_quirks quirks; > > } usb_quirks[] = { > > + { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_SOUNDKEY, ANY, { > > UQ_NO_SET_IDLE }}, { USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE, > > 0x100, { UQ_NO_SET_PROTO}}, { USB_VENDOR_INSIDEOUT, > > USB_PRODUCT_INSIDEOUT_EDGEPORT4, 0x094, { UQ_SWAP_UNICODE}}, > > Index: usb_quirks.h > > =================================================================== > > RCS file: /cvs/src/sys/dev/usb/usb_quirks.h,v > > retrieving revision 1.16 > > diff -u -p -u -p -r1.16 usb_quirks.h > > --- usb_quirks.h 19 Jul 2010 05:08:37 -0000 1.16 > > +++ usb_quirks.h 18 Aug 2020 13:36:13 -0000 > > @@ -49,6 +49,7 @@ struct usbd_quirks { > > #define UQ_MS_LEADING_BYTE 0x00010000 /* mouse sends unknown > > leading byte */ #define UQ_EHCI_NEEDTO_DISOWN 0x00020000 /* > > must hand device over to USB 1.1 if attached to EHCI */ > > +#define UQ_NO_SET_IDLE 0x00040000 /* cannot handle > > set idle request */ }; > > > > extern const struct usbd_quirks usbd_no_quirk; > > Index: usbdevs > > =================================================================== > > RCS file: /cvs/src/sys/dev/usb/usbdevs,v > > retrieving revision 1.720 > > diff -u -p -u -p -r1.720 usbdevs > > --- usbdevs 3 Aug 2020 14:25:44 -0000 1.720 > > +++ usbdevs 18 Aug 2020 13:36:14 -0000 > > @@ -3009,6 +3009,7 @@ product MGE UPS2 0xffff > > UPS /* Microchip Technology, Inc. products */ > > product MICROCHIP USBLCD20X2 0x0002 USB-LCD-20x2 > > product MICROCHIP USBLCD256X64 0xc002 USB-LCD-256x64 > > +product MICROCHIP SOUNDKEY 0xf0bf Cyrus soundKey > > > > /* Microdia / Sonix Techonology Co., Ltd. products */ > > product MICRODIA YUREX 0x1010 YUREX > >