USB Endpoint Halt Recovery with CLEAR_FEATURE

Trace USB endpoint halt recovery from the first STALL through CLEAR_FEATURE ENDPOINT_HALT, endpoint direction, data-toggle reset, retry, protocol state, and device reset.

usb endpoint halt, clear feature endpoint halt, usb stall loop, bulk transfer failed, usb reset, usb diagnostics

CLEAR_FEATURE(ENDPOINT_HALT) can recover USB transport state, but it does not make the command that caused a STALL valid. When a device works once, stalls a bulk endpoint, appears to recover, and immediately stalls again, the useful evidence is the complete sequence: first failing command, exact endpoint, clear-halt request, status result, first retry, and any later reset.

Direct answer: identify the endpoint address including direction, prove an explicit STALL occurred, and decode the host's standard endpoint-recipient clear-feature request. Confirm that it targets the same endpoint, completes successfully, and is followed by a correctly synchronized transfer. If the next command stalls again, inspect firmware protocol state and command validity rather than repeatedly clearing the endpoint.

Bus Scope can show transfer results, setup fields, endpoint metadata, raw command bytes, and resets in one timeline. It cannot show the private firmware branch that deliberately chose STALL, so pair the capture with device logs or state instrumentation when the bus evidence isolates that branch.

Halt recovery begins with an explicit STALL

Do not start a clear-halt workflow from a generic timeout. Classify the evidence:

Observation Meaning Recovery path
Bulk or interrupt endpoint returns STALL endpoint is halted or reports a stall condition inspect cause and clear halt
Transfer remains incomplete until API timeout no completion before software deadline inspect readiness, queue, or submission
Device disconnects or resets old endpoint context is gone re-enumerate and reopen
Endpoint traffic completes but app reports error USB path may be healthy inspect driver or application

An application can map several conditions to one error code. The capture must contain the actual USB result before the team decides to call libusb_clear_halt, reset a pipe, or reset the entire device.

The USB endpoint STALL and timeout guide covers this classification in more detail.

Endpoint direction is part of identity

Endpoint address 0x81 is endpoint 1 IN. Address 0x01 is endpoint 1 OUT. They can belong to the same interface and share the endpoint number, but they are separate directions and separate recovery targets.

Record:

  • endpoint address in hexadecimal;
  • direction;
  • transfer type;
  • interface and alternate setting;
  • last successful transfer;
  • first STALL;
  • command or response expected at that moment.

A report that says "endpoint 1 stalled" is incomplete. If IN stalled but the host clears OUT, the successful control request does not recover the affected pipe.

Decode the clear-feature request

For standard endpoint halt recovery, inspect the endpoint-recipient control request:

Setup field Expected diagnostic meaning
bmRequestType host-to-device, standard, endpoint recipient
bRequest CLEAR_FEATURE
wValue ENDPOINT_HALT selector
wIndex halted endpoint address, including direction
wLength zero

Then verify the no-data control transfer's status stage. Seeing the setup packet alone does not prove the device accepted it.

Create an evidence line:

Bulk IN 0x82 STALL at 14.228 s;
CLEAR_FEATURE(ENDPOINT_HALT, 0x82) completed at 14.231 s;
first retry completed at 14.234 s.

That statement is actionable. "Clear halt seemed to work" is not.

Transport state and protocol state are separate

The clear-feature request addresses endpoint transport state. Firmware may also maintain:

  • current application command;
  • expected message phase;
  • partial payload length;
  • checksum or framing state;
  • buffer ownership;
  • class-specific error status;
  • bootloader or update state.

If firmware clears only the controller halt bit but leaves an invalid command pending, the first retry can enter the same error branch. Conversely, firmware can reset all application state on clear halt even when the protocol expects a narrower recovery, causing data loss.

Document the product contract:

Condition USB action Protocol action
unsupported command STALL response endpoint discard command and await next header
checksum failure defined error response or STALL reset frame parser
host abort clear halt if needed release partial buffer
severe internal fault device reset reconnect and renegotiate session

The correct protocol action is product-specific; the USB trace proves whether the documented action occurred.

Data-toggle synchronization matters

Bulk and interrupt transfers use data-toggle sequencing to detect duplicate transactions. Standard halt clearing includes defined synchronization behavior for the affected endpoint. Device controller hardware or firmware must implement the recovery correctly.

Symptoms of synchronization trouble can include:

  • clear-feature request completes, but every retry fails;
  • a retry appears duplicated or is ignored;
  • direct device reset recovers while clear halt does not;
  • one controller driver works and another repeats the failure.

Do not manually force toggle state from application code without understanding the host-controller and device-controller responsibilities. Capture the first transfer after recovery and compare with a known-good implementation.

Find the command that caused the first STALL

Recovery-only captures are weak because they omit the trigger. Preserve enough traffic before the failure to answer:

  • What command or class request preceded the STALL?
  • Was its length valid?
  • Was it sent on the intended OUT endpoint?
  • Was the device in the correct protocol state?
  • Did a required initialization request complete?
  • Was a response already pending?
  • Did the host retry the same bytes after recovery?

For a command/response protocol, reconstruct the exchange:

