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

📄 wavepdd.cpp

📁 此代码为WCE5.0下声卡的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#define ZONE_WPDD 0

//  
//  Module Name:  
//  
//      wavepdd.c
//  
//  Abstract:  
//      The PDD (Platform Dependent Driver) is responsible for 
//      communicating with the audio circuit to start and stop playback
//      and/or recording and initialize and deinitialize the circuits.
//  
//  Functions:
//      PDD_AudioGetInterruptType
//      PDD_AudioMessage
//      PDD_AudioInitialize
//      PDD_AudioDeinitialize
//      PDD_AudioPowerHandler
//      PDD_WaveProc
//  
//  Notes:
//  
// -----------------------------------------------------------------------------
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <excpt.h>
#include <nkintr.h>
#include <ceddk.h>
#include <cardserv.h>
#include <devload.h>
#include <ddkreg.h>
#include <giisr.h>
#include <wavedbg.h>
#include <waveddsi.h>
#include "es1371.h"

#define ZONE_VOLUME 0

// Globals 

typedef VOID (* PFNDMATRANSFER) (PWAVEHDR pwh, PBYTE pBuffer, ULONG cbBytes);

DWORD    g_dwBusNumber;
INTERFACE_TYPE g_IfcType;

struct _global_volume
{
    ULONG   dwMasterVolume;
    ULONG   dwLineInVolume;
    ULONG   dwMicVolume;
    BOOL    fMasterMute;
    BOOL    fLineInMute;
    BOOL    fMicMute;
    ULONG   dwInputSelect;
} g_VolumeSettings;


CES1371* pCES1371;
const ULONG  dma_buffer_size = 4096;

BOOL             g_fInUse[2];
PBYTE            g_dma_buffer[2]; 
PHYSICAL_ADDRESS g_dma_logical_address[2];
ULONG            g_dmapos[2];		// last known DMA position for the stream
UCHAR            g_dmachannel[2];	// ES1371_DAC0 or ES1371_ADC
PWAVEFORMATEX    g_pwfx[2];
UCHAR            g_silence;
PFNDMATRANSFER   g_pfnDmaTransfer[2];

HANDLE g_IsrHandle = NULL;

VOID private_AudioGetBuffer (PWAVEHDR pwh, PBYTE pSrcBuffer, ULONG cbSrcBytes);
VOID private_AudioCompleteAndFill (PWAVEHDR pwh, PBYTE pDstBuffer, ULONG cbDstBytes);

// Volume Linear to Log Lookup table
// aproximates to roughly 2 db's per increment
UCHAR volumeLUT[] = {
0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x2,
0x2,0x3,0x3,0x3,0x4,0x4,0x5,0x5,
0x6,0x6,0x7,0x8,0x9,0x9,0xA,0xB,
0xC,0xE,0xF,0x11,0x13,0x15,0x19,0x1F};

