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