📄 hwctxt.cpp
字号:
//------------------------------------------------------------------------------
//
// FUNCTION: TransferInputBuffer
//
// DESCRIPTION: Actual function to transfer received data from
// DMA to the indicated receive buffer.
// Called by TransferInputBuffers
//
// PARAMETERS:
// bufIndex - index of receive buffer to fill
//
// RETURNS:
// Number of bytes transferred to buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferInputBuffer(UINT8 bufIndex)
{
ULONG BytesTransferred = 0;
UINT8 *pBufferStart = (UINT8 *)m_Input_pbDMA_PAGES[bufIndex];
UINT8 *pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
UINT8 *pBufferLast;
__try
{
pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, NULL);
BytesTransferred = m_InBytes[bufIndex] = pBufferLast-pBufferStart;
//DmacSetRepeatType(m_DmaRxChannel, DMAC_REPEAT_ONCE);
DDKDmacSetDestAddress(m_DmaRxChannel, m_DmaRxBuffer[bufIndex]);
//DmacStartChan(m_DmaRxChannel);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferInputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
}
return BytesTransferred;
}
//------------------------------------------------------------------------------
//
// FUNCTION: TransferInputBuffers
//
// DESCRIPTION: Calls TransferInputBuffer to transfer data from
// DMA to receive buffer. Also toggles the current
// buffer index to acheive double buffering. Stops
// input dma if nothing is transferred.
//
// PARAMETERS:
// None
//
// RETURNS:
// Number of bytes transferred to buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferInputBuffers(void)
{
UINT32 BytesTransferred = 0;
// UINT32 DmaTransferred = 0;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+TransferInputBuffers\r\n")));
// DmaTransferred = DmacGetTransSize(m_DmaRxChannel);
// RETAILMSG(1, (TEXT("DmaTransferred(%d).\r\n"), DmaTransferred));
BytesTransferred = TransferInputBuffer(m_RxBufIndex);
m_RxBufIndex = (m_RxBufIndex == 0)? 1 : 0;
// RETAILMSG(1, (TEXT("HardwareContext::TransferInputBuffers(%d).\r\n"), BytesTransferred));
// If it was our interrupt, but we weren't able to transfer any bytes
// (e.g. no empty buffers ready to be filled)
// Then stop the input DMA
if(BytesTransferred == 0)
{
StopInputDMA();
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-TransferInputBuffers: BytesTransferred=%d\r\n"), BytesTransferred));
return BytesTransferred;
}
//------------------------------------------------------------------------------
//
// FUNCTION: InterruptThread
//
// DESCRIPTION: Interrupt service routine for playback and recording
// DMA interrupts
//
// PARAMETERS:
// None
//
// RETURNS:
// None
//
//------------------------------------------------------------------------------
void HardwareContext::InterruptThread()
{
UINT32 InputTransferred;
UINT32 OutputTransferred;
UINT32 intrMask;
UINT32 DmaInterruptSource;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+InterruptThread\r\n")));
// Fast way to access embedded pointers in wave headers in other processes.
SetProcPermissions((ULONG)-1);
while(TRUE)
{
DEBUGMSG(ZONE_INTERRUPT, (TEXT("+WaitForSingleObject\r\n")));
WaitForSingleObject(m_hAudioInterrupt, INFINITE);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("-WaitForSingleObject\r\n")));
//----- 1. Grab the lock -----
DmaInterruptSource = 0;
Lock();
__try
{
//----- 2. 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.
intrMask = DDKDmacGetTransStatus(m_DmaTxChannel);
if(intrMask != DMAC_TRANSFER_STATUS_NONE)
{
if(intrMask == DMAC_TRANSFER_STATUS_COMPLETE)
{
DmaInterruptSource |= AUDIO_CH_OUT;
}
//----- 3. Acknowledge the DMA interrupt -----
DDKDmacClearChannelIntr(m_DmaTxChannel);
InterruptDone(m_dwSysintrOutput);
}
if((DmaInterruptSource & AUDIO_CH_OUT) != 0)
{
if(m_OutputDMARunning == TRUE)
{
OutputTransferred = TransferOutputBuffers();
}
}
intrMask = DDKDmacGetTransStatus(m_DmaRxChannel);
if(intrMask != DMAC_TRANSFER_STATUS_NONE)
{
if(intrMask == DMAC_TRANSFER_STATUS_COMPLETE)
{
DmaInterruptSource |= AUDIO_CH_IN;
}
//----- 3. Acknowledge the DMA interrupt -----
DDKDmacClearChannelIntr(m_DmaRxChannel);
InterruptDone(m_dwSysintrInput);
}
//----- 4. Handle any interrupts on the input source -----
// NOTE: The InterruptDone() call below automatically clears the interrupt.
if((DmaInterruptSource & AUDIO_CH_IN) != 0)
{
if(m_InputDMARunning == TRUE)
{
InputTransferred = TransferInputBuffers();
}
}
DEBUGMSG(ZONE_INTERRUPT, (TEXT("interrupt: %d\r\n"), DmaInterruptSource));
if(DmaInterruptSource == 0)
{
// Unknown interrupt!
DEBUGMSG(ZONE_INTERRUPT, (TEXT("Unknown interrupt!\r\n")));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
}
//----- 10. Give up the lock -----
Unlock();
} // while(TRUE)
DEBUGMSG(ZONE_FUNCTION, (TEXT("-InterruptThread\r\n")));
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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)
{
BOOL bSetPlayback;
BOOL bSetRecord;
bSetPlayback = ((channel & AUDIO_CH_OUT) != 0)? TRUE : FALSE;
bSetRecord = ((channel & AUDIO_CH_IN) != 0)? TRUE : FALSE;
BSPAudioSetPowerOnOff(bSetPlayback, bSetRecord, bMute);
return(TRUE);
}
//------------------------------------------------------------------------------
//
// FUNCTION: CallInterruptThread
//
// DESCRIPTION: Actual function called by interrupt service thread
//
// PARAMETERS:
// pHWContext - pointer to calling HwContext
//
// RETURNS:
// None
//
//------------------------------------------------------------------------------
void CallInterruptThread(HardwareContext *pHWContext)
{
pHWContext->InterruptThread();
}
//------------------------------------------------------------------------------
//
// FUNCTION: PmControlMessage
//
// DESCRIPTION: Power management routine.
//
// PARAMETERS:
// wCode[in] IO control code for the function to be performed.
// WAV_IOControl only supports one IOCTL value
// (IOCTL_WAV_MESSAGE)
// pBufIn[in] Pointer to the input parameter structure
// (<t MMDRV_MESSAGE_PARAMS>).
// dwLenIn[in] Size in bytes of input parameter structure
// (sizeof(<t MMDRV_MESSAGE_PARAMS>)).
// pBufOut[out] Pointer to the return value (DWORD)
// dwLenOut[out]Size of the return value variable (sizeof(DWORD)).
// pdwActualOut Unused
//
// RETURNS: TRUE for success, FALSE for failure
//
//------------------------------------------------------------------------------
BOOL HardwareContext::PmControlMessage (
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL bRetVal = FALSE;
switch (dwCode)
{
DEBUGMSG(ZONE_IOCTL, ( TEXT( "WAVE: PmControlMessage. \r\n" ) ) );
// 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_IOCTL, (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_IOCTL, (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_IOCTL, ( 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:
{
if( pBufOut != NULL &&
dwLenOut >= sizeof(CEDEVICE_POWER_STATE) &&
pdwActualOut != NULL)
{
*(CEDEVICE_POWER_STATE *)pBufOut = m_DxState;
*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
bRetVal = TRUE;
}
DEBUGMSG(ZONE_IOCTL, (TEXT("WAVE: IOCTL_POWER_GET !\r\n")));
break;
}
default:
DEBUGMSG(ZONE_ERROR, (TEXT("WAVE: Unknown IOCTL_xxx(0x%0.8X) \r\n"), dwCode));
break;
}
return bRetVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -