From owner-freebsd-usb@FreeBSD.ORG Tue Nov 20 02:57:50 2012 Return-Path: Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id EDC7A4FF for ; Tue, 20 Nov 2012 02:57:49 +0000 (UTC) (envelope-from markjdb@gmail.com) Received: from mail-ie0-f182.google.com (mail-ie0-f182.google.com [209.85.223.182]) by mx1.freebsd.org (Postfix) with ESMTP id B085D8FC12 for ; Tue, 20 Nov 2012 02:57:49 +0000 (UTC) Received: by mail-ie0-f182.google.com with SMTP id s9so1692915iec.13 for ; Mon, 19 Nov 2012 18:57:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:subject:message-id:mime-version:content-type :content-disposition:user-agent; bh=ad7b5dOLuI0rBrjg/L/YdHWg/BbjhewOaDaznyqfVGI=; b=AwH7jviFFRgYVOmbE7gDA5qRG0aZCDhG+Ib/9qQAOdtSg1qEbhhDMOP1PUmxWC0Ltu h1aucrHxw5f7SDG7NPza0J8H0oymKTtxxhA1GGgoLgw8PSJOp9OaDLS5GPgJPwdi50/o pq6mreWRNaoMNTT49+ez9HUwQ26CTmgJS3HseIY+oxkrTyyqz7o4ArN5OAzJ9JKSzpU/ L69FSx5zIceSbzpM/NgklQSEdAxRhLcv2yFIK/WNL/IPUXz3sbu1F++/kkNPqiS0Ye36 h6WEx4L9cU0QK/629bg3CzUBzUI3+RO1B2t41Xptu9R2j2T0JJQLt3y/5LrCOFCzJlQa F9BA== Received: by 10.50.173.37 with SMTP id bh5mr8798427igc.45.1353380268775; Mon, 19 Nov 2012 18:57:48 -0800 (PST) Received: from oddish ([66.11.160.25]) by mx.google.com with ESMTPS id gs6sm9391544igc.11.2012.11.19.18.57.47 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 19 Nov 2012 18:57:48 -0800 (PST) Date: Mon, 19 Nov 2012 21:57:22 -0500 From: Mark Johnston To: freebsd-usb@freebsd.org Subject: [patch] fix uplcom(4) clear stall logic for PL2303HX Message-ID: <20121120025722.GA3338@oddish> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Nov 2012 02:57:50 -0000 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); }