// -----------------------------------------------------------------------------
//
// Function to get the SysIntr and I/O port range from the registry
//
// NOTE: lpRegPath is assumed to be under HKEY_LOCAL_MACHINE
//
// Returns ERROR_SUCCESS on success or a Win32 error code on failure
//
// -----------------------------------------------------------------------------
DWORD
GetRegistryConfig(
    LPWSTR lpRegPath,
    DWORD * lpdwSysIntr,
    DWORD * lpdwIoBase,
    DWORD * lpdwIoLen,
    DWORD * lpdwDeviceID,
    DWORD * lpdwRevisionID,
    BOOL * bInstallIsr,         // OUT - TRUE if ISR Handler found in registry
    LPWSTR IsrDll,              // OUT - Name of ISR Handler dll
    LPWSTR IsrHandler,          // OUT - Name of ISR Handler routine
    DWORD * Irq,                 // OUT - IRQ number, used to hook ISR handler
    DWORD *lpdwBusNumber,
    PINTERFACE_TYPE pIfcType
    )
{
    HKEY hConfig = NULL;
    DWORD dwRet = ERROR_SUCCESS;
    DDKISRINFO dii;
    DDKWINDOWINFO dwi;
    DDKPCIINFO dpi;

    *bInstallIsr = FALSE;
    *Irq = -1;

    // get a pointer to our configuration key in the registry
    hConfig = OpenDeviceKey(lpRegPath);
    if(hConfig == NULL) {
    	DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: OpenDeviceKey('%s') failed\r\n"), lpRegPath));
        dwRet = ERROR_BADKEY;
    	goto EXIT;
    }

    // read window configuration from the registry
    dwi.cbSize = sizeof(dwi);
    dwRet = DDKReg_GetWindowInfo(hConfig, &dwi);
    if(dwRet != ERROR_SUCCESS) {
    	DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: DDKReg_GetWindowInfo() failed %d\r\n"), dwRet));
    	goto EXIT;
    } else if(dwi.dwNumIoWindows != 1) {
    	DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: %d windows configured, expected 1\r\n"), dwi.dwNumIoWindows));
    	dwRet = ERROR_INVALID_DATA;
    	goto EXIT;
    } else {
    	*lpdwIoBase = dwi.ioWindows[0].dwBase;
    	*lpdwIoLen = dwi.ioWindows[0].dwLen;
    	*lpdwBusNumber = dwi.dwBusNumber;
    	*pIfcType = (INTERFACE_TYPE) dwi.dwInterfaceType;
    }

    // get ISR configuration information
    dii.cbSize = sizeof(dii);
    dwRet = DDKReg_GetIsrInfo(hConfig, &dii);
    if(dwRet != ERROR_SUCCESS) {
    	DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: DDKReg_GetIsrInfo() failed %d\r\n"), dwRet));
    	goto EXIT;
    } else if(dii.dwSysintr == SYSINTR_NOP) {
    	DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: no SYSINTR value specified\r\n")));
    	dwRet = ERROR_INVALID_DATA;
    	goto EXIT;
    } else {
		// get installable ISR information
		if(dii.szIsrDll[0] != 0) {
			if(dii.szIsrHandler[0] == 0 || dii.dwIrq == IRQ_UNSPECIFIED) {
				DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: garbled or missing installable ISR settings\r\n")));
				dwRet = ERROR_INVALID_DATA;
				goto EXIT;
			} else {
				_tcscpy(IsrDll, dii.szIsrDll);
				_tcscpy(IsrHandler, dii.szIsrHandler);
				*bInstallIsr = TRUE;
			}
		}

		// was an IRQ specified?
		if(dii.dwIrq != IRQ_UNSPECIFIED) {
			*Irq = dii.dwIrq;
		}

    	// pass back the sysintr
    	*lpdwSysIntr = dii.dwSysintr;
    }

    // get device ID information
    dpi.cbSize = sizeof(dpi);
    dwRet = DDKReg_GetPciInfo(hConfig, &dpi);
    if(dwRet != ERROR_SUCCESS) {
    	DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: DDKReg_GetPciInfo() failed %d\r\n"), dwRet));
    	goto EXIT;
    } else if((dpi.dwWhichIds & (PCIIDM_DEVICEID | PCIIDM_REVISIONID)) != (PCIIDM_DEVICEID | PCIIDM_REVISIONID)) {
    	DEBUGMSG(ZONE_PDD, (_T("WAVEDEV: missing device or revision ID\r\n")));
    	dwRet = ERROR_INVALID_DATA;
    	goto EXIT;
    } else {
    	*lpdwDeviceID = dpi.idVals[PCIID_DEVICEID];
    	*lpdwRevisionID = dpi.idVals[PCIID_REVISIONID];
    }
    
EXIT:
    if (hConfig != NULL) {
        RegCloseKey(hConfig);
    }
    return dwRet;
}



// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
MMRESULT
private_WaveGetDevCaps(
    WAPI_INOUT apidir,
    PVOID pCaps,
    UINT  wSize
    )
{
    PWAVEINCAPS pwic  = (PWAVEINCAPS)pCaps;
    PWAVEOUTCAPS pwoc = (PWAVEOUTCAPS)pCaps;

    MMRESULT mmRet = MMSYSERR_NOERROR;

    FUNC_WPDD("+PDD_WaveGetDevCaps");

    if (pCaps == NULL)  {
        //
        // If pCaps == NULL, we are requesting if the driver PDD is capable of
        // this mode at all. In other words, if APIDIR == WAPI_IN,  we return
        // no error if input is supported, and MMSYSERR_NOTSUPPORTED otherwise.
        // Since Odo has both, we return MMSYSERR_NOERROR regardless.
        //
        return MMSYSERR_NOERROR;
    }

    //
    // Fill in the DevCaps here.
    //    
    pwoc->wMid = MM_MICROSOFT;
    pwoc->wPid = (apidir == WAPI_OUT ? 24 : 23);  // generic in or out...
    pwoc->vDriverVersion = 0x0001;

    wsprintf (pwoc->szPname, TEXT("CE/PC Audio (%hs)"), __DATE__);

    pwoc->dwFormats =   WAVE_FORMAT_1M08 | WAVE_FORMAT_1M16 |
                        WAVE_FORMAT_1S08 | WAVE_FORMAT_1S16 |
                        WAVE_FORMAT_2M08 | WAVE_FORMAT_2M16 |
                        WAVE_FORMAT_2S08 | WAVE_FORMAT_2S16 |
                        WAVE_FORMAT_4M08 | WAVE_FORMAT_4M16 |
                        WAVE_FORMAT_4S08 | WAVE_FORMAT_4S16;                        

    pwoc->wChannels = 2;
    if (apidir == WAPI_OUT) 
    {
        // Caution: the WAVEINCAPS structure doesn't have a dwSupport field. Touch here and die!
        pwoc->dwSupport = WAVECAPS_VOLUME | WAVECAPS_LRVOLUME;
    }

    FUNC_WPDD("-PDD_WaveGetDevCaps");

    return mmRet;
}    

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

