📄 mintopo.cpp
字号:
AdapterCommon = NULL;
}
if (FilterDescriptor)
{
ExFreePool (FilterDescriptor);
FilterDescriptor = NULL;
}
if (ConnectionDescriptors)
{
ExFreePool (ConnectionDescriptors);
ConnectionDescriptors = NULL;
}
if (NodeDescriptors)
{
ExFreePool (NodeDescriptors);
NodeDescriptors = NULL;
}
if (PinDescriptors)
{
ExFreePool (PinDescriptors);
PinDescriptors = NULL;
}
}
/*****************************************************************************
* CMiniportTopologyICH::DataRangeIntersection
*****************************************************************************
* Is defined in the IMiniportTopology interface. We just return
* STATUS_NOT_IMPLEMENTED and portcls will use a default handler for this.
*/
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::DataRangeIntersection
(
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength
)
{
return STATUS_NOT_IMPLEMENTED;
};
/*****************************************************************************
* CMiniportTopologyICH::Init
*****************************************************************************
* Initializes the miniport.
* We initialize the translation tables, add reference to the port driver and
* build the topology.
*/
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::Init
(
IN PUNKNOWN UnknownAdapter,
IN PRESOURCELIST ResourceList,
IN PPORTTOPOLOGY Port_
)
{
PAGED_CODE ();
ASSERT (UnknownAdapter);
ASSERT (Port_);
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::Init]"));
//
// Set the copy protect flag to FALSE.
//
m_bCopyProtectFlag = FALSE;
//
// get the IAdapterCommon interface from the adapter.
//
NTSTATUS ntStatus = UnknownAdapter->QueryInterface (IID_IAdapterCommon,
(PVOID *) &AdapterCommon);
//
// initialize translation tables
//
for (int i = 0; i < PIN_TOP_ELEMENT; i++)
{
stPinTrans[i].PinDef = PIN_INVALID;
stPinTrans[i].PinNr = -1;
}
for (i = 0; i < NODE_TOP_ELEMENT; i++)
{
stNodeTrans[i].NodeDef = NODE_INVALID;
stNodeTrans[i].NodeNr = -1;
}
// build the topology (means register pins, nodes, connections).
if (NT_SUCCESS (ntStatus))
{
ntStatus = BuildTopology ();
}
if (NT_SUCCESS (ntStatus))
{
//
// Notify AdapterCommon that we are ready now.
//
AdapterCommon->SetMiniportTopology (this);
}
else
{
//
// clean up our mess
//
// clean up AdapterCommon
if (AdapterCommon)
{
AdapterCommon->Release ();
AdapterCommon = NULL;
}
}
return ntStatus;
}
/*****************************************************************************
* CMiniportTopologyICH::GetDescription
*****************************************************************************
* Gets/returns the topology to the system.
*/
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::GetDescription
(
OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
)
{
PAGED_CODE ();
ASSERT (OutFilterDescriptor);
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::GetDescription]"));
#if (DBG)
// Dump it here. The system requests the topology only once.
DumpTopology ();
#endif
if (FilterDescriptor)
{
*OutFilterDescriptor = FilterDescriptor;
return STATUS_SUCCESS;
}
else
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
#if (DBG)
/*****************************************************************************
* CMiniportTopologyICH::DumpTopology
*****************************************************************************
* Dumps the topology for debugging.
* See the defines at the beginning of this file?
*/
void CMiniportTopologyICH::DumpTopology (void)
{
PAGED_CODE ();
if (FilterDescriptor)
{
// dump the pins
DOUT (DBG_PINS, ("TOPOLOGY MINIPORT PINS"));
for(ULONG index = 0; index < FilterDescriptor->PinCount; index++)
{
DOUT (DBG_PINS, (" %2d %s", index,
TopoPinStrings[TransPinNrToPinDef (index)]));
}
// dump the nodes
DOUT (DBG_NODES, ("TOPOLOGY MINIPORT NODES"));
for(index = 0; index < FilterDescriptor->NodeCount; index++)
{
DOUT (DBG_NODES, (" %2d %s", index,
NodeStrings[TransNodeNrToNodeDef (index)]));
}
// dump the connections
DOUT (DBG_CONNS, ("TOPOLOGY MINIPORT CONNECTIONS"));
for(index = 0; index < FilterDescriptor->ConnectionCount; index++)
{
DOUT (DBG_CONNS, (" %2d (%d,%d)->(%d,%d)", index,
FilterDescriptor->Connections[index].FromNode,
FilterDescriptor->Connections[index].FromNodePin,
FilterDescriptor->Connections[index].ToNode,
FilterDescriptor->Connections[index].ToNodePin));
}
}
}
#endif
/*****************************************************************************
* Miniport Topology V = Volume, M = Mute, L = Loudness, A = AGC
*==================== T = Treble, B = Bass, 0-9 = PinNr of node
*
* PCBEEP ---> V ---> M -----------------------------\
* PHONE ---> V ---> M ----------------------------\ \
* \ \
* WaveOut -------> V --> M --------------> 1+-----+ \ \
* MIC1 or MIC2 --> L --> A --> V --> M --> 2| SUM | \ \
* LineIn -------> V --> M --------------> 3| | \ \
* CD -------> V --> M --------------> 4| |0--->SUM--> T --> B --> L --> V --> M (MasterOut)
* Video -------> V --> M --------------> 5| |
* AUX -------> V --> M --------------> 6| |
* 3D Depth -----> V --> L --> A --------> 7| |
* 3D Center -----> V --> L --> A --------> 8| |
* Headphone -----> V --> M --------------> 9| |
* Front Speaker -> V --> M -------------->10| |
* Surround ------> V --> M -------------->11| |
* Center ------> V --> M -------------->12| |
* LFE ------> V --> M -------------->13+-----+
*
*
* virt. Pin: Tone mix mono ---> V --> M ---> 7+-------+
* virt. Pin: Tone mix stereo ---> V --> M ---> 6| |
* Phone ---> V --> M ---> 8| M |
* Mic (after AGC) ---> V --> M ---> 1| |0-----> (WaveIn)
* LineIn ---> V --> M ---> 5| U |
* CD ---> V --> M ---> 2| |
* Video ---> V --> M ---> 3| X |
* AUX ---> V --> M ---> 4+-------+
*
*
* virt. Pin: 3D mix mono ---> V ---> M ---> 1+-----+
* | MUX |0----> (MonoOut)
* Mic (after AGC) ---> V ---> M ---> 2+-----+
*
*
* Mic (after AGC) ----> V ----> M -----> (MicIn)
*
*----------------------------------------------------------------------------
*
* As you can see, the exposed topology is somewhat different from the real AC97
* topology. This is because the system that translates the topology to "mixer
* lines" gets confused if it has to deal with all the mess. So we have to make it
* plain and simple for the system.
* Some issues block us from exposing a nice plain and simple topology. The prg.
* which displayes the "Volume Control Panel" (sndvol32) does _only_ display
* Volumes, Mutes (only one "in a row"), Treble, Bass, Loudness and AGC under
* Advanced control panel. We don't have 3D controls, and before we go into a
* Muxer, there has to be Volume controls in front.
* So what do we do?
* 1) We fake 3D controls as Volume controls. The Mutes represent 3D bypass and
* 3D on/off
* 2) All inputs (including the 3D controls) go staight into a SUM. Important is
* that there are not 2 Volumes, Mutes in a row, e.g. ---> V ---> M ---> V ---> M
* In that case, only one Volume/Mute would be displayed.
* 3) We can't make a connection from the tone controls to the Wave In muxer (even
* with Volumes in front), so we create fake pins that we name user friendly.
* Same with the connection from the 3D mixer to the Mono output.
* 4) We discard all supermixer controls that would convert stereo to mono or vice
* versa. Instead, we just connect the lines and when the control is queried we
* fail a right channel request (mono has only left channel).
* 5) We have to make virtual volume and mute controls in front of each muxer.
* As you can see, these controls can be mono or stereo and there is only one
* HW register for them, so we have to cache the values and prg. the register
* each time the select changes or the selected volume control changes.
*/
/*****************************************************************************
* CMiniportTopologyICH::BuildTopology
*****************************************************************************
* Builds the topology descriptors based on hardware configuration info
* obtained from the adapter.
*/
NTSTATUS CMiniportTopologyICH::BuildTopology (void)
{
PAGED_CODE ();
NTSTATUS ntStatus = STATUS_SUCCESS;
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildTopology]"));
// allocate our filter descriptor
FilterDescriptor = (PPCFILTER_DESCRIPTOR) ExAllocatePool (PagedPool,
sizeof(PCFILTER_DESCRIPTOR));
if (FilterDescriptor)
{
// clear out the filter descriptor
RtlZeroMemory (FilterDescriptor, sizeof(PCFILTER_DESCRIPTOR));
#ifdef INCLUDE_PRIVATE_PROPERTY
// Set the Filter automation table.
FilterDescriptor->AutomationTable = &FilterAutomationPrivate;
#endif
// build the pin list
ntStatus = BuildPinDescriptors ();
if (NT_SUCCESS (ntStatus))
{
// build the node list
ntStatus = BuildNodeDescriptors ();
if (NT_SUCCESS (ntStatus))
{
// build the connection list
ntStatus = BuildConnectionDescriptors ();
}
}
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
// that's whatever one of these build... functions returned.
return ntStatus;
}
/*****************************************************************************
* CMiniportTopologyICH::BuildPinDescriptors
*****************************************************************************
* Builds the topology pin descriptors.
*/
NTSTATUS CMiniportTopologyICH::BuildPinDescriptors (void)
{
// Improvement would be to not use a Macro, use (inline) function instead.
#define INIT_PIN( pin, pinptr, category, name, index ) \
pinptr->KsPinDescriptor.Category = (GUID*) category; \
pinptr->KsPinDescriptor.Name = (GUID*) name; \
SetPinTranslation (index++, pin); \
pinptr++
PAGED_CODE ();
ULONG Index;
PPCPIN_DESCRIPTOR CurrentPin;
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildPinDescriptors]"));
// allocate our descriptor memory
PinDescriptors = PPCPIN_DESCRIPTOR (ExAllocatePool (PagedPool,
PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR)));
if (!PinDescriptors)
return STATUS_INSUFFICIENT_RESOURCES;
//
// set default pin descriptor parameters
//
RtlZeroMemory (PinDescriptors, PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR));
// spend some more time and set the pin descriptors to expected values.
for (CurrentPin = PinDescriptors, Index = 0; Index < PIN_TOP_ELEMENT;
CurrentPin++, Index++)
{
CurrentPin->KsPinDescriptor.DataRangesCount = SIZEOF_ARRAY(PinDataRangePointersAnalogBridge);
CurrentPin->KsPinDescriptor.DataRanges = PinDataRangePointersAnalogBridge;
CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
CurrentPin->KsPinDescriptor.Communication = KSPIN_COMMUNICATION_NONE;
}
//
// modify the individual pin descriptors
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -