NT4/private/ntos/dd/sound/sndblst/devcaps.c
2020-09-30 17:12:29 +02:00

635 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
devcaps.c
Abstract:
This module contains code for the device capabilities functions.
Author:
Robin Speed (RobinSp) 20-Oct-1992
Environment:
Kernel mode
Revision History:
--*/
#include "sound.h"
#include <string.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SoundWaveOutGetCaps)
#pragma alloc_text(PAGE, SoundWaveInGetCaps)
#pragma alloc_text(PAGE, SoundMidiOutGetCaps)
#pragma alloc_text(PAGE, SoundMidiInGetCaps)
#pragma alloc_text(PAGE, SoundMidiOutGetSynthCaps)
#pragma alloc_text(PAGE, SoundAuxGetCaps)
#pragma alloc_text(PAGE, SoundQueryFormat)
#endif
// non-localized strings version is wrong !!!
WCHAR STR_SNDBLST10[] = L"Creative Labs Sound Blaster 1.0";
WCHAR STR_SNDBLST15[] = L"Creative Labs Sound Blaster 1.5";
NTSTATUS
SoundWaveOutGetCaps(
IN PLOCAL_DEVICE_INFO pLDI,
IN OUT PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack
)
/*++
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
--*/
{
WAVEOUTCAPSW wc;
NTSTATUS status = STATUS_SUCCESS;
PGLOBAL_DEVICE_INFO pGDI;
pGDI = pLDI->pGlobalInfo;
//
// say how much we're sending back
//
pIrp->IoStatus.Information =
min(sizeof(wc),
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
//
// fill in the info
//
wc.wMid = MM_MICROSOFT;
wc.vDriverVersion = DRIVER_VERSION;
if (SB16(&pGDI->Hw)) {
wc.wPid = MM_MSFT_SB16_WAVEOUT;
wc.dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
WAVE_FORMAT_4M16;
if (pGDI->DmaChannel16 != 0xFFFFFFFF) {
wc.dwFormats |= WAVE_FORMAT_4S16;
}
wc.wChannels = 2;
wc.dwSupport = WAVECAPS_VOLUME | WAVECAPS_LRVOLUME;
} else {
wc.wPid = MM_MSFT_SBPRO_WAVEOUT;
if (SBPRO(&pGDI->Hw)) {
wc.dwSupport = WAVECAPS_VOLUME |
WAVECAPS_LRVOLUME;
wc.dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
WAVE_FORMAT_4M08 ;
wc.wChannels = 2 ;
} else {
wc.dwSupport = 0;
wc.dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08;
wc.wChannels = 1;
}
}
//
// Copy across the product name - we just provide the string id
//
*(PULONG)wc.szPname = IDS_WAVEOUT_PNAME;
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
&wc,
(int)pIrp->IoStatus.Information);
return status;
}
NTSTATUS
SoundWaveInGetCaps(
IN PLOCAL_DEVICE_INFO pLDI,
IN OUT PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack
)
/*++
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
--*/
{
WAVEINCAPSW wc;
NTSTATUS status = STATUS_SUCCESS;
PGLOBAL_DEVICE_INFO pGDI;
pGDI = pLDI->pGlobalInfo;
//
// say how much we're sending back
//
pIrp->IoStatus.Information =
min(sizeof(wc),
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
//
// fill in the info
//
wc.wMid = MM_MICROSOFT;
wc.vDriverVersion = DRIVER_VERSION;
if (SB16(&pGDI->Hw)) {
wc.wPid = MM_MSFT_SB16_WAVEIN;
wc.dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
WAVE_FORMAT_4M16;
if (pGDI->DmaChannel16 != 0xFFFFFFFF) {
wc.dwFormats |= WAVE_FORMAT_4S16;
}
wc.wChannels = 2;
} else {
wc.wPid = MM_MSFT_SBPRO_WAVEIN;
if (SBPRO(&pGDI->Hw)) {
wc.dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
WAVE_FORMAT_4M08 ;
wc.wChannels = 2 ;
} else {
wc.dwFormats = WAVE_FORMAT_1M08 ;
wc.wChannels = 1 ;
}
}
//
// Copy across the product name - we just provide the string id
//
*(PULONG)wc.szPname = IDS_WAVEIN_PNAME;
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
&wc,
(int)pIrp->IoStatus.Information);
return status;
}
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;
PGLOBAL_DEVICE_INFO pGDI;
pGDI = CONTAINING_RECORD(pLDI->pGlobalInfo, GLOBAL_DEVICE_INFO, Synth);
ASSERT(pGDI->Key == GDI_KEY);
//
// say how much we're sending back
//
pIrp->IoStatus.Information =
min(sizeof(mc),
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
//
// fill in the info
//
mc.wMid = MM_MICROSOFT;
mc.wPid = (USHORT)(SB16(&pGDI->Hw) ? MM_MSFT_SB16_SYNTH :
MM_MSFT_SBPRO_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,
(int)pIrp->IoStatus.Information);
return status;
}
NTSTATUS
SoundMidiOutGetCaps(
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;
PGLOBAL_DEVICE_INFO pGDI;
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_MICROSOFT;
mc.wPid = MM_MSFT_SBPRO_MIDIOUT;
mc.vDriverVersion = 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;
if (SB1(&pGDI->Hw)) {
RtlCopyMemory(mc.szPname, STR_SNDBLST10, sizeof(STR_SNDBLST10));
} else {
RtlCopyMemory(mc.szPname, STR_SNDBLST15, sizeof(STR_SNDBLST15));
}
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
&mc,
(int)pIrp->IoStatus.Information);
return status;
}
NTSTATUS
SoundMidiInGetCaps(
IN PLOCAL_DEVICE_INFO pLDI,
IN OUT PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack
)
/*++
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
--*/
{
MIDIINCAPSW mc;
NTSTATUS status = STATUS_SUCCESS;
PGLOBAL_DEVICE_INFO pGDI;
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_MICROSOFT;
mc.wPid = MM_MSFT_SBPRO_MIDIIN;
mc.wPid = MM_SNDBLST_MIDIIN;
mc.vDriverVersion = DRIVER_VERSION;
if (SB1(&pGDI->Hw)) {
RtlCopyMemory(mc.szPname, STR_SNDBLST10, sizeof(STR_SNDBLST10));
} else {
RtlCopyMemory(mc.szPname, STR_SNDBLST15, sizeof(STR_SNDBLST15));
}
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
&mc,
(int)pIrp->IoStatus.Information);
return status;
}
NTSTATUS
SoundAuxGetCaps(
IN PLOCAL_DEVICE_INFO pLDI,
IN OUT PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack
)
/*++
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
--*/
{
AUXCAPSW auxCaps;
NTSTATUS status = STATUS_SUCCESS;
PGLOBAL_DEVICE_INFO pGDI;
pGDI = pLDI->pGlobalInfo;
//
// say how much we're sending back
//
pIrp->IoStatus.Information =
min(sizeof(auxCaps),
IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
//
// fill in the info
//
auxCaps.wMid = MM_MICROSOFT;
switch (pLDI->DeviceIndex) {
case LineInDevice:
auxCaps.wPid = (USHORT)(SB16(&pGDI->Hw) ? MM_MSFT_SB16_AUX_LINE :
MM_MSFT_SBPRO_AUX_LINE);
//
// Copy across the product name - we just provide the string id
//
*(PULONG)auxCaps.szPname = IDS_AUX_LINE_PNAME;
break;
case CDInternal:
auxCaps.wPid = (USHORT)(SB16(&pGDI->Hw) ? MM_MSFT_SB16_AUX_CD :
MM_MSFT_SBPRO_AUX_CD);
//
// Copy across the product name - we just provide the string id
//
*(PULONG)auxCaps.szPname = IDS_AUX_CD_PNAME;
break;
}
auxCaps.vDriverVersion = DRIVER_VERSION;
auxCaps.wTechnology = AUXCAPS_AUXIN;
auxCaps.dwSupport = AUXCAPS_LRVOLUME | AUXCAPS_VOLUME;
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
&auxCaps,
(int)pIrp->IoStatus.Information);
return status;
}
NTSTATUS SoundQueryFormat(
IN PLOCAL_DEVICE_INFO pLDI,
IN PPCMWAVEFORMAT pFormat
)
/*++
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
--*/
{
PGLOBAL_DEVICE_INFO pGDI;
pGDI = pLDI->pGlobalInfo;
if (pFormat->wf.wFormatTag != WAVE_FORMAT_PCM ||
pFormat->wf.nChannels != 1 && pFormat->wf.nChannels != 2) {
return STATUS_NOT_SUPPORTED;
}
if (SB16(&pGDI->Hw)) {
if (pFormat->wBitsPerSample != 8 && pFormat->wBitsPerSample != 16 ||
pFormat->wf.nSamplesPerSec < 5000 ||
pFormat->wf.nSamplesPerSec > 44100) {
return STATUS_NOT_SUPPORTED;
} else {
if (pGDI->DmaChannel16 == 0xFFFFFFFF &&
pFormat->wf.nSamplesPerSec > 25000 &&
pFormat->wBitsPerSample == 16 &&
pFormat->wf.nChannels == 2) {
/* Too fast for an 8-bit channel */
return STATUS_NOT_SUPPORTED;
}
return STATUS_SUCCESS;
}
}
if (pFormat->wBitsPerSample != 8 ||
pFormat->wf.nSamplesPerSec < 4000) {
return STATUS_NOT_SUPPORTED;
}
if (SBPRO(&pGDI->Hw)) {
if (pFormat->wf.nSamplesPerSec > 44100 ||
pFormat->wf.nChannels == 2 &&
pFormat->wf.nSamplesPerSec != 11025 &&
pFormat->wf.nSamplesPerSec != 22050) {
return STATUS_NOT_SUPPORTED;
} else {
if (pGDI->MidiInUse) {
if (HwHighSpeed(&pGDI->Hw,
(ULONG)pFormat->wf.nChannels,
pFormat->wf.nSamplesPerSec,
(BOOLEAN)(pLDI->DeviceType == WAVE_OUT))) {
return STATUS_NOT_SUPPORTED;
}
}
return STATUS_SUCCESS;
}
}
if (pFormat->wf.nChannels != 1) {
return STATUS_NOT_SUPPORTED;
}
if (SB201(&pGDI->Hw)) {
if (pFormat->wf.nSamplesPerSec > 44100 ||
pLDI->DeviceType == WAVE_IN &&
pFormat->wf.nSamplesPerSec > 15000) {
return STATUS_NOT_SUPPORTED;
} else {
if (pGDI->MidiInUse) {
if (HwHighSpeed(&pGDI->Hw,
(ULONG)pFormat->wf.nChannels,
pFormat->wf.nSamplesPerSec,
(BOOLEAN)(pLDI->DeviceType == WAVE_OUT))) {
return STATUS_NOT_SUPPORTED;
}
}
return STATUS_SUCCESS;
}
}
if (pLDI->DeviceType == WAVE_IN) {
if (pFormat->wf.nSamplesPerSec > 13000) {
return STATUS_NOT_SUPPORTED;
} else {
return STATUS_SUCCESS;
}
}
if (pFormat->wf.nSamplesPerSec > 23000) {
return STATUS_NOT_SUPPORTED;
} else {
return STATUS_SUCCESS;
}
}