56f6217e107d8230ba85572e37cf37c9a2332d04
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / pin_wavecyclic.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
5 * PURPOSE: WaveCyclic IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 class CPortPinWaveCyclic : public IPortPinWaveCyclic,
12 public IServiceSink
13 {
14 public:
15 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
16
17 STDMETHODIMP_(ULONG) AddRef()
18 {
19 InterlockedIncrement(&m_Ref);
20 return m_Ref;
21 }
22 STDMETHODIMP_(ULONG) Release()
23 {
24 InterlockedDecrement(&m_Ref);
25
26 if (!m_Ref)
27 {
28 delete this;
29 return 0;
30 }
31 return m_Ref;
32 }
33 IMP_IPortPinWaveCyclic;
34 IMP_IServiceSink;
35 CPortPinWaveCyclic(IUnknown *OuterUnknown){}
36 virtual ~CPortPinWaveCyclic(){}
37
38 VOID SetState(KSSTATE State);
39
40 protected:
41
42 VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount);
43 VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount);
44 NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
45 NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
46
47
48 friend NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
49 friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
50 friend NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
51 friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
52
53 IPortWaveCyclic * m_Port;
54 IPortFilterWaveCyclic * m_Filter;
55 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
56 PMINIPORTWAVECYCLIC m_Miniport;
57 PSERVICEGROUP m_ServiceGroup;
58 PDMACHANNEL m_DmaChannel;
59 PMINIPORTWAVECYCLICSTREAM m_Stream;
60 KSSTATE m_State;
61 PKSDATAFORMAT m_Format;
62 KSPIN_CONNECT * m_ConnectDetails;
63
64 PVOID m_CommonBuffer;
65 ULONG m_CommonBufferSize;
66 ULONG m_CommonBufferOffset;
67
68 IIrpQueue * m_IrpQueue;
69
70 ULONG m_FrameSize;
71 BOOL m_Capture;
72
73 ULONG m_TotalPackets;
74 ULONG m_StopCount;
75 KSAUDIO_POSITION m_Position;
76 KSALLOCATOR_FRAMING m_AllocatorFraming;
77 SUBDEVICE_DESCRIPTOR m_Descriptor;
78
79 ULONG m_Delay;
80
81 LONG m_Ref;
82 };
83
84
85 typedef struct
86 {
87 CPortPinWaveCyclic *Pin;
88 PIO_WORKITEM WorkItem;
89 KSSTATE State;
90 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
91
92 NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
93 NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
94 NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
95 NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
96
97 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
98 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
99
100 KSPROPERTY_SET PinWaveCyclicPropertySet[] =
101 {
102 {
103 &KSPROPSETID_Connection,
104 sizeof(PinWaveCyclicConnectionSet) / sizeof(KSPROPERTY_ITEM),
105 (const KSPROPERTY_ITEM*)&PinWaveCyclicConnectionSet,
106 0,
107 NULL
108 },
109 {
110 &KSPROPSETID_Audio,
111 sizeof(PinWaveCyclicAudioSet) / sizeof(KSPROPERTY_ITEM),
112 (const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet,
113 0,
114 NULL
115 }
116 };
117
118 //==================================================================================================================================
119
120 NTSTATUS
121 NTAPI
122 CPortPinWaveCyclic::QueryInterface(
123 IN REFIID refiid,
124 OUT PVOID* Output)
125 {
126 DPRINT("IServiceSink_fnQueryInterface entered\n");
127
128 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
129 IsEqualGUIDAligned(refiid, IID_IUnknown))
130 {
131 *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
132 PUNKNOWN(*Output)->AddRef();
133 return STATUS_SUCCESS;
134 }
135
136 if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
137 {
138 *Output = PVOID(PUNKNOWN(PSERVICESINK(this)));
139 PUNKNOWN(*Output)->AddRef();
140 return STATUS_SUCCESS;
141 }
142
143 return STATUS_UNSUCCESSFUL;
144 }
145
146 NTSTATUS
147 NTAPI
148 PinWaveCyclicAllocatorFraming(
149 IN PIRP Irp,
150 IN PKSIDENTIFIER Request,
151 IN OUT PVOID Data)
152 {
153 CPortPinWaveCyclic *Pin;
154 PSUBDEVICE_DESCRIPTOR Descriptor;
155
156 // get sub device descriptor
157 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
158
159 // sanity check
160 PC_ASSERT(Descriptor);
161 PC_ASSERT(Descriptor->PortPin);
162 PC_ASSERT_IRQL(DISPATCH_LEVEL);
163
164 // cast to pin impl
165 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
166
167
168 if (Request->Flags & KSPROPERTY_TYPE_GET)
169 {
170 // copy pin framing
171 RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
172
173 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
174 return STATUS_SUCCESS;
175 }
176
177 // not supported
178 return STATUS_NOT_SUPPORTED;
179 }
180
181 NTSTATUS
182 NTAPI
183 PinWaveCyclicAudioPosition(
184 IN PIRP Irp,
185 IN PKSIDENTIFIER Request,
186 IN OUT PVOID Data)
187 {
188 CPortPinWaveCyclic *Pin;
189 PSUBDEVICE_DESCRIPTOR Descriptor;
190
191 // get sub device descriptor
192 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
193
194 // sanity check
195 PC_ASSERT(Descriptor);
196 PC_ASSERT(Descriptor->PortPin);
197 PC_ASSERT_IRQL(DISPATCH_LEVEL);
198
199 // cast to pin impl
200 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
201
202 //sanity check
203 PC_ASSERT(Pin->m_Stream);
204
205 if (Request->Flags & KSPROPERTY_TYPE_GET)
206 {
207 // FIXME non multithreading-safe
208 // copy audio position
209 RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
210
211 DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
212 Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
213 return STATUS_SUCCESS;
214 }
215
216 // not supported
217 return STATUS_NOT_SUPPORTED;
218 }
219
220
221 NTSTATUS
222 NTAPI
223 PinWaveCyclicState(
224 IN PIRP Irp,
225 IN PKSIDENTIFIER Request,
226 IN OUT PVOID Data)
227 {
228 NTSTATUS Status = STATUS_UNSUCCESSFUL;
229 CPortPinWaveCyclic *Pin;
230 PSUBDEVICE_DESCRIPTOR Descriptor;
231 PKSSTATE State = (PKSSTATE)Data;
232
233 // get sub device descriptor
234 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
235
236 // sanity check
237 PC_ASSERT(Descriptor);
238 PC_ASSERT(Descriptor->PortPin);
239 PC_ASSERT_IRQL(DISPATCH_LEVEL);
240
241 // cast to pin impl
242 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
243
244 //sanity check
245 PC_ASSERT(Pin->m_Stream);
246
247 if (Request->Flags & KSPROPERTY_TYPE_SET)
248 {
249 // try set stream
250 Status = Pin->m_Stream->SetState(*State);
251
252 DPRINT("Setting state %u %x\n", *State, Status);
253 if (NT_SUCCESS(Status))
254 {
255 // store new state
256 Pin->m_State = *State;
257 }
258 // store result
259 Irp->IoStatus.Information = sizeof(KSSTATE);
260 return Status;
261 }
262 else if (Request->Flags & KSPROPERTY_TYPE_GET)
263 {
264 // get current stream state
265 *State = Pin->m_State;
266 // store result
267 Irp->IoStatus.Information = sizeof(KSSTATE);
268
269 return STATUS_SUCCESS;
270 }
271
272 // unsupported request
273 return STATUS_NOT_SUPPORTED;
274 }
275
276 NTSTATUS
277 NTAPI
278 PinWaveCyclicDataFormat(
279 IN PIRP Irp,
280 IN PKSIDENTIFIER Request,
281 IN OUT PVOID Data)
282 {
283 NTSTATUS Status = STATUS_UNSUCCESSFUL;
284 CPortPinWaveCyclic *Pin;
285 PSUBDEVICE_DESCRIPTOR Descriptor;
286 PIO_STACK_LOCATION IoStack;
287
288 // get current irp stack location
289 IoStack = IoGetCurrentIrpStackLocation(Irp);
290
291 // get sub device descriptor
292 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
293
294 // sanity check
295 PC_ASSERT(Descriptor);
296 PC_ASSERT(Descriptor->PortPin);
297
298 // cast to pin impl
299 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
300
301 //sanity check
302 PC_ASSERT(Pin->m_Stream);
303 PC_ASSERT(Pin->m_Format);
304
305 if (Request->Flags & KSPROPERTY_TYPE_SET)
306 {
307 // try to change data format
308 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
309 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
310
311 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
312 {
313 // format is identical
314 Irp->IoStatus.Information = DataFormat->FormatSize;
315 return STATUS_SUCCESS;
316 }
317
318 // new change request
319 PC_ASSERT(Pin->m_State == KSSTATE_STOP);
320 // FIXME queue a work item when Irql != PASSIVE_LEVEL
321 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
322
323 // allocate new data format
324 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
325 if (!NewDataFormat)
326 {
327 // not enough memory
328 return STATUS_NO_MEMORY;
329 }
330
331 // copy new data format
332 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
333
334 // set new format
335 Status = Pin->m_Stream->SetFormat(NewDataFormat);
336 if (NT_SUCCESS(Status))
337 {
338 // free old format
339 FreeItem(Pin->m_Format, TAG_PORTCLASS);
340
341 // update irp queue with new format
342 Pin->m_IrpQueue->UpdateFormat((PKSDATAFORMAT)NewDataFormat);
343
344 // store new format
345 Pin->m_Format = NewDataFormat;
346 Irp->IoStatus.Information = NewDataFormat->FormatSize;
347
348 #if 0
349 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
350 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
351 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
352 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
353
354
355 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
356 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
357 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
358 #endif
359
360 }
361 else
362 {
363 // failed to set format
364 FreeItem(NewDataFormat, TAG_PORTCLASS);
365 }
366
367
368 // done
369 return Status;
370 }
371 else if (Request->Flags & KSPROPERTY_TYPE_GET)
372 {
373 // get current data format
374 PC_ASSERT(Pin->m_Format);
375
376 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
377 {
378 // buffer too small
379 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
380 return STATUS_MORE_ENTRIES;
381 }
382 // copy data format
383 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
384 // store result size
385 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
386
387 // done
388 return STATUS_SUCCESS;
389 }
390
391 // unsupported request
392 return STATUS_NOT_SUPPORTED;
393 }
394
395
396 VOID
397 CPortPinWaveCyclic::UpdateCommonBuffer(
398 ULONG Position,
399 ULONG MaxTransferCount)
400 {
401 ULONG BufferLength;
402 ULONG BytesToCopy;
403 ULONG BufferSize;
404 PUCHAR Buffer;
405 NTSTATUS Status;
406
407 BufferLength = Position - m_CommonBufferOffset;
408 BufferLength = min(BufferLength, MaxTransferCount);
409
410 while(BufferLength)
411 {
412 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
413 if (!NT_SUCCESS(Status))
414 return;
415
416 BytesToCopy = min(BufferLength, BufferSize);
417
418 if (m_Capture)
419 {
420 m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
421 }
422 else
423 {
424 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
425 }
426
427 m_IrpQueue->UpdateMapping(BytesToCopy);
428 m_CommonBufferOffset += BytesToCopy;
429
430 BufferLength = Position - m_CommonBufferOffset;
431 m_Position.PlayOffset += BytesToCopy;
432 }
433 }
434
435 VOID
436 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
437 ULONG Position,
438 ULONG MaxTransferCount)
439 {
440 ULONG BufferLength, Length, Gap;
441 ULONG BytesToCopy;
442 ULONG BufferSize;
443 PUCHAR Buffer;
444 NTSTATUS Status;
445
446
447 BufferLength = Gap = m_CommonBufferSize - m_CommonBufferOffset;
448 BufferLength = Length = min(BufferLength, MaxTransferCount);
449 while(BufferLength)
450 {
451 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
452 if (!NT_SUCCESS(Status))
453 return;
454
455 BytesToCopy = min(BufferLength, BufferSize);
456
457 if (m_Capture)
458 {
459 m_DmaChannel->CopyFrom(Buffer,
460 (PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
461 BytesToCopy);
462 }
463 else
464 {
465 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
466 Buffer,
467 BytesToCopy);
468 }
469
470 m_IrpQueue->UpdateMapping(BytesToCopy);
471 m_CommonBufferOffset += BytesToCopy;
472 m_Position.PlayOffset += BytesToCopy;
473
474 BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
475 }
476
477 if (Gap == Length)
478 {
479 m_CommonBufferOffset = 0;
480
481 MaxTransferCount -= Length;
482
483 if (MaxTransferCount)
484 {
485 UpdateCommonBuffer(Position, MaxTransferCount);
486 }
487 }
488 }
489
490 VOID
491 NTAPI
492 CPortPinWaveCyclic::RequestService()
493 {
494 ULONG Position;
495 NTSTATUS Status;
496 PUCHAR Buffer;
497 ULONG BufferSize;
498
499 PC_ASSERT_IRQL(DISPATCH_LEVEL);
500
501 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
502 if (!NT_SUCCESS(Status))
503 {
504 return;
505 }
506
507 Status = m_Stream->GetPosition(&Position);
508 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
509
510 if (Position < m_CommonBufferOffset)
511 {
512 UpdateCommonBufferOverlap(Position, m_FrameSize);
513 }
514 else if (Position >= m_CommonBufferOffset)
515 {
516 UpdateCommonBuffer(Position, m_FrameSize);
517 }
518 }
519
520 NTSTATUS
521 NTAPI
522 CPortPinWaveCyclic::NewIrpTarget(
523 OUT struct IIrpTarget **OutTarget,
524 IN PCWSTR Name,
525 IN PUNKNOWN Unknown,
526 IN POOL_TYPE PoolType,
527 IN PDEVICE_OBJECT DeviceObject,
528 IN PIRP Irp,
529 IN KSOBJECT_CREATE *CreateObject)
530 {
531 UNIMPLEMENTED
532 return STATUS_UNSUCCESSFUL;
533 }
534
535 NTSTATUS
536 NTAPI
537 CPortPinWaveCyclic::HandleKsProperty(
538 IN PIRP Irp)
539 {
540 PKSPROPERTY Property;
541 NTSTATUS Status;
542 UNICODE_STRING GuidString;
543 PIO_STACK_LOCATION IoStack;
544
545 IoStack = IoGetCurrentIrpStackLocation(Irp);
546
547 DPRINT("IPortPinWave_HandleKsProperty entered\n");
548
549 IoStack = IoGetCurrentIrpStackLocation(Irp);
550
551 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
552 {
553 DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
554
555 Irp->IoStatus.Status = STATUS_SUCCESS;
556
557 IoCompleteRequest(Irp, IO_NO_INCREMENT);
558 return STATUS_SUCCESS;
559 }
560
561 Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
562
563 if (Status == STATUS_NOT_FOUND)
564 {
565 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
566
567 RtlStringFromGUID(Property->Set, &GuidString);
568 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
569 RtlFreeUnicodeString(&GuidString);
570 }
571
572 if (Status != STATUS_PENDING)
573 {
574 Irp->IoStatus.Status = Status;
575 IoCompleteRequest(Irp, IO_NO_INCREMENT);
576 }
577
578 return Status;
579 }
580
581 NTSTATUS
582 NTAPI
583 CPortPinWaveCyclic::HandleKsStream(
584 IN PIRP Irp)
585 {
586 NTSTATUS Status;
587 InterlockedIncrement((PLONG)&m_TotalPackets);
588
589 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
590
591 Status = m_IrpQueue->AddMapping(NULL, 0, Irp);
592
593 if (NT_SUCCESS(Status))
594 {
595
596 PKSSTREAM_HEADER Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
597 PC_ASSERT(Header);
598
599 if (m_Capture)
600 m_Position.WriteOffset += Header->FrameExtent;
601 else
602 m_Position.WriteOffset += Header->DataUsed;
603
604 return STATUS_PENDING;
605
606 }
607
608 return Status;
609 }
610
611 NTSTATUS
612 NTAPI
613 CPortPinWaveCyclic::DeviceIoControl(
614 IN PDEVICE_OBJECT DeviceObject,
615 IN PIRP Irp)
616 {
617 PIO_STACK_LOCATION IoStack;
618
619 IoStack = IoGetCurrentIrpStackLocation(Irp);
620
621
622 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
623 {
624 return HandleKsProperty(Irp);
625 }
626 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
627 {
628 /// FIXME
629 /// handle enable event
630 }
631 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
632 {
633 /// FIXME
634 /// handle disable event
635 }
636 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
637 {
638 /// FIXME
639 /// handle reset state
640 }
641 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
642 {
643 return HandleKsStream(Irp);
644 }
645 else
646 {
647 return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
648 }
649
650 UNIMPLEMENTED
651
652 Irp->IoStatus.Information = 0;
653 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
654 IoCompleteRequest(Irp, IO_NO_INCREMENT);
655
656 return STATUS_UNSUCCESSFUL;
657 }
658
659 NTSTATUS
660 NTAPI
661 CPortPinWaveCyclic::Read(
662 IN PDEVICE_OBJECT DeviceObject,
663 IN PIRP Irp)
664 {
665 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
666 }
667
668 NTSTATUS
669 NTAPI
670 CPortPinWaveCyclic::Write(
671 IN PDEVICE_OBJECT DeviceObject,
672 IN PIRP Irp)
673 {
674 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
675 }
676
677 NTSTATUS
678 NTAPI
679 CPortPinWaveCyclic::Flush(
680 IN PDEVICE_OBJECT DeviceObject,
681 IN PIRP Irp)
682 {
683 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
684 }
685
686 NTSTATUS
687 NTAPI
688 CPortPinWaveCyclic::Close(
689 IN PDEVICE_OBJECT DeviceObject,
690 IN PIRP Irp)
691 {
692 DPRINT("CPortPinWaveCyclic::Close entered\n");
693
694 PC_ASSERT_IRQL(PASSIVE_LEVEL);
695
696 if (m_Format)
697 {
698 // free format
699 ExFreePool(m_Format);
700 m_Format = NULL;
701 }
702
703 if (m_IrpQueue)
704 {
705 // fixme cancel irps
706 m_IrpQueue->Release();
707 }
708
709
710 if (m_Port)
711 {
712 // release reference to port driver
713 m_Port->Release();
714 m_Port = NULL;
715 }
716
717 if (m_ServiceGroup)
718 {
719 // remove member from service group
720 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
721 m_ServiceGroup = NULL;
722 }
723
724 if (m_Stream)
725 {
726 if (m_State != KSSTATE_STOP)
727 {
728 // stop stream
729 NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP);
730 if (!NT_SUCCESS(Status))
731 {
732 DPRINT("Warning: failed to stop stream with %x\n", Status);
733 PC_ASSERT(0);
734 }
735 }
736 // set state to stop
737 m_State = KSSTATE_STOP;
738
739
740 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
741 // release stream
742 m_Stream->Release();
743
744 }
745
746
747 if (m_Filter)
748 {
749 // release reference to filter instance
750 m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
751 m_Filter->Release();
752 m_Filter = NULL;
753 }
754
755 Irp->IoStatus.Information = 0;
756 Irp->IoStatus.Status = STATUS_SUCCESS;
757 IoCompleteRequest(Irp, IO_NO_INCREMENT);
758
759 delete this;
760
761 return STATUS_SUCCESS;
762 }
763
764 NTSTATUS
765 NTAPI
766 CPortPinWaveCyclic::QuerySecurity(
767 IN PDEVICE_OBJECT DeviceObject,
768 IN PIRP Irp)
769 {
770 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
771 }
772
773 NTSTATUS
774 NTAPI
775 CPortPinWaveCyclic::SetSecurity(
776 IN PDEVICE_OBJECT DeviceObject,
777 IN PIRP Irp)
778 {
779 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
780 }
781
782 BOOLEAN
783 NTAPI
784 CPortPinWaveCyclic::FastDeviceIoControl(
785 IN PFILE_OBJECT FileObject,
786 IN BOOLEAN Wait,
787 IN PVOID InputBuffer,
788 IN ULONG InputBufferLength,
789 OUT PVOID OutputBuffer,
790 IN ULONG OutputBufferLength,
791 IN ULONG IoControlCode,
792 OUT PIO_STATUS_BLOCK StatusBlock,
793 IN PDEVICE_OBJECT DeviceObject)
794 {
795 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
796 }
797
798
799 BOOLEAN
800 NTAPI
801 CPortPinWaveCyclic::FastRead(
802 IN PFILE_OBJECT FileObject,
803 IN PLARGE_INTEGER FileOffset,
804 IN ULONG Length,
805 IN BOOLEAN Wait,
806 IN ULONG LockKey,
807 IN PVOID Buffer,
808 OUT PIO_STATUS_BLOCK StatusBlock,
809 IN PDEVICE_OBJECT DeviceObject)
810 {
811 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
812 }
813
814
815 BOOLEAN
816 NTAPI
817 CPortPinWaveCyclic::FastWrite(
818 IN PFILE_OBJECT FileObject,
819 IN PLARGE_INTEGER FileOffset,
820 IN ULONG Length,
821 IN BOOLEAN Wait,
822 IN ULONG LockKey,
823 IN PVOID Buffer,
824 OUT PIO_STATUS_BLOCK StatusBlock,
825 IN PDEVICE_OBJECT DeviceObject)
826 {
827 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
828 }
829
830
831 NTSTATUS
832 NTAPI
833 CPortPinWaveCyclic::Init(
834 IN PPORTWAVECYCLIC Port,
835 IN PPORTFILTERWAVECYCLIC Filter,
836 IN KSPIN_CONNECT * ConnectDetails,
837 IN KSPIN_DESCRIPTOR * KsPinDescriptor)
838 {
839 NTSTATUS Status;
840 PKSDATAFORMAT DataFormat;
841 PDEVICE_OBJECT DeviceObject;
842 BOOLEAN Capture;
843 PVOID SilenceBuffer;
844 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
845 //IDrmAudioStream * DrmAudio = NULL;
846
847 m_KsPinDescriptor = KsPinDescriptor;
848 m_ConnectDetails = ConnectDetails;
849 m_Miniport = GetWaveCyclicMiniport(Port);
850
851 DeviceObject = GetDeviceObject(Port);
852
853 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
854
855 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize);
856
857 Status = NewIrpQueue(&m_IrpQueue);
858 if (!NT_SUCCESS(Status))
859 return Status;
860
861 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
862 {
863 Capture = FALSE;
864 }
865 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
866 {
867 Capture = TRUE;
868 }
869 else
870 {
871 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
872 DbgBreakPoint();
873 while(TRUE);
874 }
875
876
877 Status = m_Miniport->NewStream(&m_Stream,
878 NULL,
879 NonPagedPool,
880 ConnectDetails->PinId,
881 Capture,
882 DataFormat,
883 &m_DmaChannel,
884 &m_ServiceGroup);
885 #if 0
886 Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio);
887 if (NT_SUCCESS(Status))
888 {
889 DRMRIGHTS DrmRights;
890 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
891
892 DrmRights.CopyProtect = FALSE;
893 DrmRights.Reserved = 0;
894 DrmRights.DigitalOutputDisable = FALSE;
895
896 Status = DrmAudio->SetContentId(1, &DrmRights);
897 DPRINT("Status %x\n", Status);
898 }
899 #endif
900
901 DPRINT("CPortPinWaveCyclic::Init Status %x\n", Status);
902
903 if (!NT_SUCCESS(Status))
904 return Status;
905
906 ISubdevice * Subdevice = NULL;
907 // get subdevice interface
908 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
909
910 if (!NT_SUCCESS(Status))
911 return Status;
912
913 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
914 if (!NT_SUCCESS(Status))
915 {
916 // failed to get descriptor
917 Subdevice->Release();
918 return Status;
919 }
920
921 /* set up subdevice descriptor */
922 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
923 m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
924 m_Descriptor.FilterPropertySetCount = sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET);
925 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
926 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
927 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
928 m_Descriptor.PortPin = (PVOID)this;
929
930 // release subdevice descriptor
931 Subdevice->Release();
932
933 // add ourselves to service group
934 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
935 if (!NT_SUCCESS(Status))
936 {
937 DPRINT("Failed to add pin to service group\n");
938 return Status;
939 }
940
941 m_ServiceGroup->SupportDelayedService();
942 m_Stream->SetState(KSSTATE_STOP);
943 m_State = KSSTATE_STOP;
944 m_CommonBufferOffset = 0;
945 m_CommonBufferSize = m_DmaChannel->AllocatedBufferSize();
946 m_CommonBuffer = m_DmaChannel->SystemAddress();
947 m_Capture = Capture;
948 // delay of 10 milisec
949 m_Delay = Int32x32To64(10, -10000);
950
951 Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
952
953 SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
954 if (!SilenceBuffer)
955 return STATUS_INSUFFICIENT_RESOURCES;
956
957
958 /* set up allocator framing */
959 m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
960 m_AllocatorFraming.PoolType = NonPagedPool;
961 m_AllocatorFraming.Frames = 8;
962 m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT;
963 m_AllocatorFraming.Reserved = 0;
964 m_AllocatorFraming.FrameSize = m_FrameSize;
965
966 m_Stream->Silence(SilenceBuffer, m_FrameSize);
967
968 Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, m_FrameSize, 0, SilenceBuffer);
969 if (!NT_SUCCESS(Status))
970 {
971 m_IrpQueue->Release();
972 return Status;
973 }
974
975 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
976 if (!m_Format)
977 return STATUS_INSUFFICIENT_RESOURCES;
978
979 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
980
981 PKSDATAFORMAT_WAVEFORMATEX Wave = (PKSDATAFORMAT_WAVEFORMATEX)m_Format;
982
983 DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", Wave->WaveFormatEx.wBitsPerSample, Wave->WaveFormatEx.nSamplesPerSec, Wave->WaveFormatEx.nChannels, Wave->WaveFormatEx.wFormatTag, m_FrameSize);
984
985
986
987 Port->AddRef();
988 Filter->AddRef();
989
990 m_Port = Port;
991 m_Filter = Filter;
992
993 DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
994 DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
995
996 return STATUS_SUCCESS;
997 }
998
999
1000 ULONG
1001 NTAPI
1002 CPortPinWaveCyclic::GetCompletedPosition()
1003 {
1004 UNIMPLEMENTED;
1005 return 0;
1006 }
1007
1008
1009 ULONG
1010 NTAPI
1011 CPortPinWaveCyclic::GetCycleCount()
1012 {
1013 UNIMPLEMENTED;
1014 return 0;
1015 }
1016
1017
1018 ULONG
1019 NTAPI
1020 CPortPinWaveCyclic::GetDeviceBufferSize()
1021 {
1022 return m_CommonBufferSize;
1023 }
1024
1025
1026 PVOID
1027 NTAPI
1028 CPortPinWaveCyclic::GetIrpStream()
1029 {
1030 return (PVOID)m_IrpQueue;
1031 }
1032
1033
1034 PMINIPORT
1035 NTAPI
1036 CPortPinWaveCyclic::GetMiniport()
1037 {
1038 return (PMINIPORT)m_Miniport;
1039 }
1040
1041
1042 NTSTATUS
1043 NewPortPinWaveCyclic(
1044 OUT IPortPinWaveCyclic ** OutPin)
1045 {
1046 CPortPinWaveCyclic * This;
1047
1048 This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL);
1049 if (!This)
1050 return STATUS_INSUFFICIENT_RESOURCES;
1051
1052 This->AddRef();
1053
1054 // store result
1055 *OutPin = (IPortPinWaveCyclic*)This;
1056
1057 return STATUS_SUCCESS;
1058 }
1059