Bluetooth Controller Reset Recovery: Rebuild Host State in a Defined Order

Recover a reset controller by rebuilding a new controller generation from durable product intent. Do not keep issuing commands through host objects that describe connections, advertising sets or credits the controller has already lost. The first recovery milestone is a synchronized host/controller state, not a successful reconnect to one peer.

Applicability: Bluetooth Core 6.1 HCI Reset semantics and Linux v6.12 host recovery/initialization source. The dependency sequence is a proposed integration checklist, not a universal command script. Transport, controller firmware, kernel driver and supported recovery mechanism must be pinned for a real deployment. No reset was performed here.

Six dependency gates from quiescing old work through trusted transport, completed reset, capability discovery, configuration restoration and required-role recreation.
Original recovery dependency diagram. Exact transport and driver actions remain implementation-specific; no reset or recovery-time measurement was performed.

1. Distinguish three reset boundaries

The HCI Reset command resets controller protocol operation, loses current operational state and restores specified defaults. It does not reset the HCI transport, and whether it performs a hardware reset is implementation-defined.

A transport failure therefore may require transport-specific recovery before a reliable HCI exchange is possible. A power cycle may additionally lose vendor firmware or other volatile initialization that an ordinary HCI Reset retains. Treat those as different fault histories.

Record the observed trigger: Hardware Error event, missing responses, transport removal, driver failure or externally observed controller restart. Preserve the available evidence before escalating recovery. A command timeout alone does not prove which layer reset.

Use the owning stack’s supported recovery path. Injecting a raw Reset behind a live host’s back can create exactly the state divergence this procedure is intended to repair. Do not let separate application components independently reset the same controller.

2. Close the old generation before reopening work

Enter a recovery state that stops new application submissions. Cancel or fail pending requests with an explicit controller-lost or outcome-unknown reason. A write whose response disappeared may have taken effect before reset; classify it according to the application’s idempotency contract.

Retire volatile connection handles, advertising-set handles, periodic-sync handles, pending procedures and controller-buffer accounting. Cancel queued work that refers to them. Preserve durable peer identity and authorization records unless the product explicitly requested their removal.

Maintain desired roles separately: “commissioning should be available” or “collect from these authorized peers” can survive recovery, while “handle 0x0041 is connected” cannot. The new controller generation should recreate resources from current policy rather than replay an old command log blindly.

A generation field protects host-side callbacks and work items. It is not carried in ordinary HCI events, so it cannot authenticate stale wire bytes. Establish a real transport drain/reopen/reset boundary before accepting the new event stream.

3. Observe the stack’s actual teardown

In Linux v6.12, the Hardware Error recovery worker invokes the device’s optional hardware-error hook, then closes and reopens the device when close succeeds. This is broader than merely resending HCI Reset.

The synchronous close path cancels command work, flushes processing, clears pending LE actions, flushes connections and purges queues. Its exact sequence includes driver callbacks and configuration-dependent behavior. Use it as implementation evidence, not as a recipe to duplicate from user space.

The Reset completion handler also clears volatile state such as discovery-related state and cached controller lists. That does not mean durable application ownership or every host security record should be deleted. Keep controller configuration caches distinct from persisted product policy.

For another kernel or embedded host, inspect its corresponding lifecycle code. Record which layer owns reconnection and role restoration so application retries do not race the stack’s own initialization.

4. Rebuild dependencies before enabling roles

After the transport is usable, complete the supported controller setup and reset sequence. Core prohibits additional HCI commands before the Reset Command Complete event arrives. A recovery timer expiring is not equivalent to that response.

Next establish controller identity and capabilities, supported commands and packet-buffer limits. Validate them against the intended workload. Do not assume a fallback firmware image exposes the same feature set as the image that failed.

Configure the required event reporting and controller policies before starting features that depend on those events. Restore address and identity-related controller configuration through the owning stack, then recreate advertising, scanning or connection intent as applicable.

Linux’s tagged initialization is staged: initial reset/version/features work precedes later supported-command and LE buffer discovery, followed by event-mask stages and additional defaults. Quirks can change details, including where reset occurs. The dependency lesson is to use successful earlier results to qualify later steps.

Publish readiness only when required stages and required roles succeed. Optional diagnostics can remain unavailable without hiding a required commissioning or collection failure. Keep the recovery stage and first failed operation visible to support tooling.

5. Restore intent without restoring stale conclusions

State category Recovery treatment
Authorized peer identities and product policy Retain under the documented persistent-store contract
Controller capabilities and buffer limits Re-establish or revalidate through supported initialization
Old handles and pending procedures Retire; never adopt into the new generation
Desired advertising/scanning roles Recreate in priority order after dependencies
Application operation with lost response Resolve as unknown or retry only under defined idempotency

After role restoration, ordinary peer reconnection and subscription readiness still apply. They are downstream checks, not substitutes for controller initialization. A single recovered peer does not prove that another required advertising set or scan path was restored.

Prevent restart storms by coalescing simultaneous recovery requests and bounding escalation. If the transport or mandatory initialization step cannot recover, keep the adapter unavailable with an actionable reason rather than toggling it indefinitely while discarding evidence.

6. Test divergence deliberately on controlled hardware

Propose separate fault runs for an HCI-level reset, transport interruption and controller power loss using supported lab mechanisms. Preserve host process state where that is the intended failure case. Record which old objects the host knew about at the trigger.

  • Reset while a command awaits response; verify it cannot complete a new-generation request.
  • Reset with ACL packets outstanding; verify old capacity is not added to the rebuilt pool.
  • Reset while advertising and periodic synchronization are active; verify required roles are recreated explicitly.
  • Fail an initialization stage; verify later role start remains gated.
  • Restore a controller with changed capabilities; verify unsupported intent is rejected clearly.
  • Deliver a queued old application callback after recovery; verify generation rejection.

Acceptance requires an ordered trace from failure through quiescence, trustworthy transport, successful initialization and required-role readiness. Report unresolved application outcomes separately. Recovery is complete when the host’s current claims match the new controller’s established state.

Similar Posts