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

1187 lines
53 KiB
C

/*++
*******************************************************************************
* Copyright (c) 1995 IBM Corporation
*
* Module Name: mixdvc.c
*
* Abstract: support for MIXER device
*
* Author: Jim Bozek [IBM]
*
* Environment:
*
* Comments:
*
* Rev History: Creation 09.25.95
*
*******************************************************************************
--*/
#include "common.h"
VOID cs423xWOLineChanged(PLOCAL_DEVICE_INFO pLDI, UCHAR Code);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, cs423xMixerInit)
#pragma alloc_text(PAGE, cs423xMixerGetConfig)
#pragma alloc_text(PAGE, cs423xMixerGetLineFlags)
#pragma alloc_text(PAGE, cs423xMixerGetControl)
#pragma alloc_text(PAGE, cs423xMixerGetCombCtrl)
#pragma alloc_text(PAGE, cs423xMixerSetControl)
#pragma alloc_text(PAGE, cs423xWOLineChanged)
#endif
MIXER_REGISTRY_DATA default_mregdata = {
{IBM_CS423X_DRIVER_VERSION}, {
{0xe000, 0xe000}, /* ControlMixerOutAtten */
{0x0000, 0x0000}, /* ControlMixerOutMute */
{0x0000, 0x0000}, /* ControlSpeakerMute */
{0xc000, 0xc000}, /* ControlWaveinGain */
{0x0001, 0x0000}, /* ControlHighPassFilter */
{0x0003, 0x0000}, /* ControlMux */
{0xc000, 0xc000}, /* ControlMixerInputAux1Gain */
{0x0000, 0x0000}, /* ControlMixerInputAux1Mute */
{0xc000, 0xc000}, /* ControlMixerInputLineinGain */
{0x0000, 0x0000}, /* ControlMixerInputLineinMute */
{0xc000, 0xc000}, /* ControlMixerInputAux2Gain */
{0x0000, 0x0000}, /* ControlMixerInputAux2Mute */
{0x0000, 0x0000}, /* ControlMixerInputMonoinAtten */
{0x0000, 0x0000}, /* ControlMixerInputMonoinMute */
{0xe000, 0xe000}, /* ControlMixerInputWaveoutAtten */
{0x0000, 0x0000}, /* ControlMixerInputWaveoutMute */
{0x0000, 0x0000}, /* ControlWaveoutPeak */
{0x0000, 0x0000}, /* ControlWaveinMonitorAtten */
{0x0000, 0x0000}, /* ControlWaveinMonitorEnable */
{0x0000, 0x0000}, /* ControlMuxSelectMic */
{0x0000, 0x0000}, /* ControlMicBoost */
{0x0000, 0x0000}, /* ControlMuxSelectLinein */
{0x0000, 0x0000}, /* ControlMuxSelectAux1 */
{0x0000, 0x0000},} /* ControlMuxSelectMixer */
};
/*
*********************************************************************************
* Ultimately, this routine needs to fill in all possibilities, but we'll
* start with the following:
*
* 1. The default defined in mix_objs.c is for the cs4232
* on the IBM-6070 Personal Power System (Carolina)
* 2. The cs4231 on the IBM-6015 Personal Power System (Sandalfoot)
*
*********************************************************************************
*/
VOID kpcMixerFixer(PSOUND_CONFIG_DATA pscd)
{
int index;
_dbgprint((_PRT_DBUG, "enter kpcMixerFixer(pscd: 0x%08x)\n", pscd));
/* connect the AUX1 input pin on the chip to the specified system signal */
switch (pscd->Aux1InputSignal) {
/* the AUX1 input pin on the chip is connected to both the Mixer and the MUX */
case SignalNull:
/* not defined in registry - use default definition - cs4232 on IBM PPS */
case SignalLinein:
/* default definition in mix_objs.c */
break;
case SignalNotUsed:
break;
case SignalMic:
break;
case SignalSynth:
/* a synthesizer is connected to the AUX1 input pin */
index = SourceMixerAux1;
MixerLineData[index].ShortNameStringId = IDS_SRCSYNTH_SHORT_NAME;
MixerLineData[index].LongNameStringId = IDS_SRCSYNTH_LONG_NAME;
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_MIDIOUT;
MixerLineData[index].wPid = MM_MSFT_GENERIC_MIDIOUT;
MixerLineData[index].PnameStringId = IDS_MIDIOUT_PNAME;
index = SourceMuxAux1;
MixerLineData[index].ShortNameStringId = IDS_SRCSYNTH_SHORT_NAME;
MixerLineData[index].LongNameStringId = IDS_SRCSYNTH_LONG_NAME;
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_MIDIOUT;
MixerLineData[index].wPid = MM_MSFT_GENERIC_MIDIOUT;
MixerLineData[index].PnameStringId = IDS_MIDIOUT_PNAME;
index = ControlMixerInputAux1Gain;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXSYNTH_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXSYNTH_LONG_NAME;
index = ControlMixerInputAux1Mute;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXSYNTH_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXSYNTH_LONG_NAME;
index = ControlMuxSelectAux1;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMUXSYNTH_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMUXSYNTH_LONG_NAME;
index = MuxAux1;
MixerTextData[index].dwParam2 = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
MixerTextData[index].SubControlTextStringId =IDS_SRCSYNTH_LONG_NAME;
break;
case SignalCD:
/* a CDROM audio signal is connected to the AUX1 input pin */
index = SourceMixerAux1;
MixerLineData[index].ShortNameStringId = IDS_SRCCD_SHORT_NAME;
MixerLineData[index].LongNameStringId = IDS_SRCCD_LONG_NAME;
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_CD;
MixerLineData[index].PnameStringId = IDS_AUX_CD_PNAME;
index = SourceMuxAux1;
MixerLineData[index].ShortNameStringId = IDS_SRCCD_SHORT_NAME;
MixerLineData[index].LongNameStringId = IDS_SRCCD_LONG_NAME;
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_CD;
MixerLineData[index].PnameStringId = IDS_AUX_CD_PNAME;
index = ControlMixerInputAux1Gain;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXCDROM_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXCDROM_LONG_NAME;
index = ControlMixerInputAux1Mute;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXCDROM_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXCDROM_LONG_NAME;
index = ControlMuxSelectAux1;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXCDROM_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXCDROM_LONG_NAME;
index = MuxAux1;
MixerTextData[index].dwParam2 = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
MixerTextData[index].SubControlTextStringId = IDS_SRCCD_LONG_NAME;
break;
case SignalModem:
break;
default:
break;
}
switch (pscd->Aux2InputSignal) {
/* the AUX2 input pin on the chip is connected to the Mixer only - not the MUX */
case SignalNull:
/* not defined in registry - use default definition - cs4232 on IBM PPS */
case SignalCD:
/* default definition in mix_objs.c */
break;
case SignalNotUsed:
break;
case SignalLinein:
break;
case SignalMic:
break;
case SignalSynth:
break;
case SignalModem:
/* a MODEM signal is connected to the AUX2 input pin */
index = SourceMixerAux2;
MixerLineData[index].ShortNameStringId = IDS_SRCMODEM_SHORT_NAME;
MixerLineData[index].LongNameStringId = IDS_SRCMODEM_LONG_NAME;
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_LINE;
MixerLineData[index].PnameStringId = IDS_AUX_PNAME;
index = ControlMixerInputAux2Gain;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXMODEM_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXMODEM_LONG_NAME;
index = ControlMixerInputAux2Mute;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXMODEM_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXMODEM_LONG_NAME;
break;
default:
break;
}
switch (pscd->LineInputSignal) {
/* the AUX1 input pin on the chip is connected to both the Mixer and the MUX */
case SignalNull:
/* not defined in registry - use default definition - cs4232 on IBM PPS */
case SignalSynth:
/* default definition in mix_objs.c */
break;
case SignalNotUsed:
break;
case SignalLinein:
/* a Line Level input signal is connected to the LINEIN input pin */
index = SourceMixerLinein;
MixerLineData[index].ShortNameStringId = IDS_SRCLINEIN_SHORT_NAME;
MixerLineData[index].LongNameStringId = IDS_SRCLINEIN_LONG_NAME;
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_LINE;
MixerLineData[index].PnameStringId = IDS_AUX_PNAME;
index = SourceMuxLinein;
MixerLineData[index].ShortNameStringId = IDS_SRCLINEIN_SHORT_NAME;
MixerLineData[index].LongNameStringId = IDS_SRCLINEIN_LONG_NAME;
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_LINE;
MixerLineData[index].PnameStringId = IDS_AUX_PNAME;
index = ControlMixerInputLineinGain;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXLINEIN_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXLINEIN_LONG_NAME;
index = ControlMixerInputLineinMute;
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXLINEIN_SHORT_NAME;
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXLINEIN_LONG_NAME;
index = MuxLinein;
MixerTextData[index].dwParam2 = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
MixerTextData[index].SubControlTextStringId =IDS_SRCLINEIN_LONG_NAME;
break;
case SignalMic:
break;
case SignalCD:
break;
case SignalModem:
break;
default:
break;
}
switch (pscd->MicInputSignal) {
/* the MIC input pin on the chip is connected to the MUX only - not the Mixer */
case SignalNull:
/* not defined in registry - use default definition - cs4232 on IBM PPS */
case SignalMic:
/* default definition in mix_objs.c */
break;
case SignalNotUsed:
break;
case SignalLinein:
break;
case SignalSynth:
break;
case SignalCD:
break;
case SignalModem:
break;
default:
break;
}
switch (pscd->MonoInputSignal) {
/* the MONOIN input pin on the chip is connected to the Mixer only - not the MUX */
case SignalNull:
/* not defined in registry - use default definition - cs4232 on IBM PPS */
case SignalMic:
/* default definition in mix_objs.c */
break;
case SignalNotUsed:
break;
case SignalLinein:
break;
case SignalSynth:
break;
case SignalCD:
break;
case SignalModem:
break;
default:
break;
}
_dbgprint((_PRT_DBUG, "exit kpcMixerFixer()\n"));
return;
}
/*
*********************************************************************************
*
*********************************************************************************
*/
NTSTATUS cs423xMixerInit(PLOCAL_DEVICE_INFO pLDI,
PMIXER_REGISTRY_DATA RegControlData,
BOOLEAN MixerSettingsInRegistry)
{
INT i;
PGLOBAL_DEVICE_INFO pGDI;
PLOCAL_DEVICE_INFO pLDIDev;
PMIXER_INFO pMI;
PLOCAL_MIXER_DATA LMData;
PDEVICE_OBJECT pDObj;
PSOUND_HARDWARE pHW;
PKMUTEX pKM;
PMIXER_REGISTRY_DATA pmrd;
_dbgprint((_PRT_DBUG, "cs423xMixerInit(pLDI: 0x%08x, RCData: 0x%08x, Found: 0x%08x)\n",
pLDI, RegControlData, MixerSettingsInRegistry));
/* initialize local vars */
pGDI = pLDI->pGlobalInfo;
pMI = &pGDI->MixerInfo;
pHW = &pGDI->Hw;
pKM = &pHW->HwMutex;
/* serialize on the hardware mutex */
HW_CLAIM(pKM);
/* setup callbacks for the mixer */
SoundInitMixerInfo(pMI, cs423xMixerGetLineFlags, cs423xMixerGetControl,
cs423xMixerGetCombCtrl, cs423xMixerSetControl);
/* set up the device with its mixer data */
pLDI->DeviceType = MIXER_DEVICE;
pLDI->DeviceSpecificData = (PVOID)pMI;
/* make sure each device can reference the mixer device */
pDObj = pGDI->DeviceObject[WaveInDevice]->DriverObject->DeviceObject;
for (pDObj = pDObj; pDObj != NULL; pDObj = pDObj->NextDevice) {
pLDIDev = (PLOCAL_DEVICE_INFO)pDObj->DeviceExtension;
if (pLDIDev->pGlobalInfo == pGDI)
pLDIDev->MixerDevice = pLDI;
}
/* get address of internal mixer data representation */
LMData = &pGDI->LocalMixerData;
/* if necessary, initialize internal mixer data representation from default data */
if (!MixerSettingsInRegistry) {
RtlCopyMemory(&pGDI->MixerSettings, &default_mregdata, sizeof(MIXER_REGISTRY_DATA));
cs423xSaveMixerSettings(pGDI);
}
/* initialize control notification elements of internal mixer data */
/* we do this only for settable controls, i.e., not PEAK meters */
for (i = 0; i < NumberOfMixerControls; i++) {
if ((MixerControlData[i].dwControlType & MIXERCONTROL_CT_CLASS_MASK) !=
MIXERCONTROL_CT_CLASS_METER) {
SoundInitDataItem(pMI, &LMData->ControlNotification[i],
(USHORT)MM_MIXM_CONTROL_CHANGE, (USHORT)i);
}
}
/* initialize line notification elements of internal mixer data */
for (i = 0; i < NumberOfMixerLines; i++) {
SoundInitDataItem(pMI, &LMData->LineNotification[i],
(USHORT)MM_MIXM_LINE_CHANGE, (USHORT)i);
}
/* release the hardware mutex */
HW_DISCLAIM(pKM);
/* set the chip to a known state */
pmrd = &pGDI->MixerSettings;
/* Mixer input and output attenuation, gain and mute settings */
cs423xSetSpeakerMute(pHW, (BOOLEAN)pmrd->ControlData[ControlSpeakerMute].v[MUTE].u);
if (pHW->Type == hwtype_cs4231) {
cs4231SetOutputAttenuation(pHW, pmrd,
(ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u,
(ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u);
cs4231SetOutputMute(pHW, pmrd,
(BOOLEAN)pmrd->ControlData[ControlMixerOutMute].v[MUTE].u);
}
else {
/* first do the mutes */
cs423xSetMixerInputAux2Mute(pHW,
(BOOLEAN)pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u);
cs423xSetMixerInputWaveoutMute(pHW,
(BOOLEAN)pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u);
cs423xSetMixerInputLineinMute(pHW,
(BOOLEAN)pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u);
cs423xSetMixerInputAux1Mute(pHW,
(BOOLEAN)pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u);
cs423xSetMixerInputMonoinMute(pHW,
(BOOLEAN)pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u);
cs423xSetOutputMute(pHW, (BOOLEAN)pmrd->ControlData[ControlMixerOutMute].v[MUTE].u);
/* now do the gain/attenuation */
cs423xSetMixerInputAux2Gain(pHW,
(USHORT)pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u,
(USHORT)pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u);
cs423xSetMixerInputWaveoutAttenuation(pHW,
(USHORT)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u,
(USHORT)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u);
cs423xSetMixerInputLineinGain(pHW,
(USHORT)pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u,
(USHORT)pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u);
cs423xSetMixerInputAux1Gain(pHW,
(USHORT)pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u,
(USHORT)pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u);
cs423xSetMixerInputMonoinAttenuation(pHW,
(USHORT)pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u);
cs423xSetOutputAttenuation(pHW,
(USHORT)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u,
(USHORT)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u);
}
cs423xSetWaveinMonitorAttenuation(pHW,
(USHORT)pmrd->ControlData[ControlWaveinMonitorAtten].v[LEFT].u);
cs423xSetWaveinMonitorEnable(pHW,
(BOOLEAN)pmrd->ControlData[ControlWaveinMonitorEnable].v[ENABLE].u);
/* MUX selection, gain, and mode settings */
cs423xSetMuxSelect(pHW, (ULONG)pmrd->ControlData[ControlMux].v[MUXSEL].u);
cs423xSetMicBoost(pHW, (BOOLEAN)pmrd->ControlData[ControlMicBoost].v[BOOST].u);
cs423xSetHPF(pHW, (BOOLEAN)pmrd->ControlData[ControlHighPassFilter].v[FILTER].u);
cs423xSetWaveinGain(pHW, (USHORT)pmrd->ControlData[ControlWaveinGain].v[LEFT].u,
(USHORT)pmrd->ControlData[ControlWaveinGain].v[RIGHT].u);
SoundSetLineNotify(
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveOutDevice]->DeviceExtension,
cs423xWOLineChanged);
/* Set up volume control ids for non-mixer devices - WaveOut */
SoundSetVolumeControlId(
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveOutDevice]->DeviceExtension,
ControlMixerOutAtten);
/* Set up volume control ids for non-mixer devices - WaveIn */
SoundSetVolumeControlId(
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveInDevice]->DeviceExtension,
ControlWaveinGain);
/* Set up volume control ids for non-mixer devices - Aux */
SoundSetVolumeControlId(
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[AuxDevice]->DeviceExtension,
ControlMixerInputMonoinAtten);
_dbgprint((_PRT_DBUG, "exit cs423xMixerInit(STATUS_SUCCESS)\n"));
return(STATUS_SUCCESS);
} /* cs423xMixerInit() */
/*
*********************************************************************************
*
*********************************************************************************
*/
NTSTATUS
cs423xMixerGetConfig(PLOCAL_DEVICE_INFO pLDI, PIRP pIrp, PIO_STACK_LOCATION IrpStack)
{
int i;
ULONG Length;
PCFDATA pcfData;
PMIXER_DD_CONTROL_LISTTEXT pLT;
PMIXER_DD_CONTROL_CONFIGURATION_DATA pCD;
_dbgprint((_PRT_DBUG,
"enter cs423xMixerGetConfig(pLDI: 0x%08x pIrp: 0x%08x IrpStack: 0x%08x)\n",
pLDI, pIrp, IrpStack));
/* allocate and initialize a temporary configuration data structure */
if ((pcfData = (PCFDATA)ExAllocatePool(PagedPool, sizeof(CFDATA))) == NULL) {
_dbgprint((_PRT_STAT, "exit cs423xMixerGetConfig(STATUS_INSUFFICIENT_RESOURCES)\n"));
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(pcfData, sizeof(CFDATA));
pcfData->Header.cbSize = sizeof(*pcfData);
/* copy the line, control, and text data from the constants to the local structure */
RtlCopyMemory(pcfData->LineData, MixerLineData, sizeof(MixerLineData));
RtlCopyMemory(pcfData->ControlData, MixerControlData, sizeof(MixerControlData));
RtlCopyMemory(pcfData->TextData, MixerTextData, sizeof(MixerTextData));
/* set the generic capabilities info */
pcfData->Header.DeviceCaps.wMid = MM_IBM;
pcfData->Header.DeviceCaps.wPid = MM_MSFT_WSS_OEM_MIXER;
pcfData->Header.DeviceCaps.vDriverVersion = IBM_CS423X_DRIVER_VERSION;
pcfData->Header.DeviceCaps.PnameStringId = SR_STR_DRIVER_MIXER;
pcfData->Header.DeviceCaps.fdwSupport = 0;
/* setup number of Lines and Controls */
pcfData->Header.NumberOfLines = NumberOfMixerLines;
pcfData->Header.NumberOfControls = NumberOfMixerControls;
/* compute number of destinations */
for (i = 0; i < NumberOfMixerLines; i++) {
if (MixerLineData[i].cConnections == 0) {
break;
}
}
pcfData->Header.DeviceCaps.cDestinations = i;
/* setup the text data offsets */
for (pLT = &pcfData->TextData[NumberOfTextItems - 1], pCD = pcfData->ControlData, i = 0;
i < NumberOfTextItems; pLT--, i++) {
pCD[pLT->ControlId].TextDataOffset = (PBYTE)pLT - (PBYTE)pcfData;
}
/* set the size of returned data */
Length = min(sizeof(*pcfData), IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
pIrp->IoStatus.Information = Length;
/* copy our data for return to the user side caller */
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, pcfData, pIrp->IoStatus.Information);
/* free the allocated memory */
ExFreePool(pcfData);
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetConfig(STATUS_SUCCESS)\n"));
return(STATUS_SUCCESS);
} /* cs423xMixerGetConfig() */
/*
*********************************************************************************
*
*********************************************************************************
*/
NTSTATUS cs423xMixerGetLineFlags(PMIXER_INFO MixerInfo, ULONG LineId, ULONG Length,
PVOID pData)
{
PULONG fdwLine;
_dbgprint((_PRT_DBUG, "enter cs423xMixerGetLineFlags(LId: %d Len: %d pData: 0x%08x)\n",
LineId, Length, pData));
if (LineId >= NumberOfMixerLines)
return(STATUS_INVALID_PARAMETER);
/* initialize local pointer */
fdwLine = pData;
/* fetch default - line is a source */
*fdwLine = MixerLineData[LineId].cConnections == 0 ? MIXERLINE_LINEF_SOURCE : 0;
/* determine if line is active */
*fdwLine |= MIXERLINE_LINEF_ACTIVE;
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetLineFlags(STATUS_SUCCESS)\n"));
return(STATUS_SUCCESS);
} /* cs423xMixerGetLineFlags() */
/*
*********************************************************************************
*
*********************************************************************************
*/
NTSTATUS cs423xMixerGetCombCtrl(PMIXER_INFO MixerInfo, ULONG CtrlId, ULONG Length,
PVOID pData)
{
PULONG vol;
_dbgprint((_PRT_DBUG, "enter cs423xMixerGetCombCtrl(CId: %d Len: %d pData: 0x%08x)\n",
CtrlId, Length, pData));
vol = pData;
vol[0] = 0xFFFF;
vol[1] = 0xFFFF;
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetCombCtrl(STATUS_SUCCESS)\n"));
return(STATUS_SUCCESS);
} /* cs423xMixerGetCombCtrl() */
/*
*********************************************************************************
*
*********************************************************************************
*/
NTSTATUS cs423xMixerGetControl(PMIXER_INFO MixerInfo, ULONG cid, ULONG Length, PVOID pData)
{
PGLOBAL_DEVICE_INFO pGDI;
INT i;
PMIXER_REGISTRY_DATA pmrd;
ULONG values[NumberOfMixerControls];
_dbgprint((_PRT_DBUG, "enter cs423xMixerGetControl(cid: %d Len: %d pData: 0x%08x)\n",
cid, Length, pData));
/* check for valid control ID */
if (cid >= NumberOfMixerControls)
return(STATUS_INVALID_PARAMETER);
/* obtain global device pointer */
pGDI = CONTAINING_RECORD(MixerInfo, GLOBAL_DEVICE_INFO, MixerInfo);
pmrd = &pGDI->MixerSettings;
/**************************************************************/
/* determine which control value is being requested */
/* In each case: */
/* If the DataLength is valid for the Control: */
/* - fetch the value from the memory representation */
/**************************************************************/
switch (cid) {
case ControlMixerOutAtten:
if (Length < (sizeof(ULONG) * 2))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u;
values[RIGHT] = pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerOutMute:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[MUTE] = pmrd->ControlData[ControlMixerOutMute].v[MUTE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlSpeakerMute:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[MUTE] = pmrd->ControlData[ControlSpeakerMute].v[MUTE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlWaveinGain:
if (Length < (sizeof(ULONG) * 2))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlWaveinGain].v[LEFT].u;
values[RIGHT] = pmrd->ControlData[ControlWaveinGain].v[RIGHT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlHighPassFilter:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[FILTER] = pmrd->ControlData[ControlHighPassFilter].v[FILTER].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMux:
if (Length < MixerControlData[ControlMux].cMultipleItems * sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
for (i = 0; i < MixerControlData[ControlMux].cMultipleItems; i++) {
values[i] = FALSE;
if (i == (INT)(pmrd->ControlData[ControlMux].v[MUXSEL].u))
values[i] = TRUE;
}
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputAux1Gain:
if (Length < (sizeof(ULONG) * 2))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u;
values[RIGHT] = pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputAux1Mute:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[MUTE] = pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputLineinGain:
if (Length < (sizeof(ULONG) * 2))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u;
values[RIGHT] = pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputLineinMute:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[MUTE] = pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputAux2Gain:
if (Length < (sizeof(ULONG) * 2))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u;
values[RIGHT] = pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputAux2Mute:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[MUTE] = pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputMonoinAtten:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputMonoinMute:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[MUTE] = pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputWaveoutAtten:
if (Length < (sizeof(ULONG) * 2))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u;
values[RIGHT] = pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMixerInputWaveoutMute:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[MUTE] = pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlWaveoutPeak:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
SoundPeakMeter(&pGDI->WaveOutInfo, values);
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlWaveinMonitorAtten:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[LEFT] = pmrd->ControlData[ControlWaveinMonitorAtten].v[LEFT].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlWaveinMonitorEnable:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[ENABLE] = pmrd->ControlData[ControlWaveinMonitorEnable].v[ENABLE].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMuxSelectMic:
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 2){
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
SoundPeakMeter(&pGDI->WaveInInfo, values);
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
}
break;
case ControlMicBoost:
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
values[BOOST] = pmrd->ControlData[ControlMicBoost].v[BOOST].u;
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
case ControlMuxSelectLinein:
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 0){
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
SoundPeakMeter(&pGDI->WaveInInfo, values);
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
}
break;
case ControlMuxSelectAux1:
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 1){
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
SoundPeakMeter(&pGDI->WaveInInfo, values);
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
}
break;
case ControlMuxSelectMixer:
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 3){
if (Length < sizeof(ULONG))
return(STATUS_BUFFER_TOO_SMALL);
SoundPeakMeter(&pGDI->WaveInInfo, values);
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
break;
}
break;
default:
_dbgprint((_PRT_ERRO, "cs423xMixerGetControl: unknown control device\n"));
break;
}
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetControl(STATUS_SUCCESS)\n"));
return(STATUS_SUCCESS);
} /* cs423xMixerGetControl() */
/*
*********************************************************************************
* Since the 4231 does not have an attenuator at the output of the mixer,
* we must fake it by scaling the gain/attenuation of each input
*********************************************************************************
*/
VOID cs4231SetOutputAttenuation(PSOUND_HARDWARE pHW, PMIXER_REGISTRY_DATA pmrd,
ULONG left, ULONG right)
{
ULONG tl;
ULONG tr;
_dbgprint((_PRT_DBUG,
"enter cs4231SetOutputAttenuation(pHW: 0x%08x pmrd: %d left: %d right: %d)\n",
pHW, pmrd, left, right));
tl = ((ULONG)pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u * left) / USSMAX;
tr = ((ULONG)pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u * right) / USSMAX;
cs423xSetMixerInputAux1Gain(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
tl = ((ULONG)pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u * left) / USSMAX;
tr = ((ULONG)pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u * right) / USSMAX;
cs423xSetMixerInputLineinGain(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
tl = ((ULONG)pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u * left) / USSMAX;
tr = ((ULONG)pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u * right) / USSMAX;
cs423xSetMixerInputAux2Gain(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
tl = ((ULONG)pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u * left) / USSMAX;
cs423xSetMixerInputMonoinAttenuation(pHW, (USHORT)(tl & 0xffff));
tl = ((ULONG)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u * left) / USSMAX;
tr = ((ULONG)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u * right) / USSMAX;
cs423xSetMixerInputWaveoutAttenuation(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
_dbgprint((_PRT_DBUG, "exit cs4231SetOutputAttenuation(VOID)\n"));
return;
} /* cs4231SetOutputAttenuation() */
/*
*********************************************************************************
* Since the 4231 does not have a Mute at the output of the mixer,
* we must fake it by Muting each input
*********************************************************************************
*/
VOID cs4231SetOutputMute(PSOUND_HARDWARE pHW, PMIXER_REGISTRY_DATA pmrd, BOOLEAN set)
{
ULONG tl;
ULONG tr;
_dbgprint((_PRT_DBUG,
"enter cs4231SetOutputMute(pHW: 0x%08x pmrd: %d set: 0x%04x)\n", pHW, pmrd, set));
if (set) {
cs423xSetMixerInputAux1Mute(pHW, set);
cs423xSetMixerInputLineinMute(pHW, set);
cs423xSetMixerInputAux2Mute(pHW, set);
cs423xSetMixerInputMonoinMute(pHW, set);
cs423xSetMixerInputWaveoutMute(pHW, set);
}
else {
cs423xSetMixerInputAux1Mute(pHW,
(BOOLEAN)(pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u));
cs423xSetMixerInputLineinMute(pHW,
(BOOLEAN)(pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u));
cs423xSetMixerInputAux2Mute(pHW,
(BOOLEAN)(pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u));
cs423xSetMixerInputMonoinMute(pHW,
(BOOLEAN)(pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u));
cs423xSetMixerInputWaveoutMute(pHW,
(BOOLEAN)(pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u));
}
_dbgprint((_PRT_DBUG, "exit cs4231SetOutputMute(VOID)\n"));
return;
} /* cs4231SetOutputMute() */
/*
*********************************************************************************
*
*********************************************************************************
*/
NTSTATUS cs423xMixerSetControl(PMIXER_INFO MixerInfo, ULONG cid, ULONG Length, PVOID pData)
{
PGLOBAL_DEVICE_INFO pGDI;
PULONG pul;
INT i;
PMIXER_REGISTRY_DATA pmrd;
ULONG tleft;
ULONG tright;
_dbgprint((_PRT_DBUG,
"enter cs423xMixerSetControl(pMI: 0x%08x cid: %d DLen: %d pData: 0x%08x)\n",
MixerInfo, cid, Length, pData));
/* obtain global device pointer */
pGDI = CONTAINING_RECORD(MixerInfo, GLOBAL_DEVICE_INFO, MixerInfo);
pmrd = &pGDI->MixerSettings;
/**************************************************************/
/* determine which control change is being requested */
/* In each case: */
/* If the DataLength is valid for the Control: */
/* - change it on the hardware */
/* - store the new value in the memory representation */
/* - send a ntofication */
/**************************************************************/
pul = pData;
switch (cid) {
case ControlMixerOutAtten:
if (Length != (sizeof(ULONG) * 2))
return(STATUS_INVALID_PARAMETER);
if (pGDI->Hw.Type == hwtype_cs4231)
cs4231SetOutputAttenuation(&pGDI->Hw, pmrd, pul[LEFT], pul[RIGHT]);
else
cs423xSetOutputAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
(USHORT)(pul[RIGHT] & 0xffff));
pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u = (USHORT)pul[LEFT];
pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u = (USHORT)pul[RIGHT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerOutAtten]);
break;
case ControlMixerOutMute:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
if (pGDI->Hw.Type == hwtype_cs4231)
cs4231SetOutputMute(&pGDI->Hw, pmrd, (BOOLEAN)(pul[MUTE] & 0xffff));
else
cs423xSetOutputMute(&pGDI->Hw, (BOOLEAN)(pul[MUTE] & 0xffff));
pmrd->ControlData[ControlMixerOutMute].v[MUTE].u = (USHORT)pul[MUTE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerOutMute]);
break;
case ControlSpeakerMute:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
cs423xSetSpeakerMute(&pGDI->Hw, (BOOLEAN)(pul[MUTE] & 0xffff));
pmrd->ControlData[ControlSpeakerMute].v[MUTE].u = (USHORT)pul[MUTE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlSpeakerMute]);
break;
case ControlWaveinGain:
if (Length != (sizeof(ULONG) * 2))
return(STATUS_INVALID_PARAMETER);
cs423xSetWaveinGain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
(USHORT)(pul[RIGHT] & 0xffff));
pmrd->ControlData[ControlWaveinGain].v[LEFT].u = (USHORT)pul[LEFT];
pmrd->ControlData[ControlWaveinGain].v[RIGHT].u = (USHORT)pul[RIGHT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlWaveinGain]);
break;
case ControlHighPassFilter:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
cs423xSetHPF(&pGDI->Hw, (BOOLEAN)(pul[FILTER] & 0xffff));
pmrd->ControlData[ControlHighPassFilter].v[FILTER].u = (USHORT)pul[FILTER];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlHighPassFilter]);
break;
case ControlMux:
if (Length != MixerControlData[ControlMux].cMultipleItems * sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
pmrd->ControlData[ControlMux].v[MUXSEL].u = 0;
for (i = 0; i < MixerControlData[ControlMux].cMultipleItems; i++) {
if (pul[i]) {
pmrd->ControlData[ControlMux].v[MUXSEL].u = i;
cs423xSetMuxSelect(&pGDI->Hw, (ULONG)i);
}
}
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMux]);
break;
case ControlMixerInputAux1Gain:
if (Length != (sizeof(ULONG) * 2))
return(STATUS_INVALID_PARAMETER);
if (pGDI->Hw.Type == hwtype_cs4231) {
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
cs423xSetMixerInputAux1Gain(&pGDI->Hw, (USHORT)(tleft & 0xffff),
(USHORT)(tright & 0xffff));
}
else
cs423xSetMixerInputAux1Gain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
(USHORT)(pul[RIGHT] & 0xffff));
pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u = (USHORT)pul[LEFT];
pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u = (USHORT)pul[RIGHT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux1Gain]);
break;
case ControlMixerInputAux1Mute:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
cs423xSetMixerInputAux1Mute(&pGDI->Hw, TRUE);
else
cs423xSetMixerInputAux1Mute(&pGDI->Hw, FALSE);
pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u = (USHORT)pul[MUTE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux1Mute]);
break;
case ControlMixerInputLineinGain:
if (Length != (sizeof(ULONG) * 2))
return(STATUS_INVALID_PARAMETER);
if (pGDI->Hw.Type == hwtype_cs4231) {
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
cs423xSetMixerInputLineinGain(&pGDI->Hw, (USHORT)(tleft & 0xffff),
(USHORT)(tright & 0xffff));
}
else
cs423xSetMixerInputLineinGain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
(USHORT)(pul[RIGHT] & 0xffff));
pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u = (USHORT)pul[LEFT];
pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u = (USHORT)pul[RIGHT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputLineinGain]);
break;
case ControlMixerInputLineinMute:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
cs423xSetMixerInputLineinMute(&pGDI->Hw, TRUE);
else
cs423xSetMixerInputLineinMute(&pGDI->Hw, FALSE);
pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u = (USHORT)pul[MUTE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputLineinMute]);
break;
case ControlMixerInputAux2Gain:
if (Length != (sizeof(ULONG) * 2))
return(STATUS_INVALID_PARAMETER);
if (pGDI->Hw.Type == hwtype_cs4231) {
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
cs423xSetMixerInputAux2Gain(&pGDI->Hw, (USHORT)(tleft & 0xffff),
(USHORT)(tright & 0xffff));
}
else
cs423xSetMixerInputAux2Gain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
(USHORT)(pul[RIGHT] & 0xffff));
pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u = (USHORT)pul[LEFT];
pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u = (USHORT)pul[RIGHT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux2Gain]);
break;
case ControlMixerInputAux2Mute:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
cs423xSetMixerInputAux2Mute(&pGDI->Hw, TRUE);
else
cs423xSetMixerInputAux2Mute(&pGDI->Hw, FALSE);
pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u = (USHORT)pul[MUTE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux2Mute]);
break;
case ControlMixerInputMonoinAtten:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
if (pGDI->Hw.Type == hwtype_cs4231) {
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
cs423xSetMixerInputMonoinAttenuation(&pGDI->Hw, (USHORT)(tleft & 0xffff));
}
else
cs423xSetMixerInputMonoinAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff));
pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u = (USHORT)pul[LEFT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputMonoinAtten]);
break;
case ControlMixerInputMonoinMute:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
cs423xSetMixerInputMonoinMute(&pGDI->Hw, TRUE);
else
cs423xSetMixerInputMonoinMute(&pGDI->Hw, FALSE);
pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u = (USHORT)pul[MUTE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputMonoinMute]);
break;
case ControlMixerInputWaveoutAtten:
if (Length != (sizeof(ULONG) * 2))
return(STATUS_INVALID_PARAMETER);
if (pGDI->Hw.Type == hwtype_cs4231) {
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
cs423xSetMixerInputWaveoutAttenuation(&pGDI->Hw, (USHORT)(tleft & 0xffff),
(USHORT)(tright & 0xffff));
}
else
cs423xSetMixerInputWaveoutAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
(USHORT)(pul[RIGHT] & 0xffff));
pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u = (USHORT)pul[LEFT];
pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u = (USHORT)pul[RIGHT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputWaveoutAtten]);
break;
case ControlMixerInputWaveoutMute:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
cs423xSetMixerInputWaveoutMute(&pGDI->Hw, TRUE);
else
cs423xSetMixerInputWaveoutMute(&pGDI->Hw, FALSE);
pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u = (USHORT)pul[MUTE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputWaveoutMute]);
break;
case ControlWaveoutPeak:
return(STATUS_INVALID_PARAMETER);
break;
case ControlWaveinMonitorAtten:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
cs423xSetWaveinMonitorAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff));
pmrd->ControlData[ControlWaveinMonitorAtten].v[LEFT].u = (USHORT)pul[LEFT];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlWaveinMonitorAtten]);
break;
case ControlWaveinMonitorEnable:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
cs423xSetWaveinMonitorEnable(&pGDI->Hw, (BOOLEAN)(pul[ENABLE] & 0xffff));
pmrd->ControlData[ControlWaveinMonitorEnable].v[ENABLE].u = (USHORT)pul[ENABLE];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlWaveinMonitorEnable]);
break;
case ControlMuxSelectMic:
return(STATUS_INVALID_PARAMETER);
break;
case ControlMicBoost:
if (Length != sizeof(ULONG))
return(STATUS_INVALID_PARAMETER);
cs423xSetMicBoost(&pGDI->Hw, (BOOLEAN)(pul[BOOST] & 0xffff));
pmrd->ControlData[ControlMicBoost].v[BOOST].u = (USHORT)pul[BOOST];
SoundMixerChangedItem(&pGDI->MixerInfo,
&pGDI->LocalMixerData.ControlNotification[ControlMicBoost]);
break;
case ControlMuxSelectLinein:
return(STATUS_INVALID_PARAMETER);
break;
case ControlMuxSelectAux1:
return(STATUS_INVALID_PARAMETER);
break;
case ControlMuxSelectMixer:
return(STATUS_INVALID_PARAMETER);
break;
default:
_dbgprint((_PRT_ERRO, "cs423xMixerSetControl: unknown control device\n"));
break;
}
_dbgprint((_PRT_DBUG, "exit cs423xMixerSetControl(STATUS_SUCCESS)\n"));
return(STATUS_SUCCESS);
} /* cs423xMixerSetControl() */
/*
*********************************************************************************
*
*********************************************************************************
*/
VOID cs423xSaveMixerSettings(PGLOBAL_DEVICE_INFO pGDI)
{
_dbgprint((_PRT_DBUG, "enter cs423xSaveMixerSettings(pGDI: 0x%08x)\n", pGDI));
RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, pGDI->RegPathName, SOUND_MIXER_SETTINGS_NAME,
REG_BINARY, (PVOID)&pGDI->MixerSettings, sizeof(MIXER_REGISTRY_DATA));
_dbgprint((_PRT_DBUG, "exit cs423xSaveMixerSettings()\n"));
return;
} /* cs423xSaveMixerSettings() */
/*
*********************************************************************************
*
*********************************************************************************
*/
VOID cs423xWOLineChanged(PLOCAL_DEVICE_INFO pLDI, UCHAR Code)
{
PLOCAL_MIXER_DATA LocalMixerData;
LocalMixerData = &((PGLOBAL_DEVICE_INFO)pLDI->pGlobalInfo)->LocalMixerData;
SoundMixerChangedItem(
&((PGLOBAL_DEVICE_INFO)pLDI->pGlobalInfo)->MixerInfo,
&LocalMixerData->LineNotification[SourceMixerWaveOut]);
}