[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / connectivity.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/connectivity.c
5 * PURPOSE: KS Pin functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12 KSPIN_INTERFACE StandardPinInterface =
13 {
14 {STATIC_KSINTERFACESETID_Standard},
15 KSINTERFACE_STANDARD_STREAMING,
16 0
17 };
18
19 KSPIN_MEDIUM StandardPinMedium =
20 {
21 {STATIC_KSMEDIUMSETID_Standard},
22 KSMEDIUM_TYPE_ANYINSTANCE,
23 0
24 };
25
26
27 /*
28 @implemented
29 */
30 KSDDKAPI
31 NTSTATUS
32 NTAPI
33 KsCreatePin(
34 IN HANDLE FilterHandle,
35 IN PKSPIN_CONNECT Connect,
36 IN ACCESS_MASK DesiredAccess,
37 OUT PHANDLE ConnectionHandle)
38 {
39 UINT ConnectSize = sizeof(KSPIN_CONNECT);
40
41 PKSDATAFORMAT_WAVEFORMATEX Format = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1);
42 if (Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) ||
43 Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX))
44 {
45 ConnectSize += Format->DataFormat.FormatSize;
46 }
47
48 return KspCreateObjectType(FilterHandle,
49 KSSTRING_Pin,
50 (PVOID)Connect,
51 ConnectSize,
52 DesiredAccess,
53 ConnectionHandle);
54 }
55
56 /*
57 @unimplemented
58 */
59 KSDDKAPI
60 NTSTATUS
61 NTAPI
62 KsValidateConnectRequest(
63 IN PIRP Irp,
64 IN ULONG DescriptorsCount,
65 IN KSPIN_DESCRIPTOR* Descriptor,
66 OUT PKSPIN_CONNECT* Connect)
67 {
68 PKSPIN_CONNECT ConnectDetails;
69 PKSPIN_INTERFACE Interface;
70 PKSPIN_MEDIUM Medium;
71 ULONG Size;
72 NTSTATUS Status;
73 ULONG Index;
74 ULONG Count;
75 BOOLEAN Found;
76
77 /* did the caller miss the connect parameter */
78 if (!Connect)
79 return STATUS_INVALID_PARAMETER;
80
81 /* set create param size */
82 Size = sizeof(KSPIN_CONNECT);
83
84 /* fetch create parameters */
85 Status = KspCopyCreateRequest(Irp,
86 KSSTRING_Pin,
87 &Size,
88 (PVOID*)&ConnectDetails);
89
90 /* check for success */
91 if (!NT_SUCCESS(Status))
92 return Status;
93
94 /* is pin id out of bounds */
95 if (ConnectDetails->PinId >= DescriptorsCount)
96 return STATUS_INVALID_PARAMETER;
97
98 /* does the pin have interface details filled in */
99 if (Descriptor[ConnectDetails->PinId].InterfacesCount && Descriptor[ConnectDetails->PinId].Interfaces)
100 {
101 /* use provided pin interface count */
102 Count = Descriptor[ConnectDetails->PinId].InterfacesCount;
103 Interface = (PKSPIN_INTERFACE)Descriptor[ConnectDetails->PinId].Interfaces;
104 }
105 else
106 {
107 /* use standard pin interface */
108 Count = 1;
109 Interface = &StandardPinInterface;
110 }
111
112 /* now check the interface */
113 Found = FALSE;
114 Index = 0;
115 do
116 {
117 if (IsEqualGUIDAligned(&Interface[Index].Set, &ConnectDetails->Interface.Set) &&
118 Interface[Index].Id == ConnectDetails->Interface.Id)
119 {
120 /* found a matching interface */
121 Found = TRUE;
122 break;
123 }
124 /* iterate to next interface */
125 Index++;
126 }while(Index < Count);
127
128 if (!Found)
129 {
130 /* pin doesnt support this interface */
131 return STATUS_NO_MATCH;
132 }
133
134 /* does the pin have medium details filled in */
135 if (Descriptor[ConnectDetails->PinId].MediumsCount && Descriptor[ConnectDetails->PinId].Mediums)
136 {
137 /* use provided pin interface count */
138 Count = Descriptor[ConnectDetails->PinId].MediumsCount;
139 Medium = (PKSPIN_MEDIUM)Descriptor[ConnectDetails->PinId].Mediums;
140 }
141 else
142 {
143 /* use standard pin interface */
144 Count = 1;
145 Medium = &StandardPinMedium;
146 }
147
148 /* now check the interface */
149 Found = FALSE;
150 Index = 0;
151 do
152 {
153 if (IsEqualGUIDAligned(&Medium[Index].Set, &ConnectDetails->Medium.Set) &&
154 Medium[Index].Id == ConnectDetails->Medium.Id)
155 {
156 /* found a matching interface */
157 Found = TRUE;
158 break;
159 }
160 /* iterate to next medium */
161 Index++;
162 }while(Index < Count);
163
164 if (!Found)
165 {
166 /* pin doesnt support this medium */
167 return STATUS_NO_MATCH;
168 }
169
170 /// FIXME
171 /// implement format checking
172
173 *Connect = ConnectDetails;
174 return STATUS_SUCCESS;
175 }
176
177 /*
178 @implemented
179 */
180 KSDDKAPI
181 NTSTATUS
182 NTAPI
183 KsPinPropertyHandler(
184 IN PIRP Irp,
185 IN PKSPROPERTY Property,
186 IN OUT PVOID Data,
187 IN ULONG DescriptorsCount,
188 IN const KSPIN_DESCRIPTOR* Descriptor)
189 {
190 KSP_PIN * Pin;
191 KSMULTIPLE_ITEM * Item;
192 PIO_STACK_LOCATION IoStack;
193 ULONG Size, Index;
194 PVOID Buffer;
195 PKSDATARANGE_AUDIO *WaveFormatOut;
196 PKSDATAFORMAT_WAVEFORMATEX WaveFormatIn;
197 PULONG GuidBuffer;
198 static WCHAR Speaker[] = {L"PC-Speaker"};
199
200 IoStack = IoGetCurrentIrpStackLocation(Irp);
201 Buffer = Irp->UserBuffer;
202
203 DPRINT("KsPinPropertyHandler Irp %p Property %p Data %p DescriptorsCount %u Descriptor %p OutputLength %u Id %x\n", Irp, Property, Data, DescriptorsCount, Descriptor, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id);
204
205 switch(Property->Id)
206 {
207 case KSPROPERTY_PIN_CTYPES:
208 (*(PULONG)Buffer) = DescriptorsCount;
209 Irp->IoStatus.Information = sizeof(ULONG);
210 Irp->IoStatus.Status = STATUS_SUCCESS;
211 break;
212 case KSPROPERTY_PIN_DATAFLOW:
213 Pin = (KSP_PIN*)Property;
214 if (Pin->PinId >= DescriptorsCount)
215 {
216 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
217 Irp->IoStatus.Information = 0;
218 break;
219 }
220 Size = sizeof(KSPIN_DATAFLOW);
221 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
222 {
223 Irp->IoStatus.Information = Size;
224 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
225 break;
226 }
227
228 *((KSPIN_DATAFLOW*)Buffer) = Descriptor[Pin->PinId].DataFlow;
229 Irp->IoStatus.Information = sizeof(KSPIN_DATAFLOW);
230 Irp->IoStatus.Status = STATUS_SUCCESS;
231 break;
232
233 case KSPROPERTY_PIN_DATARANGES:
234 Pin = (KSP_PIN*)Property;
235 if (Pin->PinId >= DescriptorsCount)
236 {
237 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
238 Irp->IoStatus.Information = 0;
239 break;
240 }
241 Size = sizeof(KSMULTIPLE_ITEM);
242 for (Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
243 {
244 Size += Descriptor[Pin->PinId].DataRanges[Index]->FormatSize;
245 }
246
247 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
248 {
249 Irp->IoStatus.Information = Size;
250 Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
251 break;
252 }
253
254 Item = (KSMULTIPLE_ITEM*)Buffer;
255 Item->Size = Size;
256 Item->Count = Descriptor[Pin->PinId].DataRangesCount;
257
258 Data = (PUCHAR)(Item +1);
259 for (Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
260 {
261 RtlMoveMemory(Data, Descriptor[Pin->PinId].DataRanges[Index], Descriptor[Pin->PinId].DataRanges[Index]->FormatSize);
262 Data = ((PUCHAR)Data + Descriptor[Pin->PinId].DataRanges[Index]->FormatSize);
263 }
264
265 Irp->IoStatus.Status = STATUS_SUCCESS;
266 Irp->IoStatus.Information = Size;
267 break;
268 case KSPROPERTY_PIN_INTERFACES:
269 Pin = (KSP_PIN*)Property;
270 if (Pin->PinId >= DescriptorsCount)
271 {
272 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
273 Irp->IoStatus.Information = 0;
274 break;
275 }
276
277 /* calculate size */
278 Size = sizeof(KSMULTIPLE_ITEM);
279 Size += max(1, Descriptor[Pin->PinId].InterfacesCount) * sizeof(KSPIN_INTERFACE);
280
281 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
282 {
283 Irp->IoStatus.Information = Size;
284 Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
285 break;
286 }
287
288 Item = (KSMULTIPLE_ITEM*)Buffer;
289 Item->Size = Size;
290
291 if (Descriptor[Pin->PinId].InterfacesCount)
292 {
293 Item->Count = Descriptor[Pin->PinId].InterfacesCount;
294 RtlMoveMemory((PVOID)(Item + 1), Descriptor[Pin->PinId].Interfaces, Descriptor[Pin->PinId].InterfacesCount * sizeof(KSPIN_INTERFACE));
295 }
296 else
297 {
298 Item->Count = 1;
299 RtlMoveMemory((PVOID)(Item + 1), &StandardPinInterface, sizeof(KSPIN_INTERFACE));
300 }
301
302 Irp->IoStatus.Status = STATUS_SUCCESS;
303 Irp->IoStatus.Information = Size;
304 break;
305 case KSPROPERTY_PIN_MEDIUMS:
306 Pin = (KSP_PIN*)Property;
307 if (Pin->PinId >= DescriptorsCount)
308 {
309 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
310 Irp->IoStatus.Information = 0;
311 break;
312 }
313
314 /* calculate size */
315 Size = sizeof(KSMULTIPLE_ITEM);
316 Size += max(1, Descriptor[Pin->PinId].MediumsCount) * sizeof(KSPIN_MEDIUM);
317
318 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
319 {
320 Irp->IoStatus.Information = Size;
321 Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
322 break;
323 }
324
325 Item = (KSMULTIPLE_ITEM*)Buffer;
326 Item->Size = Size;
327
328 if (Descriptor[Pin->PinId].MediumsCount)
329 {
330 Item->Count = Descriptor[Pin->PinId].MediumsCount;
331 RtlMoveMemory((PVOID)(Item + 1), Descriptor[Pin->PinId].Mediums, Descriptor[Pin->PinId].MediumsCount * sizeof(KSPIN_MEDIUM));
332 }
333 else
334 {
335 Item->Count = 1;
336 RtlMoveMemory((PVOID)(Item + 1), &StandardPinMedium, sizeof(KSPIN_MEDIUM));
337 }
338
339 Irp->IoStatus.Status = STATUS_SUCCESS;
340 Irp->IoStatus.Information = Size;
341 break;
342
343 case KSPROPERTY_PIN_COMMUNICATION:
344 Pin = (KSP_PIN*)Property;
345 if (Pin->PinId >= DescriptorsCount)
346 {
347 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
348 Irp->IoStatus.Information = 0;
349 break;
350 }
351
352 Size = sizeof(KSPIN_COMMUNICATION);
353 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
354 {
355 Irp->IoStatus.Information = Size;
356 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
357 break;
358 }
359
360 *((KSPIN_COMMUNICATION*)Buffer) = Descriptor[Pin->PinId].Communication;
361 Irp->IoStatus.Status = STATUS_SUCCESS;
362 Irp->IoStatus.Information = Size;
363 break;
364
365 case KSPROPERTY_PIN_CATEGORY:
366 Pin = (KSP_PIN*)Property;
367 if (Pin->PinId >= DescriptorsCount)
368 {
369 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
370 Irp->IoStatus.Information = 0;
371 break;
372 }
373
374 Size = sizeof(GUID);
375 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
376 {
377 Irp->IoStatus.Information = Size;
378 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
379 break;
380 }
381
382 RtlMoveMemory(Buffer, &Descriptor[Pin->PinId].Category, sizeof(GUID));
383 Irp->IoStatus.Status = STATUS_SUCCESS;
384 Irp->IoStatus.Information = Size;
385 break;
386
387 case KSPROPERTY_PIN_NAME:
388 Pin = (KSP_PIN*)Property;
389 if (Pin->PinId >= DescriptorsCount)
390 {
391 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
392 Irp->IoStatus.Information = 0;
393 break;
394 }
395
396 GuidBuffer = Buffer;
397 Size = sizeof(Speaker);
398
399 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
400 {
401 Irp->IoStatus.Information = Size;
402 Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
403 break;
404 }
405
406 RtlMoveMemory(GuidBuffer, Speaker, sizeof(Speaker));
407
408 //RtlMoveMemory(Buffer, &Descriptor[Pin->PinId].Name, sizeof(GUID));
409 Irp->IoStatus.Status = STATUS_SUCCESS;
410 Irp->IoStatus.Information = Size;
411 break;
412 case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
413 Pin = (KSP_PIN*)Property;
414 if (Pin->PinId >= DescriptorsCount)
415 {
416 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
417 Irp->IoStatus.Information = 0;
418 break;
419 }
420 Size = sizeof(KSDATAFORMAT);
421 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
422 {
423 Irp->IoStatus.Information = Size;
424 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
425 break;
426 }
427 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(KSDATAFORMAT_WAVEFORMATEX))
428 {
429 UNIMPLEMENTED
430 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
431 Irp->IoStatus.Information = 0;
432 return STATUS_NOT_IMPLEMENTED;
433 }
434
435 WaveFormatIn = (PKSDATAFORMAT_WAVEFORMATEX)Buffer;
436 if (!Descriptor[Pin->PinId].DataRanges || !Descriptor[Pin->PinId].DataRangesCount)
437 {
438 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
439 Irp->IoStatus.Information = 0;
440 return STATUS_UNSUCCESSFUL;
441 }
442 WaveFormatOut = (PKSDATARANGE_AUDIO*)Descriptor[Pin->PinId].DataRanges;
443 for(Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
444 {
445 if (WaveFormatOut[Index]->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
446 {
447 UNIMPLEMENTED
448 continue;
449 }
450
451 if (WaveFormatOut[Index]->MinimumSampleFrequency > WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
452 WaveFormatOut[Index]->MaximumSampleFrequency < WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
453 WaveFormatOut[Index]->MinimumBitsPerSample > WaveFormatIn->WaveFormatEx.wBitsPerSample ||
454 WaveFormatOut[Index]->MaximumBitsPerSample < WaveFormatIn->WaveFormatEx.wBitsPerSample ||
455 WaveFormatOut[Index]->MaximumChannels < WaveFormatIn->WaveFormatEx.nChannels)
456 {
457 Irp->IoStatus.Status = STATUS_NO_MATCH;
458 Irp->IoStatus.Information = 0;
459 return STATUS_NO_MATCH;
460 }
461 else
462 {
463 Irp->IoStatus.Status = STATUS_SUCCESS;
464 Irp->IoStatus.Information = 0;
465 return STATUS_SUCCESS;
466 }
467 }
468 Irp->IoStatus.Status = STATUS_NO_MATCH;
469 Irp->IoStatus.Information = 0;
470 return STATUS_NO_MATCH;
471 default:
472 DPRINT1("Unhandled property request %x\n", Property->Id);
473 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
474 Irp->IoStatus.Information = 0;
475 }
476
477 return Irp->IoStatus.Status;
478 }
479
480 /*
481 @implemented
482 */
483 KSDDKAPI
484 NTSTATUS
485 NTAPI
486 KsPinDataIntersection(
487 IN PIRP Irp,
488 IN PKSP_PIN Pin,
489 OUT PVOID Data,
490 IN ULONG DescriptorsCount,
491 IN const KSPIN_DESCRIPTOR* Descriptor,
492 IN PFNKSINTERSECTHANDLER IntersectHandler)
493 {
494 KSMULTIPLE_ITEM * Item;
495 KSDATARANGE * DataRange;
496 PIO_STACK_LOCATION IoStack;
497 ULONG Size;
498 ULONG Index;
499 NTSTATUS Status;
500
501 /* get current irp stack location */
502 IoStack = IoGetCurrentIrpStackLocation(Irp);
503
504 /* calculate minimum data size */
505 Size = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATARANGE);
506 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Size)
507 {
508 /* buffer too small */
509 Irp->IoStatus.Information = Size;
510 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
511 return STATUS_BUFFER_TOO_SMALL;
512 }
513 /* is pin id out of bounds */
514 if (Pin->PinId >= DescriptorsCount)
515 {
516 /* it is */
517 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
518 Irp->IoStatus.Information = 0;
519 return STATUS_INVALID_PARAMETER;
520 }
521
522 /* get start item */
523 Item = (KSMULTIPLE_ITEM*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
524 /* get first data range */
525 DataRange = (KSDATARANGE*)(Item + 1);
526 /* iterate through all data ranges */
527 for(Index = 0; Index < Item->Count; Index++, DataRange++)
528 {
529 /* call intersect handler */
530 Status = IntersectHandler(Irp, Pin, DataRange, Data);
531 if (NT_SUCCESS(Status))
532 {
533 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize)
534 {
535 /* buffer is too small */
536 Irp->IoStatus.Information = DataRange->FormatSize;
537 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
538 return STATUS_BUFFER_TOO_SMALL;
539 }
540 RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE));
541 Irp->IoStatus.Information = sizeof(KSDATARANGE);
542 Irp->IoStatus.Status = STATUS_SUCCESS;
543 return STATUS_SUCCESS;
544 }
545
546 }
547
548 Irp->IoStatus.Information = 0;
549 Irp->IoStatus.Status = STATUS_NO_MATCH;
550 return STATUS_NO_MATCH;
551 }
552
553 /*
554 @implemented
555 */
556
557 KSDDKAPI
558 NTSTATUS
559 NTAPI
560 KsHandleSizedListQuery(
561 IN PIRP Irp,
562 IN ULONG DataItemsCount,
563 IN ULONG DataItemSize,
564 IN const VOID* DataItems)
565 {
566 ULONG Size;
567 PIO_STACK_LOCATION IoStack;
568 PKSMULTIPLE_ITEM Item;
569
570 /* get current irp stack location */
571 IoStack = IoGetCurrentIrpStackLocation(Irp);
572
573 Size = DataItemSize * DataItemsCount + sizeof(KSMULTIPLE_ITEM);
574
575
576 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Size)
577 {
578 /* buffer too small */
579 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
580 Irp->IoStatus.Information = Size;
581 return STATUS_BUFFER_TOO_SMALL;
582 }
583
584 /* get multiple item */
585 Item = (PKSMULTIPLE_ITEM)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
586
587 Item->Count = DataItemsCount;
588 Item->Size = DataItemSize;
589 /* copy items */
590 RtlMoveMemory((PVOID)(Item + 1), DataItems, DataItemSize * DataItemsCount);
591 /* store result */
592 Irp->IoStatus.Status = STATUS_SUCCESS;
593 Irp->IoStatus.Information = Size;
594 /* done */
595 return STATUS_SUCCESS;
596 }
597