Sequence Direction Evidence
1 OUT valid command header
2 OUT payload length differs from header
3 IN endpoint STALL
4 control correct clear-halt request
5 IN STALL repeats

The repeated STALL is expected until the malformed command state is discarded or reset. Clearing transport state alone cannot repair the header.

Know when a STALL is intentional

A device can intentionally STALL an unsupported or state-invalid operation. The firmware defect may instead be poor recovery or undocumented host behavior.

Ask:

  1. Does the class or vendor protocol allow STALL for this condition?
  2. How should the host learn the detailed error?
  3. Should clear halt be enough, or is a class reset required?
  4. Must the failed command be resubmitted?
  5. Does firmware accept a new command after recovery?

For USB Mass Storage Bulk-Only Transport, class-specific recovery has requirements beyond a generic clear-halt call. Other classes and vendor protocols define their own sequences. Follow the relevant contract rather than applying one universal retry loop.

Repeated STALL loops

A common failure pattern is:

  1. command completes on bulk OUT;
  2. response endpoint returns STALL;
  3. host clears halt;
  4. host resubmits response read;
  5. endpoint stalls again;
  6. driver clears repeatedly;
  7. driver resets the device.

Possible causes include:

  • the response command remains invalid;
  • firmware requires a protocol reset request;
  • host cleared the wrong endpoint direction;
  • the clear request itself failed;
  • firmware did not reset endpoint/controller state;
  • host repeated a read before issuing the required next command;
  • endpoint descriptor or application endpoint selection is wrong.

Mark the first divergence from a known-good trace. Later retries add volume but often no new information.

Device reset is a different recovery boundary

If the driver resets the port or device, the old configuration and endpoint state no longer define the new session. Look for:

  • port reset;
  • a new device address;
  • descriptors retrieved again;
  • configuration selected again;
  • changed VID, PID, serial, or release identifier;
  • application reusing an old handle.

A reset can make the user-visible operation succeed while hiding a broken clear-halt path. Record whether recovery required a reset, because that affects data loss, latency, and application reconnection behavior.

If the device disappears repeatedly, continue with the USB disconnect and reset-loop guide.

Host APIs use different names

Libraries and drivers expose operations such as clear halt, reset pipe, abort pipe, flush, or reset device. These names are not guaranteed to perform the same bus sequence.

Use the capture to verify:

  • whether a standard clear-feature request was sent;
  • whether queued transfers were canceled first;
  • whether the endpoint was reopened;
  • whether a port reset occurred;
  • whether descriptors were read again.

Do not infer the USB operation solely from the API name. A driver can implement pipe recovery internally or escalate directly to device reset.

Compare before and after the firmware fix

Keep the command and environment controlled:

Capture First command STALL Clear halt First retry Reset
before malformed length case IN 0x82 completes STALL yes
after same test case IN 0x82 completes defined error response no

The post-fix trace should prove both transport recovery and protocol behavior. A test that simply avoids the original invalid command does not prove the halt path was fixed.

A repeatable endpoint halt workflow

  1. Capture before the command that triggers failure.
  2. Record firmware, device identity, interface, and endpoint map.
  3. Find the first explicit STALL.
  4. Name endpoint address, direction, and transfer type.
  5. Preserve the triggering command or request bytes.
  6. Decode CLEAR_FEATURE(ENDPOINT_HALT).
  7. Confirm the request targets the same endpoint and completes.
  8. Inspect the first transfer after clear halt.
  9. Determine whether protocol state was reset or preserved.
  10. Mark any class reset, port reset, or re-enumeration.
  11. Compare the same case with a known-good build.
  12. Save bounded before-and-after .bscope sessions.

Use Bus Scope platform capture to verify controller or usbmon-bus selection before interpreting absent recovery traffic.

QA questions

Does clear halt reset the whole device?

No. It targets an endpoint halt feature. A driver can choose additional actions, but a standard clear-feature request is not the same as a port or device reset.

Why does the endpoint stall immediately after a successful clear?

The original command may still be invalid, firmware protocol state may remain in error, the host may have cleared the wrong direction, or endpoint synchronization may be broken. Inspect the first retry and trigger, not only the clear request.

Should software call clear halt after every timeout?

No. First prove an explicit STALL or halted-pipe condition. A timeout without STALL may require queue, framing, readiness, disconnection, or application-deadline diagnosis.

Can the same endpoint number exist in both directions?

Yes. 0x01 OUT and 0x81 IN share endpoint number 1 but are distinct endpoint addresses. Recovery must target the direction that stalled.

Can Bus Scope show the firmware's internal error state?

It can show commands, endpoint results, setup requests, timing, resets, and subsequent USB behavior. Device logs or instrumentation are needed to prove the private firmware branch behind an intentional STALL.

Final diagnosis

Successful USB endpoint halt recovery is not merely a completed CLEAR_FEATURE request. It is a complete state transition: the correct endpoint was cleared, synchronization recovered, the next transfer behaved as specified, and the underlying protocol state no longer forced the same STALL. Capture that sequence and the team can fix the responsible layer instead of escalating every failure to a device reset.

<!-- 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 -->