1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/stream/driver.c
5 * PURPOSE: WDM Codec Class Driver
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "stream.h"
10
11 NTSTATUS
12 NTAPI
StreamClassAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PhysicalDeviceObject)13 StreamClassAddDevice(
14 IN PDRIVER_OBJECT DriverObject,
15 IN PDEVICE_OBJECT PhysicalDeviceObject)
16 {
17 PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension;
18 PDEVICE_OBJECT DeviceObject, LowerDeviceObject;
19 PSTREAM_DEVICE_EXTENSION DeviceExtension;
20 PKSOBJECT_CREATE_ITEM ItemList;
21 NTSTATUS Status;
22
23 /* Fetch driver object extension */
24 DriverObjectExtension = IoGetDriverObjectExtension(DriverObject, (PVOID)StreamClassAddDevice);
25 if (!DriverObjectExtension)
26 {
27 /* Failed to get driver extension */
28 return STATUS_DEVICE_DOES_NOT_EXIST;
29 }
30 /* Allocate Create Item */
31 ItemList = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
32 if (!ItemList)
33 {
34 /* Failed to allocated Create Item */
35 return STATUS_INSUFFICIENT_RESOURCES;
36 }
37
38 /* Create the FDO */
39 Status = IoCreateDevice(DriverObject, DriverObjectExtension->Data.DeviceExtensionSize + sizeof(STREAM_DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, 0, &DeviceObject);
40 if (!NT_SUCCESS(Status))
41 {
42 /* Failed to create the FDO */
43 ExFreePool(ItemList);
44 return Status;
45 }
46
47 /* Attach to device stack */
48 LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
49 if (!LowerDeviceObject)
50 {
51 /* Failed to attach */
52 IoDeleteDevice(DeviceObject);
53 ExFreePool(ItemList);
54 return STATUS_UNSUCCESSFUL;
55 }
56
57 /* Zero Create item */
58 RtlZeroMemory(ItemList, sizeof(KSOBJECT_CREATE_ITEM));
59 /* Setup object class */
60 RtlInitUnicodeString(&ItemList->ObjectClass, L"GLOBAL");
61 /* Setup CreateDispatch routine */
62 ItemList->Create = StreamClassCreateFilter;
63
64 /* Get device extension */
65 DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
66 /* Zero device extension */
67 RtlZeroMemory(DeviceExtension, sizeof(STREAM_DEVICE_EXTENSION));
68 /* Initialize Ks streaming */
69 Status = KsAllocateDeviceHeader(&DeviceExtension->Header, 1, ItemList);
70 if (!NT_SUCCESS(Status))
71 {
72 /* Cleanup resources */
73 IoDetachDevice(LowerDeviceObject);
74 IoDeleteDevice(DeviceObject);
75 ExFreePool(ItemList);
76 return Status;
77 }
78
79 /* Store lower device object */
80 DeviceExtension->LowerDeviceObject = LowerDeviceObject;
81
82 /* Store physical device object */
83 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
84 /* Store driver object extension */
85 DeviceExtension->DriverExtension = DriverObjectExtension;
86 /* Initialize memory list */
87 InitializeListHead(&DeviceExtension->MemoryResourceList);
88 /* Setup device extension */
89 DeviceExtension->DeviceExtension = (PVOID) (DeviceExtension + 1);
90 /* Init interrupt dpc */
91 KeInitializeDpc(&DeviceExtension->InterruptDpc, StreamClassInterruptDpc, (PVOID)DeviceExtension);
92
93 /* Set device transfer method */
94 DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
95 /* Clear init flag */
96 DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
97
98 return Status;
99 }
100
101 /*
102 *@implemented
103 */
104 NTSTATUS
105 STREAMAPI
StreamClassRegisterAdapter(IN PVOID Argument1,IN PVOID Argument2,IN PHW_INITIALIZATION_DATA HwInitializationData)106 StreamClassRegisterAdapter(
107 IN PVOID Argument1,
108 IN PVOID Argument2,
109 IN PHW_INITIALIZATION_DATA HwInitializationData)
110 {
111 NTSTATUS Status;
112 PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension;
113 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
114
115 /* Allocate driver extension */
116 Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)StreamClassAddDevice, sizeof(STREAM_CLASS_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
117 if (!NT_SUCCESS(Status))
118 {
119 /* Failed to allocate */
120 return STATUS_INSUFFICIENT_RESOURCES;
121 }
122
123 /* Zero driver object extension */
124 RtlZeroMemory(DriverObjectExtension, sizeof(STREAM_CLASS_DRIVER_EXTENSION));
125
126 /* copy HwInitializationData */
127 RtlCopyMemory(&DriverObjectExtension->Data, HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
128
129 /* Setup device init methods */
130 DriverObject->DriverExtension->AddDevice = StreamClassAddDevice;
131 DriverObject->DriverUnload = KsNullDriverUnload;
132
133 /* Setup irp handlers */
134 DriverObject->MajorFunction[IRP_MJ_PNP] = StreamClassPnp;
135 DriverObject->MajorFunction[IRP_MJ_POWER] = StreamClassPower;
136 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = StreamClassSystemControl;
137 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = StreamClassCleanup;
138 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = StreamClassFlushBuffers;
139 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = StreamClassDeviceControl;
140
141 /* Let Ks handle these */
142 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
143 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
144
145 return STATUS_SUCCESS;
146 }
147
148 /*
149 *@implemented
150 */
151
152 VOID
153 NTAPI
StreamClassReenumerateStreams(IN PVOID HwDeviceExtension,IN ULONG StreamDescriptorSize)154 StreamClassReenumerateStreams(
155 IN PVOID HwDeviceExtension,
156 IN ULONG StreamDescriptorSize)
157 {
158 HW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
159 PSTREAM_DEVICE_EXTENSION DeviceExtension;
160 PHW_STREAM_DESCRIPTOR StreamDescriptor;
161
162 if (!HwDeviceExtension || !StreamDescriptorSize)
163 return;
164
165 StreamDescriptor = ExAllocatePool(NonPagedPool, StreamDescriptorSize);
166 if (!StreamDescriptor)
167 return;
168
169 /* Zero stream descriptor */
170 RtlZeroMemory(StreamDescriptor, StreamDescriptorSize);
171
172 /* Get our DeviceExtension */
173 DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION));
174 ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension);
175
176
177 /* Zero RequestBlock */
178 RtlZeroMemory(&RequestBlock, sizeof(HW_STREAM_REQUEST_BLOCK_EXT));
179
180 /* Setup get stream info struct */
181 RequestBlock.Block.SizeOfThisPacket = sizeof(HW_STREAM_REQUEST_BLOCK);
182 RequestBlock.Block.Command = SRB_GET_STREAM_INFO;
183 RequestBlock.Block.CommandData.StreamBuffer = StreamDescriptor;
184 KeInitializeEvent(&RequestBlock.Event, SynchronizationEvent, FALSE);
185
186 /* FIXME SYNCHRONIZATION */
187
188 /* Send the request */
189 DeviceExtension->DriverExtension->Data.HwReceivePacket ((PHW_STREAM_REQUEST_BLOCK)&RequestBlock);
190
191 /* Is the device already completed? */
192 if (RequestBlock.Block.Status == STATUS_PENDING)
193 {
194 /* Request is pending, wait for result */
195 KeWaitForSingleObject(&RequestBlock.Event, Executive, KernelMode, FALSE, NULL);
196 }
197
198 if (!NT_SUCCESS(RequestBlock.Block.Status))
199 {
200 /* Release Stream descriptor */
201 ExFreePool(StreamDescriptor);
202 }
203 else
204 {
205 if (DeviceExtension->StreamDescriptor)
206 {
207 /* Release old stream descriptor */
208 ExFreePool(DeviceExtension->StreamDescriptor);
209 }
210
211 /* Store stream descriptor */
212 DeviceExtension->StreamDescriptor = StreamDescriptor;
213 DeviceExtension->StreamDescriptorSize = StreamDescriptorSize;
214 }
215
216 }
217
218 /*
219 *@implemented
220 */
221
222 VOID
223 NTAPI
StreamClassDebugAssert(IN PCHAR File,IN ULONG Line,IN PCHAR AssertText,IN ULONG AssertValue)224 StreamClassDebugAssert(
225 IN PCHAR File,
226 IN ULONG Line,
227 IN PCHAR AssertText,
228 IN ULONG AssertValue)
229 {
230 #if DBG
231 DbgBreakPoint();
232 #endif
233 }
234
235 /*
236 *@implemented
237 */
238 VOID
239 __cdecl
StreamClassDebugPrint(IN STREAM_DEBUG_LEVEL DebugPrintLevel,IN PCCHAR DebugMessage,...)240 StreamClassDebugPrint(
241 IN STREAM_DEBUG_LEVEL DebugPrintLevel,
242 IN PCCHAR DebugMessage,
243 ...)
244 {
245 #if DBG
246 va_list ap;
247
248 if (DebugPrintLevel <=STREAMDEBUG_LEVEL)
249 {
250 va_start(ap, DebugMessage);
251
252 DbgPrint(DebugMessage, ap);
253
254 va_end(ap);
255 }
256 #endif
257
258 }
259
260 /*
261 *@unimplemented
262 */
263 VOID
264 __cdecl
StreamClassDeviceNotification(IN STREAM_MINIDRIVER_DEVICE_NOTIFICATION_TYPE NotificationType,IN PVOID HwDeviceExtension,IN PHW_STREAM_REQUEST_BLOCK pSrb,IN PKSEVENT_ENTRY EventEntry,IN GUID * EventSet,IN ULONG EventId)265 StreamClassDeviceNotification(
266 IN STREAM_MINIDRIVER_DEVICE_NOTIFICATION_TYPE NotificationType,
267 IN PVOID HwDeviceExtension,
268 IN PHW_STREAM_REQUEST_BLOCK pSrb,
269 IN PKSEVENT_ENTRY EventEntry,
270 IN GUID *EventSet,
271 IN ULONG EventId)
272 {
273 PHW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
274 if (NotificationType == DeviceRequestComplete)
275 {
276 RequestBlock = (PHW_STREAM_REQUEST_BLOCK_EXT)pSrb;
277
278 KeSetEvent(&RequestBlock->Event, 0, FALSE);
279 return;
280 }
281
282 UNIMPLEMENTED;
283 }
284
285 /*
286 *@implemented
287 */
288 PVOID
289 STREAMAPI
StreamClassGetDmaBuffer(IN PVOID HwDeviceExtension)290 StreamClassGetDmaBuffer(
291 IN PVOID HwDeviceExtension)
292 {
293 PSTREAM_DEVICE_EXTENSION DeviceExtension;
294
295 /* Get our DeviceExtension */
296 DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION));
297 ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension);
298
299 return DeviceExtension->DmaCommonBuffer;
300 }
301
302 NTSTATUS
303 NTAPI
StreamClassRWCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)304 StreamClassRWCompletion(
305 IN PDEVICE_OBJECT DeviceObject,
306 IN PIRP Irp,
307 IN PVOID Context)
308 {
309 PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
310
311 IoStatusBlock->Information = Irp->IoStatus.Information;
312 IoStatusBlock->Status = Irp->IoStatus.Status;
313
314 return STATUS_SUCCESS;
315 }
316
317 /*
318 *@implemented
319 */
320 BOOLEAN
321 STREAMAPI
StreamClassReadWriteConfig(IN PVOID HwDeviceExtension,IN BOOLEAN Read,IN PVOID Buffer,IN ULONG OffSet,IN ULONG Length)322 StreamClassReadWriteConfig(
323 IN PVOID HwDeviceExtension,
324 IN BOOLEAN Read,
325 IN PVOID Buffer,
326 IN ULONG OffSet,
327 IN ULONG Length)
328 {
329 PIRP Irp;
330 ULONG MajorFunction;
331 KEVENT Event;
332 PSTREAM_DEVICE_EXTENSION DeviceExtension;
333 LARGE_INTEGER Offset;
334 IO_STATUS_BLOCK StatusBlock;
335 NTSTATUS Status;
336
337 /* Get our DeviceExtension */
338 DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION));
339 ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension);
340
341 if (Read)
342 {
343 /* Zero input buffer */
344 RtlZeroMemory(Buffer, Length);
345 }
346
347 /* Set request type */
348 MajorFunction = (Read ? IRP_MJ_READ : IRP_MJ_WRITE);
349
350 /* Initialize event */
351 KeInitializeEvent(&Event, NotificationEvent, FALSE);
352
353 /* Set offset */
354 Offset.QuadPart = OffSet;
355
356 /* Pre-init status block */
357 StatusBlock.Status = STATUS_NOT_SUPPORTED;
358
359 /* Create Irp */
360 Irp = IoBuildSynchronousFsdRequest(MajorFunction,
361 DeviceExtension->LowerDeviceObject, /* Verify */
362 Buffer,
363 Length,
364 &Offset,
365 &Event,
366 &StatusBlock);
367
368 if (!Irp)
369 {
370 /* Failed to allocate memory */
371 return FALSE;
372 }
373
374 /* Setup a completion routine */
375 IoSetCompletionRoutine(Irp, StreamClassRWCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
376
377 /* Call driver */
378 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
379
380 if (Status == STATUS_PENDING)
381 {
382 /* Request is pending, wait for result */
383 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
384 /* Fetch result */
385 Status = StatusBlock.Status;
386 }
387
388 if (!NT_SUCCESS(Status))
389 {
390 return FALSE;
391 }
392
393 /* FIXME Handle Length != InputLength */
394 return TRUE;
395 }
396