Support HID-only probes with no USB string descriptors (pico2-debug)#1988
Open
ajsb85 wants to merge 2 commits into
Open
Support HID-only probes with no USB string descriptors (pico2-debug)#1988ajsb85 wants to merge 2 commits into
ajsb85 wants to merge 2 commits into
Conversation
…bug) Four issues prevented pico2-debug (VID:PID 1209:2488, Dapper Miser CMSIS-DAP) from being usable on Linux: 1. 1209:2488 not in KNOWN_CMSIS_DAP_IDS — probe was silently skipped even when the HID interface was clearly CMSIS-DAP capable. 2. pyusb backend reads USB string descriptors (product, manufacturer, serial) during enumeration via control transfers. Devices that have no string descriptor support (no LangID table) raise ValueError or USBError on these reads, crashing the scan. Wrap all three reads in try/except so the probe is still discovered and gets a synthesised unique ID from its bus location. 3. Linux backend defaulted to pyusb. pyusb sends SET_CONFIGURATION and other control transfers that crash HID-only firmware. Switch Linux default to hidapiusb when available; fall back to pyusb only when hidapi is absent. 4. DAPAccessCMSISDAP.open() left the HID interface open on failure. If setup fails after _interface.open() (e.g. CMSIS-DAP identify() times out because the probe is not yet ready), _is_open stays False. A subsequent open() attempt then calls open_path() on an already-open hid.device, raising RuntimeError: already open. Wrap the post-open setup block in try/except and call _interface.close() before re-raising so the caller can retry. Tested with pico2-debug v11.00 on a Seeed Studio XIAO RP2350 (RP2350 A2) connected via WSL2 on Windows using usbipd-win. After these fixes, pyocd list, pyocd flash, and pyocd cmd all work correctly with pico2-debug. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
get_all_connected_interfaces() was calling hid.device(vid, pid, path) which auto-opens the device during enumeration. When _TemporaryOpen later called open() → open_path(), it created a second file descriptor. After _TemporaryOpen.__exit__ closed one FD, the subsequent session.open() call tried open_path() on the closed hid.device object — but after close() the underlying hid_device* pointer is freed, so the call fails with OSError: open failed. Fix: create an unopened hid.device() during enumeration, and always assign a fresh hid.device() at the start of open() so each open/close cycle starts from a clean object state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes four issues that together prevented pico2-debug (VID:PID
1209:2488, Dapper Miser CMSIS-DAP) from working with pyocd on Linux. pico2-debug is a popular software CMSIS-DAP probe for RP2040/RP2350 that deliberately exposes no USB string descriptors to save RAM.Changes
1.
interface/common.py— Add pico2-debug to known VID:PID list(0x1209, 0x2488)was not inKNOWN_CMSIS_DAP_IDS. Without this, the probe was silently skipped during enumeration whenever the product string was empty (which it always is for pico2-debug).2.
interface/pyusb_backend.py— Wrap all USB string descriptor reads in try/exceptDuring
get_all_connected_interfaces()andFindDap.__call__(), reads ofdev.product,dev.manufacturer, anddev.serial_numberare sent as USBGET_DESCRIPTOR (String)control transfers. Devices with no LangID table respond with a stall, raisingValueError: The device has no langid. These three reads are now wrapped intry/except Exceptionso the probe is still discovered and gets a synthesised unique ID from its bus location.3.
interface/__init__.py— Default Linux backend to hidapiusbLinux was defaulting to the
pyusbbackend. pyusb sendsSET_CONFIGURATIONand other control transfers during enumeration that crash HID-only firmware like pico2-debug, leaving the device in an unresponsive0000:0002 Unknown USB Devicestate. Switch Linux default tohidapiusbwhen available (matching the macOS behaviour); fall back topyusbonly when hidapi is absent.4.
dap_access_cmsis_dap.py— Close interface on setup failure to fix "already open"Session.__init__()callsprobe.create_associated_board()→associated_board_info→_TemporaryOpen. If_interface.open()(HIDopen_path) succeeds but the subsequent CMSIS-DAPidentify()call fails (timeout or protocol error),_is_openis never set toTrue._TemporaryOpen.__exit__skipsclose()because_did_open_linkwas never set. The HID device is left open at the OS level. The realsession.open()then callsopen_path()again and getsRuntimeError: already open. Wrapping the post-open CMSIS-DAP setup intry/exceptand calling_interface.close()before re-raising fixes the double-open.Test plan
pyocd listcorrectly finds and shows1209:2488probe with synthesised unique IDpyocd flash --target rp2350 firmware.elfsuccessfully programs flash through the probepyocd cmd --target rp2350 -c "halt; reg; read32 0x40000000; go"works correctlyPYOCD_USB_BACKEND=pyusb)Related
🤖 Generated with Claude Code