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