VOID
private_AudioFillBuffer (PWAVEHDR pwh, PBYTE pDstBuffer, ULONG cbDstBytes)
{
    DEBUGMSG(ZONE_WPDD, (TEXT("WPDD: FillBuffer (%08x,%5d,%08x,%5d)\r\n"), pwh, pwh->reserved, pDstBuffer, cbDstBytes));

    while ((pwh != NULL) && (cbDstBytes > 0)) {
        if (pwh->reserved >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
        }
		else {
			// trasfer min(data_in_dma, room_in_buffer)
			ULONG cbSrcBytes = pwh->dwBufferLength - pwh->reserved;
			ULONG cbBytesTransferred = min(cbSrcBytes, cbDstBytes);

		    DEBUGMSG(ZONE_WPDD, (TEXT("WPDD: memcpy (%08x,%5d,%08x,%5d)\r\n"), pwh, pwh->reserved, pDstBuffer, cbBytesTransferred));
			memcpy(pDstBuffer, pwh->lpData + pwh->reserved, cbBytesTransferred);

			pwh->reserved += cbBytesTransferred;
			pDstBuffer += cbBytesTransferred;
			cbDstBytes -= cbBytesTransferred;
		}
    }
    // Nothing left to copy, so clear the remainder of the buffer with silence
    DEBUGMSG(ZONE_WPDD, (TEXT("WPDD: memset (%08x,%5d,%08x,%5d)\r\n"), pwh, pwh?pwh->reserved:0, pDstBuffer, cbDstBytes));
	memset(pDstBuffer, g_silence, cbDstBytes);

}

VOID
private_AudioComplete(PWAVEHDR pwh, ULONG cbBytesCompleted)
{
    DEBUGMSG(ZONE_WPDD, (TEXT("WPDD: AudioAdvance (%08x,%5d)\r\n"), pwh, cbBytesCompleted));

	// we've just finished playing another cbDstBytes of data.
	// update the queued headers accordingly
	while ((pwh != NULL) && (cbBytesCompleted > 0)) {
		if (pwh->dwBytesRecorded >= pwh->reserved) {
			pwh = pwh->lpNext;
		}
		else {
			ULONG cbBytesLeft = pwh->reserved - pwh->dwBytesRecorded;
			ULONG cbAdvance = min(cbBytesCompleted, cbBytesLeft);
			cbBytesCompleted -= cbAdvance;
			pwh->dwBytesRecorded += cbAdvance;

		    DEBUGMSG(ZONE_WPDD, (TEXT("WPDD: Advance (%08x,%5d,%5d,%5d)\r\n"), pwh, cbAdvance, cbBytesCompleted));
		}
	}

}

//------------------------------------------------------------
// private_AudioCompleteAndFill:
// called after an interrupt has informed us that cbDstBytes
// have just finished playing and can be replaced with fresh data
// from the cued data starting at pwh+latency
//
//------------------------------------------------------------
VOID
private_AudioCompleteAndFill (PWAVEHDR pwh, PBYTE pDstBuffer, ULONG cbDstBytes)
{
	// update the queued headers to indicate which ones we've played out
	private_AudioComplete(pwh, cbDstBytes);

    //
    // Fill the DMA Buffer and clear the remainder if nessary 
    //
	private_AudioFillBuffer (pwh, pDstBuffer, cbDstBytes);

}


// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
private_AudioGetBuffer (PWAVEHDR pwh, PBYTE pSrcBuffer, ULONG cbSrcBytes)
{
    FUNC_VERBOSE("+PDD_AudioGetBuffer");

    //
    // Copy from the DMA buffer to the client buffer
    //

⌨️ 快捷键说明

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