605946c300c8df81cec8681c612824a646e5d33e
[reactos.git] / drivers / wdm / audio / sysaudio / deviface.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/sysaudio/deviface.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "sysaudio.h"
10
11 const GUID GUID_DEVICE_INTERFACE_ARRIVAL = {0xCB3A4004L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}};
12 const GUID GUID_DEVICE_INTERFACE_REMOVAL = {0xCB3A4005L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}};
13 const GUID KS_CATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
14 const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}};
15 const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
16
17 NTSTATUS
18 OpenDevice(
19 IN PUNICODE_STRING DeviceName,
20 IN PHANDLE HandleOut,
21 IN PFILE_OBJECT * FileObjectOut)
22 {
23 NTSTATUS Status;
24 HANDLE NodeHandle;
25 PFILE_OBJECT FileObject;
26 OBJECT_ATTRIBUTES ObjectAttributes;
27 IO_STATUS_BLOCK IoStatusBlock;
28
29 InitializeObjectAttributes(&ObjectAttributes, DeviceName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
30
31 Status = ZwCreateFile(&NodeHandle,
32 GENERIC_READ | GENERIC_WRITE,
33 &ObjectAttributes,
34 &IoStatusBlock,
35 NULL,
36 0,
37 0,
38 FILE_OPEN,
39 FILE_SYNCHRONOUS_IO_NONALERT,
40 NULL,
41 0);
42
43
44 if (!NT_SUCCESS(Status))
45 {
46 DPRINT("ZwCreateFile failed with %x %S\n", Status, DeviceName->Buffer);
47 return Status;
48 }
49
50 Status = ObReferenceObjectByHandle(NodeHandle, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
51 if (!NT_SUCCESS(Status))
52 {
53 ZwClose(NodeHandle);
54 DPRINT("ObReferenceObjectByHandle failed with %x\n", Status);
55 return Status;
56 }
57
58 *HandleOut = NodeHandle;
59 *FileObjectOut = FileObject;
60 return Status;
61 }
62
63 NTSTATUS
64 InsertAudioDevice(
65 IN PDEVICE_OBJECT DeviceObject,
66 IN PUNICODE_STRING DeviceName)
67 {
68 NTSTATUS Status = STATUS_SUCCESS;
69 PSYSAUDIODEVEXT DeviceExtension;
70 PKSAUDIO_DEVICE_ENTRY DeviceEntry = NULL;
71
72 /* a new device has arrived */
73 DeviceEntry = AllocateItem(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
74 if (!DeviceEntry)
75 {
76 /* no memory */
77 return STATUS_INSUFFICIENT_RESOURCES;
78 }
79
80 /* initialize audio device entry */
81 RtlZeroMemory(DeviceEntry, sizeof(KSAUDIO_DEVICE_ENTRY));
82
83 /* set device name */
84 DeviceEntry->DeviceName.Length = 0;
85 DeviceEntry->DeviceName.MaximumLength = DeviceName->MaximumLength + 10 * sizeof(WCHAR);
86
87 DeviceEntry->DeviceName.Buffer = AllocateItem(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
88
89 if (!DeviceEntry->DeviceName.Buffer)
90 {
91 Status = STATUS_INSUFFICIENT_RESOURCES;
92 goto cleanup;
93 }
94
95 RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\");
96 RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, DeviceName);
97
98 Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject);
99
100 if (!NT_SUCCESS(Status))
101 {
102 goto cleanup;
103 }
104
105 /* fetch device extension */
106 DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
107 /* insert new audio device */
108 ExInterlockedInsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry, &DeviceExtension->Lock);
109 InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices);
110
111 DPRINT("Successfully opened audio device %u Device %S\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->DeviceName.Buffer);
112 return Status;
113
114 cleanup:
115 if (DeviceEntry)
116 {
117 if (DeviceEntry->DeviceName.Buffer)
118 FreeItem(DeviceEntry->DeviceName.Buffer);
119
120 FreeItem(DeviceEntry);
121 }
122
123 return Status;
124
125 }
126
127
128 NTSTATUS
129 NTAPI
130 DeviceInterfaceChangeCallback(
131 IN PVOID NotificationStructure,
132 IN PVOID Context)
133 {
134 DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event;
135 NTSTATUS Status = STATUS_SUCCESS;
136 PSYSAUDIODEVEXT DeviceExtension;
137 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
138
139 DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
140
141 Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
142
143 if (IsEqualGUIDAligned(&Event->Event,
144 &GUID_DEVICE_INTERFACE_ARRIVAL))
145 {
146 Status = InsertAudioDevice(DeviceObject, Event->SymbolicLinkName);
147 return Status;
148 }
149 else
150 {
151 DPRINT("Remove interface to audio device!\n");
152 UNIMPLEMENTED
153 return STATUS_SUCCESS;
154 }
155
156
157 }
158
159 NTSTATUS
160 SysAudioRegisterNotifications(
161 IN PDRIVER_OBJECT DriverObject,
162 IN PDEVICE_OBJECT DeviceObject)
163 {
164 NTSTATUS Status;
165 PSYSAUDIODEVEXT DeviceExtension;
166
167 DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
168
169 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
170 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
171 (PVOID)&KS_CATEGORY_AUDIO,
172 DriverObject,
173 DeviceInterfaceChangeCallback,
174 (PVOID)DeviceObject,
175 (PVOID*)&DeviceExtension->KsAudioNotificationEntry);
176
177 if (!NT_SUCCESS(Status))
178 {
179 DPRINT("IoRegisterPlugPlayNotification failed with %x\n", Status);
180 }
181
182 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
183 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
184 (PVOID)&DMOCATEGORY_ACOUSTIC_ECHO_CANCEL,
185 DriverObject,
186 DeviceInterfaceChangeCallback,
187 (PVOID)DeviceObject,
188 (PVOID*)&DeviceExtension->EchoCancelNotificationEntry);
189
190 if (!NT_SUCCESS(Status))
191 {
192 /* ignore failure for now */
193 DPRINT("IoRegisterPlugPlayNotification failed for DMOCATEGORY_ACOUSTIC_ECHO_CANCEL\n", Status);
194 }
195
196 return STATUS_SUCCESS;
197 }
198
199
200
201 NTSTATUS
202 SysAudioRegisterDeviceInterfaces(
203 IN PDEVICE_OBJECT DeviceObject)
204 {
205 NTSTATUS Status;
206 UNICODE_STRING SymbolicLink;
207
208 Status = IoRegisterDeviceInterface(DeviceObject, &KSCATEGORY_PREFERRED_MIDIOUT_DEVICE, NULL, &SymbolicLink);
209 if (NT_SUCCESS(Status))
210 {
211 IoSetDeviceInterfaceState(&SymbolicLink, TRUE);
212 RtlFreeUnicodeString(&SymbolicLink);
213 }
214 else
215 {
216 DPRINT("Failed to register KSCATEGORY_PREFERRED_MIDIOUT_DEVICE interface Status %x\n", Status);
217 return Status;
218 }
219
220 Status = IoRegisterDeviceInterface(DeviceObject, &KSCATEGORY_PREFERRED_WAVEIN_DEVICE, NULL, &SymbolicLink);
221 if (NT_SUCCESS(Status))
222 {
223 IoSetDeviceInterfaceState(&SymbolicLink, TRUE);
224 RtlFreeUnicodeString(&SymbolicLink);
225 }
226 else
227 {
228 DPRINT("Failed to register KSCATEGORY_PREFERRED_WAVEIN_DEVICE interface Status %x\n", Status);
229 return Status;
230 }
231
232 Status = IoRegisterDeviceInterface(DeviceObject, &KSCATEGORY_PREFERRED_WAVEOUT_DEVICE, NULL, &SymbolicLink);
233 if (NT_SUCCESS(Status))
234 {
235 IoSetDeviceInterfaceState(&SymbolicLink, TRUE);
236 RtlFreeUnicodeString(&SymbolicLink);
237 }
238 else
239 {
240 DPRINT("Failed to register KSCATEGORY_PREFERRED_WAVEOUT_DEVICE interface Status %x\n", Status);
241 }
242
243 Status = IoRegisterDeviceInterface(DeviceObject, &KSCATEGORY_SYSAUDIO, NULL, &SymbolicLink);
244 if (NT_SUCCESS(Status))
245 {
246 IoSetDeviceInterfaceState(&SymbolicLink, TRUE);
247 RtlFreeUnicodeString(&SymbolicLink);
248 }
249 else
250 {
251 DPRINT("Failed to register KSCATEGORY_SYSAUDIO interface Status %x\n", Status);
252 }
253
254 return Status;
255 }
256