USB CDC ACM DTR and RTS Control Line Debugging

Debug CDC ACM DTR and RTS by tracing SET_CONTROL_LINE_STATE, line coding, serial-port open and close, bootloader reset, re-enumeration, and first bulk data.

usb cdc acm, dtr, rts, set control line state, serial port, bootloader reset, usb diagnostics

A CDC ACM serial port can bind and open successfully while firmware sends no data, resets into a bootloader, or disappears as soon as a terminal connects. The missing evidence is often the USB class-control sequence: SET_LINE_CODING, SET_CONTROL_LINE_STATE, DTR and RTS bits, and the first bulk transfers before or after those requests.

Direct answer: capture enumeration, application open, line-coding requests, every control-line-state transition, and the first bulk IN/OUT traffic. Compare a failing application with a working terminal. Determine whether firmware gates transmission on DTR, interprets RTS as flow control, uses a DTR/RTS edge as reset, or re-enumerates under a different identity.

Bus Scope can prove the class requests, bit values, endpoint traffic, reset, and descriptor sequence visible on USB. It cannot prove what a serial API intended before the driver translated it, so include application settings and logs when two tools produce different requests.

The control-line request is an interface request

CDC ACM's SET_CONTROL_LINE_STATE is a host-to-device class request addressed to the communication-class interface. Its value carries control signals:

Bit Common name Typical meaning
0 DTR Data Terminal Ready
1 RTS Request To Send

The exact firmware policy can go beyond traditional modem semantics. A device may:

  • start telemetry only when DTR is asserted;
  • stop streaming when DTR drops;
  • use a DTR transition to reset;
  • combine DTR and RTS edges for bootloader entry;
  • expose RTS to an external transceiver;
  • ignore both bits but still acknowledge the request.

Decode wIndex too. It identifies the target CDC control interface. Composite firmware that hard-codes interface zero can stall or ignore a valid request after interface numbering changes.

Record line coding and line state separately

SET_LINE_CODING and SET_CONTROL_LINE_STATE are different requests. Line coding carries serial-format values such as baud rate, stop bits, parity, and data bits. Control-line state carries DTR and RTS bits.

Build a chronological table:

Time Request Value Device behavior
0.000 s SET_LINE_CODING 115200 8N1 completes
0.003 s SET_CONTROL_LINE_STATE DTR=1, RTS=0 completes
0.008 s bulk IN first telemetry completes
5.100 s SET_CONTROL_LINE_STATE DTR=0, RTS=0 completes
5.120 s bulk IN none stream stops

This separates "wrong baud rate" from "firmware waited for DTR." For many USB-native CDC implementations, baud rate does not change a physical UART, but firmware can still use or validate it.

Serial-port open is a sequence, not one event

Different applications and drivers can perform different sequences:

  • set line coding before asserting DTR;
  • assert DTR immediately;
  • preserve an existing DTR state;
  • toggle DTR during open;
  • assert or deassert RTS according to flow-control settings;
  • issue class requests again after configuration changes;
  • drop both lines on close.

Compare bus evidence rather than UI checkboxes:

Application Line coding DTR after open RTS after open First data
working terminal 115200 8N1 1 1 immediate
failing script 115200 8N1 0 0 none
updater 1200 8N1 toggles toggles device resets

If only DTR differs, change the host test deliberately or document the firmware gate. If USB requests are identical, move to endpoint traffic or application parsing.

No data until DTR

Many devices intentionally wait for a host connection signal before producing data. A clear trace is:

  1. configuration completes;
  2. bulk IN endpoint exists;
  3. host opens the port;
  4. SET_CONTROL_LINE_STATE asserts DTR;
  5. telemetry starts.

If the failing application never asserts DTR, the cable and descriptor are not the primary issue. Decide whether the host should assert it or firmware should not require it.

Also inspect close behavior. If DTR drops and firmware discards buffers or enters low power, a rapid reopen can race with that transition. Capture both close and reopen.

Bootloader reset patterns

Development boards and embedded products often use control-line transitions for automated reset. Common patterns include:

  • DTR falling edge drives reset;
  • DTR and RTS are combined through hardware;
  • opening at a special baud rate then closing triggers bootloader;
  • a line-state sequence sets a firmware boot flag;
  • application firmware disconnects and bootloader reconnects with another PID.

Prove the transition:

Stage USB evidence
application opens old port class requests on original identity
DTR/RTS transition setup packet and value
device disappears disconnect or reset
bootloader enumerates new descriptor sequence
updater opens new interface class or vendor traffic on new identity

If the application retains the old port handle after re-enumeration, subsequent timeouts are expected. The host must rediscover the bootloader identity.

The USB serial COM port disappearance guide covers identity and handle recovery.

Decode DTR and RTS as transitions

The value at one moment is less informative than the transition history:

  • 0 → DTR;
  • DTR → DTR+RTS;
  • DTR+RTS → RTS;
  • RTS → 0.

