Skip to content

esp_usb_jtag: support multiple boards (--busdev-num, --esp-serial)#665

Merged
trabucayre merged 2 commits into
trabucayre:masterfrom
r4d10n:esp_usb_jtag
May 15, 2026
Merged

esp_usb_jtag: support multiple boards (--busdev-num, --esp-serial)#665
trabucayre merged 2 commits into
trabucayre:masterfrom
r4d10n:esp_usb_jtag

Conversation

@r4d10n
Copy link
Copy Markdown
Contributor

@r4d10n r4d10n commented May 14, 2026

Summary

  • libusb_open_device_with_vid_pid() returns the first VID:PID match, so with two ESP32-S3 cables connected, every invocation programmed the same board. Replace it with libusb_get_device_list() iteration that honours cable.bus_addr / cable.device_addr (already exposed via --busdev-num) and a new --esp-serial flag that matches the device iSerialNumber by substring.
  • The -d /dev/ttyACM* path cannot help: that's the CDC-ACM interface (iface 0), while JTAG is the vendor iface 2 reached via libusb; the two enumeration orderings are independent.
  • --ftdi-serial semantics are unchanged (FTDI cables only); the new --esp-serial is gated to MODE_ESP.

Test plan

  • Single-board path still works (-c esp32s3 --detect with one board)
  • --busdev-num <bus>:<dev> selects each of two connected boards
  • --esp-serial <substring> selects each of two connected boards (verified with the last byte of the MAC-derived serial: :84 vs :94)
  • Bogus serial / bus / mismatched-pair invocations all fail with a clear error echoing the supplied selectors
  • Cross-filter test (matching serial of board A combined with bus/dev of board B) is rejected — proves AND semantics across filters
  • Tested only on Linux; macOS/Windows libusb behaviour unverified

🤖 Generated with Claude Code

@trabucayre trabucayre force-pushed the esp_usb_jtag branch 2 times, most recently from 0f2106a to 2c86870 Compare May 14, 2026 16:19
…-serial-num

libusb_open_device_with_vid_pid() returns the first VID:PID match, so
with two ESP32-S3 cables connected, every invocation programmed the
same board. Replace it with a libusb_get_device_list() iteration that
also honours cable.bus_addr/device_addr (already exposed as
--busdev-num) and --usb-serial-num flag that matches the device
iSerialNumber by substring (useful with MAC-derived serials).

The -d /dev/ttyACM* path could not help: that's the CDC-ACM interface
(iface 0), while JTAG is on the vendor iface 2 reached via libusb;
ttyACM numbering and libusb enumeration order are independent.

Constraint: must keep existing single-board invocations working without flag changes
Confidence: high
Scope-risk: narrow
Directive: arguments struct uses positional aggregate init at main.cpp:120; new fields must add a matching slot
Not-tested: simultaneous two-board programming on real hardware (single-board path verified to build)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@trabucayre
Copy link
Copy Markdown
Owner

Hi @r4d10n
I have updated your PR with small things:

  • rebased branch to current master
  • ftdi-serial is now deprecated in favor of usb-serial-num
  • updated the README.md

Could you check/verify the code please?
Thanks

@r4d10n
Copy link
Copy Markdown
Contributor Author

r4d10n commented May 14, 2026

Looks good 👍

@trabucayre trabucayre merged commit 79aa75d into trabucayre:master May 15, 2026
14 checks passed
@trabucayre
Copy link
Copy Markdown
Owner

Applied.
Thanks @r4d10n !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants