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