Clearing stalls: usbd_xfer_set_stall vs usbd_do_clear_stall_callback

Trevor Blackwell trevor at anybots.com
Thu May 5 01:39:25 UTC 2011


We have a system that experiences occasional stalls due to ESD strikes in
the cable between the host & hub. So I've been extensively testing the clear
stall logic.

It's done two different ways in the standard drivers. In if_cdce it's:

if (error != USB_ERR_CANCELLED) {
                        usbd_xfer_set_stall(xfer);
usbd_transfer_submit(xfer);
}

In the midi part of uaudio it's done by setting up special control transfers
and keeping state in the driver:

 if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
chan->flags |= UMIDI_FLAG_READ_STALL;
usbd_transfer_start(chan->xfer[3]);
}
...
static void
umidi_read_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umidi_chan *chan = usbd_xfer_softc(xfer);
struct usb_xfer *xfer_other = chan->xfer[1];

if (usbd_clear_stall_callback(xfer, xfer_other)) {
DPRINTF("stall cleared\n");
chan->flags &= ~UMIDI_FLAG_READ_STALL;
usbd_transfer_start(xfer_other);
}
}

The first sure is simpler, but it doesn't seem to work. Stalls never get
cleared. Tracing through the code, it's not clear how the clear stall
request is supposed to get filled in. I can see that usb_xfer_set_stall
ultimately leads to a call to usbd_clear_stall_proc, but I can't find where
udev->ctrl_xfer[1] gets set up with the right endpoint values.



-- 
Trevor Blackwell    trevor at anybots.com    650 776 7870


More information about the freebsd-usb mailing list