Date: Mon, 19 Nov 2012 21:57:22 -0500 From: Mark Johnston <markjdb@gmail.com> To: freebsd-usb@freebsd.org Subject: [patch] fix uplcom(4) clear stall logic for PL2303HX Message-ID: <20121120025722.GA3338@oddish>
next in thread | raw e-mail | index | archive | help
Hello all, I recently bought a PL-2303 USB to serial converter (VID 0x067b, DID 0x2303) to use with an ARM board. When I start cu(1) and power on the board no messages show up, and if I enter any input, cu exits without printing anything and uplcom detaches and reinitializes itself. No error messages are printed by the kernel - all I see is that uplcom(4) disconnects and reattaches. After some debugging I found that when the USB stack sends a ENDPOINT_HALT clear to the OUT bulk endpoint, the hw seems to respond with an endpoint stalled error, and after that, the uplcom callbacks are called with error set to USB_ERROR_CANCELLED. I looked at the Linux driver for this device and found the following code in pl2303.c: if (priv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); } else { /* reset upstream data pipes */ pl2303_vendor_write(8, 0, serial); pl2303_vendor_write(9, 0, serial); } Unfortunately, I couldn't find any datasheets which indicate what these vendor-specific commands mean. However I ended up with the patch below, and now the device works perfectly. :) In particular, it seems that we don't want to send a clear ENDPOINT_HALT request to the HX variant of the device, which is what I have. I noticed that the device still seems to work if I omit the vendor commands, and being a total USB newbie I thought I'd ask the following questions: 1. What exactly is the purpose of clearing ENDPOINT_HALT when a userspace program attaches to a device? Is it just to make sure that the device fw is in some known good state before starting to transmit data? 2. uplcom(4) tries to clear any stalls after an error in its r/w and intr callbacks. Is there some way I can trigger an error so that I can test and fix that code too? I'm happy to test alternative fixes, provide debug output, etc., etc. Thanks, -Mark diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c index 4549bad..4d9ac32 100644 --- a/sys/dev/usb/serial/uplcom.c +++ b/sys/dev/usb/serial/uplcom.c @@ -433,10 +433,18 @@ uplcom_attach(device_t dev) goto detach; } /* clear stall at first run */ - mtx_lock(&sc->sc_mtx); - usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); - usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); - mtx_unlock(&sc->sc_mtx); + if (sc->sc_chiptype != TYPE_PL2303HX) { + mtx_lock(&sc->sc_mtx); + usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); + usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); + mtx_unlock(&sc->sc_mtx); + } else { + if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, + UPLCOM_SET_REQUEST, 8, 0, 0) || + uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, + UPLCOM_SET_REQUEST, 9, 0, 0)) + goto detach; + } error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, &uplcom_callback, &sc->sc_mtx); @@ -555,9 +563,6 @@ uplcom_pl2303_init(struct usb_device *udev, uint8_t chiptype) if (err) return (EIO); - if (uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 8, 0, 0) - || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 9, 0, 0)) - return (EIO); return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20121120025722.GA3338>