[WDMAUD]
[reactos.git] / reactos / drivers / wdm / audio / legacy / wdmaud / entry.c
1 /*
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
7 * Johannes Anderwald
8 */
9 #include "wdmaud.h"
10
11 const GUID KSCATEGORY_SYSAUDIO = {0xA7C7A5B1L, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}};
12 const GUID KSCATEGORY_WDMAUD = {0x3E227E76L, 0x690D, 0x11D2, {0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1}};
13
14 NTSTATUS
15 NTAPI
16 WdmAudInstallDevice(
17 IN PDRIVER_OBJECT DriverObject)
18 {
19 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\wdmaud");
20 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\wdmaud");
21 PDEVICE_OBJECT DeviceObject;
22 NTSTATUS Status;
23 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
24
25 DPRINT1("WdmAudInstallDevice called\n");
26
27 Status = IoCreateDevice(DriverObject,
28 sizeof(WDMAUD_DEVICE_EXTENSION),
29 &DeviceName,
30 FILE_DEVICE_KS,
31 0,
32 FALSE,
33 &DeviceObject);
34
35 if (!NT_SUCCESS(Status))
36 {
37 DPRINT1("IoCreateDevice failed with %x\n", Status);
38 return Status;
39 }
40
41 /* clear device extension */
42 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
43 RtlZeroMemory(DeviceExtension, sizeof(WDMAUD_DEVICE_EXTENSION));
44
45 /* register device interfaces */
46 Status = WdmAudRegisterDeviceInterface(DeviceObject, DeviceExtension);
47 if (!NT_SUCCESS(Status))
48 {
49 DPRINT1("WdmRegisterDeviceInterface failed with %x\n", Status);
50 IoDeleteDevice(DeviceObject);
51 return Status;
52 }
53
54 /* initialize sysaudio device list */
55 InitializeListHead(&DeviceExtension->SysAudioDeviceList);
56
57 /* initialize spinlock */
58 KeInitializeSpinLock(&DeviceExtension->Lock);
59
60 /* find available sysaudio devices */
61 Status = WdmAudOpenSysAudioDevices(DeviceObject, DeviceExtension);
62 if (!NT_SUCCESS(Status))
63 {
64 DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status);
65 IoDeleteSymbolicLink(&SymlinkName);
66 IoDeleteDevice(DeviceObject);
67 return Status;
68 }
69 /* allocate ks device header */
70 Status = KsAllocateDeviceHeader(&DeviceExtension->DeviceHeader, 0, NULL);
71 if (!NT_SUCCESS(Status))
72 {
73 DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status);
74 IoDeleteSymbolicLink(&SymlinkName);
75 IoDeleteDevice(DeviceObject);
76 return Status;
77 }
78
79 Status = WdmAudMixerInitialize(DeviceObject);
80 DPRINT("WdmAudMixerInitialize Status %x\n", Status);
81 Status = WdmAudWaveInitialize(DeviceObject);
82 DPRINT("WdmAudWaveInitialize Status %x\n", Status);
83
84 DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
85 DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
86
87 return STATUS_SUCCESS;
88 }
89
90 VOID
91 NTAPI
92 WdmAudUnload(
93 IN PDRIVER_OBJECT driver)
94 {
95 DPRINT1("WdmAudUnload called\n");
96 }
97
98 NTSTATUS
99 NTAPI
100 WdmAudPnp(
101 IN PDEVICE_OBJECT DeviceObject,
102 IN PIRP Irp)
103 {
104 PIO_STACK_LOCATION IrpStack;
105
106 DPRINT("WdmAudPnp called\n");
107
108 IrpStack = IoGetCurrentIrpStackLocation(Irp);
109
110 if (IrpStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
111 {
112 Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
113 return KsDefaultDispatchPnp(DeviceObject, Irp);
114 }
115 return KsDefaultDispatchPnp(DeviceObject, Irp);
116 }
117
118
119 NTSTATUS
120 NTAPI
121 WdmAudCreate(
122 IN PDEVICE_OBJECT DeviceObject,
123 IN PIRP Irp)
124 {
125 NTSTATUS Status;
126
127 PIO_STACK_LOCATION IoStack;
128 PWDMAUD_CLIENT pClient;
129
130 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
131
132 DPRINT("WdmAudCreate\n");
133
134 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
135
136 #if KS_IMPLEMENTED
137 Status = KsReferenceSoftwareBusObject((KSDEVICE_HEADER)DeviceObject->DeviceExtension);
138 if (!NT_SUCCESS(Status))
139 {
140 DPRINT1("KsReferenceSoftwareBusObject failed with %x\n", Status);
141 return Status;
142 }
143 #endif
144
145 Status = WdmAudOpenSysaudio(DeviceObject, &pClient);
146 if (!NT_SUCCESS(Status))
147 {
148 DPRINT1("Failed to open sysaudio!\n");
149 if (pClient)
150 ExFreePool(pClient);
151 }
152
153 IoStack = IoGetCurrentIrpStackLocation(Irp);
154 ASSERT(IoStack->FileObject);
155
156 /* store client context in file object */
157 IoStack->FileObject->FsContext = pClient;
158 Status = STATUS_SUCCESS;
159
160 Irp->IoStatus.Status = Status;
161 Irp->IoStatus.Information = 0;
162 IoCompleteRequest(Irp, IO_NO_INCREMENT);
163
164 return Status;
165 }
166
167 NTSTATUS
168 NTAPI
169 WdmAudClose(
170 IN PDEVICE_OBJECT DeviceObject,
171 IN PIRP Irp)
172 {
173 DPRINT("WdmAudClose\n");
174
175 #if KS_IMPLEMENTED
176 Status = KsDereferenceSoftwareBusObject(DeviceExtension->DeviceHeader);
177
178 if (NT_SUCCESS(Status))
179 {
180 if (DeviceExtension->SysAudioNotification)
181 Status = IoUnregisterPlugPlayNotification(DeviceExtension->SysAudioNotification);
182 }
183 #endif
184
185 Irp->IoStatus.Status = STATUS_SUCCESS;
186 Irp->IoStatus.Information = 0;
187 IoCompleteRequest(Irp, IO_NO_INCREMENT);
188
189 return STATUS_SUCCESS;
190 }
191
192 NTSTATUS
193 NTAPI
194 WdmAudCleanup(
195 IN PDEVICE_OBJECT DeviceObject,
196 IN PIRP Irp)
197 {
198 PIO_STACK_LOCATION IoStack;
199 WDMAUD_CLIENT *pClient;
200 ULONG Index;
201
202 DPRINT("WdmAudCleanup\n");
203
204 IoStack = IoGetCurrentIrpStackLocation(Irp);
205
206 pClient = (WDMAUD_CLIENT*)IoStack->FileObject->FsContext;
207
208 if (pClient)
209 {
210 for (Index = 0; Index < pClient->NumPins; Index++)
211 {
212 DPRINT("Index %u Pin %p Type %x\n", Index, pClient->hPins[Index].Handle, pClient->hPins[Index].Type);
213 if (pClient->hPins[Index].Handle && pClient->hPins[Index].Type != MIXER_DEVICE_TYPE)
214 {
215 ZwClose(pClient->hPins[Index].Handle);
216 }
217 }
218
219 if (pClient->hPins)
220 {
221 ExFreePool(pClient->hPins);
222 }
223
224 ExFreePool(pClient);
225 IoStack->FileObject->FsContext = NULL;
226 }
227
228 Irp->IoStatus.Status = STATUS_SUCCESS;
229 Irp->IoStatus.Information = 0;
230 IoCompleteRequest(Irp, IO_NO_INCREMENT);
231 DPRINT("WdmAudCleanup complete\n");
232 return STATUS_SUCCESS;
233 }
234
235
236
237 NTSTATUS NTAPI
238 DriverEntry(
239 IN PDRIVER_OBJECT Driver,
240 IN PUNICODE_STRING Registry_path
241 )
242 {
243 DPRINT1("Wdmaud.sys loaded\n");
244
245 Driver->DriverUnload = WdmAudUnload;
246
247 Driver->MajorFunction[IRP_MJ_CREATE] = WdmAudCreate;
248 Driver->MajorFunction[IRP_MJ_CLOSE] = WdmAudClose;
249 Driver->MajorFunction[IRP_MJ_PNP] = WdmAudPnp;
250 Driver->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
251 Driver->MajorFunction[IRP_MJ_CLEANUP] = WdmAudCleanup;
252 Driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WdmAudDeviceControl;
253 Driver->MajorFunction[IRP_MJ_WRITE] = WdmAudReadWrite;
254 Driver->MajorFunction[IRP_MJ_READ] = WdmAudReadWrite;
255 Driver->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
256
257 return WdmAudInstallDevice(Driver);
258 }