* PROGRAMMER: Andrew Greenwood
* Johannes Anderwald
*/
+
#include "wdmaud.h"
+#define NDEBUG
+#include <debug.h>
+
const GUID KSCATEGORY_SYSAUDIO = {0xA7C7A5B1L, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}};
const GUID KSCATEGORY_WDMAUD = {0x3E227E76L, 0x690D, 0x11D2, {0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1}};
+IO_WORKITEM_ROUTINE WdmAudInitWorkerRoutine;
+IO_TIMER_ROUTINE WdmAudTimerRoutine;
+
+VOID
+NTAPI
+WdmAudInitWorkerRoutine(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
+{
+ NTSTATUS Status;
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ ULONG DeviceCount;
+
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+
+ if (DeviceExtension->FileObject == NULL)
+ {
+ /* find available sysaudio devices */
+ Status = WdmAudOpenSysAudioDevices(DeviceObject, DeviceExtension);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status);
+ return;
+ }
+ }
+
+
+ /* get device count */
+ DeviceCount = GetSysAudioDeviceCount(DeviceObject);
+
+ DPRINT("WdmAudInitWorkerRoutine SysAudioDeviceCount %ld\n", DeviceCount);
+
+ /* was a device added / removed */
+ if (DeviceCount != DeviceExtension->SysAudioDeviceCount)
+ {
+ /* init mmixer library */
+ Status = WdmAudMixerInitialize(DeviceObject);
+ DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount());
+
+ /* store sysaudio device count */
+ DeviceExtension->SysAudioDeviceCount = DeviceCount;
+ }
+
+ /* signal completion */
+ KeSetEvent(&DeviceExtension->InitializationCompletionEvent, IO_NO_INCREMENT, FALSE);
+
+ /* reset work item status indicator */
+ InterlockedDecrement((volatile long *)&DeviceExtension->WorkItemActive);
+}
+
+VOID
+NTAPI
+WdmAudTimerRoutine(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
+{
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ if (InterlockedCompareExchange((volatile long *)&DeviceExtension->WorkItemActive, 1, 0) == 0)
+ {
+ /* queue work item */
+ IoQueueWorkItem(DeviceExtension->WorkItem, WdmAudInitWorkerRoutine, DelayedWorkQueue, (PVOID)DeviceExtension);
+ }
+}
+
NTSTATUS
NTAPI
-WdmAudInstallDevice(
- IN PDRIVER_OBJECT DriverObject)
+WdmaudAddDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT PhysicalDeviceObject)
{
- UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\wdmaud");
- UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\wdmaud");
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
- DPRINT("WdmAudInstallDevice called\n");
+ DPRINT("WdmaudAddDevice called\n");
Status = IoCreateDevice(DriverObject,
sizeof(WDMAUD_DEVICE_EXTENSION),
- &DeviceName,
+ NULL,
FILE_DEVICE_KS,
0,
FALSE,
return Status;
}
- /* clear device extension */
+ /* get device extension */
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(WDMAUD_DEVICE_EXTENSION));
+ /* allocate work item */
+ DeviceExtension->WorkItem = IoAllocateWorkItem(DeviceObject);
+ if (!DeviceExtension->WorkItem)
+ {
+ /* failed to allocate work item */
+ IoDeleteDevice(DeviceObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
/* register device interfaces */
- Status = WdmAudRegisterDeviceInterface(DeviceObject, DeviceExtension);
+ Status = WdmAudRegisterDeviceInterface(PhysicalDeviceObject, DeviceExtension);
if (!NT_SUCCESS(Status))
{
DPRINT1("WdmRegisterDeviceInterface failed with %x\n", Status);
/* initialize spinlock */
KeInitializeSpinLock(&DeviceExtension->Lock);
- /* find available sysaudio devices */
- Status = WdmAudOpenSysAudioDevices(DeviceObject, DeviceExtension);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status);
- IoDeleteSymbolicLink(&SymlinkName);
- IoDeleteDevice(DeviceObject);
- return Status;
- }
+ /* initialization completion event */
+ KeInitializeEvent(&DeviceExtension->InitializationCompletionEvent, NotificationEvent, FALSE);
+
+ /* initialize timer */
+ IoInitializeTimer(DeviceObject, WdmAudTimerRoutine, (PVOID)WdmAudTimerRoutine);
+
/* allocate ks device header */
Status = KsAllocateDeviceHeader(&DeviceExtension->DeviceHeader, 0, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status);
- IoDeleteSymbolicLink(&SymlinkName);
IoDeleteDevice(DeviceObject);
return Status;
}
- Status = WdmAudMixerInitialize(DeviceObject);
- DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount());
+ /* attach to device stack */
+ DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
+ KsSetDevicePnpAndBaseObject(DeviceExtension->DeviceHeader, DeviceExtension->NextDeviceObject, DeviceObject);
+
+
+ /* start the timer */
+ IoStartTimer(DeviceObject);
DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
PWDMAUD_CLIENT pClient;
- //PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
/* get device extension */
- //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
#if KS_IMPLEMENTED
Status = KsReferenceSoftwareBusObject((KSDEVICE_HEADER)DeviceObject->DeviceExtension);
}
#endif
+ if (DeviceExtension->FileObject == NULL)
+ {
+ /* initialize */
+ WdmAudInitWorkerRoutine(DeviceObject, NULL);
+ }
+
+
Status = WdmAudOpenSysaudio(DeviceObject, &pClient);
if (!NT_SUCCESS(Status))
{
/* found an still open audio pin */
ZwClose(pClient->hPins[Index].Handle);
}
+ WdmAudCloseAllMixers(DeviceObject, pClient, Index);
}
/* free pin array */
Driver->MajorFunction[IRP_MJ_WRITE] = WdmAudReadWrite;
Driver->MajorFunction[IRP_MJ_READ] = WdmAudReadWrite;
Driver->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
+ Driver->DriverExtension->AddDevice = WdmaudAddDevice;
- return WdmAudInstallDevice(Driver);
+ return STATUS_SUCCESS;
}