706 lines
17 KiB
C
706 lines
17 KiB
C
/*****************************************************************************
|
||
|
||
Copyright (c) 1993 Media Vision Inc. All Rights Reserved
|
||
|
||
Module Name:
|
||
|
||
devcaps.c
|
||
|
||
Abstract:
|
||
|
||
This module contains code for the device capabilities functions.
|
||
|
||
Author:
|
||
|
||
Nigel Thompson (nigelt) 7-Apr-1991
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
Robin Speed (RobinSp) 29-Jan-1992 - Add other devices and rewrite
|
||
Stephen Estrop (StephenE) 16-Apr-1992 - Converted to Unicode
|
||
EPA 01-11-93 Add PAS 16 support
|
||
|
||
*****************************************************************************/
|
||
|
||
#include "sound.h"
|
||
|
||
CONST WCHAR STR_MV_MIDI_OUT[] = L"MVI PAS 16 Midi Output";
|
||
CONST WCHAR STR_MV_MIDI_IN[] = L"MVI PAS 16 Midi Input";
|
||
|
||
//
|
||
// Driver Versions
|
||
//
|
||
|
||
#define WAVE_DRIVER_VERSION 0x0100
|
||
#define MIDI_DRIVER_VERSION 0x0100
|
||
#define AUX_DRIVER_VERSION 0x0100
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, SoundWaveOutGetCaps)
|
||
#pragma alloc_text(PAGE, SoundWaveInGetCaps)
|
||
#pragma alloc_text(PAGE, SoundMidiOutGetCaps)
|
||
#pragma alloc_text(PAGE, SoundMidiOutGetSynthCaps)
|
||
#pragma alloc_text(PAGE, SoundAuxGetCaps)
|
||
#pragma alloc_text(PAGE, SoundQueryFormat)
|
||
#pragma alloc_text(PAGE, GetWaveoutPid)
|
||
#pragma alloc_text(PAGE, GetWaveinPid)
|
||
#endif
|
||
|
||
//
|
||
// local functions
|
||
//
|
||
|
||
USHORT
|
||
GetWaveoutPid(
|
||
IN PGLOBAL_DEVICE_INFO pGDI
|
||
)
|
||
{
|
||
if ( pGDI->PASInfo.Caps.CapsBits.CDPC)
|
||
{
|
||
return MM_CDPC_WAVEOUT;
|
||
}
|
||
else
|
||
{
|
||
if ( IS_MIXER_508(pGDI))
|
||
{
|
||
return MM_PROAUD_16_WAVEOUT;
|
||
}
|
||
else
|
||
{
|
||
if ( pGDI->PASInfo.Caps.CapsBits.OPL_3)
|
||
{
|
||
return MM_PROAUD_PLUS_WAVEOUT;
|
||
}
|
||
else
|
||
{
|
||
return MM_PROAUD_WAVEOUT;
|
||
}
|
||
} // End ELSE
|
||
} // End ELSE
|
||
}
|
||
|
||
|
||
USHORT
|
||
GetWaveinPid(
|
||
IN PGLOBAL_DEVICE_INFO pGDI
|
||
)
|
||
{
|
||
if ( pGDI->PASInfo.Caps.CapsBits.CDPC)
|
||
{
|
||
return MM_CDPC_WAVEIN;
|
||
}
|
||
else
|
||
{
|
||
if ( IS_MIXER_508(pGDI))
|
||
{
|
||
return MM_PROAUD_16_WAVEIN;
|
||
}
|
||
else
|
||
{
|
||
if ( pGDI->PASInfo.Caps.CapsBits.OPL_3)
|
||
{
|
||
return MM_PROAUD_PLUS_WAVEIN;
|
||
}
|
||
else
|
||
{
|
||
return MM_PROAUD_WAVEIN;
|
||
}
|
||
} // End ELSE
|
||
} // End ELSE
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
|
||
Routine Description:
|
||
|
||
Return device capabilities for wave output device.
|
||
Data is truncated if not enough space is provided.
|
||
Irp is always completed.
|
||
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to local device info
|
||
pIrp - the Irp
|
||
IrpStack - the current stack location
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - always succeeds
|
||
|
||
*****************************************************************************/
|
||
NTSTATUS SoundWaveOutGetCaps( IN PLOCAL_DEVICE_INFO pLDI,
|
||
IN OUT PIRP pIrp,
|
||
IN PIO_STACK_LOCATION IrpStack )
|
||
{
|
||
/***** Local Variables *****/
|
||
|
||
WAVEOUTCAPSW wc;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
|
||
/***** Start *****/
|
||
|
||
dprintf2(("SoundWaveOutGetCaps(): Start " ));
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// say how much we're sending back
|
||
//
|
||
|
||
pIrp->IoStatus.Information = min(sizeof(wc),
|
||
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||
|
||
//
|
||
// fill in the info
|
||
//
|
||
|
||
//
|
||
// Copy across the product name - we just provide the string id
|
||
//
|
||
|
||
*(PULONG)wc.szPname = IDS_WAVEOUT_PNAME;
|
||
|
||
wc.wMid = MM_MEDIAVISION;
|
||
wc.vDriverVersion = WAVE_DRIVER_VERSION;
|
||
wc.wChannels = 2;
|
||
wc.dwSupport = WAVECAPS_VOLUME |
|
||
WAVECAPS_LRVOLUME;
|
||
// Playback Rate is NOT supported in SOUNDLIB
|
||
WAVECAPS_PLAYBACKRATE;
|
||
wc.dwFormats = WAVE_FORMAT_1M08 |
|
||
WAVE_FORMAT_1S08 |
|
||
WAVE_FORMAT_2M08 |
|
||
WAVE_FORMAT_2S08 |
|
||
WAVE_FORMAT_4M08 |
|
||
WAVE_FORMAT_4S08;
|
||
|
||
// only 16bit dac can support 16bit formats
|
||
if ( pGDI->PASInfo.Caps.CapsBits.DAC16 )
|
||
{
|
||
wc.dwFormats |= WAVE_FORMAT_1M16 |
|
||
WAVE_FORMAT_1S16 |
|
||
WAVE_FORMAT_2M16 |
|
||
WAVE_FORMAT_2S16 |
|
||
WAVE_FORMAT_4M16 |
|
||
WAVE_FORMAT_4S16;
|
||
|
||
} // End IF (pGDI->PASInfo.Caps.CapsBits.DAC16)
|
||
|
||
wc.wPid = GetWaveoutPid(pGDI);
|
||
|
||
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,
|
||
&wc,
|
||
pIrp->IoStatus.Information);
|
||
|
||
return status;
|
||
|
||
} // End SoundWaveOutGetCaps()
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
|
||
Routine Description:
|
||
|
||
Return device capabilities for wave input device.
|
||
Data is truncated if not enough space is provided.
|
||
Irp is always completed.
|
||
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to local device info
|
||
pIrp - the Irp
|
||
IrpStack - the current stack location
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - always succeeds
|
||
|
||
*****************************************************************************/
|
||
NTSTATUS SoundWaveInGetCaps(IN PLOCAL_DEVICE_INFO pLDI,
|
||
IN OUT PIRP pIrp,
|
||
IN PIO_STACK_LOCATION IrpStack )
|
||
{
|
||
/***** Local Variables *****/
|
||
|
||
WAVEINCAPSW wc;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
|
||
/***** Start *****/
|
||
|
||
dprintf2(("SoundWaveInGetCaps(): Start " ));
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// say how much we're sending back
|
||
//
|
||
pIrp->IoStatus.Information = min(sizeof(wc),
|
||
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||
|
||
//
|
||
// fill in the info
|
||
//
|
||
|
||
//
|
||
// Copy across the product name - we just provide the string id
|
||
//
|
||
|
||
*(PULONG)wc.szPname = IDS_WAVEIN_PNAME;
|
||
|
||
wc.wMid = MM_MEDIAVISION;
|
||
wc.vDriverVersion = WAVE_DRIVER_VERSION;
|
||
wc.wChannels = 2;
|
||
wc.dwFormats = WAVE_FORMAT_1M08 |
|
||
WAVE_FORMAT_1S08 |
|
||
WAVE_FORMAT_2M08 |
|
||
WAVE_FORMAT_2S08 |
|
||
WAVE_FORMAT_4M08 |
|
||
WAVE_FORMAT_4S08;
|
||
|
||
// only 16bit dac can support 16bit formats
|
||
if ( pGDI->PASInfo.Caps.CapsBits.DAC16 )
|
||
{
|
||
wc.dwFormats |= WAVE_FORMAT_1M16 |
|
||
WAVE_FORMAT_1S16 |
|
||
WAVE_FORMAT_2M16 |
|
||
WAVE_FORMAT_2S16 |
|
||
WAVE_FORMAT_4M16 |
|
||
WAVE_FORMAT_4S16;
|
||
|
||
} // End IF (pGDI->PASInfo.Caps.CapsBits.DAC16)
|
||
|
||
wc.wPid = GetWaveinPid(pGDI);
|
||
|
||
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,
|
||
&wc,
|
||
pIrp->IoStatus.Information);
|
||
|
||
return status;
|
||
|
||
} // End SoundWaveInGetCaps()
|
||
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
|
||
Routine Description:
|
||
|
||
Return device capabilities for midi output device.
|
||
Data is truncated if not enough space is provided.
|
||
Irp is always completed.
|
||
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to local device info
|
||
pIrp - the Irp
|
||
IrpStack - the current stack location
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - always succeeds
|
||
|
||
*****************************************************************************/
|
||
NTSTATUS SoundMidiOutGetCaps( IN PLOCAL_DEVICE_INFO pLDI,
|
||
IN OUT PIRP pIrp,
|
||
IN PIO_STACK_LOCATION IrpStack )
|
||
|
||
{
|
||
/***** Local Variables *****/
|
||
|
||
MIDIOUTCAPSW mc;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
|
||
/***** Start *****/
|
||
|
||
dprintf2(("SoundMidiOutGetCaps(): Start " ));
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// say how much we're sending back
|
||
//
|
||
|
||
pIrp->IoStatus.Information = min(sizeof(mc),
|
||
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||
|
||
//
|
||
// fill in the info
|
||
//
|
||
|
||
mc.wMid = MM_MEDIAVISION;
|
||
mc.vDriverVersion = MIDI_DRIVER_VERSION;
|
||
mc.wTechnology = MOD_MIDIPORT;
|
||
mc.wVoices = 0; // not used for ports
|
||
mc.wNotes = 0; // not used for ports
|
||
mc.wChannelMask = 0xFFFF; // all channels
|
||
mc.dwSupport = 0L;
|
||
|
||
RtlCopyMemory( mc.szPname,
|
||
STR_MV_MIDI_OUT,
|
||
sizeof(STR_MV_MIDI_OUT));
|
||
|
||
//
|
||
// Get the Proper Product ID
|
||
//
|
||
if ( pGDI->PASInfo.Caps.CapsBits.CDPC )
|
||
mc.wPid = MM_CDPC_MIDIOUT;
|
||
else
|
||
if ( IS_MIXER_508(pGDI) )
|
||
mc.wPid = MM_PROAUD_16_MIDIOUT;
|
||
else
|
||
if ( pGDI->PASInfo.Caps.CapsBits.OPL_3 )
|
||
mc.wPid = MM_PROAUD_PLUS_MIDIOUT;
|
||
else
|
||
mc.wPid = MM_PROAUD_MIDIOUT;
|
||
|
||
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,
|
||
&mc,
|
||
pIrp->IoStatus.Information);
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
|
||
Routine Description:
|
||
|
||
Return device capabilities for midi input device.
|
||
Data is truncated if not enough space is provided.
|
||
Irp is always completed.
|
||
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to local device info
|
||
pIrp - the Irp
|
||
IrpStack - the current stack location
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - always succeeds
|
||
|
||
*****************************************************************************/
|
||
NTSTATUS SoundMidiInGetCaps( IN PLOCAL_DEVICE_INFO pLDI,
|
||
IN OUT PIRP pIrp,
|
||
IN PIO_STACK_LOCATION IrpStack )
|
||
{
|
||
/***** Local Variables *****/
|
||
|
||
MIDIINCAPSW mc;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
|
||
/***** Start *****/
|
||
|
||
dprintf2(("SoundMidiInGetCaps(): Start " ));
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// say how much we're sending back
|
||
//
|
||
|
||
pIrp->IoStatus.Information = min(sizeof(mc),
|
||
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||
|
||
//
|
||
// fill in the info
|
||
//
|
||
|
||
mc.wMid = MM_MEDIAVISION;
|
||
mc.vDriverVersion = MIDI_DRIVER_VERSION;
|
||
|
||
RtlCopyMemory( mc.szPname,
|
||
STR_MV_MIDI_IN,
|
||
sizeof(STR_MV_MIDI_IN));
|
||
|
||
|
||
//
|
||
// Get the Proper Product ID
|
||
//
|
||
if ( pGDI->PASInfo.Caps.CapsBits.CDPC )
|
||
mc.wPid = MM_CDPC_MIDIIN;
|
||
else
|
||
if ( IS_MIXER_508(pGDI) )
|
||
mc.wPid = MM_PROAUD_16_MIDIIN;
|
||
else
|
||
if ( pGDI->PASInfo.Caps.CapsBits.OPL_3 )
|
||
mc.wPid = MM_PROAUD_PLUS_MIDIIN;
|
||
else
|
||
mc.wPid = MM_PROAUD_MIDIIN;
|
||
|
||
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
|
||
&mc,
|
||
pIrp->IoStatus.Information);
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
|
||
Routine Description:
|
||
|
||
Return device capabilities for axu devices
|
||
Data is truncated if not enough space is provided.
|
||
Irp is always completed.
|
||
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to local device info
|
||
pIrp - the Irp
|
||
IrpStack - the current stack location
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - always succeeds
|
||
|
||
*****************************************************************************/
|
||
NTSTATUS SoundAuxGetCaps( IN PLOCAL_DEVICE_INFO pLDI,
|
||
IN OUT PIRP pIrp,
|
||
IN PIO_STACK_LOCATION IrpStack )
|
||
{
|
||
/***** Local Variables *****/
|
||
|
||
AUXCAPSW auxCaps;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
// PWSTR DeviceName;
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
ULONG pName;
|
||
|
||
/***** Start *****/
|
||
|
||
dprintf2(("SoundAuxGetCaps(): Start " ));
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// Find the device name
|
||
//
|
||
switch (pLDI->DeviceIndex)
|
||
{
|
||
case LineInDevice:
|
||
pName = IDS_AUX_PNAME;
|
||
break;
|
||
|
||
case CDInternal:
|
||
pName = IDS_AUX_PNAME;
|
||
break;
|
||
|
||
default:
|
||
dprintf1(("ERROR: SoundAuxGetCaps(): Getting aux caps for non-aux device!"));
|
||
return STATUS_INTERNAL_ERROR;
|
||
break;
|
||
} // End SWITCH (pLDI->DeviceIndex)
|
||
|
||
|
||
//
|
||
// say how much we're sending back
|
||
//
|
||
|
||
pIrp->IoStatus.Information = min(sizeof(auxCaps),
|
||
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||
|
||
//
|
||
// fill in the info
|
||
//
|
||
|
||
auxCaps.wMid = MM_MEDIAVISION;
|
||
auxCaps.vDriverVersion = AUX_DRIVER_VERSION;
|
||
auxCaps.wTechnology = AUXCAPS_AUXIN;
|
||
#ifdef CDINTERNAL
|
||
if (pLDI->DeviceIndex == CDInternal) {
|
||
auxCaps.wTechnology = AUXCAPS_CDAUDIO;
|
||
}
|
||
#endif
|
||
auxCaps.dwSupport = AUXCAPS_LRVOLUME | AUXCAPS_VOLUME;
|
||
auxCaps.wPid = MM_PROAUD_AUX;
|
||
|
||
*(PULONG)auxCaps.szPname = pName;
|
||
|
||
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
|
||
&auxCaps,
|
||
pIrp->IoStatus.Information);
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
|
||
Routine Description:
|
||
|
||
Tell the caller whether the wave format specified (input or
|
||
output) is supported
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to local device info
|
||
pFormat - format being queried
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - format is supported
|
||
STATUS_NOT_SUPPORTED - format not supported
|
||
|
||
*****************************************************************************/
|
||
NTSTATUS SoundQueryFormat( IN PLOCAL_DEVICE_INFO pLDI,
|
||
IN PPCMWAVEFORMAT pFormat )
|
||
{
|
||
/***** Local Variables *****/
|
||
|
||
PGLOBAL_DEVICE_INFO pGDI;
|
||
|
||
/***** Start *****/
|
||
|
||
dprintf5(("SoundQueryFormat(): Start " ));
|
||
|
||
pGDI = pLDI->pGlobalInfo;
|
||
|
||
//
|
||
// Check the PCM Wave Format
|
||
//
|
||
if ( pFormat->wf.wFormatTag != WAVE_FORMAT_PCM ||
|
||
pFormat->wf.nChannels > 2 ||
|
||
pFormat->wf.nSamplesPerSec < pGDI->MinHz ||
|
||
pFormat->wf.nSamplesPerSec > pGDI->MaxOutHz ||
|
||
pFormat->wf.nBlockAlign < 1 )
|
||
{
|
||
dprintf1(("ERROR: SoundQueryFormat(): Wave Format NOT Supported" ));
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
//
|
||
// Check for 8 Bit Stereo with an Invalid block align of 1
|
||
//
|
||
if ( pFormat->wBitsPerSample == 8 &&
|
||
pFormat->wf.nChannels == 2 &&
|
||
pFormat->wf.nBlockAlign == 1 )
|
||
{
|
||
dprintf1(("ERROR: SoundQueryFormat(): Wave Format NOT Supported" ));
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
//
|
||
// Check the Sample Rate
|
||
//
|
||
if ( pGDI->PASInfo.Caps.CapsBits.DAC16 )
|
||
{
|
||
//
|
||
// PAS 16
|
||
//
|
||
if ( pFormat->wBitsPerSample != 8 &&
|
||
pFormat->wBitsPerSample != 12 &&
|
||
pFormat->wBitsPerSample != 16 )
|
||
{
|
||
dprintf1(("ERROR: SoundQueryFormat(): Wave Format NOT Supported" ));
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
} // End IF (pGDI->PASInfo.Caps.CapsBits.DAC16)
|
||
else
|
||
{
|
||
//
|
||
// 8 Bit cards
|
||
//
|
||
if ( pFormat->wBitsPerSample != 8 )
|
||
{
|
||
dprintf1(("ERROR: SoundQueryFormat(): Wave Format NOT Supported" ));
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
} // End ELSE
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // End SoundQueryFormat()
|
||
|
||
|
||
NTSTATUS
|
||
SoundMidiOutGetSynthCaps(
|
||
IN PLOCAL_DEVICE_INFO pLDI,
|
||
IN OUT PIRP pIrp,
|
||
IN PIO_STACK_LOCATION IrpStack
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Return device capabilities for midi output device.
|
||
Data is truncated if not enough space is provided.
|
||
Irp is always completed.
|
||
|
||
|
||
Arguments:
|
||
|
||
pLDI - pointer to local device info
|
||
pIrp - the Irp
|
||
IrpStack - the current stack location
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - always succeeds
|
||
|
||
--*/
|
||
|
||
{
|
||
MIDIOUTCAPSW mc;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
|
||
//
|
||
// say how much we're sending back
|
||
//
|
||
|
||
pIrp->IoStatus.Information =
|
||
min(sizeof(mc),
|
||
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||
|
||
//
|
||
// fill in the info
|
||
//
|
||
|
||
mc.wMid = MM_MEDIAVISION;
|
||
mc.wPid = MM_PROAUD_SYNTH;
|
||
mc.wTechnology = MOD_FMSYNTH;
|
||
mc.wVoices = 128;
|
||
mc.wNotes = 18;
|
||
mc.wChannelMask = 0xffff; // all channels
|
||
mc.vDriverVersion = DRIVER_VERSION;
|
||
mc.dwSupport = MIDICAPS_VOLUME | MIDICAPS_LRVOLUME;
|
||
|
||
//
|
||
// Copy across the product name - we just provide the string id
|
||
//
|
||
|
||
*(PULONG)mc.szPname = IDS_SYNTH_PNAME;
|
||
|
||
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
|
||
&mc,
|
||
pIrp->IoStatus.Information);
|
||
|
||
return status;
|
||
}
|
||
|
||
/************************************ END ***********************************/
|
||
|