2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/wdmaud/main.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Andrew Greenwood
15 const GUID KSCATEGORY_SYSAUDIO
= {0xA7C7A5B1L
, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}};
16 const GUID KSCATEGORY_WDMAUD
= {0x3E227E76L
, 0x690D, 0x11D2, {0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1}};
18 IO_WORKITEM_ROUTINE WdmAudInitWorkerRoutine
;
19 IO_TIMER_ROUTINE WdmAudTimerRoutine
;
23 WdmAudInitWorkerRoutine(
24 IN PDEVICE_OBJECT DeviceObject
,
28 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
31 /* get device extension */
32 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
35 if (DeviceExtension
->FileObject
== NULL
)
37 /* find available sysaudio devices */
38 Status
= WdmAudOpenSysAudioDevices(DeviceObject
, DeviceExtension
);
39 if (!NT_SUCCESS(Status
))
41 DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status
);
47 /* get device count */
48 DeviceCount
= GetSysAudioDeviceCount(DeviceObject
);
50 DPRINT("WdmAudInitWorkerRoutine SysAudioDeviceCount %ld\n", DeviceCount
);
52 /* was a device added / removed */
53 if (DeviceCount
!= DeviceExtension
->SysAudioDeviceCount
)
55 /* init mmixer library */
56 Status
= WdmAudMixerInitialize(DeviceObject
);
57 DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status
, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount());
59 /* store sysaudio device count */
60 DeviceExtension
->SysAudioDeviceCount
= DeviceCount
;
63 /* signal completion */
64 KeSetEvent(&DeviceExtension
->InitializationCompletionEvent
, IO_NO_INCREMENT
, FALSE
);
66 /* reset work item status indicator */
67 InterlockedDecrement((volatile long *)&DeviceExtension
->WorkItemActive
);
73 IN PDEVICE_OBJECT DeviceObject
,
76 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
78 /* get device extension */
79 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
81 if (InterlockedCompareExchange((volatile long *)&DeviceExtension
->WorkItemActive
, 1, 0) == 0)
84 IoQueueWorkItem(DeviceExtension
->WorkItem
, WdmAudInitWorkerRoutine
, DelayedWorkQueue
, (PVOID
)DeviceExtension
);
91 IN PDRIVER_OBJECT DriverObject
,
92 IN PDEVICE_OBJECT PhysicalDeviceObject
)
94 PDEVICE_OBJECT DeviceObject
;
96 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
98 DPRINT("WdmaudAddDevice called\n");
100 Status
= IoCreateDevice(DriverObject
,
101 sizeof(WDMAUD_DEVICE_EXTENSION
),
108 if (!NT_SUCCESS(Status
))
110 DPRINT1("IoCreateDevice failed with %x\n", Status
);
114 /* get device extension */
115 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
116 RtlZeroMemory(DeviceExtension
, sizeof(WDMAUD_DEVICE_EXTENSION
));
118 /* allocate work item */
119 DeviceExtension
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
120 if (!DeviceExtension
->WorkItem
)
122 /* failed to allocate work item */
123 IoDeleteDevice(DeviceObject
);
124 return STATUS_INSUFFICIENT_RESOURCES
;
127 /* register device interfaces */
128 Status
= WdmAudRegisterDeviceInterface(PhysicalDeviceObject
, DeviceExtension
);
129 if (!NT_SUCCESS(Status
))
131 DPRINT1("WdmRegisterDeviceInterface failed with %x\n", Status
);
132 IoDeleteDevice(DeviceObject
);
136 /* initialize sysaudio device list */
137 InitializeListHead(&DeviceExtension
->SysAudioDeviceList
);
139 /* initialize client context device list */
140 InitializeListHead(&DeviceExtension
->WdmAudClientList
);
142 /* initialize spinlock */
143 KeInitializeSpinLock(&DeviceExtension
->Lock
);
145 /* initialization completion event */
146 KeInitializeEvent(&DeviceExtension
->InitializationCompletionEvent
, NotificationEvent
, FALSE
);
148 /* initialize timer */
149 IoInitializeTimer(DeviceObject
, WdmAudTimerRoutine
, (PVOID
)WdmAudTimerRoutine
);
151 /* allocate ks device header */
152 Status
= KsAllocateDeviceHeader(&DeviceExtension
->DeviceHeader
, 0, NULL
);
153 if (!NT_SUCCESS(Status
))
155 DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status
);
156 IoDeleteDevice(DeviceObject
);
160 /* attach to device stack */
161 DeviceExtension
->NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
162 KsSetDevicePnpAndBaseObject(DeviceExtension
->DeviceHeader
, DeviceExtension
->NextDeviceObject
, DeviceObject
);
165 /* start the timer */
166 IoStartTimer(DeviceObject
);
168 DeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
169 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
171 return STATUS_SUCCESS
;
177 IN PDRIVER_OBJECT driver
)
179 DPRINT("WdmAudUnload called\n");
185 IN PDEVICE_OBJECT DeviceObject
,
188 PIO_STACK_LOCATION IrpStack
;
190 DPRINT("WdmAudPnp called\n");
192 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
194 if (IrpStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
196 Irp
->IoStatus
.Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
197 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
199 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
206 IN PDEVICE_OBJECT DeviceObject
,
210 PIO_STACK_LOCATION IoStack
;
211 PWDMAUD_CLIENT pClient
;
212 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
214 /* get device extension */
215 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
218 Status
= KsReferenceSoftwareBusObject((KSDEVICE_HEADER
)DeviceObject
->DeviceExtension
);
219 if (!NT_SUCCESS(Status
))
221 DPRINT1("KsReferenceSoftwareBusObject failed with %x\n", Status
);
226 if (DeviceExtension
->FileObject
== NULL
)
229 WdmAudInitWorkerRoutine(DeviceObject
, NULL
);
233 Status
= WdmAudOpenSysaudio(DeviceObject
, &pClient
);
234 if (!NT_SUCCESS(Status
))
236 DPRINT1("Failed to open sysaudio!\n");
238 /* complete and forget */
239 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
240 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
242 return STATUS_UNSUCCESSFUL
;
245 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
246 ASSERT(IoStack
->FileObject
);
248 /* store client context in file object */
249 IoStack
->FileObject
->FsContext
= pClient
;
250 Status
= STATUS_SUCCESS
;
252 Irp
->IoStatus
.Status
= Status
;
253 Irp
->IoStatus
.Information
= 0;
254 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
262 IN PDEVICE_OBJECT DeviceObject
,
265 /* nothing to do complete request */
267 Status
= KsDereferenceSoftwareBusObject(DeviceExtension
->DeviceHeader
);
269 if (NT_SUCCESS(Status
))
271 if (DeviceExtension
->SysAudioNotification
)
272 Status
= IoUnregisterPlugPlayNotification(DeviceExtension
->SysAudioNotification
);
276 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
277 Irp
->IoStatus
.Information
= 0;
278 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
281 return STATUS_SUCCESS
;
287 IN PDEVICE_OBJECT DeviceObject
,
290 PIO_STACK_LOCATION IoStack
;
291 PWDMAUD_CLIENT pClient
;
292 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
296 /* get device extension */
297 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
299 /* get current irp stack location */
300 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
303 ASSERT(IoStack
->FileObject
);
305 /* get client context struct */
306 pClient
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
311 /* acquire client context list lock */
312 KeAcquireSpinLock(&DeviceExtension
->Lock
, &OldIrql
);
315 RemoveEntryList(&pClient
->Entry
);
318 KeReleaseSpinLock(&DeviceExtension
->Lock
, OldIrql
);
320 /* check if all audio pins have been closed */
321 for (Index
= 0; Index
< pClient
->NumPins
; Index
++)
323 DPRINT("Index %u Pin %p Type %x\n", Index
, pClient
->hPins
[Index
].Handle
, pClient
->hPins
[Index
].Type
);
324 if (pClient
->hPins
[Index
].Handle
&& pClient
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
326 /* found an still open audio pin */
327 ZwClose(pClient
->hPins
[Index
].Handle
);
329 WdmAudCloseAllMixers(DeviceObject
, pClient
, Index
);
334 FreeItem(pClient
->hPins
);
336 /* free client context struct */
339 /* clear old client pointer */
340 IoStack
->FileObject
->FsContext
= NULL
;
342 /* complete request */
343 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
344 Irp
->IoStatus
.Information
= 0;
345 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
348 return STATUS_SUCCESS
;
354 IN PDRIVER_OBJECT Driver
,
355 IN PUNICODE_STRING Registry_path
358 DPRINT("Wdmaud.sys loaded\n");
360 Driver
->DriverUnload
= WdmAudUnload
;
362 Driver
->MajorFunction
[IRP_MJ_CREATE
] = WdmAudCreate
;
363 Driver
->MajorFunction
[IRP_MJ_CLOSE
] = WdmAudClose
;
364 Driver
->MajorFunction
[IRP_MJ_PNP
] = WdmAudPnp
;
365 Driver
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
366 Driver
->MajorFunction
[IRP_MJ_CLEANUP
] = WdmAudCleanup
;
367 Driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = WdmAudDeviceControl
;
368 Driver
->MajorFunction
[IRP_MJ_WRITE
] = WdmAudReadWrite
;
369 Driver
->MajorFunction
[IRP_MJ_READ
] = WdmAudReadWrite
;
370 Driver
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
371 Driver
->DriverExtension
->AddDevice
= WdmaudAddDevice
;
373 return STATUS_SUCCESS
;