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