xref: /reactos/drivers/wdm/audio/legacy/stream/filter.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/filter.c
5  * PURPOSE:         filter instance handling
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 
10 #include "stream.h"
11 
12 
13 NTSTATUS
14 NTAPI
StreamClassCreatePin(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)15 StreamClassCreatePin(
16     IN  PDEVICE_OBJECT DeviceObject,
17     IN  PIRP Irp)
18 {
19     UNIMPLEMENTED;
20 
21     Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
22     Irp->IoStatus.Information = 0;
23     IoCompleteRequest(Irp, IO_NO_INCREMENT);
24     return STATUS_NOT_IMPLEMENTED;
25 }
26 
27 
28 NTSTATUS
29 NTAPI
FilterDispatch_fnDeviceIoControl(PDEVICE_OBJECT DeviceObject,PIRP Irp)30 FilterDispatch_fnDeviceIoControl(
31     PDEVICE_OBJECT DeviceObject,
32     PIRP Irp)
33 {
34     DPRINT1("FilterDispatch Called\n");
35 
36     Irp->IoStatus.Status = STATUS_SUCCESS;
37     Irp->IoStatus.Information = 0;
38     IoCompleteRequest(Irp, IO_NO_INCREMENT);
39     return STATUS_SUCCESS;
40 }
41 
42 
43 NTSTATUS
44 NTAPI
FilterDispatch_fnClose(PDEVICE_OBJECT DeviceObject,PIRP Irp)45 FilterDispatch_fnClose(
46     PDEVICE_OBJECT DeviceObject,
47     PIRP Irp)
48 {
49     NTSTATUS Status = STATUS_SUCCESS;
50     PSTREAM_DEVICE_EXTENSION DeviceExtension;
51     HW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
52 
53    /* Get device extension */
54     DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
55 
56     if (!DeviceExtension->DriverExtension->Data.FilterInstanceExtensionSize)
57     {
58         /* driver supports only one instance */
59         if (DeviceExtension->InstanceCount)
60         {
61             /* there is already one instance open */
62             return STATUS_UNSUCCESSFUL;
63         }
64     }
65     else
66     {
67         /* driver supports more than one filter instance */
68         RtlZeroMemory(&RequestBlock, sizeof(HW_STREAM_REQUEST_BLOCK_EXT));
69 
70         /* set up request block */
71         RequestBlock.Block.Command = SRB_CLOSE_DEVICE_INSTANCE;
72         RequestBlock.Block.HwDeviceExtension = DeviceExtension->DeviceExtension;
73         RequestBlock.Block.Irp = Irp;
74         KeInitializeEvent(&RequestBlock.Event, SynchronizationEvent, FALSE);
75 
76         /*FIXME SYNCHRONIZATION */
77 
78         /* Send the request */
79         DeviceExtension->DriverExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)&RequestBlock);
80         if (RequestBlock.Block.Status == STATUS_PENDING)
81         {
82             /* Wait for the request */
83             KeWaitForSingleObject(&RequestBlock.Event, Executive, KernelMode, FALSE, NULL);
84         }
85     }
86 
87     /* Increment total instance count */
88     InterlockedDecrement(&DeviceExtension->InstanceCount);
89 
90     Irp->IoStatus.Status = Status;
91     Irp->IoStatus.Information = 0;
92     IoCompleteRequest(Irp, IO_NO_INCREMENT);
93     return Status;
94 }
95 
96 static KSDISPATCH_TABLE DispatchTable =
97 {
98     FilterDispatch_fnDeviceIoControl,
99     KsDispatchInvalidDeviceRequest,
100     KsDispatchInvalidDeviceRequest,
101     KsDispatchInvalidDeviceRequest,
102     FilterDispatch_fnClose,
103     NULL,
104     NULL,
105     NULL,
106     NULL,
107     NULL
108 };
109 
110 VOID
RegisterDeviceInterfaces(IN PSTREAM_DEVICE_EXTENSION DeviceExtension)111 RegisterDeviceInterfaces(
112     IN PSTREAM_DEVICE_EXTENSION DeviceExtension)
113 {
114     ULONG Index;
115     PHW_STREAM_INFORMATION StreamInformation;
116     UNICODE_STRING SymbolicLink;
117     NTSTATUS Status;
118 
119     /* Sanity check */
120     ASSERT(DeviceExtension->StreamDescriptor);
121     ASSERT(DeviceExtension->StreamDescriptorSize);
122 
123     /* Loop all stream descriptors and register device interfaces */
124     StreamInformation = (PHW_STREAM_INFORMATION)&DeviceExtension->StreamDescriptor->StreamInfo;
125 
126     for(Index = 0; DeviceExtension->StreamDescriptor->StreamHeader.NumberOfStreams; Index++)
127     {
128         if (StreamInformation->Category)
129         {
130             /* Register device interface */
131             Status = IoRegisterDeviceInterface(DeviceExtension->PhysicalDeviceObject,
132                                                StreamInformation->Category,
133                                                NULL, /* see CORE-4218 and r42457 */
134                                                &SymbolicLink);
135 
136             if (NT_SUCCESS(Status))
137             {
138                 /* Activate device interface */
139                 IoSetDeviceInterfaceState(&SymbolicLink, TRUE);
140                 /* Release Symbolic Link */
141                 RtlFreeUnicodeString(&SymbolicLink);
142             }
143         }
144         StreamInformation = (PHW_STREAM_INFORMATION) (ULONG_PTR)StreamInformation + DeviceExtension->StreamDescriptor->StreamHeader.SizeOfHwStreamInformation;
145     }
146 
147 }
148 
149 NTSTATUS
InitializeFilterWithKs(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)150 InitializeFilterWithKs(
151     IN PDEVICE_OBJECT DeviceObject,
152     IN PIRP Irp)
153 {
154     NTSTATUS Status;
155     PSTREAM_DEVICE_EXTENSION DeviceExtension;
156     KSOBJECT_HEADER ObjectHeader;
157     PKSOBJECT_CREATE_ITEM CreateItem;
158     PIO_STACK_LOCATION IoStack;
159     HW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
160     PVOID HwInstanceExtension = NULL;
161 
162    /* Get device extension */
163     DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
164 
165     if (!DeviceExtension->DriverExtension->Data.FilterInstanceExtensionSize)
166     {
167         /* driver supports only one instance */
168         if (DeviceExtension->InstanceCount)
169         {
170             /* there is already one instance open */
171             return STATUS_UNSUCCESSFUL;
172         }
173     }
174     else
175     {
176         /* driver supports more than one filter instance */
177         RtlZeroMemory(&RequestBlock, sizeof(HW_STREAM_REQUEST_BLOCK_EXT));
178 
179         /* allocate instance extension */
180         HwInstanceExtension = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->Data.FilterInstanceExtensionSize);
181         if (!HwInstanceExtension)
182         {
183             /* Not enough memory */
184             return STATUS_INSUFFICIENT_RESOURCES;
185         }
186 
187         /* Zero instance extension */
188         RtlZeroMemory(HwInstanceExtension, DeviceExtension->DriverExtension->Data.FilterInstanceExtensionSize);
189 
190         /* set up request block */
191         RequestBlock.Block.Command = SRB_OPEN_DEVICE_INSTANCE;
192         RequestBlock.Block.HwDeviceExtension = DeviceExtension->DeviceExtension;
193         RequestBlock.Block.Irp = Irp;
194         RequestBlock.Block.HwInstanceExtension = HwInstanceExtension;
195         KeInitializeEvent(&RequestBlock.Event, SynchronizationEvent, FALSE);
196 
197         /*FIXME SYNCHRONIZATION */
198 
199         /* Send the request */
200         DeviceExtension->DriverExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)&RequestBlock);
201         if (RequestBlock.Block.Status == STATUS_PENDING)
202         {
203             /* Wait for the request */
204             KeWaitForSingleObject(&RequestBlock.Event, Executive, KernelMode, FALSE, NULL);
205         }
206         /* Check for success */
207         if (!NT_SUCCESS(RequestBlock.Block.Status))
208         {
209             /* Resource is not available */
210             ExFreePool(HwInstanceExtension);
211             return RequestBlock.Block.Status;
212         }
213     }
214 
215     /* Allocate create item */
216     CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
217     if (!CreateItem)
218     {
219         /* not enough memory */
220         return STATUS_INSUFFICIENT_RESOURCES;
221     }
222 
223     /* Zero create item */
224     RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
225     /* Initialize createitem */
226     RtlInitUnicodeString(&CreateItem->ObjectClass, KSSTRING_Pin);
227     CreateItem->Create = StreamClassCreatePin;
228 
229     /* Get current irp stack location */
230     IoStack = IoGetCurrentIrpStackLocation(Irp);
231     /* Create Ks streaming object header */
232     Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);
233     if (!NT_SUCCESS(Status))
234     {
235         /* Failed to create header */
236         ExFreePool(CreateItem);
237         if (HwInstanceExtension)
238         {
239             /* free instance buffer */
240             ExFreePool(HwInstanceExtension);
241         }
242         return Status;
243     }
244 
245     /* Store instance buffer in file object context */
246     IoStack->FileObject->FsContext2 = HwInstanceExtension;
247 
248     /* Increment total instance count */
249     InterlockedIncrement(&DeviceExtension->InstanceCount);
250 
251     /* Register device stream interfaces */
252     RegisterDeviceInterfaces(DeviceExtension);
253 
254     /* Return result */
255     return Status;
256 
257 }
258 
259 NTSTATUS
260 NTAPI
StreamClassCreateFilter(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)261 StreamClassCreateFilter(
262     IN  PDEVICE_OBJECT DeviceObject,
263     IN  PIRP Irp)
264 {
265     NTSTATUS Status;
266     DPRINT1("StreamClassCreateFilter Called\n");
267 
268     /* Init filter */
269     Status = InitializeFilterWithKs(DeviceObject, Irp);
270 
271     Irp->IoStatus.Status = Status;
272     Irp->IoStatus.Information = 0;
273     IoCompleteRequest(Irp, IO_NO_INCREMENT);
274     return Status;
275 }
276 
277 
278 
279