- Register sysaudio device interfaces
[reactos.git] / reactos / drivers / wdm / audio / sysaudio / main.c
1 /*
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
7 *
8 * HISTORY:
9 * 8 Jul 07 Started basic implementation
10 */
11
12 #include <ntddk.h>
13 #include <ks.h>
14 #define YDEBUG
15 #include <debug.h>
16 //#include <dxsdk/mediaobj.h>
17 #include "sysaudio.h"
18
19
20
21 const GUID KS_CATEGORY_AUDIO = {0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
22 VOID
23 NTAPI
24 SysAudio_Unload(IN PDRIVER_OBJECT DriverObject)
25 {
26 DPRINT1("SysAudio_Unload called\n");
27 }
28
29 NTSTATUS
30 NTAPI
31 SysAudio_Pnp(
32 IN PDEVICE_OBJECT DeviceObject,
33 IN PIRP Irp)
34 {
35 PIO_STACK_LOCATION IrpStack;
36 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
37 SYSAUDIODEVEXT *DeviceExtension;
38
39 DPRINT1("SysAudio_Pnp called\n");
40
41
42 IrpStack = IoGetCurrentIrpStackLocation(Irp);
43
44 DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
45
46 if (IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
47 {
48 if (DeviceExtension->EchoCancelNotificationEntry)
49 IoUnregisterPlugPlayNotification(DeviceExtension->EchoCancelNotificationEntry);
50
51 if (DeviceExtension->KsAudioNotificationEntry)
52 IoUnregisterPlugPlayNotification(DeviceExtension->KsAudioNotificationEntry);
53
54 IoDeleteSymbolicLink(&SymlinkName);
55 }
56
57 return KsDefaultDispatchPnp(DeviceObject, Irp);
58 }
59
60 NTSTATUS
61 NTAPI
62 DeviceInterfaceChangeCallback(
63 IN PVOID NotificationStructure,
64 IN PVOID Context)
65 {
66 DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
67
68 DPRINT1("DeviceInterfaceChangeCallback called %p\n", Event);
69 return STATUS_SUCCESS;
70 }
71
72 NTSTATUS
73 NTAPI
74 DispatchCreate(
75 IN PDEVICE_OBJECT DeviceObject,
76 IN PIRP Irp)
77 {
78 DPRINT1("DispatchCreate\n");
79
80 return STATUS_SUCCESS;
81 }
82
83 const GUID KSCATEGORY_AUDIO_DEVICE = {0xFBF6F530L, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
84 const GUID KSCATEGORY_PREFERRED_WAVEOUT_DEVICE = {0xD6C5066EL, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
85 const GUID KSCATEGORY_PREFERRED_WAVEIN_DEVICE = {0xD6C50671L, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
86 const GUID KSCATEGORY_PREFERRED_MIDIOUT_DEVICE = {0xD6C50674L, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
87
88
89
90 NTSTATUS
91 NTAPI
92 SysAudio_AddDevice(
93 IN PDRIVER_OBJECT DriverObject,
94 IN PDEVICE_OBJECT PhysicalDeviceObject)
95 {
96 NTSTATUS Status;
97 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio");
98 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
99 PDEVICE_OBJECT DeviceObject;
100 PDEVICE_OBJECT NextDeviceObject;
101 KSOBJECT_CREATE_ITEM CreateItem;
102 SYSAUDIODEVEXT *DeviceExtension;
103 UNICODE_STRING SymbolicLink;
104
105 DPRINT1("SysAudio_AddDevice called\n");
106
107 /* create the device */
108 Status = IoCreateDevice(DriverObject,
109 sizeof(SYSAUDIODEVEXT),
110 &DeviceName,
111 FILE_DEVICE_KS,
112 0,
113 FALSE,
114 &DeviceObject);
115
116 /* check for success */
117 if (!NT_SUCCESS(Status))
118 {
119 DPRINT("Failed to create \\Device\\sysaudio !\n");
120 return Status;
121 }
122
123 /* create the symbolic link */
124 Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
125 if (!NT_SUCCESS(Status))
126 {
127 IoDeleteDevice(DeviceObject);
128 DPRINT("Failed to create \\DosDevices\\sysaudio symlink!\n");
129 return Status;
130 }
131
132
133 DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
134 /* initialize device extension */
135 RtlZeroMemory(DeviceExtension, sizeof(SYSAUDIODEVEXT));
136
137 KeInitializeMutex(&DeviceExtension->Mutex, 0);
138
139 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
140
141 /* initialize create item struct */
142 RtlZeroMemory(&CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
143 CreateItem.Create = DispatchCreate;
144
145 Status = KsAllocateDeviceHeader(&DeviceExtension->KsDeviceHeader,
146 1,
147 &CreateItem);
148
149 if (NT_SUCCESS(Status))
150 {
151 NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
152 if (NextDeviceObject)
153 {
154 /// FIXME
155 /// KsSetDevicePnpAndBaseObject(DeviceExtension->KsDeviceHeader, NextDeviceObject, DeviceObject);
156 ///
157
158 DeviceExtension->NextDeviceObject = NextDeviceObject;
159
160 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
161 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
162 (PVOID)&KS_CATEGORY_AUDIO,
163 DriverObject,
164 DeviceInterfaceChangeCallback,
165 (PVOID)DeviceExtension,
166 (PVOID*)&DeviceExtension->KsAudioNotificationEntry);
167 if (!NT_SUCCESS(Status))
168 {
169 DPRINT1("IoRegisterPlugPlayNotification failed with %x\n", Status);
170 return Status;
171 }
172 #if 0
173 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
174 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
175 &DMOCATEGORY_ACOUSTIC_ECHO_CANCEL,
176 DriverObject,
177 DeviceInterfaceChangeCallback,
178 (PVOID)DeviceExtension,
179 &DeviceExtension->EchoCancelNotificationEntry);
180 if (!NT_SUCCESS(Status))
181 {
182 DPRINT1("IoRegisterPlugPlayNotification failed with %x\n", Status);
183 return Status;
184 }
185 #endif
186
187 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_PREFERRED_MIDIOUT_DEVICE, NULL, &SymbolicLink);
188 if (!NT_SUCCESS(Status))
189 {
190 DPRINT1("Failed to register KSCATEGORY_PREFERRED_MIDIOUT_DEVICE interface\n");
191 return Status;
192 }
193 RtlFreeUnicodeString(&SymbolicLink);
194
195 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_PREFERRED_WAVEIN_DEVICE, NULL, &SymbolicLink);
196 if (!NT_SUCCESS(Status))
197 {
198 DPRINT1("Failed to register KSCATEGORY_PREFERRED_WAVEIN_DEVICE interface\n");
199 return Status;
200 }
201 RtlFreeUnicodeString(&SymbolicLink);
202
203 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_PREFERRED_WAVEOUT_DEVICE, NULL, &SymbolicLink);
204 if (!NT_SUCCESS(Status))
205 {
206 DPRINT1("Failed to register KSCATEGORY_PREFERRED_WAVEOUT_DEVICE interface\n");
207 return Status;
208 }
209 RtlFreeUnicodeString(&SymbolicLink);
210
211 /* set io flags */
212 DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
213 /* clear initializing flag */
214 DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
215 }
216 }
217
218
219
220 DPRINT("Device SysAudio_AddDevice result %x\n", Status);
221
222 return Status;
223 }
224
225 NTSTATUS NTAPI
226 DriverEntry(
227 IN PDRIVER_OBJECT DriverObject,
228 IN PUNICODE_STRING RegistryPath)
229 {
230 DPRINT1("System audio graph builder (sysaudio) started\n");
231
232 DPRINT1("Setting KS function handlers\n");
233 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
234 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
235 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
236 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
237
238 DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
239 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
240 DriverObject->MajorFunction[IRP_MJ_PNP] = SysAudio_Pnp;
241 DriverObject->DriverUnload = SysAudio_Unload;
242 DriverObject->DriverExtension->AddDevice = SysAudio_AddDevice;
243
244 return STATUS_SUCCESS;
245 }