xref: /reactos/drivers/wdm/audio/legacy/stream/driver.c (revision c2c66aff)
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