sync with trunk r47227
[reactos.git] / 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 protected:
39
40 VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount);
41 VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount);
42 VOID GeneratePositionEvents(IN ULONGLONG OldOffset, IN ULONGLONG NewOffset);
43
44 friend NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
45 friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
46 friend NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
47 friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
48 friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
49 friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
50 friend VOID CALLBACK PinSetStateWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
51
52 IPortWaveCyclic * m_Port;
53 IPortFilterWaveCyclic * m_Filter;
54 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
55 PMINIPORTWAVECYCLIC m_Miniport;
56 PSERVICEGROUP m_ServiceGroup;
57 PDMACHANNEL m_DmaChannel;
58 PMINIPORTWAVECYCLICSTREAM m_Stream;
59 KSSTATE m_State;
60 PKSDATAFORMAT m_Format;
61 PKSPIN_CONNECT m_ConnectDetails;
62
63 PVOID m_CommonBuffer;
64 ULONG m_CommonBufferSize;
65 ULONG m_CommonBufferOffset;
66
67 IIrpQueue * m_IrpQueue;
68
69 ULONG m_FrameSize;
70 BOOL m_Capture;
71
72 ULONG m_TotalPackets;
73 ULONG m_StopCount;
74 KSAUDIO_POSITION m_Position;
75 KSALLOCATOR_FRAMING m_AllocatorFraming;
76 SUBDEVICE_DESCRIPTOR m_Descriptor;
77
78 KSPIN_LOCK m_EventListLock;
79 LIST_ENTRY m_EventList;
80
81 KSRESET m_ResetState;
82
83 ULONG m_Delay;
84
85 LONG m_Ref;
86 };
87
88
89 typedef struct
90 {
91 ULONG bLoopedStreaming;
92 ULONGLONG Position;
93 }LOOPEDSTREAMING_EVENT_CONTEXT, *PLOOPEDSTREAMING_EVENT_CONTEXT;
94
95 typedef struct
96 {
97 ULONG bLoopedStreaming;
98 }ENDOFSTREAM_EVENT_CONTEXT, *PENDOFSTREAM_EVENT_CONTEXT;
99
100
101
102 NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
103 NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
104 NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
105 NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
106 NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
107 NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
108
109
110 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
111 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
112
113 KSEVENT_ITEM PinWaveCyclicConnectionEventSet =
114 {
115 KSEVENT_CONNECTION_ENDOFSTREAM,
116 sizeof(KSEVENTDATA),
117 sizeof(ENDOFSTREAM_EVENT_CONTEXT),
118 PinWaveCyclicAddEndOfStreamEvent,
119 0,
120 0
121 };
122
123 KSEVENT_ITEM PinWaveCyclicStreamingEventSet =
124 {
125 KSEVENT_LOOPEDSTREAMING_POSITION,
126 sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA),
127 sizeof(LOOPEDSTREAMING_EVENT_CONTEXT),
128 PinWaveCyclicAddLoopedStreamEvent,
129 0,
130 0
131 };
132
133
134 KSPROPERTY_SET PinWaveCyclicPropertySet[] =
135 {
136 {
137 &KSPROPSETID_Connection,
138 sizeof(PinWaveCyclicConnectionSet) / sizeof(KSPROPERTY_ITEM),
139 (const KSPROPERTY_ITEM*)&PinWaveCyclicConnectionSet,
140 0,
141 NULL
142 },
143 {
144 &KSPROPSETID_Audio,
145 sizeof(PinWaveCyclicAudioSet) / sizeof(KSPROPERTY_ITEM),
146 (const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet,
147 0,
148 NULL
149 }
150 };
151
152 KSEVENT_SET PinWaveCyclicEventSet[] =
153 {
154 {
155 &KSEVENTSETID_LoopedStreaming,
156 sizeof(PinWaveCyclicStreamingEventSet) / sizeof(KSEVENT_ITEM),
157 (const KSEVENT_ITEM*)&PinWaveCyclicStreamingEventSet
158 },
159 {
160 &KSEVENTSETID_Connection,
161 sizeof(PinWaveCyclicConnectionEventSet) / sizeof(KSEVENT_ITEM),
162 (const KSEVENT_ITEM*)&PinWaveCyclicConnectionEventSet
163 }
164 };
165
166
167 //==================================================================================================================================
168
169 NTSTATUS
170 NTAPI
171 CPortPinWaveCyclic::QueryInterface(
172 IN REFIID refiid,
173 OUT PVOID* Output)
174 {
175 DPRINT("IServiceSink_fnQueryInterface entered\n");
176
177 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
178 IsEqualGUIDAligned(refiid, IID_IUnknown))
179 {
180 *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
181 PUNKNOWN(*Output)->AddRef();
182 return STATUS_SUCCESS;
183 }
184
185 if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
186 {
187 *Output = PVOID(PUNKNOWN(PSERVICESINK(this)));
188 PUNKNOWN(*Output)->AddRef();
189 return STATUS_SUCCESS;
190 }
191
192 return STATUS_UNSUCCESSFUL;
193 }
194
195 NTSTATUS
196 NTAPI
197 PinWaveCyclicAddEndOfStreamEvent(
198 IN PIRP Irp,
199 IN PKSEVENTDATA EventData,
200 IN PKSEVENT_ENTRY EventEntry)
201 {
202 PENDOFSTREAM_EVENT_CONTEXT Entry;
203 PSUBDEVICE_DESCRIPTOR Descriptor;
204 CPortPinWaveCyclic *Pin;
205
206 // get sub device descriptor
207 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
208
209 // sanity check
210 PC_ASSERT(Descriptor);
211 PC_ASSERT(Descriptor->PortPin);
212 PC_ASSERT_IRQL(DISPATCH_LEVEL);
213
214 // cast to pin impl
215 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
216
217 // get extra size
218 Entry = (PENDOFSTREAM_EVENT_CONTEXT)(EventEntry + 1);
219
220 // not a looped event
221 Entry->bLoopedStreaming = FALSE;
222
223 // insert item
224 (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
225
226 // done
227 return STATUS_SUCCESS;
228 }
229
230 NTSTATUS
231 NTAPI
232 PinWaveCyclicAddLoopedStreamEvent(
233 IN PIRP Irp,
234 IN PKSEVENTDATA EventData,
235 IN PKSEVENT_ENTRY EventEntry)
236 {
237 PLOOPEDSTREAMING_POSITION_EVENT_DATA Data;
238 PLOOPEDSTREAMING_EVENT_CONTEXT Entry;
239 PSUBDEVICE_DESCRIPTOR Descriptor;
240 CPortPinWaveCyclic *Pin;
241
242 // get sub device descriptor
243 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
244
245 // sanity check
246 PC_ASSERT(Descriptor);
247 PC_ASSERT(Descriptor->PortPin);
248 PC_ASSERT_IRQL(DISPATCH_LEVEL);
249
250 // cast to pin impl
251 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
252
253 // cast to looped event
254 Data = (PLOOPEDSTREAMING_POSITION_EVENT_DATA)EventData;
255
256 // get extra size
257 Entry = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
258
259 Entry->bLoopedStreaming = TRUE;
260 Entry->Position = Data->Position;
261
262 DPRINT1("Added event\n");
263
264 // insert item
265 (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
266
267 // done
268 return STATUS_SUCCESS;
269 }
270
271 NTSTATUS
272 NTAPI
273 PinWaveCyclicAllocatorFraming(
274 IN PIRP Irp,
275 IN PKSIDENTIFIER Request,
276 IN OUT PVOID Data)
277 {
278 CPortPinWaveCyclic *Pin;
279 PSUBDEVICE_DESCRIPTOR Descriptor;
280
281 // get sub device descriptor
282 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
283
284 // sanity check
285 PC_ASSERT(Descriptor);
286 PC_ASSERT(Descriptor->PortPin);
287 PC_ASSERT_IRQL(DISPATCH_LEVEL);
288
289 // cast to pin impl
290 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
291
292
293 if (Request->Flags & KSPROPERTY_TYPE_GET)
294 {
295 // copy pin framing
296 RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
297
298 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
299 return STATUS_SUCCESS;
300 }
301
302 // not supported
303 return STATUS_NOT_SUPPORTED;
304 }
305
306 NTSTATUS
307 NTAPI
308 PinWaveCyclicAudioPosition(
309 IN PIRP Irp,
310 IN PKSIDENTIFIER Request,
311 IN OUT PVOID Data)
312 {
313 CPortPinWaveCyclic *Pin;
314 PSUBDEVICE_DESCRIPTOR Descriptor;
315 PKSAUDIO_POSITION Position;
316
317 // get sub device descriptor
318 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
319
320 // sanity check
321 PC_ASSERT(Descriptor);
322 PC_ASSERT(Descriptor->PortPin);
323 PC_ASSERT_IRQL(DISPATCH_LEVEL);
324
325 // cast to pin impl
326 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
327
328 //sanity check
329 PC_ASSERT(Pin->m_Stream);
330
331 if (Request->Flags & KSPROPERTY_TYPE_GET)
332 {
333 // FIXME non multithreading-safe
334 // copy audio position
335
336 Position = (PKSAUDIO_POSITION)Data;
337
338 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING)
339 {
340 RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
341 DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
342 }
343 else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
344 {
345 Position->PlayOffset = Pin->m_Position.PlayOffset;
346 Position->WriteOffset = (ULONGLONG)Pin->m_IrpQueue->GetCurrentIrpOffset();
347 DPRINT("Play %lu Write %lu\n", Position->PlayOffset, Position->WriteOffset);
348 }
349
350 Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
351 return STATUS_SUCCESS;
352 }
353
354 // not supported
355 return STATUS_NOT_SUPPORTED;
356 }
357
358 typedef struct
359 {
360 CPortPinWaveCyclic *Pin;
361 KSSTATE NewState;
362 PIO_WORKITEM WorkItem;
363 PIRP Irp;
364
365 }SETPIN_CONTEXT, *PSETPIN_CONTEXT;
366
367 VOID
368 CALLBACK
369 PinSetStateWorkerRoutine(
370 IN PDEVICE_OBJECT DeviceObject,
371 IN PVOID Context)
372 {
373 PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context;
374 NTSTATUS Status;
375
376 // try set stream
377 Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState);
378
379 DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status);
380 if (NT_SUCCESS(Status))
381 {
382 // store new state
383 PinWorkContext->Pin->m_State = PinWorkContext->NewState;
384
385 if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
386 {
387 /* FIXME complete pending irps with successfull state */
388 PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
389 }
390 //HACK
391 //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
392 }
393
394 // store result
395 PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE);
396 PinWorkContext->Irp->IoStatus.Status = Status;
397
398 // complete irp
399 IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT);
400
401 // free work item
402 IoFreeWorkItem(PinWorkContext->WorkItem);
403
404 // free work context
405 FreeItem(PinWorkContext, TAG_PORTCLASS);
406
407 }
408
409
410 NTSTATUS
411 NTAPI
412 PinWaveCyclicState(
413 IN PIRP Irp,
414 IN PKSIDENTIFIER Request,
415 IN OUT PVOID Data)
416 {
417 NTSTATUS Status = STATUS_UNSUCCESSFUL;
418 CPortPinWaveCyclic *Pin;
419 PSUBDEVICE_DESCRIPTOR Descriptor;
420 PKSSTATE State = (PKSSTATE)Data;
421
422 // get sub device descriptor
423 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
424
425 // sanity check
426 PC_ASSERT(Descriptor);
427 PC_ASSERT(Descriptor->PortPin);
428 PC_ASSERT_IRQL(DISPATCH_LEVEL);
429
430 // cast to pin impl
431 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
432
433 //sanity check
434 PC_ASSERT(Pin->m_Stream);
435
436 if (Request->Flags & KSPROPERTY_TYPE_SET)
437 {
438 // try set stream
439 Status = Pin->m_Stream->SetState(*State);
440
441 DPRINT("Setting state %u %x\n", *State, Status);
442 if (NT_SUCCESS(Status))
443 {
444 // store new state
445 Pin->m_State = *State;
446
447 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP)
448 {
449 // FIXME
450 // complete with successful state
451 Pin->m_IrpQueue->CancelBuffers();
452 Pin->m_Position.PlayOffset = 0;
453 Pin->m_Position.WriteOffset = 0;
454 }
455 else if (Pin->m_State == KSSTATE_STOP)
456 {
457 Pin->m_IrpQueue->CancelBuffers();
458 Pin->m_Position.PlayOffset = 0;
459 Pin->m_Position.WriteOffset = 0;
460 }
461 // store result
462 Irp->IoStatus.Information = sizeof(KSSTATE);
463 }
464 return Status;
465 }
466 else if (Request->Flags & KSPROPERTY_TYPE_GET)
467 {
468 // get current stream state
469 *State = Pin->m_State;
470 // store result
471 Irp->IoStatus.Information = sizeof(KSSTATE);
472
473 return STATUS_SUCCESS;
474 }
475
476 // unsupported request
477 return STATUS_NOT_SUPPORTED;
478 }
479
480 NTSTATUS
481 NTAPI
482 PinWaveCyclicDataFormat(
483 IN PIRP Irp,
484 IN PKSIDENTIFIER Request,
485 IN OUT PVOID Data)
486 {
487 NTSTATUS Status = STATUS_UNSUCCESSFUL;
488 CPortPinWaveCyclic *Pin;
489 PSUBDEVICE_DESCRIPTOR Descriptor;
490 PIO_STACK_LOCATION IoStack;
491
492 // get current irp stack location
493 IoStack = IoGetCurrentIrpStackLocation(Irp);
494
495 // get sub device descriptor
496 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
497
498 // sanity check
499 PC_ASSERT(Descriptor);
500 PC_ASSERT(Descriptor->PortPin);
501
502 // cast to pin impl
503 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
504
505 //sanity check
506 PC_ASSERT(Pin->m_Stream);
507 PC_ASSERT(Pin->m_Format);
508
509 if (Request->Flags & KSPROPERTY_TYPE_SET)
510 {
511 // try to change data format
512 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
513 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
514
515 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
516 {
517 // format is identical
518 Irp->IoStatus.Information = DataFormat->FormatSize;
519 return STATUS_SUCCESS;
520 }
521
522 // new change request
523 PC_ASSERT(Pin->m_State != KSSTATE_RUN);
524 // FIXME queue a work item when Irql != PASSIVE_LEVEL
525 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
526
527 // allocate new data format
528 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
529 if (!NewDataFormat)
530 {
531 // not enough memory
532 return STATUS_NO_MEMORY;
533 }
534
535 // copy new data format
536 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
537
538 // set new format
539 Status = Pin->m_Stream->SetFormat(NewDataFormat);
540 if (NT_SUCCESS(Status))
541 {
542 // free old format
543 FreeItem(Pin->m_Format, TAG_PORTCLASS);
544
545 // store new format
546 Pin->m_Format = NewDataFormat;
547 Irp->IoStatus.Information = NewDataFormat->FormatSize;
548
549 #if 0
550 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
551 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
552 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
553 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
554
555
556 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
557 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
558 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
559 #endif
560
561 }
562 else
563 {
564 // failed to set format
565 FreeItem(NewDataFormat, TAG_PORTCLASS);
566 }
567
568
569 // done
570 return Status;
571 }
572 else if (Request->Flags & KSPROPERTY_TYPE_GET)
573 {
574 // get current data format
575 PC_ASSERT(Pin->m_Format);
576
577 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
578 {
579 // buffer too small
580 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
581 return STATUS_MORE_ENTRIES;
582 }
583 // copy data format
584 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
585 // store result size
586 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
587
588 // done
589 return STATUS_SUCCESS;
590 }
591
592 // unsupported request
593 return STATUS_NOT_SUPPORTED;
594 }
595
596 VOID
597 CPortPinWaveCyclic::GeneratePositionEvents(
598 IN ULONGLONG OldOffset,
599 IN ULONGLONG NewOffset)
600 {
601 PLIST_ENTRY Entry;
602 PKSEVENT_ENTRY EventEntry;
603 PLOOPEDSTREAMING_EVENT_CONTEXT Context;
604
605 // acquire event lock
606 KeAcquireSpinLockAtDpcLevel(&m_EventListLock);
607
608 // point to first entry
609 Entry = m_EventList.Flink;
610
611 while(Entry != &m_EventList)
612 {
613 // get event entry
614 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
615
616 // get event entry context
617 Context = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
618
619 if (Context->bLoopedStreaming == TRUE)
620 {
621 if (NewOffset > OldOffset)
622 {
623 /* buffer progress no overlap */
624 if (OldOffset < Context->Position && Context->Position <= NewOffset)
625 {
626 /* when someone eventually fixes sprintf... */
627 DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
628 DPRINT("Context->Position %I64u\n", Context->Position);
629 DPRINT("NewOffset %I64u\n", NewOffset);
630 /* generate event */
631 KsGenerateEvent(EventEntry);
632 }
633 }
634 else
635 {
636 /* buffer wrap-arround */
637 if (OldOffset < Context->Position || NewOffset > Context->Position)
638 {
639 /* when someone eventually fixes sprintf... */
640 DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
641 DPRINT("Context->Position %I64u\n", Context->Position);
642 DPRINT("NewOffset %I64u\n", NewOffset);
643 /* generate event */
644 KsGenerateEvent(EventEntry);
645 }
646 }
647 }
648
649 // move to next entry
650 Entry = Entry->Flink;
651 }
652
653 // release lock
654 KeReleaseSpinLockFromDpcLevel(&m_EventListLock);
655 }
656
657 VOID
658 CPortPinWaveCyclic::UpdateCommonBuffer(
659 ULONG Position,
660 ULONG MaxTransferCount)
661 {
662 ULONG BufferLength;
663 ULONG BytesToCopy;
664 ULONG BufferSize;
665 PUCHAR Buffer;
666 NTSTATUS Status;
667
668 BufferLength = Position - m_CommonBufferOffset;
669 BufferLength = min(BufferLength, MaxTransferCount);
670
671 while(BufferLength)
672 {
673 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
674 if (!NT_SUCCESS(Status))
675 return;
676
677 BytesToCopy = min(BufferLength, BufferSize);
678
679 if (m_Capture)
680 {
681 m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
682 }
683 else
684 {
685 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
686 }
687
688 m_IrpQueue->UpdateMapping(BytesToCopy);
689 m_CommonBufferOffset += BytesToCopy;
690
691 BufferLength = Position - m_CommonBufferOffset;
692 m_Position.PlayOffset += BytesToCopy;
693
694 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
695 {
696 if (m_Position.WriteOffset)
697 {
698 // normalize position
699 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
700 }
701 }
702 }
703 }
704
705 VOID
706 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
707 ULONG Position,
708 ULONG MaxTransferCount)
709 {
710 ULONG BufferLength, Length, Gap;
711 ULONG BytesToCopy;
712 ULONG BufferSize;
713 PUCHAR Buffer;
714 NTSTATUS Status;
715
716
717 BufferLength = Gap = m_CommonBufferSize - m_CommonBufferOffset;
718 BufferLength = Length = min(BufferLength, MaxTransferCount);
719 while(BufferLength)
720 {
721 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
722 if (!NT_SUCCESS(Status))
723 return;
724
725 BytesToCopy = min(BufferLength, BufferSize);
726
727 if (m_Capture)
728 {
729 m_DmaChannel->CopyFrom(Buffer,
730 (PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
731 BytesToCopy);
732 }
733 else
734 {
735 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
736 Buffer,
737 BytesToCopy);
738 }
739
740 m_IrpQueue->UpdateMapping(BytesToCopy);
741 m_CommonBufferOffset += BytesToCopy;
742 m_Position.PlayOffset += BytesToCopy;
743
744 BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
745
746 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
747 {
748 if (m_Position.WriteOffset)
749 {
750 // normalize position
751 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
752 }
753 }
754
755 }
756
757 if (Gap == Length)
758 {
759 m_CommonBufferOffset = 0;
760
761 MaxTransferCount -= Length;
762
763 if (MaxTransferCount)
764 {
765 UpdateCommonBuffer(Position, MaxTransferCount);
766 }
767 }
768 }
769
770 VOID
771 NTAPI
772 CPortPinWaveCyclic::RequestService()
773 {
774 ULONG Position;
775 NTSTATUS Status;
776 PUCHAR Buffer;
777 ULONG BufferSize;
778 ULONGLONG OldOffset, NewOffset;
779
780 PC_ASSERT_IRQL(DISPATCH_LEVEL);
781
782 if (m_State == KSSTATE_RUN)
783 {
784 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
785 if (!NT_SUCCESS(Status))
786 {
787 return;
788 }
789
790 Status = m_Stream->GetPosition(&Position);
791 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
792
793 OldOffset = m_Position.PlayOffset;
794
795 if (Position < m_CommonBufferOffset)
796 {
797 UpdateCommonBufferOverlap(Position, m_FrameSize);
798 }
799 else if (Position >= m_CommonBufferOffset)
800 {
801 UpdateCommonBuffer(Position, m_FrameSize);
802 }
803
804 NewOffset = m_Position.PlayOffset;
805
806 GeneratePositionEvents(OldOffset, NewOffset);
807 }
808 }
809
810 NTSTATUS
811 NTAPI
812 CPortPinWaveCyclic::NewIrpTarget(
813 OUT struct IIrpTarget **OutTarget,
814 IN PCWSTR Name,
815 IN PUNKNOWN Unknown,
816 IN POOL_TYPE PoolType,
817 IN PDEVICE_OBJECT DeviceObject,
818 IN PIRP Irp,
819 IN KSOBJECT_CREATE *CreateObject)
820 {
821 UNIMPLEMENTED
822 return STATUS_UNSUCCESSFUL;
823 }
824
825 NTSTATUS
826 NTAPI
827 CPortPinWaveCyclic::DeviceIoControl(
828 IN PDEVICE_OBJECT DeviceObject,
829 IN PIRP Irp)
830 {
831 PIO_STACK_LOCATION IoStack;
832 PKSPROPERTY Property;
833 UNICODE_STRING GuidString;
834 NTSTATUS Status = STATUS_NOT_SUPPORTED;
835 ULONG Data = 0;
836 KSRESET ResetValue;
837
838 /* get current irp stack location */
839 IoStack = IoGetCurrentIrpStackLocation(Irp);
840
841 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
842 {
843 /* handle property with subdevice descriptor */
844 Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
845
846 if (Status == STATUS_NOT_FOUND)
847 {
848 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
849
850 RtlStringFromGUID(Property->Set, &GuidString);
851 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
852 RtlFreeUnicodeString(&GuidString);
853 }
854 }
855 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
856 {
857 Status = PcHandleEnableEventWithTable(Irp, &m_Descriptor);
858 }
859 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
860 {
861 Status = PcHandleDisableEventWithTable(Irp, &m_Descriptor);
862 }
863 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
864 {
865 Status = KsAcquireResetValue(Irp, &ResetValue);
866 DPRINT("Status %x Value %u\n", Status, ResetValue);
867 /* check for success */
868 if (NT_SUCCESS(Status))
869 {
870 if (ResetValue == KSRESET_BEGIN)
871 {
872 m_IrpQueue->CancelBuffers();
873 m_ResetState = KSRESET_BEGIN;
874 }
875 else if (ResetValue == KSRESET_END)
876 {
877 m_ResetState = KSRESET_END;
878 }
879 }
880 }
881 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
882 {
883 /* increment total number of packets */
884 InterlockedIncrement((PLONG)&m_TotalPackets);
885
886 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
887
888 /* is the device not currently reset */
889 if (m_ResetState == KSRESET_END)
890 {
891 /* add the mapping */
892 Status = m_IrpQueue->AddMapping(Irp, &Data);
893
894 /* check for success */
895 if (NT_SUCCESS(Status))
896 {
897 m_Position.WriteOffset += Data;
898 Status = STATUS_PENDING;
899 }
900 }
901 else
902 {
903 /* reset request is currently in progress */
904 Status = STATUS_DEVICE_NOT_READY;
905 DPRINT1("NotReady\n");
906 }
907 }
908 else
909 {
910 return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
911 }
912
913 if (Status != STATUS_PENDING)
914 {
915 Irp->IoStatus.Status = Status;
916 IoCompleteRequest(Irp, IO_NO_INCREMENT);
917 }
918
919 return Status;
920 }
921
922 NTSTATUS
923 NTAPI
924 CPortPinWaveCyclic::Read(
925 IN PDEVICE_OBJECT DeviceObject,
926 IN PIRP Irp)
927 {
928 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
929 }
930
931 NTSTATUS
932 NTAPI
933 CPortPinWaveCyclic::Write(
934 IN PDEVICE_OBJECT DeviceObject,
935 IN PIRP Irp)
936 {
937 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
938 }
939
940 NTSTATUS
941 NTAPI
942 CPortPinWaveCyclic::Flush(
943 IN PDEVICE_OBJECT DeviceObject,
944 IN PIRP Irp)
945 {
946 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
947 }
948
949 NTSTATUS
950 NTAPI
951 CPortPinWaveCyclic::Close(
952 IN PDEVICE_OBJECT DeviceObject,
953 IN PIRP Irp)
954 {
955 DPRINT("CPortPinWaveCyclic::Close entered\n");
956
957 PC_ASSERT_IRQL(PASSIVE_LEVEL);
958
959 if (m_Format)
960 {
961 // free format
962 ExFreePool(m_Format);
963 m_Format = NULL;
964 }
965
966 if (m_IrpQueue)
967 {
968 // fixme cancel irps
969 m_IrpQueue->Release();
970 }
971
972
973 if (m_Port)
974 {
975 // release reference to port driver
976 m_Port->Release();
977 m_Port = NULL;
978 }
979
980 if (m_ServiceGroup)
981 {
982 // remove member from service group
983 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
984 m_ServiceGroup = NULL;
985 }
986
987 if (m_Stream)
988 {
989 if (m_State != KSSTATE_STOP)
990 {
991 // stop stream
992 NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP);
993 if (!NT_SUCCESS(Status))
994 {
995 DPRINT("Warning: failed to stop stream with %x\n", Status);
996 PC_ASSERT(0);
997 }
998 }
999 // set state to stop
1000 m_State = KSSTATE_STOP;
1001
1002
1003 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
1004 // release stream
1005 m_Stream->Release();
1006
1007 }
1008
1009
1010 if (m_Filter)
1011 {
1012 // release reference to filter instance
1013 m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
1014 m_Filter->Release();
1015 m_Filter = NULL;
1016 }
1017
1018 Irp->IoStatus.Information = 0;
1019 Irp->IoStatus.Status = STATUS_SUCCESS;
1020 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1021
1022 delete this;
1023
1024 return STATUS_SUCCESS;
1025 }
1026
1027 NTSTATUS
1028 NTAPI
1029 CPortPinWaveCyclic::QuerySecurity(
1030 IN PDEVICE_OBJECT DeviceObject,
1031 IN PIRP Irp)
1032 {
1033 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1034 }
1035
1036 NTSTATUS
1037 NTAPI
1038 CPortPinWaveCyclic::SetSecurity(
1039 IN PDEVICE_OBJECT DeviceObject,
1040 IN PIRP Irp)
1041 {
1042 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1043 }
1044
1045 BOOLEAN
1046 NTAPI
1047 CPortPinWaveCyclic::FastDeviceIoControl(
1048 IN PFILE_OBJECT FileObject,
1049 IN BOOLEAN Wait,
1050 IN PVOID InputBuffer,
1051 IN ULONG InputBufferLength,
1052 OUT PVOID OutputBuffer,
1053 IN ULONG OutputBufferLength,
1054 IN ULONG IoControlCode,
1055 OUT PIO_STATUS_BLOCK StatusBlock,
1056 IN PDEVICE_OBJECT DeviceObject)
1057 {
1058 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
1059 }
1060
1061
1062 BOOLEAN
1063 NTAPI
1064 CPortPinWaveCyclic::FastRead(
1065 IN PFILE_OBJECT FileObject,
1066 IN PLARGE_INTEGER FileOffset,
1067 IN ULONG Length,
1068 IN BOOLEAN Wait,
1069 IN ULONG LockKey,
1070 IN PVOID Buffer,
1071 OUT PIO_STATUS_BLOCK StatusBlock,
1072 IN PDEVICE_OBJECT DeviceObject)
1073 {
1074 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1075 }
1076
1077
1078 BOOLEAN
1079 NTAPI
1080 CPortPinWaveCyclic::FastWrite(
1081 IN PFILE_OBJECT FileObject,
1082 IN PLARGE_INTEGER FileOffset,
1083 IN ULONG Length,
1084 IN BOOLEAN Wait,
1085 IN ULONG LockKey,
1086 IN PVOID Buffer,
1087 OUT PIO_STATUS_BLOCK StatusBlock,
1088 IN PDEVICE_OBJECT DeviceObject)
1089 {
1090 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1091 }
1092
1093
1094 NTSTATUS
1095 NTAPI
1096 CPortPinWaveCyclic::Init(
1097 IN PPORTWAVECYCLIC Port,
1098 IN PPORTFILTERWAVECYCLIC Filter,
1099 IN KSPIN_CONNECT * ConnectDetails,
1100 IN KSPIN_DESCRIPTOR * KsPinDescriptor)
1101 {
1102 NTSTATUS Status;
1103 PKSDATAFORMAT DataFormat;
1104 PDEVICE_OBJECT DeviceObject;
1105 BOOLEAN Capture;
1106 PVOID SilenceBuffer;
1107 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
1108 //IDrmAudioStream * DrmAudio = NULL;
1109
1110 m_KsPinDescriptor = KsPinDescriptor;
1111 m_ConnectDetails = ConnectDetails;
1112 m_Miniport = GetWaveCyclicMiniport(Port);
1113
1114 DeviceObject = GetDeviceObject(Port);
1115
1116 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
1117
1118 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize);
1119
1120 Status = NewIrpQueue(&m_IrpQueue);
1121 if (!NT_SUCCESS(Status))
1122 return Status;
1123
1124 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
1125 {
1126 Capture = FALSE;
1127 }
1128 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
1129 {
1130 Capture = TRUE;
1131 }
1132 else
1133 {
1134 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
1135 DbgBreakPoint();
1136 while(TRUE);
1137 }
1138
1139
1140 Status = m_Miniport->NewStream(&m_Stream,
1141 NULL,
1142 NonPagedPool,
1143 ConnectDetails->PinId,
1144 Capture,
1145 DataFormat,
1146 &m_DmaChannel,
1147 &m_ServiceGroup);
1148 #if 0
1149 Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio);
1150 if (NT_SUCCESS(Status))
1151 {
1152 DRMRIGHTS DrmRights;
1153 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
1154
1155 DrmRights.CopyProtect = FALSE;
1156 DrmRights.Reserved = 0;
1157 DrmRights.DigitalOutputDisable = FALSE;
1158
1159 Status = DrmAudio->SetContentId(1, &DrmRights);
1160 DPRINT("Status %x\n", Status);
1161 }
1162 #endif
1163
1164 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
1165 DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize);
1166
1167 if (!NT_SUCCESS(Status))
1168 return Status;
1169
1170 ISubdevice * Subdevice = NULL;
1171 // get subdevice interface
1172 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
1173
1174 if (!NT_SUCCESS(Status))
1175 return Status;
1176
1177 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
1178 if (!NT_SUCCESS(Status))
1179 {
1180 // failed to get descriptor
1181 Subdevice->Release();
1182 return Status;
1183 }
1184
1185 /* initialize event management */
1186 InitializeListHead(&m_EventList);
1187 KeInitializeSpinLock(&m_EventListLock);
1188
1189 /* set up subdevice descriptor */
1190 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
1191 m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
1192 m_Descriptor.FilterPropertySetCount = sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET);
1193 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
1194 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
1195 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
1196 m_Descriptor.PortPin = (PVOID)this;
1197 m_Descriptor.EventSetCount = sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET);
1198 m_Descriptor.EventSet = PinWaveCyclicEventSet;
1199 m_Descriptor.EventList = &m_EventList;
1200 m_Descriptor.EventListLock = &m_EventListLock;
1201
1202 // initialize reset state
1203 m_ResetState = KSRESET_END;
1204
1205 // release subdevice descriptor
1206 Subdevice->Release();
1207
1208 // add ourselves to service group
1209 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
1210 if (!NT_SUCCESS(Status))
1211 {
1212 DPRINT("Failed to add pin to service group\n");
1213 return Status;
1214 }
1215
1216 m_Stream->SetState(KSSTATE_STOP);
1217 m_State = KSSTATE_STOP;
1218 m_CommonBufferOffset = 0;
1219 m_CommonBufferSize = m_DmaChannel->AllocatedBufferSize();
1220 m_CommonBuffer = m_DmaChannel->SystemAddress();
1221 m_Capture = Capture;
1222 // delay of 10 milisec
1223 m_Delay = Int32x32To64(10, -10000);
1224
1225 Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
1226 PC_ASSERT(NT_SUCCESS(Status));
1227 PC_ASSERT(m_FrameSize);
1228
1229 SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
1230 if (!SilenceBuffer)
1231 return STATUS_INSUFFICIENT_RESOURCES;
1232
1233
1234 /* set up allocator framing */
1235 m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
1236 m_AllocatorFraming.PoolType = NonPagedPool;
1237 m_AllocatorFraming.Frames = 8;
1238 m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT;
1239 m_AllocatorFraming.Reserved = 0;
1240 m_AllocatorFraming.FrameSize = m_FrameSize;
1241
1242 m_Stream->Silence(SilenceBuffer, m_FrameSize);
1243 m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
1244
1245 Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0, SilenceBuffer);
1246 if (!NT_SUCCESS(Status))
1247 {
1248 m_IrpQueue->Release();
1249 return Status;
1250 }
1251
1252 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
1253 if (!m_Format)
1254 return STATUS_INSUFFICIENT_RESOURCES;
1255
1256 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
1257
1258 Port->AddRef();
1259 Filter->AddRef();
1260
1261 m_Port = Port;
1262 m_Filter = Filter;
1263
1264 //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
1265 //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
1266
1267 return STATUS_SUCCESS;
1268 }
1269
1270
1271 ULONG
1272 NTAPI
1273 CPortPinWaveCyclic::GetCompletedPosition()
1274 {
1275 UNIMPLEMENTED;
1276 return 0;
1277 }
1278
1279
1280 ULONG
1281 NTAPI
1282 CPortPinWaveCyclic::GetCycleCount()
1283 {
1284 UNIMPLEMENTED;
1285 return 0;
1286 }
1287
1288
1289 ULONG
1290 NTAPI
1291 CPortPinWaveCyclic::GetDeviceBufferSize()
1292 {
1293 return m_CommonBufferSize;
1294 }
1295
1296
1297 PVOID
1298 NTAPI
1299 CPortPinWaveCyclic::GetIrpStream()
1300 {
1301 return (PVOID)m_IrpQueue;
1302 }
1303
1304
1305 PMINIPORT
1306 NTAPI
1307 CPortPinWaveCyclic::GetMiniport()
1308 {
1309 return (PMINIPORT)m_Miniport;
1310 }
1311
1312
1313 NTSTATUS
1314 NewPortPinWaveCyclic(
1315 OUT IPortPinWaveCyclic ** OutPin)
1316 {
1317 CPortPinWaveCyclic * This;
1318
1319 This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL);
1320 if (!This)
1321 return STATUS_INSUFFICIENT_RESOURCES;
1322
1323 This->AddRef();
1324
1325 // store result
1326 *OutPin = (IPortPinWaveCyclic*)This;
1327
1328 return STATUS_SUCCESS;
1329 }
1330