/***************************************************************************** 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 ***********************************/