Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ASFW.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -893,10 +893,10 @@
A6D30FC4AF96CBDC4F5B068E /* ASFWMCPMockTransport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASFWMCPMockTransport.swift; sourceTree = "<group>"; };
A6F6F643214F7280A18611DC /* DiceProfileRegistry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiceProfileRegistry.hpp; sourceTree = "<group>"; };
A7EFDA6CC5CB7D2153F013D3 /* FWTypes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FWTypes.hpp; sourceTree = "<group>"; };
A805D0AD31C67B2D10A9507A /* TxWirePayloadTelemetry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TxWirePayloadTelemetry.hpp; sourceTree = "<group>"; };
A855F971A611AE8F859F3579 /* DICERestartSession.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DICERestartSession.hpp; sourceTree = "<group>"; };
A94CBEC3E242E8D452CA2EEF /* ZtsTelemetry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ZtsTelemetry.hpp; sourceTree = "<group>"; };
A9EFB67D49B05DCD5C9C661D /* RomSummarizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RomSummarizer.swift; sourceTree = "<group>"; };
AA48E4986D21FB2A52856349 /* IsochAudioTransport.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IsochAudioTransport.hpp; sourceTree = "<group>"; };
AA497F39DA363DBDFD6C9CCE /* WriteCommand.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WriteCommand.cpp; sourceTree = "<group>"; };
AA6636F29737F75466534B0E /* GapCountOptimizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GapCountOptimizer.cpp; sourceTree = "<group>"; };
AA6E283C66645521931AA351 /* StatusPublisher.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StatusPublisher.hpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1118,6 +1118,7 @@
F49607C2B6C75A5EACC56433 /* IAmdtpTxSlotProvider.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IAmdtpTxSlotProvider.hpp; sourceTree = "<group>"; };
F4A7F52D42A80A09468F41F1 /* PayloadWriterTelemetry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PayloadWriterTelemetry.hpp; sourceTree = "<group>"; };
F50437CCB59475ED6F54FC52 /* MCPBusResetToolsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCPBusResetToolsTests.swift; sourceTree = "<group>"; };
F5252BDAC15F6AA21DCD3E28 /* IsochTxQueue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IsochTxQueue.hpp; sourceTree = "<group>"; };
F714F267E66F185F1C86F905 /* SBP2CommandORB.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SBP2CommandORB.hpp; sourceTree = "<group>"; };
F71A638FD501761865722676 /* AudioCoordinator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AudioCoordinator.cpp; sourceTree = "<group>"; };
F7AAEEA6F540F467BB7E4B7D /* DeviceDiscoveryWireFormats.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeviceDiscoveryWireFormats.hpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1512,6 +1513,7 @@
children = (
8548E1DA1006A1671CC85CF1 /* IsochDmaGeometry.hpp */,
3DC0A6CF3AE91F3EF65A4BAB /* IsochEventGroup.hpp */,
F5252BDAC15F6AA21DCD3E28 /* IsochTxQueue.hpp */,
72BE64F16BB205405D7F37A1 /* IsochTypes.hpp */,
);
path = Core;
Expand Down Expand Up @@ -1913,7 +1915,6 @@
845D81D6F290A50E0EE157C1 /* AudioGeometryPolicy.hpp */,
D4073B97E1CA0CE1A021785D /* AudioHalBufferProfiles.hpp */,
F46044243554D4B325071905 /* AudioTimingGeometry.hpp */,
AA48E4986D21FB2A52856349 /* IsochAudioTransport.hpp */,
);
path = Isoch;
sourceTree = "<group>";
Expand Down Expand Up @@ -2706,6 +2707,7 @@
8A1E58C964900982CCFC790B /* DirectAudioDebugSnapshot.hpp */,
F4A7F52D42A80A09468F41F1 /* PayloadWriterTelemetry.hpp */,
C211D6E382A537B9689088FD /* TxSytTrace.hpp */,
A805D0AD31C67B2D10A9507A /* TxWirePayloadTelemetry.hpp */,
);
path = Runtime;
sourceTree = "<group>";
Expand Down
6 changes: 3 additions & 3 deletions ASFWDriver/Audio/Core/AudioEndpointRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include "../DriverKit/Runtime/DirectAudioBindingSource.hpp"
#include "../Model/ASFWAudioDevice.hpp"
#include "../../Shared/Isoch/IsochAudioTransport.hpp"
#include "../Config/AudioConstants.hpp"
#include "../Wire/AMDTP/AmdtpRateGeometry.hpp"
#include "../../Logging/Logging.hpp"

