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
;
34 /* get device count */
35 DeviceCount
= GetSysAudioDeviceCount(DeviceObject
);
37 DPRINT("WdmAudInitWorkerRoutine SysAudioDeviceCount %ld\n", DeviceCount
);
39 /* was a device added / removed */
40 if (DeviceCount
!= DeviceExtension
->SysAudioDeviceCount
)
42 /* init mmixer library */
43 Status
= WdmAudMixerInitialize(DeviceObject
);
44 DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status
, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount());
46 /* store sysaudio device count */
47 DeviceExtension
->SysAudioDeviceCount
= DeviceCount
;
50 /* signal completion */
51 KeSetEvent(&DeviceExtension
->InitializationCompletionEvent
, IO_NO_INCREMENT
, FALSE
);
53 /* reset work item status indicator */
54 InterlockedDecrement((volatile long *)&DeviceExtension
->WorkItemActive
);
60 IN PDEVICE_OBJECT DeviceObject
,
63 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
65 /* get device extension */
66 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
68 if (InterlockedCompareExchange((volatile long *)&DeviceExtension
->WorkItemActive
, 1, 0) == 0)
71 IoQueueWorkItem(DeviceExtension
->WorkItem
, WdmAudInitWorkerRoutine
, DelayedWorkQueue
, (PVOID
)DeviceExtension
);
78 IN PDRIVER_OBJECT DriverObject
)
80 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\wdmaud");
81 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices\\wdmaud");
82 PDEVICE_OBJECT DeviceObject
;
84 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
86 DPRINT("WdmAudInstallDevice called\n");
88 Status
= IoCreateDevice(DriverObject
,
89 sizeof(WDMAUD_DEVICE_EXTENSION
),
96 if (!NT_SUCCESS(Status
))
98 DPRINT1("IoCreateDevice failed with %x\n", Status
);
102 /* get device extension */
103 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
104 RtlZeroMemory(DeviceExtension
, sizeof(WDMAUD_DEVICE_EXTENSION
));
106 /* allocate work item */
107 DeviceExtension
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
108 if (!DeviceExtension
->WorkItem
)
110 /* failed to allocate work item */
111 IoDeleteDevice(DeviceObject
);
112 return STATUS_INSUFFICIENT_RESOURCES
;
115 /* register device interfaces */
116 Status
= WdmAudRegisterDeviceInterface(DeviceObject
, DeviceExtension
);
117 if (!NT_SUCCESS(Status
))
119 DPRINT1("WdmRegisterDeviceInterface failed with %x\n", Status
);
120 IoDeleteDevice(DeviceObject
);
124 /* initialize sysaudio device list */
125 InitializeListHead(&DeviceExtension
->SysAudioDeviceList
);
127 /* initialize client context device list */
128 InitializeListHead(&DeviceExtension
->WdmAudClientList
);
130 /* initialize spinlock */
131 KeInitializeSpinLock(&DeviceExtension
->Lock
);
133 /* initialization completion event */
134 KeInitializeEvent(&DeviceExtension
->InitializationCompletionEvent
, NotificationEvent
, FALSE
);
136 /* initialize timer */
137 IoInitializeTimer(DeviceObject
, WdmAudTimerRoutine
, (PVOID
)WdmAudTimerRoutine
);
139 /* find available sysaudio devices */
140 Status
= WdmAudOpenSysAudioDevices(DeviceObject
, DeviceExtension
);
141 if (!NT_SUCCESS(Status
))
143 DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status
);
144 IoDeleteSymbolicLink(&SymlinkName
);
145 IoDeleteDevice(DeviceObject
);
149 /* allocate ks device header */
150 Status
= KsAllocateDeviceHeader(&DeviceExtension
->DeviceHeader
, 0, NULL
);
151 if (!NT_SUCCESS(Status
))
153 DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status
);
154 IoDeleteSymbolicLink(&SymlinkName
);
155 IoDeleteDevice(DeviceObject
);
159 /* start the timer */
160 IoStartTimer(DeviceObject
);
162 DeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
163 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
165 return STATUS_SUCCESS
;
171 IN PDRIVER_OBJECT driver
)
173 DPRINT("WdmAudUnload called\n");
179 IN PDEVICE_OBJECT DeviceObject
,
182 PIO_STACK_LOCATION IrpStack
;
184 DPRINT("WdmAudPnp called\n");
186 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
188 if (IrpStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
190 Irp
->IoStatus
.Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
191 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
193 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
200 IN PDEVICE_OBJECT DeviceObject
,
204 PIO_STACK_LOCATION IoStack
;
205 PWDMAUD_CLIENT pClient
;
206 //PWDMAUD_DEVICE_EXTENSION DeviceExtension;
208 /* get device extension */
209 //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
212 Status
= KsReferenceSoftwareBusObject((KSDEVICE_HEADER
)DeviceObject
->DeviceExtension
);
213 if (!NT_SUCCESS(Status
))
215 DPRINT1("KsReferenceSoftwareBusObject failed with %x\n", Status
);
220 Status
= WdmAudOpenSysaudio(DeviceObject
, &pClient
);
221 if (!NT_SUCCESS(Status
))
223 DPRINT1("Failed to open sysaudio!\n");
225 /* complete and forget */
226 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
227 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
229 return STATUS_UNSUCCESSFUL
;
232 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
233 ASSERT(IoStack
->FileObject
);
235 /* store client context in file object */
236 IoStack
->FileObject
->FsContext
= pClient
;
237 Status
= STATUS_SUCCESS
;
239 Irp
->IoStatus
.Status
= Status
;
240 Irp
->IoStatus
.Information
= 0;
241 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
249 IN PDEVICE_OBJECT DeviceObject
,
252 /* nothing to do complete request */
254 Status
= KsDereferenceSoftwareBusObject(DeviceExtension
->DeviceHeader
);
256 if (NT_SUCCESS(Status
))
258 if (DeviceExtension
->SysAudioNotification
)
259 Status
= IoUnregisterPlugPlayNotification(DeviceExtension
->SysAudioNotification
);
263 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
264 Irp
->IoStatus
.Information
= 0;
265 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
268 return STATUS_SUCCESS
;
274 IN PDEVICE_OBJECT DeviceObject
,
277 PIO_STACK_LOCATION IoStack
;
278 PWDMAUD_CLIENT pClient
;
279 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
283 /* get device extension */
284 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
286 /* get current irp stack location */
287 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
290 ASSERT(IoStack
->FileObject
);
292 /* get client context struct */
293 pClient
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
298 /* acquire client context list lock */
299 KeAcquireSpinLock(&DeviceExtension
->Lock
, &OldIrql
);
302 RemoveEntryList(&pClient
->Entry
);
305 KeReleaseSpinLock(&DeviceExtension
->Lock
, OldIrql
);
307 /* check if all audio pins have been closed */
308 for (Index
= 0; Index
< pClient
->NumPins
; Index
++)
310 DPRINT("Index %u Pin %p Type %x\n", Index
, pClient
->hPins
[Index
].Handle
, pClient
->hPins
[Index
].Type
);
311 if (pClient
->hPins
[Index
].Handle
&& pClient
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
313 /* found an still open audio pin */
314 ZwClose(pClient
->hPins
[Index
].Handle
);
320 FreeItem(pClient
->hPins
);
322 /* free client context struct */
325 /* clear old client pointer */
326 IoStack
->FileObject
->FsContext
= NULL
;
328 /* complete request */
329 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
330 Irp
->IoStatus
.Information
= 0;
331 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
334 return STATUS_SUCCESS
;
340 IN PDRIVER_OBJECT Driver
,
341 IN PUNICODE_STRING Registry_path
344 DPRINT("Wdmaud.sys loaded\n");
346 Driver
->DriverUnload
= WdmAudUnload
;
348 Driver
->MajorFunction
[IRP_MJ_CREATE
] = WdmAudCreate
;
349 Driver
->MajorFunction
[IRP_MJ_CLOSE
] = WdmAudClose
;
350 Driver
->MajorFunction
[IRP_MJ_PNP
] = WdmAudPnp
;
351 Driver
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
352 Driver
->MajorFunction
[IRP_MJ_CLEANUP
] = WdmAudCleanup
;
353 Driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = WdmAudDeviceControl
;
354 Driver
->MajorFunction
[IRP_MJ_WRITE
] = WdmAudReadWrite
;
355 Driver
->MajorFunction
[IRP_MJ_READ
] = WdmAudReadWrite
;
356 Driver
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
358 return WdmAudInstallDevice(Driver
);