Firmware bugs often trigger on an edge:

  • reset fires on both assertion and deassertion;
  • debounce or timer logic sees two rapid edges;
  • state is initialized incorrectly after resume;
  • a repeated identical request is treated as a new edge;
  • interface-routing code sends one function's line state to another.

Record previous and new values in firmware logs, and match them to USB timestamps.

RTS is not proof of physical hardware flow control

USB CDC ACM can carry RTS state even when the device has no physical RTS pin. Host UI options such as "hardware flow control" can change line-state requests, but the USB bulk endpoint itself does not become a UART wire.

Ask:

  • Does firmware expose RTS to a UART or transceiver?
  • Does it gate bulk IN or OUT on RTS?
  • Is CTS reported through serial-state notifications?
  • Does the host application expect RTS/CTS semantics?
  • Is RTS repurposed for reset or mode selection?

Document repurposed behavior. Otherwise a user may enable flow control and unintentionally trigger a bootloader.

Serial-state notifications are another path

CDC communication interfaces can expose an interrupt IN endpoint for notifications such as serial-state changes. If firmware claims modem-line behavior, capture those notifications too.

Check:

  • notification endpoint address;
  • target interface;
  • notification type and length;
  • bitmap meaning;
  • relationship to DTR/RTS requests and bulk traffic.

Do not confuse host-to-device DTR/RTS control with device-to-host status notification. They travel in different directions and answer different questions.

Missing bulk data after valid line state

If DTR and RTS are as expected and requests complete, continue down the data path:

  1. validate CDC data-interface bulk endpoint addresses;
  2. check whether an OUT command is required before IN data;
  3. compare requested and completed lengths;
  4. inspect endpoint STALL or timeout;
  5. check firmware buffer priming;
  6. verify the application opened the intended port instance.

A successful control-line request does not prove bulk queues are ready. Use the USB endpoint timeout guide for that layer.

Composite CDC descriptor checks

CDC ACM commonly uses a communication interface plus a data interface. Validate:

  • Interface Association Descriptor range where used;
  • CDC union descriptor master and subordinate interfaces;
  • communication interface class tuple;
  • notification endpoint;
  • data interface bulk IN and OUT endpoints;
  • actual wIndex in class requests.

If the COM port never appears, fix descriptors and binding before analyzing DTR. The USB composite-device guide covers that parent problem.

Cross-platform comparisons

A Windows terminal, Linux terminal, browser serial API, Python library, and firmware updater can drive DTR and RTS differently. Keep the test controlled:

  • same physical device and firmware;
  • same port and topology;
  • same requested serial settings;
  • same open/wait/write/close timing;
  • exact class-request timeline;
  • exact first bulk exchange.

Do not conclude "Linux supports the device but Windows does not" if the only difference is application policy. Name the first differing setup request or transition.

A repeatable CDC line-state workflow

  1. Record firmware, VID, PID, serial, OS, driver, and application version.
  2. Capture from connection through port open and close.
  3. Map CDC communication and data interfaces.
  4. Decode line-coding requests.
  5. Decode every control-line-state value and transition.
  6. Mark DTR and RTS separately.
  7. Correlate each transition with bulk traffic and firmware behavior.
  8. Detect reset, disconnect, and re-enumeration.
  9. Compare with a working application.
  10. Check first data after reopen and resume.
  11. Save a bounded .bscope session and sequence table.

Use Bus Scope platform capture to select the correct USBPcap controller or usbmon bus.

QA questions

Why does the CDC port open but send no data?

Firmware may wait for DTR, require an initialization command, have unprimed bulk buffers, or be bound to a different port instance. Trace control-line state and first bulk transfers before changing baud rate blindly.

Does baud rate matter for a USB CDC device?

It can. Some firmware configures a physical UART; other firmware treats the rate as metadata or a command trigger. The capture proves what line coding the host sent, while device design defines its effect.

Why does opening the serial monitor reset the device?

The monitor or driver may toggle DTR or RTS, and hardware or firmware may use that edge as reset or bootloader entry. Capture the transition followed by disconnect and new enumeration.

Is RTS the same as USB flow control?

No. It is a control-line state carried by the CDC class request. Whether it controls a physical line, gates firmware, or is ignored depends on the device implementation.

Can Bus Scope prove what the application intended?

It can prove the USB requests and transfers produced by the application/driver stack. Application settings and source logs are needed to prove intent before that translation.

Final diagnosis

A CDC ACM line-state bug becomes specific when the report states which interface received which DTR/RTS transition, what firmware did next, and whether the device continued, reset, or re-enumerated. Capture open and close as sequences, then assign the fix to host policy, descriptor routing, firmware line-state handling, bootloader recovery, or bulk endpoint operation.

Archive the decoded control request beside the matching endpoint traffic and the application action that triggered it. This proves whether the failure follows line-state policy or only appears later in the data path.

<!-- multilingual-related-reading:start -->

Related guides

Continue with the same-language pages below. They cover adjacent stages without changing the canonical owner of this topic:

<!-- multilingual-related-reading:end -->