RME Fireface 800: Stage 5C-5H bounded circular playback integration#83
Open
Clip4food wants to merge 7 commits into
Open
RME Fireface 800: Stage 5C-5H bounded circular playback integration#83Clip4food wants to merge 7 commits into
Clip4food wants to merge 7 commits into
Conversation
added 7 commits
July 20, 2026 03:43
… 5G/5H) Safety commit of uncommitted RME work before continuing Stage 5H development, per user request. Scope is intentionally narrow: RMEFireface800Protocol (new) and the Isoch transmit-path changes it depends on. Related supporting edits (DeviceProtocolFactory, AudioProfileRegistry, device IDs, RMEAudioProfiles.hpp, etc.) remain uncommitted in the working tree and were left out of this snapshot.
… and test build fix
Rounds out the earlier RME/Isoch backup commit with everything that
feature depends on to actually compile and run:
- No-CIP (tag=0) isoch header support end to end: IsochAudioTransport
header build/decode helpers, includeCipHeader plumbed through
AmdtpStreamConfig/AmdtpTxPacketizer/AudioStreamConfig/
DiceStreamConfigMapper, and the OHCI TX descriptor path.
- Core Audio wiring for the RME read-only nub: AudioCoordinator
publishes/tears down the Stage 5C endpoint, ASFWAudioDevice enters
the Stage 5C preflight-only StartIO/StopIO path, ASFWAudioDriverZts
primes the FF800 blocking cadence instead of NO-DATA.
- Discovery: FWDevice parses Model_ID (0x17) from the Unit Directory,
DeviceRegistry recovers model_id from the raw Config ROM as a
fallback (RME publishes it in the Unit Directory, not the root),
DeviceManager refreshes identity on rediscovery.
- DeviceProtocolFactory/IDeviceProtocol/AudioProfileRegistry/
AudioDeviceIds/AudioProfileTypes/RMEAudioProfiles: RME identity,
kReadOnlyNub integration mode, and the bounded playback preflight
seam (PlaybackPreflightRoute / RunBoundedPlaybackIntegrationPreflight)
the Stage 5G/5H protocol implementation calls into.
- Info.plist: IOPCIMatch for this bench's TI 104C:823F controller,
ASFWAutoStartAudioStreams=false (StartIO stays rejected per the
Stage 5G/5H invariant). DriverContext.cpp: interrupt setup gets
MSI-X/MSI/fallback diagnostics for bring-up on this board.
- project.pbxproj/ASFW.xcscheme: adds the new RME/RMEAudioProfiles
file references so Xcode builds them. Hand-edited because xcodegen
isn't installed in this environment -- re-run `xcodegen generate`
once it is, to get a canonical regenerated project and diff-check
it against this.
- tests/{protocols,devices}/CMakeLists.txt: add ConfigROMParser.cpp
to the three test targets that compile DeviceRegistry.cpp, which
now calls ConfigROMParser::ParseDirectory (previously an unresolved
symbol at link time for SessionRegistryTests/SBP2HandlerTests/
AudioDuplexCoordinatorTests).
Replaces the hand-edited project.pbxproj from the previous commit with a canonical `xcodegen generate` output now that Homebrew + xcodegen are installed on this machine. Also restores ASFWDriver.xcscheme, which project.yml already declares (schemes.ASFWDriver) -- its earlier deletion just meant every future `xcodegen generate` would keep recreating it as a diff. The stray backup/OLD artifacts (Info.plist.original, DriverContext.cpp.backup-*, DMAMemoryManager.cpp.backup-dma, ASFWDriverOLD.zip, ASFW.xcodeprojOLD/, projectOLD.pbxproj) were deleted before regenerating -- they lived under ASFWDriver/, which project.yml globs in full, so a prior generate had folded them into the dext target as build Resources. That is almost certainly what forced the earlier hand-edit workaround in the first place.
Hardware testing on the Fireface 800 (Stage 5H build) surfaced a real bug: right after a bus reset, ReservePlaybackResourcesPreflight's IRM snapshot read can race IRMClient's own IRM-node resolution -- IRMClient::ReadIRMWindow returns NotFound while irmNodeId_ is still 0xFF, before bus manager/Self-ID processing has caught up. There was no retry, so playbackPreflightRoute_ stayed at 0 forever and every subsequent StartIO logged "verified IRM route is not ready" until the next full protocol reinit. Reproduced live: a mid-session bus reset left the route permanently unarmed on the unpatched build. Mirrors the existing PollDeviceTxIsochChannel bounded retry idiom in this same file: up to 10 attempts, 50ms apart, before giving up. Confirmed on hardware after the fix: Stage 5H's bounded circular silent playback burst (48 descriptors, 100ms, clean OHCI/FF800/IRM teardown) passes cleanly on a fresh dext load. The IRM snapshot happened to succeed on first read this run (no NotFound race hit), so the retry branch itself is unexercised by this specific run; still pending is forcing another bus reset while the dext is live to confirm the retry path recovers instead of stranding the route again.
Turns the bounded 100ms Stage 5H circular silence burst into a maintained
continuous stream, reachable only through a new developer-gated
UserClient/MCP path -- never through real Core Audio StartIO, which keeps
returning kIOReturnUnsupported unchanged.
Reuses the Stage 5H self-looping 48-descriptor D-D-D-S ring builder
verbatim (it was already duration-agnostic; only the run/cleanup entry
points were bounded). New transport-layer methods start the ring and
return immediately instead of polling for a fixed window, plus a
non-blocking health check (DEAD/event-error/anchor-advance) reused by
both a new Watchdog heartbeat (~1s, anomaly-only logging) and an
on-demand UserClient query.
RMEFireface800Protocol gains Start/Stop/Health hooks mirroring
RunBoundedPlaybackIntegrationPreflight's shape, guarded by a separate
continuousPlaybackInFlight_ flag checked alongside stage5hInFlight_ (same
OHCI context/IRM route, must never run both at once). Extracted the
FF800-stop+IRM-release tail into StopDeviceEngineAndReleaseIrm so it's
shared instead of duplicated between the bounded and continuous paths.
IsochTransmitContext::Stop() now stops an in-flight continuous cadence
too, since it deliberately never enters State::Running and would
otherwise be missed by driver teardown.
New UserClient selectors 64-66 (GUID-keyed, full 64-bit -- the existing
kMethodStartAudioStreaming=62/63 are an unrelated generic AV/C developer
path and hard-reject RME already) plumbed through to new MCP tools
asfw_continuous_tx_{start,stop,health}_dev, mirroring the existing
asfw_bus_reset_dev developer-trigger pattern.
Verified: full build (dext + Swift app) succeeds, ./build.sh --test-only
stays at 1334/1335 (same pre-existing unrelated failure, no regression).
Hardware verification of the continuous run itself is still pending --
blocked on a stuck systemextensionsctl uninstall requiring a reboot.
…cation StartContinuousIsochTxSilence's prepareHost step called IsochService:: PrepareTransmit directly, which requires the shared payload/metadata/ control memory to already exist. Stage 5H never had this problem because it only ever runs from inside a real Core Audio StartIO, which allocates that memory via AllocateTxIsochResources before ever reaching the RME branch. This dev-only path is driven straight from UserClient with no CoreAudio session, so the buffer was never allocated -- every start attempt failed with kIOReturnNotReady (confirmed live: kr=0xe00002d8). Fix: allocate it explicitly with the same fixed no-CIP RME wire geometry validated since Stage 5A (1536 bytes/packet: 32 frames x 12 dbs x 4 bytes, no CIP header) before calling PrepareTransmit, and free it symmetrically on stop. Also bumps ASFWDriver's CURRENT_PROJECT_VERSION from 2 to a fixed 100. Every iteration during Stage 6 development produced a dext with the same CFBundleVersion as whatever was already active system-extension-side; OSSystemExtensionRequest won't replace an equal-or-lower version, so the only path forward was systemextensionsctl uninstall -- which got stuck in "terminating for uninstall but still running" (recoverable only by a full reboot) three separate times this session. A comfortably high fixed value means future installs are a normal automatic upgrade instead.
The buffer-allocation fix in StartContinuousIsochTxSilence (previous commit) has not been exercised end to end on hardware yet. Every live attempt this session failed earlier, at GetPlaybackPreflightRoute() returning false, before ever reaching this function's body -- something on the system (observed pattern consistent with coreaudiod) wins the race for the single-use Stage 5F playback route within about a second of every bus reset, ahead of this dev-only MCP-triggered path's three sequential HTTP round trips. Not a Stage 6 regression: Stage 5H shows the identical symptom whenever something beats it to the route. Documented in place so the next session doesn't have to rediscover this; two candidate next steps noted in the comment.
Owner
|
Hi and thanks for contribution! I'm looking into it. I want to finish some architecture shifts before actually merging/resolving conflicts and fixing some critical bugs in FireWire driver itself, so please wait some time. |
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
ASFWDriver/Audio/Protocols/RME/) and the no-CIP (tag=0) isoch wire-format support it depends on acrossAudio/Wire/AMDTP,Shared/Isoch/IsochAudioTransport.hpp, and the Isoch transmit path (IsochTxDmaRing,IsochTransmitContext,IsochService).FWDevice/DeviceRegistryrecovermodel_idfrom the Unit Directory (RME publishes it there, not the root directory).StartIOdeliberately stays rejected (kIOReturnUnsupported) after a single bounded Stage 5H integration burst — no live streaming yet.ReservePlaybackResourcesPreflight's IRM snapshot read racedIRMClient's own IRM-node resolution right after a bus reset (NotFoundwhileirmNodeId_ == 0xFF), permanently stranding the playback route with no retry. Now retries up to 10x/50ms, mirroring the existingPollDeviceTxIsochChannelidiom.Heads up for review
405cb99;mainhas since moved ~18 commits (notablyrefactor(isoch): make transmit queue payload opaqueand the isoch receive-seam refactors), so this will likely need a rebase/conflict pass before merge — flagging so it's not a surprise.Test plan
./build.sh --test-only— 1334/1335 C++ tests pass (1 pre-existing unrelated failure:IsochDMAMemoryManagerTest.PayloadSlicingAndPageAlignment, page-alignment assumption in the host-test memory stub)../build.sh --config Release(Xcode, x86_64) +./sign.sh— builds and signs cleanly.0x000a3500f021a1b4): Stage 5H's bounded circular silent playback burst (48 descriptors, 36 data packets, 12 skips, 100 ms) passed cleanly across a cold boot, a protocol reinit, and a forced bus reset — clean OHCI/FF800/IRM teardown each time, zero event errors, zero DEAD.NotFound-retry branch fixed above did not get re-exercised live (the race window is narrow and didn't reproduce on demand) — verified by code inspection and the original incident log instead.🤖 Generated with Claude Code