2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/sysaudio/main.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Andrew Greenwood
9 * 8 Jul 07 Started basic implementation
17 const GUID KSCATEGORY_SYSAUDIO
= {0xA7C7A5B1L
, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}};
18 const GUID KSCATEGORY_AUDIO_DEVICE
= {0xFBF6F530L
, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
19 const GUID KSCATEGORY_PREFERRED_WAVEOUT_DEVICE
= {0xD6C5066EL
, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
20 const GUID KSCATEGORY_PREFERRED_WAVEIN_DEVICE
= {0xD6C50671L
, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
21 const GUID KSCATEGORY_PREFERRED_MIDIOUT_DEVICE
= {0xD6C50674L
, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
25 IN POOL_TYPE PoolType
,
26 IN SIZE_T NumberOfBytes
)
28 PVOID Item
= ExAllocatePool(PoolType
, NumberOfBytes
);
32 RtlZeroMemory(Item
, NumberOfBytes
);
46 SysAudio_Unload(IN PDRIVER_OBJECT DriverObject
)
48 DPRINT("SysAudio_Unload called\n");
54 IN PDEVICE_OBJECT DeviceObject
,
57 PKSAUDIO_DEVICE_ENTRY DeviceEntry
;
58 PSYSAUDIODEVEXT DeviceExtension
;
61 DPRINT("SysAudio_Shutdown called\n");
63 DeviceExtension
= (PSYSAUDIODEVEXT
)DeviceObject
->DeviceExtension
;
65 while(!IsListEmpty(&DeviceExtension
->KsAudioDeviceList
))
67 Entry
= RemoveHeadList(&DeviceExtension
->KsAudioDeviceList
);
68 DeviceEntry
= (PKSAUDIO_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, KSAUDIO_DEVICE_ENTRY
, Entry
);
70 DPRINT("Freeing item %wZ\n", &DeviceEntry
->DeviceName
);
72 /* dereference audio device file object */
73 ObDereferenceObject(DeviceEntry
->FileObject
);
75 /* close audio device handle */
76 ZwClose(DeviceEntry
->Handle
);
78 /* free device string */
79 RtlFreeUnicodeString(&DeviceEntry
->DeviceName
);
81 /* free audio device entry */
82 FreeItem(DeviceEntry
);
85 Irp
->IoStatus
.Information
= 0;
86 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
87 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
88 return STATUS_SUCCESS
;
95 IN PDEVICE_OBJECT DeviceObject
,
98 PIO_STACK_LOCATION IrpStack
;
99 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices\\sysaudio");
100 SYSAUDIODEVEXT
*DeviceExtension
;
102 /* Get current irp stack */
103 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
105 /* Fetch the device extension */
106 DeviceExtension
= (SYSAUDIODEVEXT
*)DeviceObject
->DeviceExtension
;
107 ASSERT(DeviceExtension
);
109 if (IrpStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
111 /* Unregister the echo cancel hook */
112 if (DeviceExtension
->EchoCancelNotificationEntry
)
113 IoUnregisterPlugPlayNotification(DeviceExtension
->EchoCancelNotificationEntry
);
115 /* Unregister the ks audio hook */
116 if (DeviceExtension
->KsAudioNotificationEntry
)
117 IoUnregisterPlugPlayNotification(DeviceExtension
->KsAudioNotificationEntry
);
119 /* Destroy our symbolic link */
120 IoDeleteSymbolicLink(&SymlinkName
);
122 else if (IrpStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
124 /* Sysaudio can not be disabled */
125 Irp
->IoStatus
.Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
128 /* Perform default pnp actions */
129 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
135 IN PDRIVER_OBJECT DriverObject
,
136 IN PDEVICE_OBJECT PhysicalDeviceObject
)
139 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\sysaudio");
140 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices\\sysaudio");
141 PDEVICE_OBJECT DeviceObject
, NextDeviceObject
;
142 SYSAUDIODEVEXT
*DeviceExtension
;
144 DPRINT("SysAudio_AddDevice called\n");
146 /* Create the device */
147 Status
= IoCreateDevice(DriverObject
,
148 sizeof(SYSAUDIODEVEXT
),
155 /* Check for success */
156 if (!NT_SUCCESS(Status
))
158 DPRINT("Failed to create \\Device\\sysaudio !\n");
162 /* Register device interfaces */
163 Status
= SysAudioRegisterDeviceInterfaces(PhysicalDeviceObject
);
164 if (!NT_SUCCESS(Status
))
166 /* Failed to register
167 * Create a hack interface
169 Status
= IoCreateSymbolicLink(&SymlinkName
, &DeviceName
);
170 if (!NT_SUCCESS(Status
))
172 IoDeleteDevice(DeviceObject
);
173 DPRINT1("Failed to create sysaudio symlink!\n");
177 /* Acquire device extension */
178 DeviceExtension
= (SYSAUDIODEVEXT
*)DeviceObject
->DeviceExtension
;
179 /* Initialize device extension */
180 RtlZeroMemory(DeviceExtension
, sizeof(SYSAUDIODEVEXT
));
182 /* Initialize the mutex */
183 KeInitializeSpinLock(&DeviceExtension
->Lock
);
185 /* Initialize the ks audio device list */
186 InitializeListHead(&DeviceExtension
->KsAudioDeviceList
);
188 /* Allocate kernel streaming device header */
189 Status
= SysAudioAllocateDeviceHeader(DeviceExtension
);
190 if (!NT_SUCCESS(Status
))
192 DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status
);
196 /* Register device notification hooks */
197 Status
= SysAudioRegisterNotifications(DriverObject
,
199 if (!NT_SUCCESS(Status
))
201 DPRINT1("Failed to register device notifications\n");
206 Status
= SysAudioOpenKMixer(DeviceExtension
);
207 if (!NT_SUCCESS(Status
))
209 DPRINT1("SysAudioOpenKMixer failed with %x\n", Status
);
214 DeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
215 /* clear initializing flag */
216 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
218 /* atttach to device stack */
219 NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
220 KsSetDevicePnpAndBaseObject(DeviceExtension
->KsDeviceHeader
, NextDeviceObject
, DeviceObject
);
222 /* register shutdown notification */
223 IoRegisterShutdownNotification(DeviceObject
);
227 return STATUS_SUCCESS
;
231 if (DeviceExtension
->KsAudioNotificationEntry
)
232 IoUnregisterPlugPlayNotification(DeviceExtension
->KsAudioNotificationEntry
);
234 if (DeviceExtension
->EchoCancelNotificationEntry
)
235 IoUnregisterPlugPlayNotification(DeviceExtension
->EchoCancelNotificationEntry
);
237 IoDeleteSymbolicLink(&SymlinkName
);
238 IoDeleteDevice(DeviceObject
);
245 IN PDRIVER_OBJECT DriverObject
,
246 IN PUNICODE_STRING RegistryPath
)
248 DPRINT("System audio graph builder (sysaudio) started\n");
250 /* Let ks handle these */
251 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CREATE
);
252 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CLOSE
);
253 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_WRITE
);
254 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_DEVICE_CONTROL
);
256 /* Let ks handle these */
257 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
258 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
260 /* Use provided ks unload function */
261 DriverObject
->DriverUnload
= KsNullDriverUnload
;
263 /* Sysaudio needs to do work on pnp, so handle it */
264 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = SysAudio_Pnp
;
265 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = SysAudio_Shutdown
;
266 DriverObject
->DriverExtension
->AddDevice
= SysAudio_AddDevice
;
269 return STATUS_SUCCESS
;