f9df3e2d9819608d59d9006a8d8f1e7d3acab14a
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / propertyhandler.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/propertyhandler.cpp
5 * PURPOSE: Pin property handler
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 NTSTATUS
12 HandlePropertyInstances(
13 IN PIO_STATUS_BLOCK IoStatus,
14 IN PKSIDENTIFIER Request,
15 IN OUT PVOID Data,
16 IN PSUBDEVICE_DESCRIPTOR Descriptor,
17 IN BOOL Global)
18 {
19 KSPIN_CINSTANCES * Instances;
20 KSP_PIN * Pin = (KSP_PIN*)Request;
21
22 if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount)
23 {
24 IoStatus->Information = 0;
25 IoStatus->Status = STATUS_INVALID_PARAMETER;
26 return STATUS_INVALID_PARAMETER;
27 }
28
29 Instances = (KSPIN_CINSTANCES*)Data;
30
31 if (Global)
32 Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxGlobalInstanceCount;
33 else
34 Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxFilterInstanceCount;
35
36 Instances->CurrentCount = Descriptor->Factory.Instances[Pin->PinId].CurrentPinInstanceCount;
37
38 IoStatus->Information = sizeof(KSPIN_CINSTANCES);
39 IoStatus->Status = STATUS_SUCCESS;
40 return STATUS_SUCCESS;
41 }
42
43 NTSTATUS
44 HandleNecessaryPropertyInstances(
45 IN PIO_STATUS_BLOCK IoStatus,
46 IN PKSIDENTIFIER Request,
47 IN OUT PVOID Data,
48 IN PSUBDEVICE_DESCRIPTOR Descriptor)
49 {
50 PULONG Result;
51 KSP_PIN * Pin = (KSP_PIN*)Request;
52
53 if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount)
54 {
55 IoStatus->Information = 0;
56 IoStatus->Status = STATUS_INVALID_PARAMETER;
57 return STATUS_INVALID_PARAMETER;
58 }
59
60 Result = (PULONG)Data;
61 *Result = Descriptor->Factory.Instances[Pin->PinId].MinFilterInstanceCount;
62
63 IoStatus->Information = sizeof(ULONG);
64 IoStatus->Status = STATUS_SUCCESS;
65 return STATUS_SUCCESS;
66 }
67
68 NTSTATUS
69 HandleDataIntersection(
70 IN PIO_STATUS_BLOCK IoStatus,
71 IN PKSIDENTIFIER Request,
72 IN OUT PVOID Data,
73 IN ULONG DataLength,
74 IN PSUBDEVICE_DESCRIPTOR Descriptor,
75 IN ISubdevice *SubDevice)
76 {
77 KSP_PIN * Pin = (KSP_PIN*)Request;
78 PKSMULTIPLE_ITEM MultipleItem;
79 PKSDATARANGE DataRange;
80 NTSTATUS Status = STATUS_NO_MATCH;
81 ULONG Index, Length;
82
83 // Access parameters
84 MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
85 DataRange = (PKSDATARANGE)(MultipleItem + 1);
86
87 for(Index = 0; Index < MultipleItem->Count; Index++)
88 {
89 // Call miniport's properitary handler
90 PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRangesCount);
91 PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0]);
92 Status = SubDevice->DataRangeIntersection(Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0],
93 DataLength, Data, &Length);
94
95 if (Status == STATUS_SUCCESS)
96 {
97 IoStatus->Information = Length;
98 break;
99 }
100 DataRange = (PKSDATARANGE) UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
101 }
102
103 IoStatus->Status = Status;
104 return Status;
105 }
106
107 NTSTATUS
108 HandlePhysicalConnection(
109 IN PIO_STATUS_BLOCK IoStatus,
110 IN PKSIDENTIFIER Request,
111 IN ULONG RequestLength,
112 IN OUT PVOID Data,
113 IN ULONG DataLength,
114 IN PSUBDEVICE_DESCRIPTOR Descriptor)
115 {
116 PKSP_PIN Pin;
117 PLIST_ENTRY Entry;
118 PKSPIN_PHYSICALCONNECTION Connection;
119 PPHYSICAL_CONNECTION_ENTRY ConEntry;
120
121 // get pin
122 Pin = (PKSP_PIN)Request;
123
124 if (RequestLength < sizeof(KSP_PIN))
125 {
126 // input buffer must be at least sizeof KSP_PIN
127 DPRINT1("input length too small\n");
128 return STATUS_INVALID_PARAMETER;
129 }
130
131 if (IsListEmpty(&Descriptor->PhysicalConnectionList))
132 {
133 DPRINT1("no connection\n");
134 return STATUS_NOT_FOUND;
135 }
136
137 // get first item
138 Entry = Descriptor->PhysicalConnectionList.Flink;
139
140 do
141 {
142 ConEntry = (PPHYSICAL_CONNECTION_ENTRY)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION_ENTRY, Entry);
143
144 if (ConEntry->FromPin == Pin->PinId)
145 {
146 Connection = (PKSPIN_PHYSICALCONNECTION)Data;
147 DPRINT("FoundEntry %S Size %u\n", ConEntry->Connection.SymbolicLinkName, ConEntry->Connection.Size);
148 IoStatus->Information = ConEntry->Connection.Size;
149
150 if (!DataLength)
151 {
152 IoStatus->Information = ConEntry->Connection.Size;
153 return STATUS_MORE_ENTRIES;
154 }
155
156 if (DataLength < ConEntry->Connection.Size)
157 {
158 return STATUS_BUFFER_TOO_SMALL;
159 }
160
161 RtlMoveMemory(Data, &ConEntry->Connection, ConEntry->Connection.Size);
162 return STATUS_SUCCESS;
163 }
164
165 // move to next item
166 Entry = Entry->Flink;
167 }while(Entry != &Descriptor->PhysicalConnectionList);
168
169 IoStatus->Information = 0;
170 return STATUS_NOT_FOUND;
171 }
172
173 NTSTATUS
174 NTAPI
175 PinPropertyHandler(
176 IN PIRP Irp,
177 IN PKSIDENTIFIER Request,
178 IN OUT PVOID Data)
179 {
180 PIO_STACK_LOCATION IoStack;
181 //PKSOBJECT_CREATE_ITEM CreateItem;
182 PSUBDEVICE_DESCRIPTOR Descriptor;
183 IIrpTarget * IrpTarget;
184 IPort *Port;
185 ISubdevice *SubDevice;
186
187
188 NTSTATUS Status = STATUS_UNSUCCESSFUL;
189
190 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
191 PC_ASSERT(Descriptor);
192
193 // get current irp stack
194 IoStack = IoGetCurrentIrpStackLocation(Irp);
195
196 // Get the IrpTarget
197 IrpTarget = (IIrpTarget*)IoStack->FileObject->FsContext;
198 PC_ASSERT(IrpTarget);
199
200 // Get the parent
201 Status = IrpTarget->QueryInterface(IID_IPort, (PVOID*)&Port);
202 if (!NT_SUCCESS(Status))
203 {
204 DPRINT1("Failed to obtain IPort interface from filter\n");
205 Irp->IoStatus.Information = 0;
206 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
207 return STATUS_UNSUCCESSFUL;
208 }
209
210 // Get private ISubdevice interface
211 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice);
212 if (!NT_SUCCESS(Status))
213 {
214 DPRINT1("Failed to obtain ISubdevice interface from port driver\n");
215 KeBugCheck(0);
216 }
217
218 // get current stack location
219 IoStack = IoGetCurrentIrpStackLocation(Irp);
220
221 switch(Request->Id)
222 {
223 case KSPROPERTY_PIN_CTYPES:
224 case KSPROPERTY_PIN_DATAFLOW:
225 case KSPROPERTY_PIN_DATARANGES:
226 case KSPROPERTY_PIN_INTERFACES:
227 case KSPROPERTY_PIN_MEDIUMS:
228 case KSPROPERTY_PIN_COMMUNICATION:
229 case KSPROPERTY_PIN_CATEGORY:
230 case KSPROPERTY_PIN_NAME:
231 case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
232 Status = KsPinPropertyHandler(Irp, Request, Data, Descriptor->Factory.PinDescriptorCount, Descriptor->Factory.KsPinDescriptor);
233 break;
234 case KSPROPERTY_PIN_GLOBALCINSTANCES:
235 Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, TRUE);
236 break;
237 case KSPROPERTY_PIN_CINSTANCES:
238 Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, FALSE);
239 break;
240 case KSPROPERTY_PIN_NECESSARYINSTANCES:
241 Status = HandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, Descriptor);
242 break;
243
244 case KSPROPERTY_PIN_DATAINTERSECTION:
245 Status = HandleDataIntersection(&Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor, SubDevice);
246 break;
247 case KSPROPERTY_PIN_PHYSICALCONNECTION:
248 Status = HandlePhysicalConnection(&Irp->IoStatus, Request, IoStack->Parameters.DeviceIoControl.InputBufferLength, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor);
249 break;
250 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
251 UNIMPLEMENTED
252 Status = STATUS_NOT_IMPLEMENTED;
253 break;
254 default:
255 UNIMPLEMENTED
256 Status = STATUS_UNSUCCESSFUL;
257 }
258
259 // Release reference
260 Port->Release();
261
262 // Release subdevice reference
263 SubDevice->Release();
264
265 return Status;
266 }
267
268 NTSTATUS
269 NTAPI
270 TopologyPropertyHandler(
271 IN PIRP Irp,
272 IN PKSIDENTIFIER Request,
273 IN OUT PVOID Data)
274 {
275 PSUBDEVICE_DESCRIPTOR Descriptor;
276
277 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
278
279 return KsTopologyPropertyHandler(Irp, Request, Data, Descriptor->Topology);
280 }