⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prophnd.cpp

📁 AC97 Sample Driver and Related Code Samples. This directory contains a sample AC97 adapter driver a
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 * 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 + -