Expand Down Expand Up @@ -430,8 +430,8 @@ class AudioEndpointRuntime final : public Runtime::IDirectAudioBindingSource {
const uint32_t inputChannels = ClampAudioChannels(
config_.inputChannelCount ? config_.inputChannelCount : config_.channelCount);
const uint32_t sampleRateHz = config_.currentSampleRate ? config_.currentSampleRate : 48000;
const uint32_t outputFrames = IsochTransport::kAudioRingBufferFrames;
const uint32_t inputFrames = IsochTransport::kAudioRingBufferFrames;
const uint32_t outputFrames = Isoch::Config::kAudioRingBufferFrames;
const uint32_t inputFrames = Isoch::Config::kAudioRingBufferFrames;

if (outputChannels == 0 || inputChannels == 0 || sampleRateHz == 0) {
ASFW_LOG(DirectAudio,
Expand Down
60 changes: 34 additions & 26 deletions ASFWDriver/Audio/DriverKit/ASFWAudioDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "../Config/TimingCursorPolicy.hpp"
#include "Config/AudioProfileRegistry.hpp"
#include "../../Common/DriverKitOwnership.hpp"
#include "../../Shared/Isoch/IsochAudioTransport.hpp"
#include "../../Isoch/Core/IsochTxQueue.hpp"

#include <DriverKit/DriverKit.h>
#include <DriverKit/IOLib.h>
Expand Down Expand Up @@ -79,9 +79,10 @@ kern_return_t ASFWAudioDevice::StartIO(IOUserAudioStartStopFlags in_flags) {
ivars.txControlBuffer = nullptr;
ivars.runtime.txSlotProvider.payloadBase = nullptr;
ivars.runtime.txSlotProvider.metadataRing = nullptr;
ivars.runtime.txSlotProvider.controlBlock = nullptr;
ivars.runtime.txSlotProvider.queueControl = nullptr;
ivars.runtime.txSlotProvider.audioControl = nullptr;
ivars.runtime.txSlotProvider.numSlots = 0;
ivars.runtime.txExecutionTimeline.controlBlock = nullptr;
ivars.runtime.txExecutionTimeline.queueControl = nullptr;

// Secondary playback stream resources.
ivars.txPayloadMapSecondary = nullptr;
Expand All @@ -92,7 +93,8 @@ kern_return_t ASFWAudioDevice::StartIO(IOUserAudioStartStopFlags in_flags) {
ivars.txControlBufferSecondary = nullptr;
ivars.runtime.txSlotProviderSecondary.payloadBase = nullptr;
ivars.runtime.txSlotProviderSecondary.metadataRing = nullptr;
ivars.runtime.txSlotProviderSecondary.controlBlock = nullptr;
ivars.runtime.txSlotProviderSecondary.queueControl = nullptr;
ivars.runtime.txSlotProviderSecondary.audioControl = nullptr;
ivars.runtime.txSlotProviderSecondary.numSlots = 0;
ivars.runtime.txSecondaryActive = false;

Expand Down Expand Up @@ -217,22 +219,23 @@ kern_return_t ASFWAudioDevice::StartIO(IOUserAudioStartStopFlags in_flags) {
}

uint8_t* payloadBase = reinterpret_cast<uint8_t*>(ivars.txPayloadMap->GetAddress());
auto* metadataRing = reinterpret_cast<ASFW::IsochTransport::TxPacketMeta*>(ivars.txMetadataMap->GetAddress());
auto* controlBlock = reinterpret_cast<ASFW::IsochTransport::TxStreamControl*>(ivars.txControlMap->GetAddress());
auto* metadataRing = reinterpret_cast<ASFW::Isoch::IsochTxPacketMeta*>(ivars.txMetadataMap->GetAddress());
auto* queueControl = reinterpret_cast<ASFW::Isoch::IsochTxQueueControl*>(ivars.txControlMap->GetAddress());

// Clear stale runtime cursors before prefill: the shared slab can be
// reused across StartIO/StopIO probes (CoreAudio re-probes on a
// sample-rate change), and a carried-over exposeCursor fails the IT
// sample-rate change), and a carried-over committed cursor fails the IT
// prime ("committed prefill > slots").
controlBlock->ResetForStart();
queueControl->ResetProducerForStart();

ivars.runtime.txSlotProvider.payloadBase = payloadBase;
ivars.runtime.txSlotProvider.metadataRing = metadataRing;
ivars.runtime.txSlotProvider.controlBlock = controlBlock;
ivars.runtime.txSlotProvider.queueControl = queueControl;
ivars.runtime.txSlotProvider.audioControl = control;
ivars.runtime.txSlotProvider.numSlots = numSlots;
ivars.runtime.txSlotProvider.slotStrideBytes = maxPacketBytes;

ivars.runtime.txExecutionTimeline.controlBlock = controlBlock;
ivars.runtime.txExecutionTimeline.queueControl = queueControl;

if (!ivars.runtime.txStreamEngine.Configure(*profile, txConfig)) {
ASFW_LOG(Audio, "ASFWAudioDevice: txStreamEngine Configure failed");
Expand Down Expand Up @@ -308,14 +311,15 @@ kern_return_t ASFWAudioDevice::StartIO(IOUserAudioStartStopFlags in_flags) {
if (allocKr2 != kIOReturnSuccess) { kr = failStart(allocKr2, "MapTxControl2"); return; }

uint8_t* payloadBase2 = reinterpret_cast<uint8_t*>(ivars.txPayloadMapSecondary->GetAddress());
auto* metadataRing2 = reinterpret_cast<ASFW::IsochTransport::TxPacketMeta*>(ivars.txMetadataMapSecondary->GetAddress());
auto* controlBlock2 = reinterpret_cast<ASFW::IsochTransport::TxStreamControl*>(ivars.txControlMapSecondary->GetAddress());
auto* metadataRing2 = reinterpret_cast<ASFW::Isoch::IsochTxPacketMeta*>(ivars.txMetadataMapSecondary->GetAddress());
auto* queueControl2 = reinterpret_cast<ASFW::Isoch::IsochTxQueueControl*>(ivars.txControlMapSecondary->GetAddress());

controlBlock2->ResetForStart();
queueControl2->ResetProducerForStart();

ivars.runtime.txSlotProviderSecondary.payloadBase = payloadBase2;
ivars.runtime.txSlotProviderSecondary.metadataRing = metadataRing2;
ivars.runtime.txSlotProviderSecondary.controlBlock = controlBlock2;
ivars.runtime.txSlotProviderSecondary.queueControl = queueControl2;
ivars.runtime.txSlotProviderSecondary.audioControl = control;
ivars.runtime.txSlotProviderSecondary.numSlots = numSlots2;
ivars.runtime.txSlotProviderSecondary.slotStrideBytes = maxPacketBytes2;

Expand All @@ -337,10 +341,10 @@ kern_return_t ASFWAudioDevice::StartIO(IOUserAudioStartStopFlags in_flags) {
// --- Prefill TX ring ---
ASFW::Audio::DriverKit::PrefillTxRingBeforeStart(ivars);

auto* prefillControl = ivars.runtime.txSlotProvider.controlBlock;
auto* prefillControl = ivars.runtime.txSlotProvider.queueControl;
const uint64_t prefillExpose =
prefillControl
? prefillControl->exposeCursor.load(std::memory_order_acquire)
? prefillControl->committedEnd.load(std::memory_order_acquire)
: 0;
const uint32_t expectedPrefill =
ivars.runtime.txSlotProvider.numSlots;
Expand Down Expand Up @@ -374,18 +378,20 @@ kern_return_t ASFWAudioDevice::StartIO(IOUserAudioStartStopFlags in_flags) {
// StartAudioStreaming initializes the shared transport control block.
// Validate it immediately afterward; failStart stops the partially
// started stream before returning any mismatch to AudioDriverKit.
auto* txControl = ivars.runtime.txSlotProvider.controlBlock;
auto* txControl = ivars.runtime.txSlotProvider.queueControl;
if (!txControl ||
txControl->abiVersion != ASFW::IsochTransport::kTransportAbiVersion ||
txControl->abiVersion != ASFW::Isoch::kTxQueueAbiVersion ||
txControl->numSlots != ASFW::IsochTransport::AudioTimingGeometry::kTxSharedSlotPackets ||
txControl->interruptInterval != ASFW::IsochTransport::AudioTimingGeometry::kTxPacketsPerGroup ||
txControl->ztsPeriodFrames != ASFW::IsochTransport::AudioTimingGeometry::kHalZeroTimestampPeriodFrames) {
txControl->slotStrideBytes != ivars.runtime.txSlotProvider.slotStrideBytes ||
txControl->maxPacketBytes != ivars.runtime.txSlotProvider.slotStrideBytes ||
txControl->interruptInterval != ASFW::IsochTransport::AudioTimingGeometry::kTxPacketsPerGroup) {
ASFW_LOG(Audio,
"ASFWAudioDevice: TX geometry/ABI mismatch abi=%u slots=%u group=%u zts=%u",
"ASFWAudioDevice: TX queue ABI/geometry mismatch abi=%u slots=%u stride=%u max=%u group=%u",
txControl ? txControl->abiVersion : 0,
txControl ? txControl->numSlots : 0,
txControl ? txControl->interruptInterval : 0,
txControl ? txControl->ztsPeriodFrames : 0);
txControl ? txControl->slotStrideBytes : 0,
txControl ? txControl->maxPacketBytes : 0,
txControl ? txControl->interruptInterval : 0);
kr = failStart(
kIOReturnUnsupported, "ValidateTxTransportGeometry");
return;
Expand Down Expand Up @@ -585,9 +591,10 @@ kern_return_t ASFWAudioDevice::StopIO(IOUserAudioStartStopFlags in_flags) {
ivars.txControlBuffer = nullptr;
ivars.runtime.txSlotProvider.payloadBase = nullptr;
ivars.runtime.txSlotProvider.metadataRing = nullptr;
ivars.runtime.txSlotProvider.controlBlock = nullptr;
ivars.runtime.txSlotProvider.queueControl = nullptr;
ivars.runtime.txSlotProvider.audioControl = nullptr;
ivars.runtime.txSlotProvider.numSlots = 0;
ivars.runtime.txExecutionTimeline.controlBlock = nullptr;
ivars.runtime.txExecutionTimeline.queueControl = nullptr;

// Secondary playback stream teardown. Drop txSecondaryActive first so the
// RT pump/IO paths stop touching the secondary engine before its mapped
Expand All @@ -601,7 +608,8 @@ kern_return_t ASFWAudioDevice::StopIO(IOUserAudioStartStopFlags in_flags) {
ivars.txControlBufferSecondary = nullptr;
ivars.runtime.txSlotProviderSecondary.payloadBase = nullptr;
ivars.runtime.txSlotProviderSecondary.metadataRing = nullptr;
ivars.runtime.txSlotProviderSecondary.controlBlock = nullptr;
ivars.runtime.txSlotProviderSecondary.queueControl = nullptr;
ivars.runtime.txSlotProviderSecondary.audioControl = nullptr;
ivars.runtime.txSlotProviderSecondary.numSlots = 0;

if (ivars.device.audioNub) {
Expand Down
2 changes: 1 addition & 1 deletion ASFWDriver/Audio/DriverKit/ASFWAudioDriverGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "../Config/TimingCursorPolicy.hpp"
#include "../../Common/TimingUtils.hpp"
#include "../../Common/DriverKitOwnership.hpp"
#include "../../Shared/Isoch/IsochAudioTransport.hpp"
#include "../../Shared/Isoch/AudioTimingGeometry.hpp"
#include "../../Audio/Wire/AMDTP/AmdtpRateGeometry.hpp"
#include "../../Logging/Logging.hpp"

Expand Down
8 changes: 4 additions & 4 deletions ASFWDriver/Audio/DriverKit/ASFWAudioDriverIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ kern_return_t InstallIOOperationHandler(IOUserAudioDevice& audioDevice,
hostBuffer.frameCapacity = memory.outputFrameCapacity;
hostBuffer.channels = channels;

const uint64_t completionCursor = driverIvars->runtime.txSlotProvider.controlBlock
? driverIvars->runtime.txSlotProvider.controlBlock->completionCursor.load(std::memory_order_acquire)
const uint64_t completionCursor = driverIvars->runtime.txSlotProvider.queueControl
? driverIvars->runtime.txSlotProvider.queueControl->completionCursor.load(std::memory_order_acquire)
: 0;
const uint64_t writeEndFrame =
sampleTime + ioBufferFrameSize;
Expand All @@ -214,8 +214,8 @@ kern_return_t InstallIOOperationHandler(IOUserAudioDevice& audioDevice,
// payload writer reads channels [16, 32) via sourceChannelOffset.
if (driverIvars->runtime.txSecondaryActive) {
const uint64_t secondaryCompletion =
driverIvars->runtime.txSlotProviderSecondary.controlBlock
? driverIvars->runtime.txSlotProviderSecondary.controlBlock
driverIvars->runtime.txSlotProviderSecondary.queueControl
? driverIvars->runtime.txSlotProviderSecondary.queueControl
->completionCursor.load(std::memory_order_acquire)
: 0;
driverIvars->runtime.txStreamEngineSecondary.WriteHostOutputFloat32(
Expand Down
8 changes: 5 additions & 3 deletions ASFWDriver/Audio/DriverKit/ASFWAudioDriverLifecycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,10 @@ void PerformLoudTeardown(ASFWAudioDriver_IVars& ivars, const char* reason) noexc
ivars.txControlBuffer = nullptr;
ivars.runtime.txSlotProvider.payloadBase = nullptr;
ivars.runtime.txSlotProvider.metadataRing = nullptr;
ivars.runtime.txSlotProvider.controlBlock = nullptr;
ivars.runtime.txSlotProvider.queueControl = nullptr;
ivars.runtime.txSlotProvider.audioControl = nullptr;
ivars.runtime.txSlotProvider.numSlots = 0;
ivars.runtime.txExecutionTimeline.controlBlock = nullptr;
ivars.runtime.txExecutionTimeline.queueControl = nullptr;

// Secondary playback stream teardown (mirrors the master above).
ivars.runtime.txSecondaryActive = false;
Expand All @@ -306,7 +307,8 @@ void PerformLoudTeardown(ASFWAudioDriver_IVars& ivars, const char* reason) noexc
ivars.txControlBufferSecondary = nullptr;
ivars.runtime.txSlotProviderSecondary.payloadBase = nullptr;
ivars.runtime.txSlotProviderSecondary.metadataRing = nullptr;
ivars.runtime.txSlotProviderSecondary.controlBlock = nullptr;
ivars.runtime.txSlotProviderSecondary.queueControl = nullptr;
ivars.runtime.txSlotProviderSecondary.audioControl = nullptr;
ivars.runtime.txSlotProviderSecondary.numSlots = 0;

ivars.device.audioNub->FreeTxIsochResources();
Expand Down
Loading
Loading