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

📄 prophnd.cpp

📁 AC97 Sample Driver and Related Code Samples. This directory contains a sample AC97 adapter driver a
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            Range->Reserved         = 0;

            // set the return value size
            PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) +
                                         sizeof(KSPROPERTY_MEMBERSHEADER) +
                                         sizeof(KSPROPERTY_STEPPING_LONG);

            DOUT (DBG_PROPERTY, ("BASIC_SUPPORT: %s max=0x%x min=0x%x step=0x%x",
                NodeStrings[that->TransNodeNrToNodeDef (PropertyRequest->Node)],
                Range->Bounds.SignedMaximum, Range->Bounds.SignedMinimum,
                Range->SteppingDelta));
        } else
        {
            // we hadn't enough space for the range information; 
            // set the return value size
            PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
        }

        ntStatus = STATUS_SUCCESS;
    }
    else if (PropertyRequest->ValueSize >= sizeof(ULONG))
    {
        // if return buffer can hold a ULONG, return the access flags
        PULONG AccessFlags = (PULONG)PropertyRequest->Value;

        *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT |
                       KSPROPERTY_TYPE_GET |
                       KSPROPERTY_TYPE_SET;

        // set the return value size
        PropertyRequest->ValueSize = sizeof(ULONG);
        ntStatus = STATUS_SUCCESS;
    }

    // In case there was not even enough space for a ULONG in the return buffer,
    // we fail this request with STATUS_INVALID_DEVICE_REQUEST.
    // Any other case will return STATUS_SUCCESS.
    return ntStatus;
}

/*****************************************************************************
 * CMiniportTopologyICH::PropertyHandler_Level
 *****************************************************************************
 * Accesses a KSAUDIO_LEVEL property.
 * This function (property handler) is called by portcls every time there is a
 * get, set or basic support request for the node. The connection between the
 * node type and the property handler is made in the automation table which is
 * referenced when you register the node.
 * We use this property handler for all volume controls (and virtual volume
 * controls for recording).
 */
