[PORTCLS]
[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 }
605
606
607 return STATUS_PENDING;
608 }
609
610 NTSTATUS
611 NTAPI
612 CPortPinWaveCyclic::DeviceIoControl(
613 IN PDEVICE_OBJECT DeviceObject,
614 IN PIRP Irp)
615 {
616 PIO_STACK_LOCATION IoStack;
617
618 IoStack = IoGetCurrentIrpStackLocation(Irp);
619
620
621 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
622 {
623 return HandleKsProperty(Irp);
624 }
625 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
626 {
627 /// FIXME
628 /// handle enable event
629 }
630 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
631 {
632 /// FIXME
633 /// handle disable event
634 }
635 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
636 {
637 /// FIXME
638 /// handle reset state
639 }
640 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
641 {
642 return HandleKsStream(Irp);
643 }
644 else
645 {
646 return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
647 }
648
649 UNIMPLEMENTED
650
651 Irp->IoStatus.Information = 0;
652 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
653 IoCompleteRequest(Irp, IO_NO_INCREMENT);
654
655 return STATUS_UNSUCCESSFUL;
656 }
657
658 NTSTATUS
659 NTAPI
660 CPortPinWaveCyclic::Read(
661 IN PDEVICE_OBJECT DeviceObject,
662 IN PIRP Irp)
663 {
664 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
665 }
666
667 NTSTATUS
668 NTAPI
669 CPortPinWaveCyclic::Write(
670 IN PDEVICE_OBJECT DeviceObject,
671 IN PIRP Irp)
672 {
673 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
674 }
675
676 NTSTATUS
677 NTAPI
678 CPortPinWaveCyclic::Flush(
679 IN PDEVICE_OBJECT DeviceObject,
680 IN PIRP Irp)
681 {
682 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
683 }
684
685 NTSTATUS
686 NTAPI
687 CPortPinWaveCyclic::Close(
688 IN PDEVICE_OBJECT DeviceObject,
689 IN PIRP Irp)
690 {
691 DPRINT("CPortPinWaveCyclic::Close entered\n");
692
693 PC_ASSERT_IRQL(PASSIVE_LEVEL);
694
695 if (m_Format)
696 {
697 // free format
698 ExFreePool(m_Format);
699 m_Format = NULL;
700 }
701
702 if (m_IrpQueue)
703 {
704 // fixme cancel irps
705 m_IrpQueue->Release();
706 }
707
708
709 if (m_Port)
710 {
711 // release reference to port driver
712 m_Port->Release();
713 m_Port = NULL;
714 }
715
716 if (m_ServiceGroup)
717 {
718 // remove member from service group
719 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
720 m_ServiceGroup = NULL;
721 }
722
723 if (m_Stream)
724 {
725 if (m_State != KSSTATE_STOP)
726 {
727 // stop stream
728 NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP);
729 if (!NT_SUCCESS(Status))
730 {
731 DPRINT("Warning: failed to stop stream with %x\n", Status);
732 PC_ASSERT(0);
733 }
734 }
735 // set state to stop
736 m_State = KSSTATE_STOP;
737
738
739 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
740 // release stream
741 m_Stream->Release();
742
743 }
744
745
746 if (m_Filter)
747 {
748 // release reference to filter instance
749 m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
750 m_Filter->Release();
751 m_Filter = NULL;
752 }
753
754 Irp->IoStatus.Information = 0;
755 Irp->IoStatus.Status = STATUS_SUCCESS;
756 IoCompleteRequest(Irp, IO_NO_INCREMENT);
757
758 delete this;
759
760 return STATUS_SUCCESS;
761 }
762
763 NTSTATUS
764 NTAPI
765 CPortPinWaveCyclic::QuerySecurity(
766 IN PDEVICE_OBJECT DeviceObject,
767 IN PIRP Irp)
768 {
769 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
770 }
771
772 NTSTATUS
773 NTAPI
774 CPortPinWaveCyclic::SetSecurity(
775 IN PDEVICE_OBJECT DeviceObject,
776 IN PIRP Irp)
777 {
778 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
779 }
780
781 BOOLEAN
782 NTAPI
783 CPortPinWaveCyclic::FastDeviceIoControl(
784 IN PFILE_OBJECT FileObject,
785 IN BOOLEAN Wait,
786 IN PVOID InputBuffer,
787 IN ULONG InputBufferLength,
788 OUT PVOID OutputBuffer,
789 IN ULONG OutputBufferLength,
790 IN ULONG IoControlCode,
791 OUT PIO_STATUS_BLOCK StatusBlock,
792 IN PDEVICE_OBJECT DeviceObject)
793 {
794 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
795 }
796
797
798 BOOLEAN
799 NTAPI
800 CPortPinWaveCyclic::FastRead(
801 IN PFILE_OBJECT FileObject,
802 IN PLARGE_INTEGER FileOffset,
803 IN ULONG Length,
804 IN BOOLEAN Wait,
805 IN ULONG LockKey,
806 IN PVOID Buffer,
807 OUT PIO_STATUS_BLOCK StatusBlock,
808 IN PDEVICE_OBJECT DeviceObject)
809 {
810 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
811 }
812
813
814 BOOLEAN
815 NTAPI
816 CPortPinWaveCyclic::FastWrite(
817 IN PFILE_OBJECT FileObject,
818 IN PLARGE_INTEGER FileOffset,
819 IN ULONG Length,
820 IN BOOLEAN Wait,
821 IN ULONG LockKey,
822 IN PVOID Buffer,
823 OUT PIO_STATUS_BLOCK StatusBlock,
824 IN PDEVICE_OBJECT DeviceObject)
825 {
826 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
827 }
828
829
830 NTSTATUS
831 NTAPI
832 CPortPinWaveCyclic::Init(
833 IN PPORTWAVECYCLIC Port,
834 IN PPORTFILTERWAVECYCLIC Filter,
835 IN KSPIN_CONNECT * ConnectDetails,
836 IN KSPIN_DESCRIPTOR * KsPinDescriptor)
837 {
838 NTSTATUS Status;
839 PKSDATAFORMAT DataFormat;
840 PDEVICE_OBJECT DeviceObject;
841 BOOLEAN Capture;
842 PVOID SilenceBuffer;
843 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
844 //IDrmAudioStream * DrmAudio = NULL;
845
846 m_KsPinDescriptor = KsPinDescriptor;
847 m_ConnectDetails = ConnectDetails;
848 m_Miniport = GetWaveCyclicMiniport(Port);
849
850 DeviceObject = GetDeviceObject(Port);
851
852 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
853
854 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize);
855
856 Status = NewIrpQueue(&m_IrpQueue);
857 if (!NT_SUCCESS(Status))
858 return Status;
859
860 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
861 {
862 Capture = FALSE;
863 }
864 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
865 {
866 Capture = TRUE;
867 }
868 else
869 {
870 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
871 KeBugCheck(0);
872 }
873
874
875 Status = m_Miniport->NewStream(&m_Stream,
876 NULL,
877 NonPagedPool,
878 ConnectDetails->PinId,
879 Capture,
880 DataFormat,
881 &m_DmaChannel,
882 &m_ServiceGroup);
883 #if 0
884 Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio);
885 if (NT_SUCCESS(Status))
886 {
887 DRMRIGHTS DrmRights;
888 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
889
890 DrmRights.CopyProtect = FALSE;
891 DrmRights.Reserved = 0;
892 DrmRights.DigitalOutputDisable = FALSE;
893
894 Status = DrmAudio->SetContentId(1, &DrmRights);
895 DPRINT("Status %x\n", Status);
896 }
897 #endif
898
899 DPRINT("CPortPinWaveCyclic::Init Status %x\n", Status);
900
901 if (!NT_SUCCESS(Status))
902 return Status;
903
904 ISubdevice * Subdevice = NULL;
905 // get subdevice interface
906 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
907
908 if (!NT_SUCCESS(Status))
909 return Status;
910
911 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
912 if (!NT_SUCCESS(Status))
913 {
914 // failed to get descriptor
915 Subdevice->Release();
916 return Status;
917 }
918
919 /* set up subdevice descriptor */
920 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
921 m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
922 m_Descriptor.FilterPropertySetCount = sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET);
923 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
924 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
925 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
926 m_Descriptor.PortPin = (PVOID)this;
927
928 // release subdevice descriptor
929 Subdevice->Release();
930
931 // add ourselves to service group
932 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
933 if (!NT_SUCCESS(Status))
934 {
935 DPRINT("Failed to add pin to service group\n");
936 return Status;
937 }
938
939 m_ServiceGroup->SupportDelayedService();
940 m_Stream->SetState(KSSTATE_STOP);
941 m_State = KSSTATE_STOP;
942 m_CommonBufferOffset = 0;
943 m_CommonBufferSize = m_DmaChannel->AllocatedBufferSize();
944 m_CommonBuffer = m_DmaChannel->SystemAddress();
945 m_Capture = Capture;
946 // delay of 10 milisec
947 m_Delay = Int32x32To64(10, -10000);
948
949 Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
950
951 SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
952 if (!SilenceBuffer)
953 return STATUS_INSUFFICIENT_RESOURCES;
954
955
956 /* set up allocator framing */
957 m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
958 m_AllocatorFraming.PoolType = NonPagedPool;
959 m_AllocatorFraming.Frames = 8;
960 m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT;
961 m_AllocatorFraming.Reserved = 0;
962 m_AllocatorFraming.FrameSize = m_FrameSize;
963
964 m_Stream->Silence(SilenceBuffer, m_FrameSize);
965
966 Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, m_FrameSize, 0, SilenceBuffer);
967 if (!NT_SUCCESS(Status))
968 {
969 m_IrpQueue->Release();
970 return Status;
971 }
972
973 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
974 if (!m_Format)
975 return STATUS_INSUFFICIENT_RESOURCES;
976
977 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
978
979
980 Port->AddRef();
981 Filter->AddRef();
982
983 m_Port = Port;
984 m_Filter = Filter;
985
986 DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
987 DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
988 DPRINT("Setting state to run %x\n", m_Stream->SetState(KSSTATE_RUN));
989 m_State = KSSTATE_RUN;
990
991
992 return STATUS_SUCCESS;
993 }
994
995
996 ULONG
997 NTAPI
998 CPortPinWaveCyclic::GetCompletedPosition()
999 {
1000 UNIMPLEMENTED;
1001 return 0;
1002 }
1003
1004
1005 ULONG
1006 NTAPI
1007 CPortPinWaveCyclic::GetCycleCount()
1008 {
1009 UNIMPLEMENTED;
1010 return 0;
1011 }
1012
1013
1014 ULONG
1015 NTAPI
1016 CPortPinWaveCyclic::GetDeviceBufferSize()
1017 {
1018 return m_CommonBufferSize;
1019 }
1020
1021
1022 PVOID
1023 NTAPI
1024 CPortPinWaveCyclic::GetIrpStream()
1025 {
1026 return (PVOID)m_IrpQueue;
1027 }
1028
1029
1030 PMINIPORT
1031 NTAPI
1032 CPortPinWaveCyclic::GetMiniport()
1033 {
1034 return (PMINIPORT)m_Miniport;
1035 }
1036
1037
1038 NTSTATUS
1039 NewPortPinWaveCyclic(
1040 OUT IPortPinWaveCyclic ** OutPin)
1041 {
1042 CPortPinWaveCyclic * This;
1043
1044 This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL);
1045 if (!This)
1046 return STATUS_INSUFFICIENT_RESOURCES;
1047
1048 This->AddRef();
1049
1050 // store result
1051 *OutPin = (IPortPinWaveCyclic*)This;
1052
1053 return STATUS_SUCCESS;
1054 }
1055