7732b1a2aa6b72682a64c4aa601bf8f4350a94f9
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / pin_wavepci.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
5 * PURPOSE: WavePci IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 class CPortPinWavePci : public IPortPinWavePci,
12 public IServiceSink,
13 public IPortWavePciStream
14 {
15 public:
16 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
17
18 STDMETHODIMP_(ULONG) AddRef()
19 {
20 InterlockedIncrement(&m_Ref);
21 return m_Ref;
22 }
23 STDMETHODIMP_(ULONG) Release()
24 {
25 InterlockedDecrement(&m_Ref);
26
27 if (!m_Ref)
28 {
29 delete this;
30 return 0;
31 }
32 return m_Ref;
33 }
34 IMP_IPortPinWavePci;
35 IMP_IServiceSink;
36 IMP_IPortWavePciStream;
37 CPortPinWavePci(IUnknown *OuterUnknown) {}
38 virtual ~CPortPinWavePci(){}
39
40 VOID NTAPI SetState( IN KSSTATE State);
41 VOID NTAPI CloseStream();
42 protected:
43
44 IPortWavePci * m_Port;
45 IPortFilterWavePci * m_Filter;
46 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
47 PMINIPORTWAVEPCI m_Miniport;
48 PSERVICEGROUP m_ServiceGroup;
49 PDMACHANNEL m_DmaChannel;
50 PMINIPORTWAVEPCISTREAM m_Stream;
51 KSSTATE m_State;
52 PKSDATAFORMAT m_Format;
53 KSPIN_CONNECT * m_ConnectDetails;
54
55 BOOL m_Capture;
56 PDEVICE_OBJECT m_DeviceObject;
57 IIrpQueue * m_IrpQueue;
58
59 ULONG m_TotalPackets;
60 ULONG m_PreCompleted;
61 ULONG m_PostCompleted;
62 ULONG m_StopCount;
63
64 ULONG m_Delay;
65
66 BOOL m_bUsePrefetch;
67 ULONG m_PrefetchOffset;
68
69 KSALLOCATOR_FRAMING m_AllocatorFraming;
70
71 LONG m_Ref;
72
73 NTSTATUS NTAPI HandleKsProperty(IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN PIO_STATUS_BLOCK IoStatusBlock);
74 VOID NTAPI SetStreamState( IN KSSTATE State);
75 };
76
77 typedef struct
78 {
79 CPortPinWavePci *Pin;
80 PIO_WORKITEM WorkItem;
81 KSSTATE State;
82 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
83
84 //==================================================================================================================================
85 NTSTATUS
86 NTAPI
87 CPortPinWavePci::QueryInterface(
88 IN REFIID refiid,
89 OUT PVOID* Output)
90 {
91 DPRINT("CPortPinWavePci::QueryInterface entered\n");
92
93 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
94 IsEqualGUIDAligned(refiid, IID_IUnknown))
95 {
96 *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
97 PUNKNOWN(*Output)->AddRef();
98 return STATUS_SUCCESS;
99 }
100
101 if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
102 {
103 *Output = PVOID(PSERVICESINK(this));
104 PUNKNOWN(*Output)->AddRef();
105 return STATUS_SUCCESS;
106 }
107
108
109 if (IsEqualGUIDAligned(refiid, IID_IPortWavePciStream))
110 {
111 *Output = PVOID(PPORTWAVEPCISTREAM(this));
112 PUNKNOWN(*Output)->AddRef();
113 return STATUS_SUCCESS;
114 }
115
116 return STATUS_UNSUCCESSFUL;
117 }
118
119 NTSTATUS
120 NTAPI
121 CPortPinWavePci::GetMapping(
122 IN PVOID Tag,
123 OUT PPHYSICAL_ADDRESS PhysicalAddress,
124 OUT PVOID *VirtualAddress,
125 OUT PULONG ByteCount,
126 OUT PULONG Flags)
127 {
128
129 PC_ASSERT_IRQL(DISPATCH_LEVEL);
130 return m_IrpQueue->GetMappingWithTag(Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags);
131 }
132
133 NTSTATUS
134 NTAPI
135 CPortPinWavePci::ReleaseMapping(
136 IN PVOID Tag)
137 {
138
139 PC_ASSERT_IRQL(DISPATCH_LEVEL);
140 return m_IrpQueue->ReleaseMappingWithTag(Tag);
141 }
142
143 NTSTATUS
144 NTAPI
145 CPortPinWavePci::TerminatePacket()
146 {
147 UNIMPLEMENTED
148 PC_ASSERT_IRQL(DISPATCH_LEVEL);
149 return STATUS_SUCCESS;
150 }
151
152
153 VOID
154 CPortPinWavePci::SetState(KSSTATE State)
155 {
156 ULONG MinimumDataThreshold;
157 ULONG MaximumDataThreshold;
158
159 // Has the audio stream resumed?
160 if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
161 return;
162
163 // Set the state
164 if (NT_SUCCESS(m_Stream->SetState(State)))
165 {
166 // Save new internal state
167 m_State = State;
168
169 if (m_State == KSSTATE_STOP)
170 {
171 // reset start stream
172 m_IrpQueue->CancelBuffers(); //FIX function name
173 //This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup);
174 // increase stop counter
175 m_StopCount++;
176 // get current data threshold
177 MinimumDataThreshold = m_IrpQueue->GetMinimumDataThreshold();
178 // get maximum data threshold
179 MaximumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)m_Format)->WaveFormatEx.nAvgBytesPerSec;
180 // increase minimum data threshold by 10 frames
181 MinimumDataThreshold += m_AllocatorFraming.FrameSize * 10;
182
183 // assure it has not exceeded
184 MinimumDataThreshold = min(MinimumDataThreshold, MaximumDataThreshold);
185 // store minimum data threshold
186 m_IrpQueue->SetMinimumDataThreshold(MinimumDataThreshold);
187
188 DPRINT1("Stopping PreCompleted %u PostCompleted %u StopCount %u MinimumDataThreshold %u\n", m_PreCompleted, m_PostCompleted, m_StopCount, MinimumDataThreshold);
189 }
190 if (m_State == KSSTATE_RUN)
191 {
192 // start the notification timer
193 //m_ServiceGroup->RequestDelayedService(m_ServiceGroup, m_Delay);
194 }
195 }
196
197
198 }
199
200 VOID
201 NTAPI
202 PinWavePciSetStreamWorkerRoutine(
203 IN PDEVICE_OBJECT DeviceObject,
204 IN PVOID Context)
205 {
206 CPortPinWavePci * This;
207 PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
208 KSSTATE State;
209
210 This = Ctx->Pin;
211 State = Ctx->State;
212
213 IoFreeWorkItem(Ctx->WorkItem);
214 FreeItem(Ctx, TAG_PORTCLASS);
215
216 This->SetState(State);
217 }
218
219 VOID
220 NTAPI
221 CPortPinWavePci::SetStreamState(
222 IN KSSTATE State)
223 {
224 PDEVICE_OBJECT DeviceObject;
225 PIO_WORKITEM WorkItem;
226 PSETSTREAM_CONTEXT Context;
227
228 PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
229
230 // Has the audio stream resumed?
231 if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
232 return;
233
234 // Has the audio state already been set?
235 if (m_State == State)
236 return;
237
238 // Get device object
239 DeviceObject = GetDeviceObjectFromPortWavePci(m_Port);
240
241 // allocate set state context
242 Context = (PSETSTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
243
244 if (!Context)
245 return;
246
247 // allocate work item
248 WorkItem = IoAllocateWorkItem(DeviceObject);
249
250 if (!WorkItem)
251 {
252 ExFreePool(Context);
253 return;
254 }
255
256 Context->Pin = this;
257 Context->WorkItem = WorkItem;
258 Context->State = State;
259
260 // queue the work item
261 IoQueueWorkItem(WorkItem, PinWavePciSetStreamWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
262 }
263
264
265 VOID
266 NTAPI
267 CPortPinWavePci::RequestService()
268 {
269 PC_ASSERT_IRQL(DISPATCH_LEVEL);
270
271 if (m_IrpQueue->HasLastMappingFailed())
272 {
273 if (m_IrpQueue->NumMappings() == 0)
274 {
275 DPRINT("Stopping stream...\n");
276 SetStreamState(KSSTATE_STOP);
277 return;
278 }
279 }
280
281 m_Stream->Service();
282 //TODO
283 //generate events
284 }
285
286 //==================================================================================================================================
287
288 NTSTATUS
289 NTAPI
290 CPortPinWavePci::NewIrpTarget(
291 OUT struct IIrpTarget **OutTarget,
292 IN PCWSTR Name,
293 IN PUNKNOWN Unknown,
294 IN POOL_TYPE PoolType,
295 IN PDEVICE_OBJECT DeviceObject,
296 IN PIRP Irp,
297 IN KSOBJECT_CREATE *CreateObject)
298 {
299 UNIMPLEMENTED
300
301 Irp->IoStatus.Information = 0;
302 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
303 IoCompleteRequest(Irp, IO_NO_INCREMENT);
304
305 return STATUS_UNSUCCESSFUL;
306 }
307
308 NTSTATUS
309 NTAPI
310 CPortPinWavePci::HandleKsProperty(
311 IN PVOID InputBuffer,
312 IN ULONG InputBufferLength,
313 IN PVOID OutputBuffer,
314 IN ULONG OutputBufferLength,
315 IN PIO_STATUS_BLOCK IoStatusBlock)
316 {
317 PKSPROPERTY Property;
318 NTSTATUS Status;
319 UNICODE_STRING GuidString;
320
321 DPRINT("IPortPinWavePci_HandleKsProperty entered\n");
322
323 if (InputBufferLength < sizeof(KSPROPERTY))
324 {
325 IoStatusBlock->Information = 0;
326 IoStatusBlock->Status = STATUS_INVALID_PARAMETER;
327 return STATUS_INVALID_PARAMETER;
328 }
329
330 Property = (PKSPROPERTY)InputBuffer;
331
332 if (IsEqualGUIDAligned(Property->Set, KSPROPSETID_Connection))
333 {
334 if (Property->Id == KSPROPERTY_CONNECTION_STATE)
335 {
336 PKSSTATE State = (PKSSTATE)OutputBuffer;
337
338 PC_ASSERT_IRQL(DISPATCH_LEVEL);
339 if (OutputBufferLength < sizeof(KSSTATE))
340 {
341 IoStatusBlock->Information = sizeof(KSSTATE);
342 IoStatusBlock->Status = STATUS_BUFFER_TOO_SMALL;
343 return STATUS_BUFFER_TOO_SMALL;
344 }
345
346 if (Property->Flags & KSPROPERTY_TYPE_SET)
347 {
348 Status = STATUS_UNSUCCESSFUL;
349 IoStatusBlock->Information = 0;
350
351 if (m_Stream)
352 {
353 Status = m_Stream->SetState(*State);
354
355 DPRINT1("Setting state %u %x\n", *State, Status);
356 if (NT_SUCCESS(Status))
357 {
358 m_State = *State;
359 }
360 }
361 IoStatusBlock->Status = Status;
362 return Status;
363 }
364 else if (Property->Flags & KSPROPERTY_TYPE_GET)
365 {
366 *State = m_State;
367 IoStatusBlock->Information = sizeof(KSSTATE);
368 IoStatusBlock->Status = STATUS_SUCCESS;
369 return STATUS_SUCCESS;
370 }
371 }
372 else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
373 {
374 PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)OutputBuffer;
375 if (Property->Flags & KSPROPERTY_TYPE_SET)
376 {
377 PKSDATAFORMAT NewDataFormat;
378 if (!RtlCompareMemory(DataFormat, m_Format, DataFormat->FormatSize))
379 {
380 IoStatusBlock->Information = DataFormat->FormatSize;
381 IoStatusBlock->Status = STATUS_SUCCESS;
382 return STATUS_SUCCESS;
383 }
384
385 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
386 if (!NewDataFormat)
387 {
388 IoStatusBlock->Information = 0;
389 IoStatusBlock->Status = STATUS_NO_MEMORY;
390 return STATUS_NO_MEMORY;
391 }
392 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
393
394 if (m_Stream)
395 {
396 #if 0
397 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
398 ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
399 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
400 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
401 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
402
403 ASSERT(This->State == KSSTATE_STOP);
404 #endif
405 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
406 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
407 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
408
409 Status = m_Stream->SetFormat(NewDataFormat);
410 if (NT_SUCCESS(Status))
411 {
412 if (m_Format)
413 ExFreePoolWithTag(m_Format, TAG_PORTCLASS);
414
415 m_IrpQueue->UpdateFormat((PKSDATAFORMAT)NewDataFormat);
416 m_Format = NewDataFormat;
417 IoStatusBlock->Information = DataFormat->FormatSize;
418 IoStatusBlock->Status = STATUS_SUCCESS;
419 return STATUS_SUCCESS;
420 }
421 }
422 DPRINT1("Failed to set format\n");
423 IoStatusBlock->Information = 0;
424 IoStatusBlock->Status = STATUS_UNSUCCESSFUL;
425 return STATUS_UNSUCCESSFUL;
426 }
427 else if (Property->Flags & KSPROPERTY_TYPE_GET)
428 {
429 if (!m_Format)
430 {
431 DPRINT1("No format\n");
432 IoStatusBlock->Information = 0;
433 IoStatusBlock->Status = STATUS_UNSUCCESSFUL;
434 return STATUS_UNSUCCESSFUL;
435 }
436 if (m_Format->FormatSize > OutputBufferLength)
437 {
438 IoStatusBlock->Information = m_Format->FormatSize;
439 IoStatusBlock->Status = STATUS_BUFFER_TOO_SMALL;
440 return STATUS_BUFFER_TOO_SMALL;
441 }
442
443 RtlMoveMemory(DataFormat, m_Format, m_Format->FormatSize);
444 IoStatusBlock->Information = DataFormat->FormatSize;
445 IoStatusBlock->Status = STATUS_SUCCESS;
446 return STATUS_SUCCESS;
447 }
448 }
449 else if (Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING)
450 {
451 PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING)OutputBuffer;
452
453 PC_ASSERT_IRQL(DISPATCH_LEVEL);
454 // Validate input buffer
455 if (OutputBufferLength < sizeof(KSALLOCATOR_FRAMING))
456 {
457 IoStatusBlock->Information = sizeof(KSALLOCATOR_FRAMING);
458 IoStatusBlock->Status = STATUS_BUFFER_TOO_SMALL;
459 return STATUS_BUFFER_TOO_SMALL;
460 }
461 // copy frame allocator struct
462 RtlMoveMemory(Framing, &m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
463
464 IoStatusBlock->Information = sizeof(KSALLOCATOR_FRAMING);
465 IoStatusBlock->Status = STATUS_SUCCESS;
466 return STATUS_SUCCESS;
467 }
468 }
469
470 RtlStringFromGUID(Property->Set, &GuidString);
471 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
472 RtlFreeUnicodeString(&GuidString);
473
474 IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED;
475 IoStatusBlock->Information = 0;
476 return STATUS_NOT_IMPLEMENTED;
477 }
478
479 NTSTATUS
480 NTAPI
481 CPortPinWavePci::DeviceIoControl(
482 IN PDEVICE_OBJECT DeviceObject,
483 IN PIRP Irp)
484 {
485 PIO_STACK_LOCATION IoStack;
486 NTSTATUS Status;
487
488 IoStack = IoGetCurrentIrpStackLocation(Irp);
489
490 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
491 {
492 Status = HandleKsProperty(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, IoStack->Parameters.DeviceIoControl.InputBufferLength, Irp->UserBuffer, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &Irp->IoStatus);
493 IoCompleteRequest(Irp, IO_NO_INCREMENT);
494 return Status;
495 }
496
497
498 UNIMPLEMENTED
499
500 Irp->IoStatus.Information = 0;
501 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
502 IoCompleteRequest(Irp, IO_NO_INCREMENT);
503
504 return STATUS_UNSUCCESSFUL;
505 }
506
507 NTSTATUS
508 NTAPI
509 CPortPinWavePci::Read(
510 IN PDEVICE_OBJECT DeviceObject,
511 IN PIRP Irp)
512 {
513 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
514 }
515
516 NTSTATUS
517 NTAPI
518 CPortPinWavePci::Write(
519 IN PDEVICE_OBJECT DeviceObject,
520 IN PIRP Irp)
521 {
522 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
523 }
524
525 NTSTATUS
526 NTAPI
527 CPortPinWavePci::Flush(
528 IN PDEVICE_OBJECT DeviceObject,
529 IN PIRP Irp)
530 {
531 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
532 }
533
534 VOID
535 NTAPI
536 CPortPinWavePci::CloseStream()
537 {
538 PMINIPORTWAVEPCISTREAM Stream;
539 ISubdevice *ISubDevice;
540 NTSTATUS Status;
541 PSUBDEVICE_DESCRIPTOR Descriptor;
542
543 if (m_Stream)
544 {
545 if (m_State != KSSTATE_STOP)
546 {
547 m_Stream->SetState(KSSTATE_STOP);
548 }
549 }
550
551 if (m_ServiceGroup)
552 {
553 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
554 }
555
556 Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
557 if (NT_SUCCESS(Status))
558 {
559 Status = ISubDevice->GetDescriptor(&Descriptor);
560 if (NT_SUCCESS(Status))
561 {
562 Descriptor->Factory.Instances[m_ConnectDetails->PinId].CurrentPinInstanceCount--;
563 }
564 ISubDevice->Release();
565 }
566
567 if (m_Format)
568 {
569 ExFreePool(m_Format);
570 m_Format = NULL;
571 }
572
573 if (m_Stream)
574 {
575 Stream = m_Stream;
576 m_Stream = 0;
577 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
578 Stream->Release();
579 }
580 }
581
582 VOID
583 NTAPI
584 PinWavePciCloseStreamRoutine(
585 IN PDEVICE_OBJECT DeviceObject,
586 IN PVOID Context)
587 {
588 CPortPinWavePci * This;
589 PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
590
591 This = (CPortPinWavePci*)Ctx->Pin;
592
593 This->CloseStream();
594
595 // complete the irp
596 Ctx->Irp->IoStatus.Information = 0;
597 Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
598 IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
599
600 // free the work item
601 IoFreeWorkItem(Ctx->WorkItem);
602
603 // free work item ctx
604 FreeItem(Ctx, TAG_PORTCLASS);
605 }
606
607 NTSTATUS
608 NTAPI
609 CPortPinWavePci::Close(
610 IN PDEVICE_OBJECT DeviceObject,
611 IN PIRP Irp)
612 {
613 PCLOSESTREAM_CONTEXT Ctx;
614
615 if (m_Stream)
616 {
617 Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
618 if (!Ctx)
619 {
620 DPRINT1("Failed to allocate stream context\n");
621 goto cleanup;
622 }
623
624 Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
625 if (!Ctx->WorkItem)
626 {
627 DPRINT1("Failed to allocate work item\n");
628 goto cleanup;
629 }
630
631 Ctx->Irp = Irp;
632 Ctx->Pin = (PVOID)this;
633
634 IoMarkIrpPending(Irp);
635 Irp->IoStatus.Information = 0;
636 Irp->IoStatus.Status = STATUS_PENDING;
637
638 // defer work item
639 IoQueueWorkItem(Ctx->WorkItem, PinWavePciCloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
640 // Return result
641 return STATUS_PENDING;
642 }
643
644 Irp->IoStatus.Information = 0;
645 Irp->IoStatus.Status = STATUS_SUCCESS;
646 IoCompleteRequest(Irp, IO_NO_INCREMENT);
647
648 return STATUS_SUCCESS;
649
650 cleanup:
651
652 if (Ctx)
653 FreeItem(Ctx, TAG_PORTCLASS);
654
655 Irp->IoStatus.Information = 0;
656 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
657 IoCompleteRequest(Irp, IO_NO_INCREMENT);
658 return STATUS_UNSUCCESSFUL;
659
660 }
661
662 NTSTATUS
663 NTAPI
664 CPortPinWavePci::QuerySecurity(
665 IN PDEVICE_OBJECT DeviceObject,
666 IN PIRP Irp)
667 {
668 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
669 }
670
671 NTSTATUS
672 NTAPI
673 CPortPinWavePci::SetSecurity(
674 IN PDEVICE_OBJECT DeviceObject,
675 IN PIRP Irp)
676 {
677 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
678 }
679
680 BOOLEAN
681 NTAPI
682 CPortPinWavePci::FastDeviceIoControl(
683 IN PFILE_OBJECT FileObject,
684 IN BOOLEAN Wait,
685 IN PVOID InputBuffer,
686 IN ULONG InputBufferLength,
687 OUT PVOID OutputBuffer,
688 IN ULONG OutputBufferLength,
689 IN ULONG IoControlCode,
690 OUT PIO_STATUS_BLOCK StatusBlock,
691 IN PDEVICE_OBJECT DeviceObject)
692 {
693 return FALSE;
694 }
695
696 BOOLEAN
697 NTAPI
698 CPortPinWavePci::FastRead(
699 IN PFILE_OBJECT FileObject,
700 IN PLARGE_INTEGER FileOffset,
701 IN ULONG Length,
702 IN BOOLEAN Wait,
703 IN ULONG LockKey,
704 IN PVOID Buffer,
705 OUT PIO_STATUS_BLOCK StatusBlock,
706 IN PDEVICE_OBJECT DeviceObject)
707 {
708 return FALSE;
709 }
710
711 BOOLEAN
712 NTAPI
713 CPortPinWavePci::FastWrite(
714 IN PFILE_OBJECT FileObject,
715 IN PLARGE_INTEGER FileOffset,
716 IN ULONG Length,
717 IN BOOLEAN Wait,
718 IN ULONG LockKey,
719 IN PVOID Buffer,
720 OUT PIO_STATUS_BLOCK StatusBlock,
721 IN PDEVICE_OBJECT DeviceObject)
722 {
723 return FALSE;
724 }
725
726
727 NTSTATUS
728 NTAPI
729 CPortPinWavePci::Init(
730 IN PPORTWAVEPCI Port,
731 IN PPORTFILTERWAVEPCI Filter,
732 IN KSPIN_CONNECT * ConnectDetails,
733 IN KSPIN_DESCRIPTOR * KsPinDescriptor,
734 IN PDEVICE_OBJECT DeviceObject)
735 {
736 NTSTATUS Status;
737 PKSDATAFORMAT DataFormat;
738 BOOL Capture;
739
740 Port->AddRef();
741 Filter->AddRef();
742
743 m_Port = Port;
744 m_Filter = Filter;
745 m_KsPinDescriptor = KsPinDescriptor;
746 m_ConnectDetails = ConnectDetails;
747 m_Miniport = GetWavePciMiniport(Port);
748 m_DeviceObject = DeviceObject;
749
750 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
751
752 DPRINT("IPortPinWavePci_fnInit entered\n");
753
754 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
755 if (!m_Format)
756 return STATUS_INSUFFICIENT_RESOURCES;
757
758 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
759
760 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
761 {
762 Capture = FALSE;
763 }
764 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
765 {
766 Capture = TRUE;
767 }
768 else
769 {
770 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
771 KeBugCheck(0);
772 }
773
774 Status = m_Miniport->NewStream(&m_Stream,
775 NULL,
776 NonPagedPool,
777 PPORTWAVEPCISTREAM(this),
778 ConnectDetails->PinId,
779 Capture,
780 m_Format,
781 &m_DmaChannel,
782 &m_ServiceGroup);
783
784 DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
785
786 if (!NT_SUCCESS(Status))
787 return Status;
788
789 if (m_ServiceGroup)
790 {
791 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
792 if (!NT_SUCCESS(Status))
793 {
794 DPRINT1("Failed to add pin to service group\n");
795 return Status;
796 }
797 m_ServiceGroup->SupportDelayedService();
798 }
799
800 // delay of 10 milisec
801 m_Delay = Int32x32To64(10, -10000);
802
803 Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
804 if (!NT_SUCCESS(Status))
805 {
806 DPRINT1("GetAllocatorFraming failed with %x\n", Status);
807 return Status;
808 }
809
810 DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
811 m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
812
813 Status = NewIrpQueue(&m_IrpQueue);
814 if (!NT_SUCCESS(Status))
815 return Status;
816
817 Status = m_IrpQueue->Init(ConnectDetails, m_Format, DeviceObject, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, NULL);
818 if (!NT_SUCCESS(Status))
819 {
820 DPRINT1("IrpQueue_Init failed with %x\n", Status);
821 return Status;
822 }
823
824 m_State = KSSTATE_STOP;
825 m_Capture = Capture;
826
827 return STATUS_SUCCESS;
828 }
829
830 PVOID
831 NTAPI
832 CPortPinWavePci::GetIrpStream()
833 {
834 return (PVOID)m_IrpQueue;
835 }
836
837
838 PMINIPORT
839 NTAPI
840 CPortPinWavePci::GetMiniport()
841 {
842 return (PMINIPORT)m_Miniport;
843 }
844
845
846 NTSTATUS
847 NewPortPinWavePci(
848 OUT IPortPinWavePci ** OutPin)
849 {
850 CPortPinWavePci * This;
851
852 This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWavePci(NULL);
853 if (!This)
854 return STATUS_INSUFFICIENT_RESOURCES;
855
856 This->AddRef();
857
858 // store result
859 *OutPin = (IPortPinWavePci*)This;
860
861 return STATUS_SUCCESS;
862 }
863