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