Skip to content

Auto-select COM ports on Windows#2

Merged
ramseymcgrath merged 6 commits into
mainfrom
feat/win-vcom-autoselect
Jun 16, 2026
Merged

Auto-select COM ports on Windows#2
ramseymcgrath merged 6 commits into
mainfrom
feat/win-vcom-autoselect

Conversation

@ramseymcgrath

Copy link
Copy Markdown
Contributor

Summary

On Windows, --device and --virtual-port are now auto-detected, mirroring the existing Unix glob-based auto-discovery. Running hurra-bridge.exe with no flags now Just Works when a Hurra device and a com0com pair are present.

  • Firmware device (--device): a new SetupAPI enumerator walks GUID_DEVCLASS_PORTS and classifies ports by hardware ID. The WCH CH343 (VID_1A86) is auto-selected when exactly one is present; zero or multiple produce a clear error listing what was found.
  • com0com virtual port (--virtual-port): auto-selected (lowest-numbered pair end, since the ends are interchangeable) when the VCOM endpoint is chosen. KMBox endpoint users never need com0com. If no pair exists, the existing "install com0com" guidance is shown — no auto-creation.
  • Explicit flags always override auto-selection.
  • Graceful degradation: enumeration failure falls back to the explicit-flag error paths.

Implementation

  • New serial_enum module: a pure, host-testable hardware-ID classifier (serial_enum.c) plus a Windows SetupAPI enumerator (serial_enum_win32.c) and a non-Windows stub (serial_enum_stub.c).
  • bridge.c wires both auto-selects into main(); the --device-required-on-Windows rejection is removed.
  • setupapi linked on Windows; help text and README updated.

Test Plan

  • Classifier unit tests (tests/serial_enum_test.c, via CTest) — firmware/com0com/other, case-insensitivity, priority, empty/NULL
  • Clean build + full CTest suite pass on macOS (stub path)
  • Windows compile + setupapi link verified by the windows-latest CI job
  • Manual on Windows hardware: no-flag run auto-detects both ports; unplug → "No Hurra device found"; two CH343 → "Multiple Hurra devices found"; explicit --device/--virtual-port override; KMBox endpoint works with no com0com pair

Copilot AI review requested due to automatic review settings June 16, 2026 05:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Windows auto-discovery for the firmware COM port (--device) and com0com virtual port (--virtual-port), aligning Windows behavior with the existing Unix auto-discovery so hurra-bridge.exe can run with no flags in common setups.

Changes:

  • Introduces a new serial_enum module: a pure hardware-ID classifier plus a Win32 SetupAPI enumerator (and a non-Windows stub).
  • Wires Windows auto-selection into bridge.c and updates help/error messaging accordingly.
  • Adds classifier unit tests and updates CMake/README (including linking setupapi on Windows).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/serial_enum_test.c Adds unit tests for the pure HWID classifier logic.
src/serial_enum.h Declares the serial port candidate model + classifier/enumerator API.
src/serial_enum.c Implements the case-insensitive HWID classifier.
src/serial_enum_win32.c Implements COM port enumeration via SetupAPI and classification.
src/serial_enum_stub.c Provides a non-Windows serial_enum() stub returning 0 candidates.
src/bridge.c Integrates Windows auto-detection for --device and --virtual-port; updates usage and failure paths.
README.md Updates Windows quickstart and flag documentation to reflect auto-detection.
CMakeLists.txt Adds new sources/tests and links setupapi on Windows builds.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/serial_enum_win32.c
Comment on lines +63 to +65
char name[32];
if (!read_port_name(set, &dev, name, sizeof name)) continue;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1ea3a29 — skip any PortName beginning LPT during enumeration, so parallel ports don't clutter error listings or consume candidate slots.

Comment thread src/serial_enum.h
Comment on lines +33 to +35
/* Enumerate present COM ports, newest API available per platform. Fills up to
* `max` candidates, returns the count. Returns 0 on failure or non-Windows. */
size_t serial_enum(serial_cand_t *out, size_t max);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Collapsing failure and empty into a single 0 return is intentional here, not an oversight — it's the documented design (spec: "SetupAPI / registry failures degrade to 'zero candidates' → existing explicit error paths fire").

The two states aren't actionably different at the call sites: in both cases the bridge cannot auto-select a port and must fall back to the explicit-flag error path. Distinguishing them would only change error wording, while complicating the API contract (out-param or sentinel) that every caller has to handle. That's the graceful degradation the summary refers to — a failed SetupAPI call lands on the same clean bridge_fail as 'no device plugged in', never a crash. Keeping the simple size_t count contract on purpose (YAGNI).

GUID_DEVCLASS_PORTS covers both COM and LPT devices; filter out LPT
PortNames so parallel ports don't clutter error listings or consume
candidate slots.
@ramseymcgrath
ramseymcgrath merged commit c3e0e24 into main Jun 16, 2026
9 checks passed
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