From e74ad9434c1c0fb00537d4c10b82bfbc8d7603ae Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 18 Jun 2026 19:37:49 +0100 Subject: [PATCH] Utilise str_set_vid_pid_serno() for ch341a.c --- src/avrdude.1 | 9 +++++---- src/avrftdi.c | 2 +- src/ch341a.c | 32 ++++++++++++++++++-------------- src/doc/avrdude.texi | 7 ++++--- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index 7c458e78..3650e411 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -613,18 +613,19 @@ they are automatically identified via their vendor and product IDs from avrdude.conf or .avrduderc. Only when there are multiple programmers of the same type plugged into the host computer is the -P option needed, see below. Some -c programmers, however, ignore the -P option altogether, eg, -pickit2, teensy or ch341a; these cannot distinguish multiple plugged-in +pickit2 or teensy; these cannot distinguish multiple plugged-in programmers. .Pp -Most USB programmers, however, support the command-line syntax -P +Most USB programmers, however, support the command-line syntax -P usb[::][:] which allows the user to override the vendor and product IDs with hexadecimal numbers and and/or request a match of the desired device's serial number with . The match is done after stripping any existing colons from the given serial number on the command line, and right-to-left, so only the least significant bytes from the serial number need to be given. The JTAG ICE -mkII, JTAGICE3, SNAP, PICKit5 and avrftdi programmers are examples for -this -P port syntax. +mkII, JTAGICE3, SNAP, PICKit5, CH341A and avrftdi programmers are examples +for this -P port syntax. Some of these in turn, e.g. the CH341A, are not +capable of matching serial numbers. .Pp If .Nm diff --git a/src/avrftdi.c b/src/avrftdi.c index d2ade11e..15596d43 100644 --- a/src/avrftdi.c +++ b/src/avrftdi.c @@ -645,7 +645,7 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) { pmsg_debug("%s(\"%s\")\n", __func__, port); - // Override/set pid, vid and/or serno from -P usb[::][:] + // Set new_vid, new_pid and/or serno from -P usb[::][:] if((numids = str_set_vid_pid_serno(port, &new_vid, &new_pid, serno, sizeof serno)) < 0) { pmsg_error("invalid -P %s; drop -P option or use -P usb[::][:]\n", port); return LIBAVRDUDE_EXIT_FAIL; diff --git a/src/ch341a.c b/src/ch341a.c index 3a71ac3b..883fbc65 100644 --- a/src/ch341a.c +++ b/src/ch341a.c @@ -196,29 +196,33 @@ bool CH341ChipSelect(const PROGRAMMER *pgm, unsigned int cs, bool enable) { } static int ch341a_open(PROGRAMMER *pgm, const char *port) { - LNODEID usbpid = lfirst(pgm->usbpid); - int pid, vid, j, r; + int pid, vid, j, r, numids; int errorCode = USB_ERROR_NOTFOUND; libusb_device_handle *handle = NULL; + char serno[64] = {0}; + unsigned short new_vid = 0, new_pid = 0; pmsg_debug("%s(\"%s\")\n", __func__, port); - if(!str_caseeq(port, "usb")) - pmsg_warning("option -P %s ignored\n", port); + + // Set new_vid, new_pid and/or serno from -P usb[::] + if((numids = str_set_vid_pid_serno(port, &new_vid, &new_pid, serno, sizeof serno)) < 0) { + pmsg_error("invalid -P %s; drop -P option or use -P usb[::]\n", port); + return LIBAVRDUDE_EXIT_FAIL; + } + if(*serno) + pmsg_warning("ignoring serial number %s given in -P %s\n", serno, port); + + // Set vid/pid in following priority: command-line, config, default + vid = numids >= 2? new_vid: pgm->usbvid? pgm->usbvid: CH341A_VID; + LNODEID usbpid = lfirst(pgm->usbpid); + pid = numids >= 2? new_pid: usbpid? *(int *) ldata(usbpid): CH341A_PID; + if(numids < 2 && usbpid && lnext(usbpid)) + pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid); if(!my.USB_init) { my.USB_init = 1; libusb_init(&my.ctx); } - - if(usbpid) { - pid = *(int *) ldata(usbpid); - if(lnext(usbpid)) - pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid); - } else { - pid = CH341A_PID; - } - vid = pgm->usbvid? pgm->usbvid: CH341A_VID; - libusb_device **dev_list; int dev_list_len = libusb_get_device_list(my.ctx, &dev_list); diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 946d60ff..a7bcc128 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -840,7 +840,7 @@ they are automatically identified via their vendor and product IDs from @code{avrdude.conf} or @code{.avrduderc}. Only when there are multiple programmers of the same type plugged into the host computer is the @code{-P} option needed, see below. Some @code{-c} programmers, however, -ignore the @code{-P} option altogether, eg, pickit5, teensy or ch341a; +ignore the @code{-P} option altogether, eg, pickit5 or teensy; these cannot distinguish multiple plugged-in programmers. Most USB programmers, however, support the command-line syntax @code{-P @@ -850,8 +850,9 @@ override the vendor and product IDs with hexadecimal numbers @var{vid} and with @var{serialno}. The match is done after stripping any existing colons from the given serial number on the command line, and right-to-left, so only the least significant bytes from the serial number need to be given. -The JTAG ICE mkII, JTAGICE3, SNAP, PICKit5 and avrftdi programmers are -examples for this @code{-P} port syntax. +The JTAG ICE mkII, JTAGICE3, SNAP, PICKit5, CH341A and avrftdi programmers +are examples for this @code{-P} port syntax. Some of these in turn, e.g. +the CH341A, are not capable of matching serial numbers. If avrdude has been configured with libserialport support, a serial port can be specified using a predefined serial adapter type in