NTSTATUS CMiniportTopologyICH::PropertyHandler_Level
(
    IN      PPCPROPERTY_REQUEST   PropertyRequest
)
{
    PAGED_CODE ();

    ASSERT (PropertyRequest);

    DOUT (DBG_PRINT, ("[CMiniportTopologyICH::PropertyHandler_Level]"));

    NTSTATUS        ntStatus = STATUS_INVALID_PARAMETER;
    TopoNodes       NodeDef;
    LONG            channel;
    LONG            lMinimum, lMaximum;
    ULONG           uStep;
    // The major target is the object pointer to the topology miniport.
    CMiniportTopologyICH *that =
        (CMiniportTopologyICH *) PropertyRequest->MajorTarget;

    ASSERT (that);

    // 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(LONG)))
            return ntStatus;

        // get channel information
        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;

        // get the buffer
        PLONG Level = (PLONG)PropertyRequest->Value;

        // Switch on the node id. This is just for parameter checking.
        // If something goes wrong, we will immideately return with
        // ntStatus, which is STATUS_INVALID_PARAMETER.
        switch(NodeDef = that->TransNodeNrToNodeDef (PropertyRequest->Node))
        {
            // these are mono channels, don't respond to a right channel
            // request.
            case NODE_PCBEEP_VOLUME:
            case NODE_PHONE_VOLUME:
            case NODE_MIC_VOLUME:
            case NODE_VIRT_MONOOUT_VOLUME1:
            case NODE_VIRT_MONOOUT_VOLUME2:
            case NODE_VIRT_MASTER_INPUT_VOLUME1:
            case NODE_VIRT_MASTER_INPUT_VOLUME7:
            case NODE_VIRT_MASTER_INPUT_VOLUME8:
            case NODE_MICIN_VOLUME:
            case NODE_VIRT_MASTERMONO_VOLUME:
            case NODE_CENTER_VOLUME:
            case NODE_LFE_VOLUME:
                // check type
                if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)
                    return ntStatus;
                // check channel
                if (channel == CHAN_RIGHT)
                    return ntStatus;
                // Well, this is a fake for the routine below that should work
                // for all nodes ... On AC97 the right channel are the LSBs and
                // mono channels have only LSBs used. Windows however thinks that
                // mono channels are left channels (only). So we could say here
                // we have a right channel request (to prg. the LSBs) instead of
                // a left channel request. But we have some controls that are HW-
                // stereo, but exposed to the system as mono. These are the virtual
                // volume controls in front of the wave-in muxer for the MIC, PHONE
                // and MONO MIX signals (see to the switch:
                // NODE_VIRT_MASTER_INPUT_VOLUME1, 7 and 8). Saying we have a MASTER
                // request makes sure the value is prg. for left and right channel,
                // but on HW-mono controls the right channel is prg. only, cause the
                // mask in ac97reg.h leads to a 0-mask for left channel prg. which
                // just does nothing ;)
                channel = CHAN_MASTER;
                break;
            
            // These are stereo channels.
            case NODE_MASTEROUT_VOLUME:
            case NODE_FRONT_VOLUME:
            case NODE_SURROUND_VOLUME:
            case NODE_HPOUT_VOLUME:
            case NODE_LINEIN_VOLUME:
            case NODE_CD_VOLUME:
            case NODE_VIDEO_VOLUME:
            case NODE_AUX_VOLUME:
            case NODE_WAVEOUT_VOLUME:
            case NODE_VIRT_MASTER_INPUT_VOLUME2:
            case NODE_VIRT_MASTER_INPUT_VOLUME3:
            case NODE_VIRT_MASTER_INPUT_VOLUME4:
            case NODE_VIRT_MASTER_INPUT_VOLUME5:
            case NODE_VIRT_MASTER_INPUT_VOLUME6:
                // check type
                if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)
                    return ntStatus;
                // check channel; we don't support a get with master
                if ((channel == CHAN_MASTER) &&
                    (PropertyRequest->Verb & KSPROPERTY_TYPE_GET))
                    return ntStatus;
                break;

            case NODE_INVALID:
            default:
                // Ooops
                DOUT (DBG_ERROR, ("PropertyHandler_Level: Invalid node requested."));
                return ntStatus;
        }

        // Now, do some action!

        // get the registered dB values.
        ntStatus = GetDBValues (that->AdapterCommon, NodeDef, &lMinimum,
                                &lMaximum, &uStep);
        if (!NT_SUCCESS (ntStatus))
            return ntStatus;

        // do a get
        if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
        {
            WORD    wRegister;

            // Read the HW register for the node except NODE_VIRT_MASTERMONO_VOLUME
            // since this is pure virtual.
            if (NodeDef != NODE_VIRT_MASTERMONO_VOLUME)
            {
                // 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 and rotate.
                if (channel == CHAN_LEFT)
                {
                    wRegister = (wRegister & (that->AdapterCommon->GetNodeMask (NodeDef)
                                & AC97REG_MASK_LEFT)) >> 8;
                }
                else    // here goes mono or stereo-right
                {
                    wRegister &= (that->AdapterCommon->GetNodeMask (NodeDef) &
                                  AC97REG_MASK_RIGHT);
                }
            
                // Oops - NODE_PCBEEP_VOLUME doesn't use bit0. We have to adjust.
                if (NodeDef == NODE_PCBEEP_VOLUME)
                    wRegister >>= 1;

                // we have to translate the reg to dB.dB value.

                switch (NodeDef)
                {
                    // for record, we calculate it reverse.
                    case NODE_VIRT_MASTER_INPUT_VOLUME1:
                    case NODE_VIRT_MASTER_INPUT_VOLUME2:
                    case NODE_VIRT_MASTER_INPUT_VOLUME3:
                    case NODE_VIRT_MASTER_INPUT_VOLUME4:
                    case NODE_VIRT_MASTER_INPUT_VOLUME5:
                    case NODE_VIRT_MASTER_INPUT_VOLUME6:
                    case NODE_VIRT_MASTER_INPUT_VOLUME7:
                    case NODE_VIRT_MASTER_INPUT_VOLUME8:
                    case NODE_MICIN_VOLUME:
                        *Level = lMinimum + uStep * wRegister;
                        break;
                    default:
                        *Level = lMaximum - uStep * wRegister;
                        break;
                }
                
                // For the virtual controls, which are in front of a muxer, there
                // is no mute control displayed. But we have a HW mute control, so
                // what we do is enabling this mute when the user moves the slider
                // down to the bottom and disabling it on every other position.
                // We will return a PROP_MOST_NEGATIVE value in case the slider
                // is moved to the bottom.
                // We do this only for the "mono muxer" since the volume there ranges
                // from 0 to -46.5dB. The record volumes only have a range from
                // 0 to +22.5dB and we cannot mute them when the slider is down.
                if ((NodeDef == NODE_VIRT_MONOOUT_VOLUME1) ||
                    (NodeDef == NODE_VIRT_MONOOUT_VOLUME2))
                {
                    // read the register again.
                    ntStatus = that->AdapterCommon->ReadCodecRegister (
                               that->AdapterCommon->GetNodeReg (NodeDef), &wRegister);
                    if (!NT_SUCCESS (ntStatus))
                        return ntStatus;
                    // return most negative value in case it is checked.
                    if (wRegister & AC97REG_MASK_MUTE)
                        *Level = PROP_MOST_NEGATIVE;
                }
            }
            else    // This is master mono volume.
            {
                // Assume 0dB for master mono volume.
                *Level = 0;
            }

            // when we have cache information then return this instead
            // of the calculated value. if we don't, store the calculated
            // value.
            // We do that twice for master because in case we didn't set
            // the NodeCache yet it will be set then.
            if ((channel == CHAN_LEFT) || (channel == CHAN_MASTER))
            {
                if (that->stNodeCache[NodeDef].bLeftValid)
                    *Level = that->stNodeCache[NodeDef].lLeft;
                else
                {
                    that->stNodeCache[NodeDef].lLeft = *Level;
                    that->stNodeCache[NodeDef].bLeftValid = -1;
                }
            }

            if ((channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
            {
                if (that->stNodeCache[NodeDef].bRightValid)
                    *Level = that->stNodeCache[NodeDef].lRight;
                else
                {
                    that->stNodeCache[NodeDef].lRight = *Level;
                    that->stNodeCache[NodeDef].bRightValid = -1;
                }
            }

            // thats all, good bye.
            PropertyRequest->ValueSize = sizeof(LONG);
            DOUT (DBG_PROPERTY, ("GET: %s(%s) = 0x%x",NodeStrings[NodeDef],
                    channel==CHAN_LEFT ? "L" : "R", *Level));
            
            // ntStatus was set with the read call! whatever this is, return it.
        }
        else        // this must be a set
        {
            WORD    wRegister;
            LONG    lLevel = *Level;

            //
            // Check borders.
            //
            // These 2 lines will have a special effect on sndvol32.
            // Whenever you move the balance slider on a volume, one channel
            // keeps the same and the other volume channel gets descreased.
            // With ac97 on recording controls, the default slider position
            // is at 0dB and the range of the volume is 0dB till +22.5dB.
            // That means that panning (moving the balance slider) is simply

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -