📄 hwctxt.cpp
字号:
SetOutputGain(m_dwOutputGain);
SetInputGain(m_dwInputGain);
SetOutputMute(m_fOutputMute);
SetInputMute(m_fInputMute);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: PowerDown()
Description: Powers down the audio codec chip.
Notes: Even if the input/output channels are muted, this
function powers down the audio codec chip in order
to conserve battery power.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::PowerDown()
{
StopOutputDMA();
AudioMute((DMA_CH_OUT | DMA_CH_MIC), TRUE);
}
//############################################ Helper Functions #############################################
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: TransferOutputBuffer()
Description: Retrieves the next "mixed" audio buffer of data to
DMA into the output channel.
Returns: Number of bytes needing to be transferred.
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferOutputBuffer(ULONG NumBuf)
{
ULONG BytesTransferred = 0;
PBYTE pBufferStart = m_Output_pbDMA_PAGES[NumBuf];
PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
PBYTE pBufferLast;
__try
{
pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
BytesTransferred = m_OutBytes[NumBuf] = pBufferLast-pBufferStart;
// Enable if you need to clear the rest of the DMA buffer
StreamContext::ClearBuffer(pBufferLast,pBufferEnd);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferOutputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
}
return BytesTransferred;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: TransferInputBuffer()
Description: Retrieves the chunk of recorded sound data and inputs
it into an audio buffer for potential "mixing".
Returns: Number of bytes needing to be transferred.
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferInputBuffer(ULONG NumBuf)
{
ULONG BytesTransferred = 0;
PBYTE pBufferStart = m_Input_pbDMA_PAGES[NumBuf];
PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
PBYTE pBufferLast;
__try
{
pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
BytesTransferred = pBufferLast-pBufferStart;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferInputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
}
return BytesTransferred;
}
void HardwareContext::InterruptThread()
{
while (TRUE)
{
// Wait for DMA input and/or output interrupts
WaitForSingleObject(m_hAudioInterrupt, INFINITE);
//----- 1. Grab the lock -----
Lock();
__try
{
//----- Determine the interrupt source (input DMA operation or output DMA operation?) -----
//----- NOTE: Often, platforms use two separate DMA channels for input/output operations but
// have the OAL return SYSINTR_AUDIO as the interrupt source. If this is the case,
// then the interrupt source (input or output DMA channel) must be determined in
// this step.
UINT32 IntMask = s2410INT->INTMSK;
// Look at the output channel
if ( IntMask & (1 << IRQ_DMA2) )
{
ULONG ByteCount;
//----- 1. Transfer the data -----
ByteCount = TransferOutputBuffer(m_OutputDMABuffer);
//----- 2. Stop the DMA if necessary -----
// For output DMA, if we stop the DMA as soon as we have no data to transfer,
// we may cutoff unplayed data in the other buffer. Therefore, we can't stop
// the output DMA until all output buffers are totally empty.
ByteCount = m_OutBytes[OUT_BUFFER_A] + m_OutBytes[OUT_BUFFER_B];
if (ByteCount==0)
{
StopOutputDMA();
}
else // setup for the next DMA operation
{
// Reset buffer pointers and setup next DMA
if (OUT_BUFFER_A==m_OutputDMABuffer)
{
g_pDMAregs->DISRC2 = g_PhysDMABufferAddr.LowPart;
m_OutputDMABuffer=OUT_BUFFER_B;
}
else
{
g_pDMAregs->DISRC2 = g_PhysDMABufferAddr.LowPart + AUDIO_DMA_PAGE_SIZE;
m_OutputDMABuffer=OUT_BUFFER_A;
}
}
//----- 3. Acknowledge the DMA interrupt -----
InterruptDone(m_dwSysintrOutput);
}
// Look at the input channel
if ( IntMask & (1 << IRQ_DMA1) )
{
ULONG ByteCount;
//----- 1. Transfer the data -----
ByteCount = TransferInputBuffer(m_InputDMABuffer);
//----- 2. Stop the DMA if necessary -----
// For input DMA, we can stop the DMA as soon as we have no data to transfer.
if (ByteCount==0)
{
StopInputDMA();
}
else // setup for the next DMA operation
{
// Reset buffer pointers and setup next DMA
if (IN_BUFFER_A==m_InputDMABuffer)
{
g_pDMAregs->DIDST1 = g_PhysDMABufferAddr.LowPart + (2 * AUDIO_DMA_PAGE_SIZE);
m_InputDMABuffer=IN_BUFFER_B;
}
else
{
g_pDMAregs->DIDST1 = g_PhysDMABufferAddr.LowPart + (3 * AUDIO_DMA_PAGE_SIZE);
m_InputDMABuffer=IN_BUFFER_A;
}
}
//----- 3. Acknowledge the DMA interrupt -----
InterruptDone(m_dwSysintrInput);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
}
//----- 10. Give up the lock -----
Unlock();
}
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: AudioMute()
Description: Mutes/unmutes the specified audio channel.
Notes: If both audio channels are MUTED, then the chip
is powered down to conserve battery life.
Alternatively, if either audio channel is unMUTED,
the chip is powered up.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::AudioMute(DWORD channel, BOOL bMute)
{
static DWORD dwActiveChannel = 0;
return(TRUE);
}
void CallInterruptThread(HardwareContext *pHWContext)
{
pHWContext->InterruptThread();
}
//------------------------------------------------------------------------------
//
// Function: PmControlMessage
//
// Power management routine.
//
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
BOOL
HardwareContext::PmControlMessage (
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL bRetVal = FALSE;
switch (dwCode)
{
// Return device specific power capabilities.
case IOCTL_POWER_CAPABILITIES:
{
PPOWER_CAPABILITIES ppc = (PPOWER_CAPABILITIES) pBufOut;
// Check arguments.
if ( ppc && (dwLenOut >= sizeof(POWER_CAPABILITIES)) && pdwActualOut )
{
// Clear capabilities structure.
memset( ppc, 0, sizeof(POWER_CAPABILITIES) );
// Set power capabilities. Supports D0 and D4.
ppc->DeviceDx = DX_MASK(D0)|DX_MASK(D4);
DEBUGMSG(ZONE_FUNCTION, (TEXT("WAVE: IOCTL_POWER_CAPABILITIES = 0x%x\r\n"), ppc->DeviceDx));
// Update returned data size.
*pdwActualOut = sizeof(*ppc);
bRetVal = TRUE;
}
else
{
DEBUGMSG(ZONE_ERROR, ( TEXT( "WAVE: Invalid parameter.\r\n" ) ) );
}
break;
}
// Indicate if the device is ready to enter a new device power state.
case IOCTL_POWER_QUERY:
{
PCEDEVICE_POWER_STATE pDxState = (PCEDEVICE_POWER_STATE)pBufOut;
// Check arguments.
if (pDxState && (dwLenOut >= sizeof(CEDEVICE_POWER_STATE)) && pdwActualOut)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("WAVE: IOCTL_POWER_QUERY = %d\r\n"), *pDxState));
// Check for any valid power state.
if (VALID_DX (*pDxState))
{
*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
bRetVal = TRUE;
}
else
{
DEBUGMSG(ZONE_ERROR, ( TEXT( "WAVE: IOCTL_POWER_QUERY invalid power state.\r\n" ) ) );
}
}
else
{
DEBUGMSG(ZONE_ERROR, ( TEXT( "WAVE: IOCTL_POWER_QUERY invalid parameter.\r\n" ) ) );
}
break;
}
// Request a change from one device power state to another.
case IOCTL_POWER_SET:
{
PCEDEVICE_POWER_STATE pDxState = (PCEDEVICE_POWER_STATE)pBufOut;
// Check arguments.
if (pDxState && (dwLenOut >= sizeof(CEDEVICE_POWER_STATE)))
{
DEBUGMSG(ZONE_FUNCTION, ( TEXT( "WAVE: IOCTL_POWER_SET = %d.\r\n"), *pDxState));
// Check for any valid power state.
if (VALID_DX(*pDxState))
{
Lock();
// Power off.
if ( *pDxState == D4 )
{
PowerDown();
}
// Power on.
else
{
PowerUp();
}
m_DxState = *pDxState;
Unlock();
bRetVal = TRUE;
}
else
{
DEBUGMSG(ZONE_ERROR, ( TEXT( "WAVE: IOCTL_POWER_SET invalid power state.\r\n" ) ) );
}
}
else
{
DEBUGMSG(ZONE_ERROR, ( TEXT( "WAVE: IOCTL_POWER_SET invalid parameter.\r\n" ) ) );
}
break;
}
// Return the current device power state.
case IOCTL_POWER_GET:
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("WAVE: IOCTL_POWER_GET -- not supported!\r\n")));
break;
}
default:
DEBUGMSG(ZONE_WARN, (TEXT("WAVE: Unknown IOCTL_xxx(0x%0.8X) \r\n"), dwCode));
break;
}
return bRetVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -