Author: janderwald
Date: Fri Nov 13 02:48:28 2009
New Revision: 44122
URL:
http://svn.reactos.org/svn/reactos?rev=44122&view=rev
Log:
[WDMAUD_KERNEL]
- Implement kernel side of notifying clients of volume / mute control changes
Modified:
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/deviface.c
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] Fri Nov 13
02:48:28 2009
@@ -372,6 +372,8 @@
return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_QUERYDEVICEINTERFACESTRING:
return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo);
+ case IOCTL_GET_MIXER_EVENT:
+ return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_GETPOS:
case IOCTL_GETDEVID:
case IOCTL_GETVOLUME:
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/deviface.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/deviface.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/deviface.c [iso-8859-1] Fri Nov 13
02:48:28 2009
@@ -205,22 +205,41 @@
PWDMAUD_CLIENT Client;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ /* get device extension */
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (!DeviceExtension->NumSysAudioDevices)
+ {
+ /* wdmaud failed to open sysaudio */
return STATUS_UNSUCCESSFUL;
-
+ }
+
+ /* sanity check */
ASSERT(!IsListEmpty(&DeviceExtension->SysAudioDeviceList));
+ /* allocate client context struct */
Client = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_CLIENT));
+
+ /* check for allocation failure */
if (!Client)
{
+ /* not enough memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
+ /* zero client context struct */
RtlZeroMemory(Client, sizeof(WDMAUD_CLIENT));
+
+ /* initialize mixer event list */
+ InitializeListHead(&Client->MixerEventList);
+
+ /* store result */
*pClient = Client;
+ /* insert client into list */
+ ExInterlockedInsertTailList(&DeviceExtension->WdmAudClientList,
&Client->Entry, &DeviceExtension->Lock);
+
+ /* done */
return STATUS_SUCCESS;
}
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c [iso-8859-1] Fri Nov 13 02:48:28
2009
@@ -54,6 +54,9 @@
/* initialize sysaudio device list */
InitializeListHead(&DeviceExtension->SysAudioDeviceList);
+ /* initialize client context device list */
+ InitializeListHead(&DeviceExtension->WdmAudClientList);
+
/* initialize spinlock */
KeInitializeSpinLock(&DeviceExtension->Lock);
@@ -123,14 +126,11 @@
IN PIRP Irp)
{
NTSTATUS Status;
-
PIO_STACK_LOCATION IoStack;
PWDMAUD_CLIENT pClient;
-
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
- DPRINT("WdmAudCreate\n");
-
+ /* get device extension */
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
#if KS_IMPLEMENTED
@@ -146,8 +146,12 @@
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to open sysaudio!\n");
- if (pClient)
- ExFreePool(pClient);
+
+ /* complete and forget */
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ /* done */
+ return STATUS_UNSUCCESSFUL;
}
IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -170,8 +174,7 @@
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- DPRINT("WdmAudClose\n");
-
+ /* nothing to do complete request */
#if KS_IMPLEMENTED
Status = KsDereferenceSoftwareBusObject(DeviceExtension->DeviceHeader);
@@ -186,6 +189,7 @@
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ /* done */
return STATUS_SUCCESS;
}
@@ -196,45 +200,67 @@
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
- WDMAUD_CLIENT *pClient;
+ PWDMAUD_CLIENT pClient;
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
ULONG Index;
-
- DPRINT("WdmAudCleanup\n");
-
+ KIRQL OldIrql;
+
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
- pClient = (WDMAUD_CLIENT*)IoStack->FileObject->FsContext;
-
- if (pClient)
- {
- for (Index = 0; Index < pClient->NumPins; Index++)
- {
- DPRINT("Index %u Pin %p Type %x\n", Index,
pClient->hPins[Index].Handle, pClient->hPins[Index].Type);
- if (pClient->hPins[Index].Handle && pClient->hPins[Index].Type
!= MIXER_DEVICE_TYPE)
- {
- ZwClose(pClient->hPins[Index].Handle);
- }
- }
-
- if (pClient->hPins)
- {
- ExFreePool(pClient->hPins);
- }
-
- ExFreePool(pClient);
- IoStack->FileObject->FsContext = NULL;
- }
-
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+
+ /* get client context struct */
+ pClient = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
+
+ /* sanity check */
+ ASSERT(pClient);
+
+ /* acquire client context list lock */
+ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
+
+ /* remove entry */
+ RemoveEntryList(&pClient->Entry);
+
+ /* release lock */
+ KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
+
+ /* check if all audio pins have been closed */
+ for (Index = 0; Index < pClient->NumPins; Index++)
+ {
+ DPRINT("Index %u Pin %p Type %x\n", Index,
pClient->hPins[Index].Handle, pClient->hPins[Index].Type);
+ if (pClient->hPins[Index].Handle && pClient->hPins[Index].Type !=
MIXER_DEVICE_TYPE)
+ {
+ /* found an still open audio pin */
+ ZwClose(pClient->hPins[Index].Handle);
+ }
+ }
+
+ /* free pin array */
+ if (pClient->hPins)
+ ExFreePool(pClient->hPins);
+
+ /* free client context struct */
+ ExFreePool(pClient);
+
+ /* clear old client pointer */
+ IoStack->FileObject->FsContext = NULL;
+
+ /* complete request */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- DPRINT("WdmAudCleanup complete\n");
+
+ /* done */
return STATUS_SUCCESS;
}
-
-
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
DriverEntry(
IN PDRIVER_OBJECT Driver,
IN PUNICODE_STRING Registry_path
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h [iso-8859-1] Fri Nov 13
02:48:28 2009
@@ -49,9 +49,17 @@
LPWSTR DeviceInterfaceString;
ULONG DeviceInterfaceStringSize;
}Interface;
+
+ struct
+ {
+ HANDLE hMixer;
+ ULONG NotificationType;
+ ULONG Value;
+ }MixerEvent;
KSSTATE State;
ULONG Volume;
ULONG FrameSize;
+ HANDLE hNotifyEvent;
}u;
}WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO;
@@ -336,4 +344,21 @@
METHOD_BUFFERED, \
FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS)
+/// IOCTL_GET_MIXER_EVENT
+///
+/// Description: This IOCTL queries for
+///
+/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure,
+/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure
+/// Note: The hDevice member must be set
+/// Result: The result is returned in the struct MixerInfo
+/// ReturnCode: STATUS_SUCCESS indicates success
+
+#define IOCTL_GET_MIXER_EVENT \
+ CTL_CODE(FILE_DEVICE_SOUND, \
+ 16, \
+ METHOD_BUFFERED, \
+ FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS)
+
+
#endif
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] Fri Nov 13 02:48:28
2009
@@ -1770,6 +1770,7 @@
{
/* re-use pseudo handle */
DeviceInfo->hDevice = (HANDLE)DeviceInfo->DeviceIndex;
+ ClientInfo->hPins[Index].hNotifyEvent = DeviceInfo->u.hNotifyEvent;
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}
}
@@ -1787,6 +1788,7 @@
ClientInfo->hPins = Handels;
ClientInfo->hPins[ClientInfo->NumPins].Handle =
(HANDLE)DeviceInfo->DeviceIndex;
ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE;
+ ClientInfo->hPins[ClientInfo->NumPins].hNotifyEvent =
DeviceInfo->u.hNotifyEvent;
ClientInfo->NumPins++;
}
else
@@ -2050,10 +2052,94 @@
}
NTSTATUS
+NotifyWdmAudClients(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG NotificationType,
+ IN HANDLE hMixer,
+ IN ULONG Value)
+{
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ PLIST_ENTRY Entry;
+ PWDMAUD_CLIENT CurClient;
+ PKEVENT EventObject;
+ PMIXER_EVENT Event;
+ KIRQL OldIrql;
+ ULONG Index;
+ NTSTATUS Status;
+
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* acquire client context lock */
+ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
+
+ /* point to first entry */
+ Entry = DeviceExtension->WdmAudClientList.Flink;
+
+ /* iterate through all clients */
+ while(Entry != &DeviceExtension->WdmAudClientList)
+ {
+ /* get client context */
+ CurClient = (PWDMAUD_CLIENT)CONTAINING_RECORD(Entry, WDMAUD_CLIENT, Entry);
+
+ /* now iterate through all pins and try to find an matching handle */
+ for(Index = 0; Index < CurClient->NumPins; Index++)
+ {
+ if (CurClient->hPins[Index].Handle == hMixer &&
CurClient->hPins[Index].Type == MIXER_DEVICE_TYPE &&
CurClient->hPins[Index].hNotifyEvent)
+ {
+ /* found a matching mixer handle and a valid notify event */
+ Status =
ObReferenceObjectByHandle(CurClient->hPins[Index].hNotifyEvent, EVENT_MODIFY_STATE,
ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Invalid notify event passed %p from client %p\n",
CurClient->hPins[Index].hNotifyEvent, CurClient);
+ break;
+ }
+
+ /* allocate event entry */
+ Event = (PMIXER_EVENT)ExAllocatePool(NonPagedPool, sizeof(MIXER_EVENT));
+ if (!Event)
+ {
+ /* no memory */
+ ObDereferenceObject(EventObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* initialize event entry */
+ Event->hMixer = hMixer;
+ Event->NotificationType = NotificationType;
+ Event->Value = Value;
+
+ /* insert event entry */
+ InsertTailList(&CurClient->MixerEventList, &Event->Entry);
+
+ /* now signal the event */
+ KeSetEvent(EventObject, 0, FALSE);
+
+ /* dereference event */
+ ObDereferenceObject(EventObject);
+
+ /* search next client */
+ break;
+ }
+ }
+
+ /* move to next client */
+ Entry = Entry->Flink;
+ }
+
+ /* release client context lock */
+ KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
+
+ /* done */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
SetGetMuteControlDetails(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG DeviceId,
IN ULONG NodeId,
+ IN ULONG dwLineID,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN ULONG bSet)
{
@@ -2074,9 +2160,21 @@
/* set control details */
Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet,
KSPROPERTY_AUDIO_MUTE, MAXULONG, &Value);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
/* FIXME SEH */
if (!bSet)
+ {
Input->fValue = Value;
+ return Status;
+ }
+ else
+ {
+ /* notify clients of a line change */
+ NotifyWdmAudClients(DeviceObject, MM_MIXM_LINE_CHANGE, DeviceInfo->hDevice,
dwLineID);
+ }
+
return Status;
}
@@ -2147,8 +2245,74 @@
}
Input->dwValue = VolumeData->InputSteppingDelta *
(VolumeData->ValuesCount-1);
}
-
+ else
+ {
+ /* notify clients of a line change */
+ NotifyWdmAudClients(DeviceObject, MM_MIXM_CONTROL_CHANGE, DeviceInfo->hDevice,
MixerControl->dwControlID);
+ }
return Status;
+}
+
+NTSTATUS
+NTAPI
+WdmAudGetMixerEvent(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PWDMAUD_DEVICE_INFO DeviceInfo,
+ IN PWDMAUD_CLIENT ClientInfo)
+{
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ PMIXER_EVENT Event = NULL;
+ PLIST_ENTRY Entry;
+ KIRQL OldIrql;
+
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* acquire client context lock */
+ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
+
+ /* point to first entry */
+ Entry = ClientInfo->MixerEventList.Flink;
+
+ while(Entry != &ClientInfo->MixerEventList)
+ {
+ /* get mixer event */
+ Event = (PMIXER_EVENT)CONTAINING_RECORD(Entry, MIXER_EVENT, Entry);
+
+ if (Event->hMixer == DeviceInfo->hDevice)
+ {
+ /* found an event for that particular device */
+ break;
+ }
+
+ /* no match found */
+ Event = NULL;
+
+ /* move to next entry */
+ Entry = Entry->Flink;
+ }
+
+
+ /* release client context lock */
+ KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
+
+ if (!Event)
+ {
+ /* no events available */
+ return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
+ }
+
+ /* store event result */
+ DeviceInfo->u.MixerEvent.hMixer = Event->hMixer;
+ DeviceInfo->u.MixerEvent.NotificationType = Event->NotificationType;
+ DeviceInfo->u.MixerEvent.Value = Event->Value;
+
+ /* free event info */
+ ExFreePool(Event);
+
+ /* done */
+ return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
@@ -2193,7 +2357,7 @@
if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
{
/* send the request */
- Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex,
NodeId, DeviceInfo, TRUE);
+ Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex,
NodeId, MixerLine->Line.dwLineID, DeviceInfo, TRUE);
}
else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
{
@@ -2245,7 +2409,7 @@
if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
{
/* send the request */
- Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex,
NodeId, DeviceInfo, FALSE);
+ Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex,
NodeId, MixerLine->Line.dwLineID, DeviceInfo, FALSE);
}
else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
{
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] Fri Nov 13
02:48:28 2009
@@ -18,19 +18,30 @@
typedef struct
{
+ LIST_ENTRY Entry;
+ HANDLE hMixer;
+ ULONG NotificationType;
+ ULONG Value;
+}MIXER_EVENT, *PMIXER_EVENT;
+
+
+typedef struct
+{
HANDLE Handle;
SOUND_DEVICE_TYPE Type;
ULONG FilterId;
ULONG PinId;
+ HANDLE hNotifyEvent;
}WDMAUD_HANDLE, *PWDMAUD_HANDLE;
-
-typedef struct
-{
+typedef struct
+{
+ LIST_ENTRY Entry;
HANDLE hProcess;
ULONG NumPins;
WDMAUD_HANDLE * hPins;
+ LIST_ENTRY MixerEventList;
}WDMAUD_CLIENT, *PWDMAUD_CLIENT;
typedef struct
@@ -115,7 +126,7 @@
ULONG WaveOutDeviceCount;
LIST_ENTRY WaveOutList;
-
+ LIST_ENTRY WdmAudClientList;
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
NTSTATUS
@@ -245,6 +256,14 @@
NTSTATUS
NTAPI
+WdmAudGetMixerEvent(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PWDMAUD_DEVICE_INFO DeviceInfo,
+ IN PWDMAUD_CLIENT ClientInfo);
+
+NTSTATUS
+NTAPI
WdmAudGetControlDetails(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,