sync with trunk r47227
[reactos.git] / 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 protected:
40
41 friend NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
42 friend NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
43 friend NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
44 friend NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
45
46 IPortWavePci * m_Port;
47 IPortFilterWavePci * m_Filter;
48 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
49 PMINIPORTWAVEPCI m_Miniport;
50 PSERVICEGROUP m_ServiceGroup;
51 PDMACHANNEL m_DmaChannel;
52 PMINIPORTWAVEPCISTREAM m_Stream;
53 KSSTATE m_State;
54 PKSDATAFORMAT m_Format;
55 KSPIN_CONNECT * m_ConnectDetails;
56
57 BOOL m_Capture;
58 PDEVICE_OBJECT m_DeviceObject;
59 IIrpQueue * m_IrpQueue;
60
61 ULONG m_TotalPackets;
62 KSAUDIO_POSITION m_Position;
63 ULONG m_StopCount;
64
65 ULONG m_Delay;
66
67 BOOL m_bUsePrefetch;
68 ULONG m_PrefetchOffset;
69 SUBDEVICE_DESCRIPTOR m_Descriptor;
70
71 KSALLOCATOR_FRAMING m_AllocatorFraming;
72
73 LONG m_Ref;
74
75 NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
76 NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
77 };
78
79 typedef struct
80 {
81 CPortPinWavePci *Pin;
82 PIO_WORKITEM WorkItem;
83 KSSTATE State;
84 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
85
86 NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
87 NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
88 NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
89 NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
90
91 DEFINE_KSPROPERTY_CONNECTIONSET(PinWavePciConnectionSet, PinWavePciState, PinWavePciDataFormat, PinWavePciAllocatorFraming);
92 DEFINE_KSPROPERTY_AUDIOSET(PinWavePciAudioSet, PinWavePciAudioPosition);
93
94 KSPROPERTY_SET PinWavePciPropertySet[] =
95 {
96 {
97 &KSPROPSETID_Connection,
98 sizeof(PinWavePciConnectionSet) / sizeof(KSPROPERTY_ITEM),
99 (const KSPROPERTY_ITEM*)&PinWavePciConnectionSet,
100 0,
101 NULL
102 },
103 {
104 &KSPROPSETID_Audio,
105 sizeof(PinWavePciAudioSet) / sizeof(KSPROPERTY_ITEM),
106 (const KSPROPERTY_ITEM*)&PinWavePciAudioSet,
107 0,
108 NULL
109 }
110 };
111
112
113 NTSTATUS
114 NTAPI
115 PinWavePciAllocatorFraming(
116 IN PIRP Irp,
117 IN PKSIDENTIFIER Request,
118 IN OUT PVOID Data)
119 {
120 CPortPinWavePci *Pin;
121 PSUBDEVICE_DESCRIPTOR Descriptor;
122
123 // get sub device descriptor
124 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
125
126 // sanity check
127 PC_ASSERT(Descriptor);
128 PC_ASSERT(Descriptor->PortPin);
129 PC_ASSERT_IRQL(DISPATCH_LEVEL);
130
131 // cast to pin impl
132 Pin = (CPortPinWavePci*)Descriptor->PortPin;
133
134
135 if (Request->Flags & KSPROPERTY_TYPE_GET)
136 {
137 // copy pin framing
138 RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
139
140 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
141 return STATUS_SUCCESS;
142 }
143
144 // not supported
145 return STATUS_NOT_SUPPORTED;
146 }
147
148 NTSTATUS
149 NTAPI
150 PinWavePciAudioPosition(
151 IN PIRP Irp,
152 IN PKSIDENTIFIER Request,
153 IN OUT PVOID Data)
154 {
155 CPortPinWavePci *Pin;
156 PSUBDEVICE_DESCRIPTOR Descriptor;
157
158 // get sub device descriptor
159 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
160
161 // sanity check
162 PC_ASSERT(Descriptor);
163 PC_ASSERT(Descriptor->PortPin);
164 PC_ASSERT_IRQL(DISPATCH_LEVEL);
165
166 // cast to pin impl
167 Pin = (CPortPinWavePci*)Descriptor->PortPin;
168
169 //sanity check
170 PC_ASSERT(Pin->m_Stream);
171
172 if (Request->Flags & KSPROPERTY_TYPE_GET)
173 {
174 // FIXME non multithreading-safe
175 // copy audio position
176 RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
177
178 DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
179 Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
180 return STATUS_SUCCESS;
181 }
182
183 // not supported
184 return STATUS_NOT_SUPPORTED;
185 }
186
187
188 NTSTATUS
189 NTAPI
190 PinWavePciState(
191 IN PIRP Irp,
192 IN PKSIDENTIFIER Request,
193 IN OUT PVOID Data)
194 {
195 NTSTATUS Status = STATUS_UNSUCCESSFUL;
196 CPortPinWavePci *Pin;
197 PSUBDEVICE_DESCRIPTOR Descriptor;
198 PVOID FirstTag, LastTag;
199 ULONG MappingsRevoked;
200 PKSSTATE State = (PKSSTATE)Data;
201
202 // get sub device descriptor
203 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
204
205 // sanity check
206 PC_ASSERT(Descriptor);
207 PC_ASSERT(Descriptor->PortPin);
208 PC_ASSERT_IRQL(DISPATCH_LEVEL);
209
210 // cast to pin impl
211 Pin = (CPortPinWavePci*)Descriptor->PortPin;
212
213 //sanity check
214 PC_ASSERT(Pin->m_Stream);
215
216 if (Request->Flags & KSPROPERTY_TYPE_SET)
217 {
218 // try set stream
219 Status = Pin->m_Stream->SetState(*State);
220
221 DPRINT("Setting state %u %x\n", *State, Status);
222 if (NT_SUCCESS(Status))
223 {
224 // store new state
225 Pin->m_State = *State;
226 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP)
227 {
228 // FIXME
229 // complete with successful state
230 Pin->m_IrpQueue->CancelBuffers();
231 while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag))
232 {
233 Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked);
234 DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked);
235 KeStallExecutionProcessor(10);
236 }
237 Pin->m_Position.PlayOffset = 0;
238 Pin->m_Position.WriteOffset = 0;
239 }
240 else if (Pin->m_State == KSSTATE_STOP)
241 {
242 Pin->m_IrpQueue->CancelBuffers();
243 while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag))
244 {
245 Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked);
246 DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked);
247 KeStallExecutionProcessor(10);
248 }
249 Pin->m_Position.PlayOffset = 0;
250 Pin->m_Position.WriteOffset = 0;
251 }
252 // store result
253 Irp->IoStatus.Information = sizeof(KSSTATE);
254
255 }
256 // store result
257 Irp->IoStatus.Information = sizeof(KSSTATE);
258 return Status;
259 }
260 else if (Request->Flags & KSPROPERTY_TYPE_GET)
261 {
262 // get current stream state
263 *State = Pin->m_State;
264 // store result
265 Irp->IoStatus.Information = sizeof(KSSTATE);
266
267 return STATUS_SUCCESS;
268 }
269
270 // unsupported request
271 return STATUS_NOT_SUPPORTED;
272 }
273
274 NTSTATUS
275 NTAPI
276 PinWavePciDataFormat(
277 IN PIRP Irp,
278 IN PKSIDENTIFIER Request,
279 IN OUT PVOID Data)
280 {
281 NTSTATUS Status = STATUS_UNSUCCESSFUL;
282 CPortPinWavePci *Pin;
283 PSUBDEVICE_DESCRIPTOR Descriptor;
284 PIO_STACK_LOCATION IoStack;
285
286 // get current irp stack location
287 IoStack = IoGetCurrentIrpStackLocation(Irp);
288
289 // get sub device descriptor
290 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
291
292 // sanity check
293 PC_ASSERT(Descriptor);
294 PC_ASSERT(Descriptor->PortPin);
295
296 // cast to pin impl
297 Pin = (CPortPinWavePci*)Descriptor->PortPin;
298
299 //sanity check
300 PC_ASSERT(Pin->m_Stream);
301 PC_ASSERT(Pin->m_Format);
302
303 if (Request->Flags & KSPROPERTY_TYPE_SET)
304 {
305 // try to change data format
306 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
307 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
308
309 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
310 {
311 // format is identical
312 Irp->IoStatus.Information = DataFormat->FormatSize;
313 return STATUS_SUCCESS;
314 }
315
316 // new change request
317 PC_ASSERT(Pin->m_State == KSSTATE_STOP);
318 // FIXME queue a work item when Irql != PASSIVE_LEVEL
319 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
320
321 // allocate new data format
322 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
323 if (!NewDataFormat)
324 {
325 // not enough memory
326 return STATUS_NO_MEMORY;
327 }
328
329 // copy new data format
330 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
331
332 // set new format
333 Status = Pin->m_Stream->SetFormat(NewDataFormat);
334 if (NT_SUCCESS(Status))
335 {
336 // free old format
337 FreeItem(Pin->m_Format, TAG_PORTCLASS);
338
339 // store new format
340 Pin->m_Format = NewDataFormat;
341 Irp->IoStatus.Information = NewDataFormat->FormatSize;
342
343 #if 0
344 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
345 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
346 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
347 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
348
349
350 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
351 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
352 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
353 #endif
354
355 }
356 else
357 {
358 // failed to set format
359 FreeItem(NewDataFormat, TAG_PORTCLASS);
360 }
361
362
363 // done
364 return Status;
365 }
366 else if (Request->Flags & KSPROPERTY_TYPE_GET)
367 {
368 // get current data format
369 PC_ASSERT(Pin->m_Format);
370
371 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
372 {
373 // buffer too small
374 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
375 return STATUS_MORE_ENTRIES;
376 }
377 // copy data format
378 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
379 // store result size
380 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
381
382 // done
383 return STATUS_SUCCESS;
384 }
385
386 // unsupported request
387 return STATUS_NOT_SUPPORTED;
388 }
389
390
391 //==================================================================================================================================
392 NTSTATUS
393 NTAPI
394 CPortPinWavePci::QueryInterface(
395 IN REFIID refiid,
396 OUT PVOID* Output)
397 {
398 //DPRINT("CPortPinWavePci::QueryInterface entered\n");
399
400 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
401 IsEqualGUIDAligned(refiid, IID_IUnknown))
402 {
403 *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
404 PUNKNOWN(*Output)->AddRef();
405 return STATUS_SUCCESS;
406 }
407
408 if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
409 {
410 *Output = PVOID(PSERVICESINK(this));
411 PUNKNOWN(*Output)->AddRef();
412 return STATUS_SUCCESS;
413 }
414
415
416 if (IsEqualGUIDAligned(refiid, IID_IPortWavePciStream))
417 {
418 *Output = PVOID(PPORTWAVEPCISTREAM(this));
419 PUNKNOWN(*Output)->AddRef();
420 return STATUS_SUCCESS;
421 }
422
423 return STATUS_UNSUCCESSFUL;
424 }
425
426 NTSTATUS
427 NTAPI
428 CPortPinWavePci::GetMapping(
429 IN PVOID Tag,
430 OUT PPHYSICAL_ADDRESS PhysicalAddress,
431 OUT PVOID *VirtualAddress,
432 OUT PULONG ByteCount,
433 OUT PULONG Flags)
434 {
435
436 PC_ASSERT_IRQL(DISPATCH_LEVEL);
437 return m_IrpQueue->GetMappingWithTag(Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags);
438 }
439
440 NTSTATUS
441 NTAPI
442 CPortPinWavePci::ReleaseMapping(
443 IN PVOID Tag)
444 {
445
446 PC_ASSERT_IRQL(DISPATCH_LEVEL);
447 return m_IrpQueue->ReleaseMappingWithTag(Tag);
448 }
449
450 NTSTATUS
451 NTAPI
452 CPortPinWavePci::TerminatePacket()
453 {
454 UNIMPLEMENTED
455 PC_ASSERT_IRQL(DISPATCH_LEVEL);
456 return STATUS_SUCCESS;
457 }
458
459
460 VOID
461 NTAPI
462 CPortPinWavePci::RequestService()
463 {
464 PC_ASSERT_IRQL(DISPATCH_LEVEL);
465
466 if (m_State == KSSTATE_RUN)
467 {
468 m_Stream->Service();
469 //TODO
470 //generate events
471 }
472 }
473
474 //==================================================================================================================================
475
476 NTSTATUS
477 NTAPI
478 CPortPinWavePci::NewIrpTarget(
479 OUT struct IIrpTarget **OutTarget,
480 IN PCWSTR Name,
481 IN PUNKNOWN Unknown,
482 IN POOL_TYPE PoolType,
483 IN PDEVICE_OBJECT DeviceObject,
484 IN PIRP Irp,
485 IN KSOBJECT_CREATE *CreateObject)
486 {
487 UNIMPLEMENTED
488
489 Irp->IoStatus.Information = 0;
490 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
491 IoCompleteRequest(Irp, IO_NO_INCREMENT);
492
493 return STATUS_UNSUCCESSFUL;
494 }
495
496 NTSTATUS
497 NTAPI
498 CPortPinWavePci::HandleKsProperty(
499 IN PIRP Irp)
500 {
501 PKSPROPERTY Property;
502 NTSTATUS Status;
503 //UNICODE_STRING GuidString;
504 PIO_STACK_LOCATION IoStack;
505
506 IoStack = IoGetCurrentIrpStackLocation(Irp);
507
508 //DPRINT("IPortPinWave_HandleKsProperty entered\n");
509
510 IoStack = IoGetCurrentIrpStackLocation(Irp);
511
512 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
513 {
514 //DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
515
516 Irp->IoStatus.Status = STATUS_SUCCESS;
517
518 IoCompleteRequest(Irp, IO_NO_INCREMENT);
519 return STATUS_SUCCESS;
520 }
521
522 Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
523
524 if (Status == STATUS_NOT_FOUND)
525 {
526 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
527 #if 0
528 RtlStringFromGUID(Property->Set, &GuidString);
529 //DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
530 RtlFreeUnicodeString(&GuidString);
531 #endif
532 }
533
534 if (Status != STATUS_PENDING)
535 {
536 Irp->IoStatus.Status = Status;
537 IoCompleteRequest(Irp, IO_NO_INCREMENT);
538 }
539
540 return Status;
541 }
542
543 NTSTATUS
544 NTAPI
545 CPortPinWavePci::HandleKsStream(
546 IN PIRP Irp)
547 {
548 NTSTATUS Status;
549 ULONG Data = 0;
550 BOOLEAN bFailed;
551 InterlockedIncrement((PLONG)&m_TotalPackets);
552
553 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
554
555 bFailed = m_IrpQueue->HasLastMappingFailed();
556
557 Status = m_IrpQueue->AddMapping(Irp, &Data);
558
559 if (NT_SUCCESS(Status))
560 {
561 if (m_Capture)
562 m_Position.WriteOffset += Data;
563 else
564 m_Position.WriteOffset += Data;
565
566 if (bFailed)
567 {
568 // notify stream of new mapping
569 m_Stream->MappingAvailable();
570 }
571
572 return STATUS_PENDING;
573 }
574
575 return Status;
576 }
577
578
579 NTSTATUS
580 NTAPI
581 CPortPinWavePci::DeviceIoControl(
582 IN PDEVICE_OBJECT DeviceObject,
583 IN PIRP Irp)
584 {
585 PIO_STACK_LOCATION IoStack;
586
587 IoStack = IoGetCurrentIrpStackLocation(Irp);
588
589 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
590 {
591 return HandleKsProperty(Irp);
592 }
593 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
594 {
595 return HandleKsStream(Irp);
596 }
597
598 UNIMPLEMENTED
599
600 Irp->IoStatus.Information = 0;
601 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
602 IoCompleteRequest(Irp, IO_NO_INCREMENT);
603
604 return STATUS_UNSUCCESSFUL;
605 }
606
607 NTSTATUS
608 NTAPI
609 CPortPinWavePci::Read(
610 IN PDEVICE_OBJECT DeviceObject,
611 IN PIRP Irp)
612 {
613 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
614 }
615
616 NTSTATUS
617 NTAPI
618 CPortPinWavePci::Write(
619 IN PDEVICE_OBJECT DeviceObject,
620 IN PIRP Irp)
621 {
622 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
623 }
624
625 NTSTATUS
626 NTAPI
627 CPortPinWavePci::Flush(
628 IN PDEVICE_OBJECT DeviceObject,
629 IN PIRP Irp)
630 {
631 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
632 }
633
634 NTSTATUS
635 NTAPI
636 CPortPinWavePci::Close(
637 IN PDEVICE_OBJECT DeviceObject,
638 IN PIRP Irp)
639 {
640 ISubdevice *SubDevice;
641 NTSTATUS Status;
642 PSUBDEVICE_DESCRIPTOR Descriptor;
643
644 if (m_ServiceGroup)
645 {
646 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
647 }
648
649 if (m_Stream)
650 {
651 if (m_State != KSSTATE_STOP)
652 {
653 m_Stream->SetState(KSSTATE_STOP);
654 }
655 m_Stream->Release();
656 }
657
658 Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice);
659 if (NT_SUCCESS(Status))
660 {
661 Status = SubDevice->GetDescriptor(&Descriptor);
662 if (NT_SUCCESS(Status))
663 {
664 Descriptor->Factory.Instances[m_ConnectDetails->PinId].CurrentPinInstanceCount--;
665 }
666 SubDevice->Release();
667 }
668
669 if (m_Format)
670 {
671 ExFreePool(m_Format);
672 m_Format = NULL;
673 }
674
675 Irp->IoStatus.Status = STATUS_SUCCESS;
676 Irp->IoStatus.Information = 0;
677 IoCompleteRequest(Irp, IO_NO_INCREMENT);
678
679 return STATUS_SUCCESS;
680 }
681
682 NTSTATUS
683 NTAPI
684 CPortPinWavePci::QuerySecurity(
685 IN PDEVICE_OBJECT DeviceObject,
686 IN PIRP Irp)
687 {
688 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
689 }
690
691 NTSTATUS
692 NTAPI
693 CPortPinWavePci::SetSecurity(
694 IN PDEVICE_OBJECT DeviceObject,
695 IN PIRP Irp)
696 {
697 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
698 }
699
700 BOOLEAN
701 NTAPI
702 CPortPinWavePci::FastDeviceIoControl(
703 IN PFILE_OBJECT FileObject,
704 IN BOOLEAN Wait,
705 IN PVOID InputBuffer,
706 IN ULONG InputBufferLength,
707 OUT PVOID OutputBuffer,
708 IN ULONG OutputBufferLength,
709 IN ULONG IoControlCode,
710 OUT PIO_STATUS_BLOCK StatusBlock,
711 IN PDEVICE_OBJECT DeviceObject)
712 {
713 return FALSE;
714 }
715
716 BOOLEAN
717 NTAPI
718 CPortPinWavePci::FastRead(
719 IN PFILE_OBJECT FileObject,
720 IN PLARGE_INTEGER FileOffset,
721 IN ULONG Length,
722 IN BOOLEAN Wait,
723 IN ULONG LockKey,
724 IN PVOID Buffer,
725 OUT PIO_STATUS_BLOCK StatusBlock,
726 IN PDEVICE_OBJECT DeviceObject)
727 {
728 return FALSE;
729 }
730
731 BOOLEAN
732 NTAPI
733 CPortPinWavePci::FastWrite(
734 IN PFILE_OBJECT FileObject,
735 IN PLARGE_INTEGER FileOffset,
736 IN ULONG Length,
737 IN BOOLEAN Wait,
738 IN ULONG LockKey,
739 IN PVOID Buffer,
740 OUT PIO_STATUS_BLOCK StatusBlock,
741 IN PDEVICE_OBJECT DeviceObject)
742 {
743 return FALSE;
744 }
745
746
747 NTSTATUS
748 NTAPI
749 CPortPinWavePci::Init(
750 IN PPORTWAVEPCI Port,
751 IN PPORTFILTERWAVEPCI Filter,
752 IN KSPIN_CONNECT * ConnectDetails,
753 IN KSPIN_DESCRIPTOR * KsPinDescriptor,
754 IN PDEVICE_OBJECT DeviceObject)
755 {
756 NTSTATUS Status;
757 PKSDATAFORMAT DataFormat;
758 BOOLEAN Capture;
759
760 Port->AddRef();
761 Filter->AddRef();
762
763 m_Port = Port;
764 m_Filter = Filter;
765 m_KsPinDescriptor = KsPinDescriptor;
766 m_ConnectDetails = ConnectDetails;
767 m_Miniport = GetWavePciMiniport(Port);
768 m_DeviceObject = DeviceObject;
769
770 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
771
772 DPRINT("IPortPinWavePci_fnInit entered\n");
773
774 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
775 if (!m_Format)
776 return STATUS_INSUFFICIENT_RESOURCES;
777
778 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
779
780 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
781 {
782 Capture = FALSE;
783 }
784 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
785 {
786 Capture = TRUE;
787 }
788 else
789 {
790 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
791 DbgBreakPoint();
792 while(TRUE);
793 }
794
795 Status = m_Miniport->NewStream(&m_Stream,
796 NULL,
797 NonPagedPool,
798 PPORTWAVEPCISTREAM(this),
799 ConnectDetails->PinId,
800 Capture,
801 m_Format,
802 &m_DmaChannel,
803 &m_ServiceGroup);
804
805 DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
806
807 if (!NT_SUCCESS(Status))
808 return Status;
809
810 if (m_ServiceGroup)
811 {
812 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
813 if (!NT_SUCCESS(Status))
814 {
815 DPRINT("Failed to add pin to service group\n");
816 return Status;
817 }
818 }
819
820 // delay of 10 milisec
821 m_Delay = Int32x32To64(10, -10000);
822
823 Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
824 if (!NT_SUCCESS(Status))
825 {
826 DPRINT("GetAllocatorFraming failed with %x\n", Status);
827 return Status;
828 }
829
830 DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
831 m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
832
833 ISubdevice * Subdevice = NULL;
834 // get subdevice interface
835 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
836
837 if (!NT_SUCCESS(Status))
838 return Status;
839
840 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
841
842 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
843 if (!NT_SUCCESS(Status))
844 {
845 // failed to get descriptor
846 Subdevice->Release();
847 return Status;
848 }
849
850 /* set up subdevice descriptor */
851 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
852 m_Descriptor.FilterPropertySet = PinWavePciPropertySet;
853 m_Descriptor.FilterPropertySetCount = sizeof(PinWavePciPropertySet) / sizeof(KSPROPERTY_SET);
854 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
855 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
856 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
857 m_Descriptor.PortPin = (PVOID)this;
858
859
860
861 Status = NewIrpQueue(&m_IrpQueue);
862 if (!NT_SUCCESS(Status))
863 return Status;
864
865 Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, NULL);
866 if (!NT_SUCCESS(Status))
867 {
868 DPRINT("IrpQueue_Init failed with %x\n", Status);
869 return Status;
870 }
871
872 m_State = KSSTATE_STOP;
873 m_Capture = Capture;
874
875 return STATUS_SUCCESS;
876 }
877
878 PVOID
879 NTAPI
880 CPortPinWavePci::GetIrpStream()
881 {
882 return (PVOID)m_IrpQueue;
883 }
884
885
886 PMINIPORT
887 NTAPI
888 CPortPinWavePci::GetMiniport()
889 {
890 return (PMINIPORT)m_Miniport;
891 }
892
893
894 NTSTATUS
895 NewPortPinWavePci(
896 OUT IPortPinWavePci ** OutPin)
897 {
898 CPortPinWavePci * This;
899
900 This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWavePci(NULL);
901 if (!This)
902 return STATUS_INSUFFICIENT_RESOURCES;
903
904 This->AddRef();
905
906 // store result
907 *OutPin = (IPortPinWavePci*)This;
908
909 return STATUS_SUCCESS;
910 }
911