📄 prophnd.cpp
字号:
* the property handler is made in the automation table which is referenced
* when you register the node.
* We use this property handler for all nodes that have a checkbox, means mute
* controls and the special checkbox controls under advanced properties, which
* are AGC and LOUDNESS.
*/
NTSTATUS CMiniportTopologyICH::PropertyHandler_OnOff
(
IN PPCPROPERTY_REQUEST PropertyRequest
)
{
PAGED_CODE ();
ASSERT (PropertyRequest);
NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
LONG channel;
TopoNodes NodeDef;
// The major target is the object pointer to the topology miniport.
CMiniportTopologyICH *that =
(CMiniportTopologyICH *) PropertyRequest->MajorTarget;
ASSERT (that);
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::PropertyHandler_OnOff]"));
// validate node
if (PropertyRequest->Node == (ULONG)-1)
return ntStatus;
// do the appropriate action for the request.
// we should do a get or a set?
if ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) ||
(PropertyRequest->Verb & KSPROPERTY_TYPE_SET))
{
// validate parameters
if ((PropertyRequest->InstanceSize < sizeof(LONG)) ||
(PropertyRequest->ValueSize < sizeof(BOOL)))
return ntStatus;
// get channel
channel = *(PLONG)PropertyRequest->Instance;
// check channel types, return when unknown
// as you can see, we have no multichannel support.
if ((channel != CHAN_LEFT) &&
(channel != CHAN_RIGHT) &&
(channel != CHAN_MASTER))
return ntStatus;
// We have only mono mutes or On/Off checkboxes although they might control
// a stereo path. For example, we have a 1-bit mute for CD Volume. This
// mute controls both CD Volume channels.
if (channel == CHAN_RIGHT)
return ntStatus;
// get the buffer
PBOOL OnOff = (PBOOL)PropertyRequest->Value;
// Switch on the node id. This is just for parameter checking.
// If something goes wrong, we will immediately return with
// ntStatus, which is STATUS_INVALID_PARAMETER.
switch (NodeDef = that->TransNodeNrToNodeDef (PropertyRequest->Node))
{
// These are mutes for mono volumes.
case NODE_PCBEEP_MUTE:
case NODE_PHONE_MUTE:
case NODE_MIC_MUTE:
case NODE_MICIN_MUTE:
case NODE_CENTER_MUTE:
case NODE_LFE_MUTE:
case NODE_VIRT_MASTERMONO_MUTE:
// check type
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_MUTE)
return ntStatus;
break;
// Well, this one is a AGC, although there is no _automatic_ gain
// control, but we have a mic boost (which is some kind of manual
// gain control).
// The 3D Bypass is a real fake, but that's how you get check boxes
// on the advanced control panel.
// Both controls are in a mono path.
case NODE_VIRT_WAVEOUT_3D_BYPASS:
case NODE_MIC_BOOST:
// check type
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_AGC)
return ntStatus;
break;
// Simulated Stereo is a AGC control in a stereo path.
case NODE_SIMUL_STEREO:
// check type
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_AGC)
return ntStatus;
break;
// This is a loudness control in a stereo path. We have to check the
// type.
case NODE_LOUDNESS:
// check type
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_LOUDNESS)
return ntStatus;
break;
// For 3D Enable and Mic are exposed as loudness in a mono path.
case NODE_VIRT_3D_ENABLE:
case NODE_MIC_SELECT:
// check type
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_LOUDNESS)
return ntStatus;
break;
// These are mutes in a stereo path.
// Because the HW has only one mute-bit for the stereo channel, we
// expose the mute as mono. this works in current OS and hopefully
// will work in future OS.
case NODE_WAVEOUT_MUTE:
case NODE_LINEIN_MUTE:
case NODE_CD_MUTE:
case NODE_VIDEO_MUTE:
case NODE_AUX_MUTE:
case NODE_MASTEROUT_MUTE:
case NODE_FRONT_MUTE:
case NODE_SURROUND_MUTE:
case NODE_HPOUT_MUTE:
// just check the type.
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_MUTE)
return ntStatus;
break;
case NODE_INVALID:
default:
// Ooops.
DOUT (DBG_ERROR, ("PropertyHandler_OnOff: Invalid node requested."));
return ntStatus;
}
// Now, do some action!
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
{
WORD wRegister;
// Read the HW register for the node except NODE_VIRT_MASTERMONO_MUTE,
// since this is pure virtual.
if (NodeDef != NODE_VIRT_MASTERMONO_MUTE)
{
// get the register and read it.
ntStatus = that->AdapterCommon->ReadCodecRegister (
that->AdapterCommon->GetNodeReg (NodeDef), &wRegister);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
// Mask out every unused bit.
wRegister &= that->AdapterCommon->GetNodeMask (NodeDef);
// Store the value.
*OnOff = wRegister ? TRUE : FALSE;
}
else
{
// Assume no mute for master mono.
*OnOff = FALSE;
}
// When we have cache information then return this instead of the
// calculated value. If we don't, store the calculated value.
if (that->stNodeCache[NodeDef].bLeftValid)
*OnOff = that->stNodeCache[NodeDef].lLeft;
else
{
that->stNodeCache[NodeDef].lLeft = *OnOff;
that->stNodeCache[NodeDef].bLeftValid = -1;
}
PropertyRequest->ValueSize = sizeof(BOOL);
DOUT (DBG_PROPERTY, ("GET: %s = 0x%x", NodeStrings[NodeDef], *OnOff));
// Set the return code here.
ntStatus = STATUS_SUCCESS;
}
else // this must be a set.
{
// First update the node cache.
that->stNodeCache[NodeDef].bLeftValid = -1;
that->stNodeCache[NodeDef].lLeft = (*OnOff) ? TRUE : FALSE;
//
// If we have a master mono, then we have to program the speaker
// mutes a little different.
// Check for master mono (surround or headphone present) and
// if one of the speaker mutes is requested.
//
if ((that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT)) &&
((NodeDef == NODE_VIRT_MASTERMONO_MUTE) || (NodeDef == NODE_LFE_MUTE) ||
(NodeDef == NODE_CENTER_MUTE) || (NodeDef == NODE_FRONT_MUTE) ||
(NodeDef == NODE_SURROUND_MUTE) || (NodeDef == NODE_HPOUT_MUTE)))
{
//
// For master mono we have to update all speakers.
//
if (NodeDef == NODE_VIRT_MASTERMONO_MUTE)
{
// Update all speaker mutes.
ntStatus = SetMultichannelMute (that, NODE_FRONT_MUTE);
if (that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
ntStatus = SetMultichannelMute (that, NODE_HPOUT_MUTE);
if (that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
ntStatus = SetMultichannelMute (that, NODE_SURROUND_MUTE);
if (that->AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
{
ntStatus = SetMultichannelMute (that, NODE_CENTER_MUTE);
ntStatus = SetMultichannelMute (that, NODE_LFE_MUTE);
}
}
else // Update the individual speaker mute.
{
ntStatus = SetMultichannelMute (that, NodeDef);
}
}
else
{
//
// For all other mutes/checkboxes just write the value to the HW.
//
ntStatus = that->AdapterCommon->WriteCodecRegister (
that->AdapterCommon->GetNodeReg (NodeDef),
(*OnOff) ? -1 : 0,
that->AdapterCommon->GetNodeMask (NodeDef));
}
DOUT (DBG_PROPERTY, ("SET: %s -> 0x%x", NodeStrings[NodeDef], *OnOff));
// ntStatus was set with the write call! whatever this is, return it.
}
}
return ntStatus;
}
/*****************************************************************************
* CMiniportTopologyICH::BasicSupportHandler
*****************************************************************************
* Assists in BASICSUPPORT accesses on level properties.
* This function is called internally every time there is a "basic support"
* request on a volume or tone control. The basic support is used to retrieve
* some information about the range of the control (from - to dB, steps) and
* which type of control (tone, volume).
* Basically, this function just calls GetDBValues to get the range information
* and fills the rest of the structure with some constants.
*/
NTSTATUS CMiniportTopologyICH::BasicSupportHandler
(
IN PPCPROPERTY_REQUEST PropertyRequest
)
{
PAGED_CODE ();
ASSERT (PropertyRequest);
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BasicSupportHandler]"));
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
// The major target is the object pointer to the topology miniport.
CMiniportTopologyICH *that =
(CMiniportTopologyICH *) PropertyRequest->MajorTarget;
ASSERT (that);
// if there is enough space for a KSPROPERTY_DESCRIPTION information
if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION)))
{
// we return a KSPROPERTY_DESCRIPTION structure.
PKSPROPERTY_DESCRIPTION PropDesc = (PKSPROPERTY_DESCRIPTION)PropertyRequest->Value;
PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT |
KSPROPERTY_TYPE_GET |
KSPROPERTY_TYPE_SET;
PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) +
sizeof(KSPROPERTY_STEPPING_LONG);
PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
PropDesc->PropTypeSet.Id = VT_I4;
PropDesc->PropTypeSet.Flags = 0;
PropDesc->MembersListCount = 1;
PropDesc->Reserved = 0;
// if return buffer can also hold a range description, return it too
if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG)))
{
// fill in the members header
PKSPROPERTY_MEMBERSHEADER Members = (PKSPROPERTY_MEMBERSHEADER)(PropDesc + 1);
Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
Members->MembersCount = 1;
Members->Flags = 0;
// fill in the stepped range
PKSPROPERTY_STEPPING_LONG Range = (PKSPROPERTY_STEPPING_LONG)(Members + 1);
ntStatus = GetDBValues (that->AdapterCommon,
that->TransNodeNrToNodeDef (PropertyRequest->Node),
&Range->Bounds.SignedMinimum,
&Range->Bounds.SignedMaximum,
&Range->SteppingDelta);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -