From patchwork Mon Jan 9 04:05:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keno Fischer X-Patchwork-Id: 712499 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.coreboot.org (mail.coreboot.org [80.81.252.135]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3txhSQ4sxLz9t0P for ; Mon, 9 Jan 2017 15:07:18 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=juliacomputing-com.20150623.gappssmtp.com header.i=@juliacomputing-com.20150623.gappssmtp.com header.b="KpUuANnG"; dkim-atps=neutral Received: from [127.0.0.1] (helo=ra.coresystems.de) by mail.coreboot.org with esmtp (Exim 4.86_2) (envelope-from ) id 1cQRDe-0007c1-OL; Mon, 09 Jan 2017 05:06:02 +0100 Received: from mail-qk0-f170.google.com ([209.85.220.170]) by mail.coreboot.org with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.86_2) (envelope-from ) id 1cQRDU-0007ba-Oz for flashrom@flashrom.org; Mon, 09 Jan 2017 05:05:59 +0100 Received: by mail-qk0-f170.google.com with SMTP id u25so513688790qki.2 for ; Sun, 08 Jan 2017 20:05:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=juliacomputing-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:subject:message-id:mime-version:content-disposition :user-agent; bh=RSGFBMQZnxUNHkOm4p7yFtfVMD5BzXzxGgmhzQhOB/k=; b=KpUuANnGdCGRB0qCztb7GByR++7FjdaxfVxflAGXbcCmm40oVQC91ocfk0FbeW6kh2 tePqN1jtCXJkBOgSoCJFu7wEEV2iIXHu0sZPS+g3tmb7KL8YWZs9x6w3z8r3LngRDsGL BBR+7Y5Vgf9lpgU7626rTGAh9wdirqY90plsbCI8bSCio+zZ1QyLIhBwSobMMKm0as93 Rkp2B0yHn35iAYHYBZhad4uCy46fR1ZBlho2jdKaC8f1M44Qr6SMO22j9vMqej2CAbki t3h6+NSnEbNDR8i2HLU+U6ZnZSRmiWcY+IUpYS7bdKC3kXh9lIQE6wHcFqht1DpbZwTH wO8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition:user-agent; bh=RSGFBMQZnxUNHkOm4p7yFtfVMD5BzXzxGgmhzQhOB/k=; b=dRgUOd1ajtWPsmp4pF4CpqA5dUtngozrx7rgSBucINYF1EGSfWKAGsyV5Z322ETUnw +o2/qn8wVc+tp5JnNwhLjyFybMJZx2nABbE9cYsNPpbkw2d67iSkgaxgPAvAOyemqQPE pynw4XZgAllfWG3SuxO5eDQvQ7uBo0vLAjCaY67KcYew5UgvQsXmCvyRZAtth6DVzs9f ZmEUytdn2HeZirL+RAspINNFA+7WEOmVn1g2R55D3FoL0rJqF2Tf1+h8pvoaLU1Twl/0 KGzjCr+grGdcac8V87kZznB+93mi85+HyaekWOmi1dSJwnxvy+c/Uj5xedblELlcuxjn tVzg== X-Gm-Message-State: AIkVDXKQEozzUCyBU0NJa8rSG9OGE6PNJy2bhcjPIiC20XG+oFCOEhVDH8Zd/dhcik6Eb7Sd X-Received: by 10.55.43.149 with SMTP id r21mr92246583qkr.123.1483934750471; Sun, 08 Jan 2017 20:05:50 -0800 (PST) Received: from juliacomputing.com ([2601:184:4380:e6e:102a:a31c:48eb:f476]) by smtp.gmail.com with ESMTPSA id q53sm56649616qtq.0.2017.01.08.20.05.49 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 08 Jan 2017 20:05:50 -0800 (PST) Date: Sun, 8 Jan 2017 23:05:48 -0500 From: Keno Fischer To: flashrom@flashrom.org Message-ID: <20170109040548.GA15650@juliacomputing.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.6.1 (2016-04-27) X-Spam-Score: -1.6 (-) Subject: [flashrom] [PATCH] Give warning for CH341A programmer in alternate mode X-BeenThere: flashrom@flashrom.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: flashrom discussion and development mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: flashrom-bounces@flashrom.org Sender: "flashrom" X-Duff: Orig. Duff, Duff Lite, Duff Dry, Duff Dark, Raspberry Duff, Lady Duff, Red Duff, Tartar Control Duff My programmer with this chip has a jumper to select between USB <-> UART translation and USB <-> SPI translation. Only the latter is applicable for use as an SPI programmer of course, but it's an easy and non-obvious mistake to make. The UART mode (and a printer mode not exposed on my programmer, but available on the chip according to the datasheet), are indicated through different USB IDs, which we can easily detect. Do so, and print an informative warning when such a device is detected. Signed-off-by: Keno Fischer --- ch341a_spi.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/ch341a_spi.c b/ch341a_spi.c index 6eb2804..7eba6b1 100644 --- a/ch341a_spi.c +++ b/ch341a_spi.c @@ -93,6 +93,16 @@ const struct dev_entry devs_ch341a_spi[] = { {0}, }; +/* The CH341A has alternate modes, indicated as different USB device IDs and + * generally selectible on programmers via jumpers. Those alternate modes are + * unsuitable for use as a programmer, but we want to be able to detect them, + * to give a nice error message to the user. */ +const struct dev_entry devs_ch341a_spi_alternate[] = { + {0x1A86, 0x5523, OK, "Winchiphead (WCH)", "CH341A Serial"}, + {0x1A86, 0x5584, OK, "Winchiphead (WCH)", "CH341A Printer"}, + {0}, +}; + enum trans_state {TRANS_ACTIVE = -2, TRANS_ERR = -1, TRANS_IDLE = 0}; static void print_hex(const void *buf, size_t len) @@ -431,6 +441,47 @@ static int ch341a_spi_shutdown(void *data) return 0; } +static bool device_matches(const struct libusb_device_descriptor *desc, const struct dev_entry *entry) +{ + return desc->idVendor == entry->vendor_id && desc->idProduct == entry->device_id; +} + +static struct libusb_device_handle *ch341a_find_device() +{ + struct libusb_device *dev, **devs; + struct libusb_device_handle *dev_handle = NULL; + size_t i = 0; + + if (libusb_get_device_list(NULL, &devs) < 0) + return dev_handle; + + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + const struct dev_entry *entry; + if (libusb_get_device_descriptor(dev, &desc) < 0) + goto out; + for (entry = devs_ch341a_spi_alternate; entry->vendor_id != 0; ++entry) { + if (device_matches(&desc, entry)) { + msg_pwarn("CH341A device in alternate mode detected.\n" + "There may be a jumper on your programmer to switch modes.\n"); + } + } + for (entry = devs_ch341a_spi; entry->vendor_id != 0; ++entry) { + if (device_matches(&desc, entry)) { + if (dev_handle) { + msg_pwarn("Multiple CH341A devices detected. Selecting the first.\n"); + goto out; + } + libusb_open(dev, &dev_handle); + } + } + } + +out: + libusb_free_device_list(devs, 1); + return dev_handle; +} + int ch341a_spi_init(void) { if (handle != NULL) { @@ -444,13 +495,11 @@ int ch341a_spi_init(void) return -1; } - libusb_set_debug(NULL, 3); // Enable information, warning and error messages (only). + libusb_set_debug(NULL, 4); // Enable information, warning and error messages (only). - uint16_t vid = devs_ch341a_spi[0].vendor_id; - uint16_t pid = devs_ch341a_spi[0].device_id; - handle = libusb_open_device_with_vid_pid(NULL, vid, pid); + handle = ch341a_find_device(); if (handle == NULL) { - msg_perr("Couldn't open device %04x:%04x.\n", vid, pid); + msg_perr("No usable CH341A USB device found.\n"); return -1; }