ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pin_wavecyclic.cpp
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
00005  * PURPOSE:         WaveCyclic IRP Audio Pin
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 #include "private.hpp"
00010 
00011 class CPortPinWaveCyclic : public IPortPinWaveCyclic,
00012                            public IServiceSink
00013 {
00014 public:
00015     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
00016 
00017     STDMETHODIMP_(ULONG) AddRef()
00018     {
00019         InterlockedIncrement(&m_Ref);
00020         return m_Ref;
00021     }
00022     STDMETHODIMP_(ULONG) Release()
00023     {
00024         InterlockedDecrement(&m_Ref);
00025 
00026         if (!m_Ref)
00027         {
00028             delete this;
00029             return 0;
00030         }
00031         return m_Ref;
00032     }
00033     IMP_IPortPinWaveCyclic;
00034     IMP_IServiceSink;
00035     CPortPinWaveCyclic(IUnknown *OuterUnknown){}
00036     virtual ~CPortPinWaveCyclic(){}
00037 
00038 protected:
00039 
00040     VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount);
00041     VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount);
00042     VOID GeneratePositionEvents(IN ULONGLONG OldOffset, IN ULONGLONG NewOffset);
00043 
00044     friend NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00045     friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00046     friend NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00047     friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00048     friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
00049     friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY EventEntry);
00050     friend VOID CALLBACK PinSetStateWorkerRoutine(IN PDEVICE_OBJECT  DeviceObject, IN PVOID  Context);
00051 
00052     IPortWaveCyclic * m_Port;
00053     IPortFilterWaveCyclic * m_Filter;
00054     KSPIN_DESCRIPTOR * m_KsPinDescriptor;
00055     PMINIPORTWAVECYCLIC m_Miniport;
00056     PSERVICEGROUP m_ServiceGroup;
00057     PDMACHANNEL m_DmaChannel;
00058     PMINIPORTWAVECYCLICSTREAM m_Stream;
00059     KSSTATE m_State;
00060     PKSDATAFORMAT m_Format;
00061     PKSPIN_CONNECT m_ConnectDetails;
00062 
00063     PVOID m_CommonBuffer;
00064     ULONG m_CommonBufferSize;
00065     ULONG m_CommonBufferOffset;
00066 
00067     IIrpQueue * m_IrpQueue;
00068 
00069     ULONG m_FrameSize;
00070     BOOL m_Capture;
00071 
00072     ULONG m_TotalPackets;
00073     ULONG m_StopCount;
00074     KSAUDIO_POSITION m_Position;
00075     KSALLOCATOR_FRAMING m_AllocatorFraming;
00076     PSUBDEVICE_DESCRIPTOR m_Descriptor;
00077 
00078     KSPIN_LOCK m_EventListLock;
00079     LIST_ENTRY m_EventList;
00080 
00081     KSRESET m_ResetState;
00082 
00083     ULONG m_Delay;
00084 
00085     LONG m_Ref;
00086 };
00087 
00088 
00089 typedef struct
00090 {
00091     ULONG bLoopedStreaming;
00092     ULONGLONG Position;
00093 }LOOPEDSTREAMING_EVENT_CONTEXT, *PLOOPEDSTREAMING_EVENT_CONTEXT;
00094 
00095 typedef struct
00096 {
00097     ULONG bLoopedStreaming;
00098 }ENDOFSTREAM_EVENT_CONTEXT, *PENDOFSTREAM_EVENT_CONTEXT;
00099 
00100 
00101 
00102 NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00103 NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00104 NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00105 NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00106 NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY  EventEntry);
00107 NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY EventEntry);
00108 NTSTATUS NTAPI PinWaveCyclicDRMHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00109 
00110 
00111 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
00112 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
00113 DEFINE_KSPROPERTY_DRMSET(PinWaveCyclicDRMSet, PinWaveCyclicDRMHandler);
00114 
00115 KSEVENT_ITEM PinWaveCyclicConnectionEventSet =
00116 {
00117     KSEVENT_CONNECTION_ENDOFSTREAM,
00118     sizeof(KSEVENTDATA),
00119     sizeof(ENDOFSTREAM_EVENT_CONTEXT),
00120     PinWaveCyclicAddEndOfStreamEvent,
00121     0,
00122     0
00123 };
00124 
00125 KSEVENT_ITEM PinWaveCyclicStreamingEventSet =
00126 {
00127     KSEVENT_LOOPEDSTREAMING_POSITION,
00128     sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA),
00129     sizeof(LOOPEDSTREAMING_EVENT_CONTEXT),
00130     PinWaveCyclicAddLoopedStreamEvent,
00131     0,
00132     0
00133 };
00134 
00135 
00136 KSPROPERTY_SET PinWaveCyclicPropertySet[] =
00137 {
00138     {
00139         &KSPROPSETID_Connection,
00140         sizeof(PinWaveCyclicConnectionSet) / sizeof(KSPROPERTY_ITEM),
00141         (const KSPROPERTY_ITEM*)&PinWaveCyclicConnectionSet,
00142         0,
00143         NULL
00144     },
00145     {
00146         &KSPROPSETID_Audio,
00147         sizeof(PinWaveCyclicAudioSet) / sizeof(KSPROPERTY_ITEM),
00148         (const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet,
00149         0,
00150         NULL
00151     },
00152     {
00153         &KSPROPSETID_DrmAudioStream,
00154         sizeof(PinWaveCyclicDRMSet) / sizeof(KSPROPERTY_ITEM),
00155         (const KSPROPERTY_ITEM*)&PinWaveCyclicDRMSet,
00156         0,
00157         NULL
00158     }
00159 };
00160 
00161 KSEVENT_SET PinWaveCyclicEventSet[] = 
00162 {
00163     {
00164         &KSEVENTSETID_LoopedStreaming,
00165         sizeof(PinWaveCyclicStreamingEventSet) / sizeof(KSEVENT_ITEM),
00166         (const KSEVENT_ITEM*)&PinWaveCyclicStreamingEventSet
00167     },
00168     {
00169         &KSEVENTSETID_Connection,
00170         sizeof(PinWaveCyclicConnectionEventSet) / sizeof(KSEVENT_ITEM),
00171         (const KSEVENT_ITEM*)&PinWaveCyclicConnectionEventSet
00172     }
00173 };
00174 
00175 
00176 //==================================================================================================================================
00177 
00178 NTSTATUS
00179 NTAPI
00180 CPortPinWaveCyclic::QueryInterface(
00181     IN  REFIID refiid,
00182     OUT PVOID* Output)
00183 {
00184     DPRINT("IServiceSink_fnQueryInterface entered\n");
00185 
00186     if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) || 
00187         IsEqualGUIDAligned(refiid, IID_IUnknown))
00188     {
00189         *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
00190         PUNKNOWN(*Output)->AddRef();
00191         return STATUS_SUCCESS;
00192     }
00193 
00194     if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
00195     {
00196         *Output = PVOID(PUNKNOWN(PSERVICESINK(this)));
00197         PUNKNOWN(*Output)->AddRef();
00198         return STATUS_SUCCESS;
00199     }
00200 
00201     return STATUS_UNSUCCESSFUL;
00202 }
00203 
00204 NTSTATUS
00205 NTAPI
00206 PinWaveCyclicDRMHandler(
00207     IN PIRP Irp,
00208     IN PKSIDENTIFIER Request,
00209     IN OUT PVOID Data)
00210 {
00211     DPRINT1("PinWaveCyclicDRMHandler\n");
00212     ASSERT(0);
00213     return STATUS_INVALID_PARAMETER;
00214 }
00215 
00216 
00217 NTSTATUS
00218 NTAPI
00219 PinWaveCyclicAddEndOfStreamEvent(
00220     IN PIRP Irp,
00221     IN PKSEVENTDATA  EventData,
00222     IN PKSEVENT_ENTRY EventEntry)
00223 {
00224     PENDOFSTREAM_EVENT_CONTEXT Entry;
00225     PSUBDEVICE_DESCRIPTOR Descriptor;
00226     CPortPinWaveCyclic *Pin;
00227 
00228     // get sub device descriptor 
00229     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
00230 
00231     // sanity check 
00232     PC_ASSERT(Descriptor);
00233     PC_ASSERT(Descriptor->PortPin);
00234     PC_ASSERT_IRQL(DISPATCH_LEVEL);
00235 
00236     // cast to pin impl
00237     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
00238 
00239      // get extra size
00240     Entry = (PENDOFSTREAM_EVENT_CONTEXT)(EventEntry + 1);
00241 
00242     // not a looped event
00243     Entry->bLoopedStreaming = FALSE;
00244 
00245     // insert item
00246     (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
00247 
00248     // done
00249     return STATUS_SUCCESS;
00250 }
00251 
00252 NTSTATUS
00253 NTAPI
00254 PinWaveCyclicAddLoopedStreamEvent(
00255     IN PIRP Irp,
00256     IN PKSEVENTDATA  EventData,
00257     IN PKSEVENT_ENTRY EventEntry)
00258 {
00259     PLOOPEDSTREAMING_POSITION_EVENT_DATA Data;
00260     PLOOPEDSTREAMING_EVENT_CONTEXT Entry;
00261     PSUBDEVICE_DESCRIPTOR Descriptor;
00262     CPortPinWaveCyclic *Pin;
00263 
00264     // get sub device descriptor 
00265     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
00266 
00267     // sanity check 
00268     PC_ASSERT(Descriptor);
00269     PC_ASSERT(Descriptor->PortPin);
00270     PC_ASSERT_IRQL(DISPATCH_LEVEL);
00271 
00272     // cast to pin impl
00273     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
00274 
00275     // cast to looped event
00276     Data = (PLOOPEDSTREAMING_POSITION_EVENT_DATA)EventData;
00277 
00278     // get extra size
00279     Entry = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
00280 
00281     Entry->bLoopedStreaming = TRUE;
00282     Entry->Position = Data->Position;
00283 
00284     DPRINT1("Added event\n");
00285 
00286     // insert item
00287     (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
00288 
00289     // done
00290     return STATUS_SUCCESS;
00291 }
00292 
00293 NTSTATUS
00294 NTAPI
00295 PinWaveCyclicAllocatorFraming(
00296     IN PIRP Irp,
00297     IN PKSIDENTIFIER Request,
00298     IN OUT PVOID Data)
00299 {
00300     CPortPinWaveCyclic *Pin;
00301     PSUBDEVICE_DESCRIPTOR Descriptor;
00302 
00303     // get sub device descriptor 
00304     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
00305 
00306     // sanity check 
00307     PC_ASSERT(Descriptor);
00308     PC_ASSERT(Descriptor->PortPin);
00309     PC_ASSERT_IRQL(DISPATCH_LEVEL);
00310 
00311     // cast to pin impl
00312     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
00313 
00314 
00315     if (Request->Flags & KSPROPERTY_TYPE_GET)
00316     {
00317         // copy pin framing
00318         RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
00319 
00320         Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
00321         return STATUS_SUCCESS;
00322     }
00323 
00324     // not supported
00325     return STATUS_NOT_SUPPORTED;
00326 }
00327 
00328 NTSTATUS
00329 NTAPI
00330 PinWaveCyclicAudioPosition(
00331     IN PIRP Irp,
00332     IN PKSIDENTIFIER Request,
00333     IN OUT PVOID Data)
00334 {
00335     CPortPinWaveCyclic *Pin;
00336     PSUBDEVICE_DESCRIPTOR Descriptor;
00337     PKSAUDIO_POSITION Position;
00338 
00339     // get sub device descriptor 
00340     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
00341 
00342     // sanity check 
00343     PC_ASSERT(Descriptor);
00344     PC_ASSERT(Descriptor->PortPin);
00345     PC_ASSERT_IRQL(DISPATCH_LEVEL);
00346 
00347     // cast to pin impl
00348     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
00349 
00350     //sanity check
00351     PC_ASSERT(Pin->m_Stream);
00352 
00353     if (Request->Flags & KSPROPERTY_TYPE_GET)
00354     {
00355         // FIXME non multithreading-safe
00356         // copy audio position
00357 
00358         Position = (PKSAUDIO_POSITION)Data;
00359 
00360         if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING)
00361         {
00362             RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
00363             DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
00364         }
00365         else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
00366         {
00367             Position->PlayOffset = Pin->m_Position.PlayOffset;
00368             Position->WriteOffset = (ULONGLONG)Pin->m_IrpQueue->GetCurrentIrpOffset();
00369             DPRINT("Play %lu Write %lu\n", Position->PlayOffset, Position->WriteOffset);
00370         }
00371 
00372         Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
00373         return STATUS_SUCCESS;
00374     }
00375 
00376     // not supported
00377     return STATUS_NOT_SUPPORTED;
00378 }
00379 
00380 typedef struct
00381 {
00382     CPortPinWaveCyclic *Pin;
00383     KSSTATE NewState;
00384     PIO_WORKITEM WorkItem;
00385     PIRP Irp;
00386 
00387 }SETPIN_CONTEXT, *PSETPIN_CONTEXT;
00388 
00389 VOID
00390 CALLBACK
00391 PinSetStateWorkerRoutine(
00392     IN PDEVICE_OBJECT  DeviceObject,
00393     IN PVOID  Context)
00394 {
00395     PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context;
00396     NTSTATUS Status;
00397 
00398     // try set stream
00399     Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState);
00400 
00401     DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status);
00402     if (NT_SUCCESS(Status))
00403     {
00404         // store new state
00405         PinWorkContext->Pin->m_State = PinWorkContext->NewState;
00406 
00407         if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
00408         {
00409             /* FIXME complete pending irps with successfull state */
00410             PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
00411         }
00412         //HACK
00413         //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
00414     }
00415 
00416     // store result
00417     PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE);
00418     PinWorkContext->Irp->IoStatus.Status = Status;
00419 
00420     // complete irp
00421     IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT);
00422 
00423     // free work item
00424     IoFreeWorkItem(PinWorkContext->WorkItem);
00425 
00426     // free work context
00427     FreeItem(PinWorkContext, TAG_PORTCLASS);
00428 
00429 }
00430 
00431 
00432 NTSTATUS
00433 NTAPI
00434 PinWaveCyclicState(
00435     IN PIRP Irp,
00436     IN PKSIDENTIFIER Request,
00437     IN OUT PVOID Data)
00438 {
00439     NTSTATUS Status = STATUS_UNSUCCESSFUL;
00440     CPortPinWaveCyclic *Pin;
00441     PSUBDEVICE_DESCRIPTOR Descriptor;
00442     PKSSTATE State = (PKSSTATE)Data;
00443 
00444     // get sub device descriptor 
00445     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
00446 
00447     // sanity check 
00448     PC_ASSERT(Descriptor);
00449     PC_ASSERT(Descriptor->PortPin);
00450     PC_ASSERT_IRQL(DISPATCH_LEVEL);
00451 
00452     // cast to pin impl
00453     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
00454 
00455     //sanity check
00456     PC_ASSERT(Pin->m_Stream);
00457 
00458     if (Request->Flags & KSPROPERTY_TYPE_SET)
00459     {
00460         // try set stream
00461         Status = Pin->m_Stream->SetState(*State);
00462 
00463         DPRINT("Setting state %u %x\n", *State, Status);
00464         if (NT_SUCCESS(Status))
00465         {
00466             // store new state
00467             Pin->m_State = *State;
00468 
00469             if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP)
00470             {
00471                 // FIXME
00472                 // complete with successful state
00473                 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
00474                 Pin->m_IrpQueue->CancelBuffers();
00475                 Pin->m_Position.PlayOffset = 0;
00476                 Pin->m_Position.WriteOffset = 0;
00477             }
00478             else if (Pin->m_State == KSSTATE_STOP)
00479             {
00480                 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
00481                 Pin->m_IrpQueue->CancelBuffers();
00482                 Pin->m_Position.PlayOffset = 0;
00483                 Pin->m_Position.WriteOffset = 0;
00484             }
00485             // store result
00486             Irp->IoStatus.Information = sizeof(KSSTATE);
00487         }
00488         return Status;
00489     }
00490     else if (Request->Flags & KSPROPERTY_TYPE_GET)
00491     {
00492         // get current stream state
00493         *State = Pin->m_State;
00494         // store result
00495         Irp->IoStatus.Information = sizeof(KSSTATE);
00496 
00497         return STATUS_SUCCESS;
00498     }
00499 
00500     // unsupported request
00501     return STATUS_NOT_SUPPORTED;
00502 }
00503 
00504 NTSTATUS
00505 NTAPI
00506 PinWaveCyclicDataFormat(
00507     IN PIRP Irp,
00508     IN PKSIDENTIFIER Request,
00509     IN OUT PVOID Data)
00510 {
00511     NTSTATUS Status = STATUS_UNSUCCESSFUL;
00512     CPortPinWaveCyclic *Pin;
00513     PSUBDEVICE_DESCRIPTOR Descriptor;
00514     PIO_STACK_LOCATION IoStack;
00515 
00516     // get current irp stack location
00517     IoStack = IoGetCurrentIrpStackLocation(Irp);
00518 
00519     // get sub device descriptor 
00520     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
00521 
00522     // sanity check 
00523     PC_ASSERT(Descriptor);
00524     PC_ASSERT(Descriptor->PortPin);
00525 
00526     // cast to pin impl
00527     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
00528 
00529     //sanity check
00530     PC_ASSERT(Pin->m_Stream);
00531     PC_ASSERT(Pin->m_Format);
00532 
00533     if (Request->Flags & KSPROPERTY_TYPE_SET)
00534     {
00535         // try to change data format
00536         PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
00537         ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
00538 
00539         if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
00540         {
00541             // format is identical
00542             Irp->IoStatus.Information = DataFormat->FormatSize;
00543             return STATUS_SUCCESS;
00544         }
00545 
00546         // new change request
00547         PC_ASSERT(Pin->m_State != KSSTATE_RUN);
00548         // FIXME queue a work item when Irql != PASSIVE_LEVEL
00549         PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
00550 
00551         // allocate new data format
00552         NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
00553         if (!NewDataFormat)
00554         {
00555             // not enough memory
00556             return STATUS_NO_MEMORY;
00557         }
00558 
00559         // copy new data format
00560         RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
00561 
00562         // set new format
00563         Status = Pin->m_Stream->SetFormat(NewDataFormat);
00564         if (NT_SUCCESS(Status))
00565         {
00566             // free old format
00567             FreeItem(Pin->m_Format, TAG_PORTCLASS);
00568 
00569             // store new format
00570             Pin->m_Format = NewDataFormat;
00571             Irp->IoStatus.Information = NewDataFormat->FormatSize;
00572 
00573 #if 0
00574             PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
00575             PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
00576             PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
00577             PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
00578 
00579 
00580             DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
00581                                                                        ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
00582                                                                        ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
00583 #endif
00584 
00585         }
00586         else
00587         {
00588             // failed to set format
00589             FreeItem(NewDataFormat, TAG_PORTCLASS);
00590         }
00591 
00592 
00593         // done
00594         return Status;
00595     }
00596     else if (Request->Flags & KSPROPERTY_TYPE_GET)
00597     {
00598         // get current data format
00599         PC_ASSERT(Pin->m_Format);
00600 
00601         if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
00602         {
00603             // buffer too small
00604             Irp->IoStatus.Information = Pin->m_Format->FormatSize;
00605             return STATUS_MORE_ENTRIES;
00606         }
00607         // copy data format
00608         RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
00609         // store result size
00610         Irp->IoStatus.Information = Pin->m_Format->FormatSize;
00611 
00612         // done
00613         return STATUS_SUCCESS;
00614     }
00615 
00616     // unsupported request
00617     return STATUS_NOT_SUPPORTED;
00618 }
00619 
00620 VOID
00621 CPortPinWaveCyclic::GeneratePositionEvents(
00622     IN ULONGLONG OldOffset,
00623     IN ULONGLONG NewOffset)
00624 {
00625     PLIST_ENTRY Entry;
00626     PKSEVENT_ENTRY EventEntry;
00627     PLOOPEDSTREAMING_EVENT_CONTEXT Context;
00628 
00629     // acquire event lock
00630     KeAcquireSpinLockAtDpcLevel(&m_EventListLock);
00631 
00632     // point to first entry
00633     Entry = m_EventList.Flink;
00634 
00635     while(Entry != &m_EventList)
00636     {
00637         // get event entry
00638         EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
00639 
00640         // get event entry context
00641         Context = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
00642 
00643         if (Context->bLoopedStreaming == TRUE)
00644         {
00645             if (NewOffset > OldOffset)
00646             {
00647                 /* buffer progress no overlap */
00648                 if (OldOffset < Context->Position && Context->Position <= NewOffset)
00649                 {
00650                     /* when someone eventually fixes sprintf... */
00651                     DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
00652                     DPRINT("Context->Position %I64u\n", Context->Position);
00653                     DPRINT("NewOffset %I64u\n", NewOffset);
00654                     /* generate event */
00655                     KsGenerateEvent(EventEntry);
00656                 }
00657             }
00658             else
00659             {
00660                 /* buffer wrap-arround */
00661                 if (OldOffset < Context->Position || NewOffset > Context->Position)
00662                 {
00663                     /* when someone eventually fixes sprintf... */
00664                     DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
00665                     DPRINT("Context->Position %I64u\n", Context->Position);
00666                     DPRINT("NewOffset %I64u\n", NewOffset);
00667                     /* generate event */
00668                     KsGenerateEvent(EventEntry);
00669                 }
00670             }
00671         }
00672 
00673         // move to next entry
00674         Entry = Entry->Flink;
00675     }
00676 
00677     // release lock
00678     KeReleaseSpinLockFromDpcLevel(&m_EventListLock);
00679 }
00680 
00681 VOID
00682 CPortPinWaveCyclic::UpdateCommonBuffer(
00683     ULONG Position,
00684     ULONG MaxTransferCount)
00685 {
00686     ULONG BufferLength;
00687     ULONG BytesToCopy;
00688     ULONG BufferSize;
00689     ULONG Gap;
00690     PUCHAR Buffer;
00691     NTSTATUS Status;
00692 
00693     BufferLength = Position - m_CommonBufferOffset;
00694     BufferLength = min(BufferLength, MaxTransferCount);
00695 
00696     while(BufferLength)
00697     {
00698         Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
00699         if (!NT_SUCCESS(Status))
00700         {
00701             Gap = Position - m_CommonBufferOffset;
00702             if (Gap > BufferLength)
00703             {
00704                 // insert silence samples
00705                 DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength);
00706                 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
00707 
00708                 m_CommonBufferOffset += BufferLength;
00709             }
00710             break;
00711         }
00712 
00713         BytesToCopy = min(BufferLength, BufferSize);
00714 
00715         if (m_Capture)
00716         {
00717             m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
00718         }
00719         else
00720         {
00721             m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
00722         }
00723 
00724         m_IrpQueue->UpdateMapping(BytesToCopy);
00725         m_CommonBufferOffset += BytesToCopy;
00726 
00727         BufferLength -= BytesToCopy;
00728         m_Position.PlayOffset += BytesToCopy;
00729 
00730         if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
00731         {
00732             if (m_Position.WriteOffset)
00733             {
00734                 // normalize position
00735                 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
00736             }
00737         }
00738     }
00739 }
00740 
00741 VOID
00742 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
00743     ULONG Position,
00744     ULONG MaxTransferCount)
00745 {
00746     ULONG BufferLength, Length, Gap;
00747     ULONG BytesToCopy;
00748     ULONG BufferSize;
00749     PUCHAR Buffer;
00750     NTSTATUS Status;
00751 
00752 
00753     BufferLength = Gap = m_CommonBufferSize - m_CommonBufferOffset;
00754     BufferLength = Length = min(BufferLength, MaxTransferCount);
00755     while(BufferLength)
00756     {
00757         Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
00758         if (!NT_SUCCESS(Status))
00759         {
00760             Gap = m_CommonBufferSize - m_CommonBufferOffset + Position;
00761             if (Gap > BufferLength)
00762             {
00763                 // insert silence samples
00764                 DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position);
00765                 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
00766 
00767                 m_CommonBufferOffset += BufferLength;
00768             }
00769             break;
00770         }
00771 
00772         BytesToCopy = min(BufferLength, BufferSize);
00773 
00774         if (m_Capture)
00775         {
00776             m_DmaChannel->CopyFrom(Buffer,
00777                                              (PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
00778                                              BytesToCopy);
00779         }
00780         else
00781         {
00782             m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
00783                                              Buffer,
00784                                              BytesToCopy);
00785         }
00786 
00787         m_IrpQueue->UpdateMapping(BytesToCopy);
00788         m_CommonBufferOffset += BytesToCopy;
00789         m_Position.PlayOffset += BytesToCopy;
00790 
00791         BufferLength -=BytesToCopy;
00792 
00793         if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
00794         {
00795             if (m_Position.WriteOffset)
00796             {
00797                 // normalize position
00798                 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
00799             }
00800         }
00801     }
00802 
00803     if (Gap == Length)
00804     {
00805         m_CommonBufferOffset = 0;
00806 
00807         MaxTransferCount -= Length;
00808 
00809         if (MaxTransferCount)
00810         {
00811             UpdateCommonBuffer(Position, MaxTransferCount);
00812         }
00813     }
00814 }
00815 
00816 VOID
00817 NTAPI
00818 CPortPinWaveCyclic::RequestService()
00819 {
00820     ULONG Position;
00821     ULONGLONG OldOffset, NewOffset;
00822 
00823     PC_ASSERT_IRQL(DISPATCH_LEVEL);
00824 
00825     if (m_State == KSSTATE_RUN && m_ResetState == KSRESET_END)
00826     {
00827         m_Stream->GetPosition(&Position);
00828 
00829         OldOffset = m_Position.PlayOffset;
00830 
00831         if (Position < m_CommonBufferOffset)
00832         {
00833             UpdateCommonBufferOverlap(Position, m_FrameSize);
00834         }
00835         else if (Position >= m_CommonBufferOffset)
00836         {
00837             UpdateCommonBuffer(Position, m_FrameSize);
00838         }
00839 
00840         NewOffset = m_Position.PlayOffset;
00841 
00842         GeneratePositionEvents(OldOffset, NewOffset);
00843     }
00844 }
00845 
00846 NTSTATUS
00847 NTAPI
00848 CPortPinWaveCyclic::NewIrpTarget(
00849     OUT struct IIrpTarget **OutTarget,
00850     IN PCWSTR Name,
00851     IN PUNKNOWN Unknown,
00852     IN POOL_TYPE PoolType,
00853     IN PDEVICE_OBJECT DeviceObject,
00854     IN PIRP Irp,
00855     IN KSOBJECT_CREATE *CreateObject)
00856 {
00857     UNIMPLEMENTED
00858     return STATUS_UNSUCCESSFUL;
00859 }
00860 
00861 NTSTATUS
00862 NTAPI
00863 CPortPinWaveCyclic::DeviceIoControl(
00864     IN PDEVICE_OBJECT DeviceObject,
00865     IN PIRP Irp)
00866 {
00867     PIO_STACK_LOCATION IoStack;
00868     PKSPROPERTY Property;
00869     UNICODE_STRING GuidString;
00870     NTSTATUS Status = STATUS_NOT_SUPPORTED;
00871     ULONG Data = 0;
00872     KSRESET ResetValue;
00873 
00874     /* get current irp stack location */
00875     IoStack = IoGetCurrentIrpStackLocation(Irp);
00876 
00877     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
00878     {
00879         /* handle property with subdevice descriptor */
00880         Status = PcHandlePropertyWithTable(Irp,  m_Descriptor->FilterPropertySetCount, m_Descriptor->FilterPropertySet, m_Descriptor);
00881 
00882         if (Status == STATUS_NOT_FOUND)
00883         {
00884             Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
00885 
00886             RtlStringFromGUID(Property->Set, &GuidString);
00887             DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
00888             RtlFreeUnicodeString(&GuidString);
00889         }
00890     }
00891     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
00892     {
00893         Status = PcHandleEnableEventWithTable(Irp, m_Descriptor);
00894     }
00895     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
00896     {
00897         Status = PcHandleDisableEventWithTable(Irp, m_Descriptor);
00898     }
00899     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
00900     {
00901         Status = KsAcquireResetValue(Irp, &ResetValue);
00902         DPRINT("Status %x Value %u\n", Status, ResetValue);
00903         /* check for success */
00904         if (NT_SUCCESS(Status))
00905         {
00906             //determine state of reset request
00907             if (ResetValue == KSRESET_BEGIN)
00908             {
00909                 // start reset procress
00910                 // incoming read/write requests will be rejected
00911                 m_ResetState = KSRESET_BEGIN;
00912 
00913                 // cancel existing buffers
00914                 m_IrpQueue->CancelBuffers();
00915             }
00916             else if (ResetValue == KSRESET_END)
00917             {
00918                 // end of reset process
00919                 m_ResetState = KSRESET_END;
00920             }
00921         }
00922     }
00923     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
00924     {
00925         /* increment total number of packets */
00926         InterlockedIncrement((PLONG)&m_TotalPackets);
00927 
00928          DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
00929 
00930          /* is the device not currently reset */
00931          if (m_ResetState == KSRESET_END)
00932          {
00933              /* add the mapping */
00934              Status = m_IrpQueue->AddMapping(Irp, &Data);
00935 
00936              /* check for success */
00937              if (NT_SUCCESS(Status))
00938              {
00939                 m_Position.WriteOffset += Data;
00940                 Status = STATUS_PENDING;
00941              }
00942          }
00943          else
00944          {
00945              /* reset request is currently in progress */
00946              Status = STATUS_DEVICE_NOT_READY;
00947              DPRINT1("NotReady\n");
00948          }
00949     }
00950     else
00951     {
00952         return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
00953     }
00954 
00955     if (Status != STATUS_PENDING)
00956     {
00957         Irp->IoStatus.Status = Status;
00958         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00959     }
00960 
00961     return Status;
00962 }
00963 
00964 NTSTATUS
00965 NTAPI
00966 CPortPinWaveCyclic::Read(
00967     IN PDEVICE_OBJECT DeviceObject,
00968     IN PIRP Irp)
00969 {
00970     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00971 }
00972 
00973 NTSTATUS
00974 NTAPI
00975 CPortPinWaveCyclic::Write(
00976     IN PDEVICE_OBJECT DeviceObject,
00977     IN PIRP Irp)
00978 {
00979     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00980 }
00981 
00982 NTSTATUS
00983 NTAPI
00984 CPortPinWaveCyclic::Flush(
00985     IN PDEVICE_OBJECT DeviceObject,
00986     IN PIRP Irp)
00987 {
00988     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00989 }
00990 
00991 NTSTATUS
00992 NTAPI
00993 CPortPinWaveCyclic::Close(
00994     IN PDEVICE_OBJECT DeviceObject,
00995     IN PIRP Irp)
00996 {
00997     DPRINT("CPortPinWaveCyclic::Close entered\n");
00998 
00999     PC_ASSERT_IRQL(PASSIVE_LEVEL);
01000 
01001     if (m_Format)
01002     {
01003         // free format
01004         FreeItem(m_Format, TAG_PORTCLASS);
01005 
01006         // format is freed
01007         m_Format = NULL;
01008     }
01009 
01010     if (m_IrpQueue)
01011     {
01012         // cancel remaining irps
01013         m_IrpQueue->CancelBuffers();
01014 
01015         // release irp queue
01016         m_IrpQueue->Release();
01017 
01018         // queue is freed
01019         m_IrpQueue = NULL;
01020     }
01021 
01022     if (m_ServiceGroup)
01023     {
01024         // remove member from service group
01025         m_ServiceGroup->RemoveMember(PSERVICESINK(this));
01026 
01027         // do not release service group, it is released by the miniport object
01028         m_ServiceGroup = NULL;
01029     }
01030 
01031     if (m_Stream)
01032     {
01033         if (m_State != KSSTATE_STOP)
01034         {
01035             // stop stream
01036             NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP);
01037             if (!NT_SUCCESS(Status))
01038             {
01039                 DPRINT("Warning: failed to stop stream with %x\n", Status);
01040                 PC_ASSERT(0);
01041             }
01042         }
01043         // set state to stop
01044         m_State = KSSTATE_STOP;
01045 
01046         DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
01047 
01048         // release stream
01049         m_Stream->Release();
01050 
01051         // stream is now freed
01052         m_Stream = NULL;
01053     }
01054 
01055 
01056     if (m_Filter)
01057     {
01058         // disconnect pin from filter
01059         m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
01060 
01061         // release filter reference
01062         m_Filter->Release();
01063 
01064         // pin is done with filter
01065         m_Filter = NULL;
01066     }
01067 
01068     if (m_Port)
01069     {
01070         // release reference to port driver
01071         m_Port->Release();
01072 
01073         // work is done for port
01074         m_Port = NULL;
01075     }
01076 
01077     Irp->IoStatus.Information = 0;
01078     Irp->IoStatus.Status = STATUS_SUCCESS;
01079     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01080 
01081     delete this;
01082 
01083     return STATUS_SUCCESS;
01084 }
01085 
01086 NTSTATUS
01087 NTAPI
01088 CPortPinWaveCyclic::QuerySecurity(
01089     IN PDEVICE_OBJECT DeviceObject,
01090     IN PIRP Irp)
01091 {
01092     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
01093 }
01094 
01095 NTSTATUS
01096 NTAPI
01097 CPortPinWaveCyclic::SetSecurity(
01098     IN PDEVICE_OBJECT DeviceObject,
01099     IN PIRP Irp)
01100 {
01101     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
01102 }
01103 
01104 BOOLEAN
01105 NTAPI
01106 CPortPinWaveCyclic::FastDeviceIoControl(
01107     IN PFILE_OBJECT FileObject,
01108     IN BOOLEAN Wait,
01109     IN PVOID InputBuffer,
01110     IN ULONG InputBufferLength,
01111     OUT PVOID OutputBuffer,
01112     IN ULONG OutputBufferLength,
01113     IN ULONG IoControlCode,
01114     OUT PIO_STATUS_BLOCK StatusBlock,
01115     IN PDEVICE_OBJECT DeviceObject)
01116 {
01117     return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
01118 }
01119 
01120 
01121 BOOLEAN
01122 NTAPI
01123 CPortPinWaveCyclic::FastRead(
01124     IN PFILE_OBJECT FileObject,
01125     IN PLARGE_INTEGER FileOffset,
01126     IN ULONG Length,
01127     IN BOOLEAN Wait,
01128     IN ULONG LockKey,
01129     IN PVOID Buffer,
01130     OUT PIO_STATUS_BLOCK StatusBlock,
01131     IN PDEVICE_OBJECT DeviceObject)
01132 {
01133     return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
01134 }
01135 
01136 
01137 BOOLEAN
01138 NTAPI
01139 CPortPinWaveCyclic::FastWrite(
01140     IN PFILE_OBJECT FileObject,
01141     IN PLARGE_INTEGER FileOffset,
01142     IN ULONG Length,
01143     IN BOOLEAN Wait,
01144     IN ULONG LockKey,
01145     IN PVOID Buffer,
01146     OUT PIO_STATUS_BLOCK StatusBlock,
01147     IN PDEVICE_OBJECT DeviceObject)
01148 {
01149     return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
01150 }
01151 
01152 
01153 NTSTATUS
01154 NTAPI
01155 CPortPinWaveCyclic::Init(
01156     IN PPORTWAVECYCLIC Port,
01157     IN PPORTFILTERWAVECYCLIC Filter,
01158     IN KSPIN_CONNECT * ConnectDetails,
01159     IN KSPIN_DESCRIPTOR * KsPinDescriptor)
01160 {
01161     NTSTATUS Status;
01162     PKSDATAFORMAT DataFormat;
01163     //PDEVICE_OBJECT DeviceObject;
01164     BOOLEAN Capture;
01165     PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
01166     //IDrmAudioStream * DrmAudio = NULL;
01167 
01168     m_KsPinDescriptor = KsPinDescriptor;
01169     m_ConnectDetails = ConnectDetails;
01170     m_Miniport = GetWaveCyclicMiniport(Port);
01171 
01172     //DeviceObject = GetDeviceObject(Port);
01173 
01174     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
01175 
01176     DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize);
01177 
01178     Status = NewIrpQueue(&m_IrpQueue);
01179     if (!NT_SUCCESS(Status))
01180         return Status;
01181 
01182     if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
01183     {
01184         Capture = FALSE;
01185     }
01186     else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
01187     {
01188         Capture = TRUE;
01189     }
01190     else
01191     {
01192         DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
01193         DbgBreakPoint();
01194         while(TRUE);
01195     }
01196 
01197 
01198     Status = m_Miniport->NewStream(&m_Stream,
01199                                    NULL,
01200                                    NonPagedPool,
01201                                    ConnectDetails->PinId,
01202                                    Capture,
01203                                    DataFormat,
01204                                    &m_DmaChannel,
01205                                    &m_ServiceGroup);
01206 #if 0
01207     Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio);
01208     if (NT_SUCCESS(Status))
01209     {
01210         DRMRIGHTS DrmRights;
01211         DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
01212 
01213         DrmRights.CopyProtect = FALSE;
01214         DrmRights.Reserved = 0;
01215         DrmRights.DigitalOutputDisable = FALSE;
01216 
01217         Status = DrmAudio->SetContentId(1, &DrmRights);
01218         DPRINT("Status %x\n", Status);
01219     }
01220 #endif
01221 
01222     DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
01223 
01224     if (!NT_SUCCESS(Status))
01225         return Status;
01226 
01227     ISubdevice * Subdevice = NULL;
01228     // get subdevice interface
01229     Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
01230 
01231     if (!NT_SUCCESS(Status))
01232         return Status;
01233 
01234     Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
01235     if (!NT_SUCCESS(Status))
01236     {
01237         // failed to get descriptor
01238         Subdevice->Release();
01239         return Status;
01240     }
01241 
01242     /* initialize event management */
01243     InitializeListHead(&m_EventList);
01244     KeInitializeSpinLock(&m_EventListLock);
01245 
01246     Status = PcCreateSubdeviceDescriptor(&m_Descriptor,
01247                                          SubDeviceDescriptor->InterfaceCount,
01248                                          SubDeviceDescriptor->Interfaces,
01249                                          0, /* FIXME KSINTERFACE_STANDARD with KSINTERFACE_STANDARD_STREAMING / KSINTERFACE_STANDARD_LOOPED_STREAMING */
01250                                          NULL,
01251                                          sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET),
01252                                          PinWaveCyclicPropertySet,
01253                                          0,
01254                                          0,
01255                                          0,
01256                                          NULL,
01257                                          sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET),
01258                                          PinWaveCyclicEventSet,
01259                                          SubDeviceDescriptor->DeviceDescriptor);
01260 
01261     m_Descriptor->UnknownStream = (PUNKNOWN)m_Stream;
01262     m_Descriptor->UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
01263     m_Descriptor->PortPin = (PVOID)this;
01264     m_Descriptor->EventList = &m_EventList;
01265     m_Descriptor->EventListLock = &m_EventListLock;
01266 
01267     // initialize reset state
01268     m_ResetState = KSRESET_END;
01269 
01270     // release subdevice descriptor
01271     Subdevice->Release();
01272 
01273     // add ourselves to service group
01274     Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
01275     if (!NT_SUCCESS(Status))
01276     {
01277         DPRINT("Failed to add pin to service group\n");
01278         return Status;
01279     }
01280 
01281     m_Stream->SetState(KSSTATE_STOP);
01282     m_State = KSSTATE_STOP;
01283     m_CommonBufferOffset = 0;
01284     m_CommonBufferSize = m_DmaChannel->AllocatedBufferSize();
01285     m_CommonBuffer = m_DmaChannel->SystemAddress();
01286     m_Capture = Capture;
01287     // delay of 10 milisec
01288     m_Delay = Int32x32To64(10, -10000);
01289 
01290     // sanity checks
01291     PC_ASSERT(m_CommonBufferSize);
01292     PC_ASSERT(m_CommonBuffer);
01293 
01294     Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
01295     PC_ASSERT(NT_SUCCESS(Status));
01296     PC_ASSERT(m_FrameSize);
01297 
01298     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());
01299 
01300 
01301     /* set up allocator framing */
01302     m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
01303     m_AllocatorFraming.PoolType = NonPagedPool;
01304     m_AllocatorFraming.Frames = 8;
01305     m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT;
01306     m_AllocatorFraming.Reserved = 0;
01307     m_AllocatorFraming.FrameSize = m_FrameSize;
01308 
01309     m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
01310 
01311     Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_FrameSize, 0, FALSE);
01312     if (!NT_SUCCESS(Status))
01313     {
01314        m_IrpQueue->Release();
01315        return Status;
01316     }
01317 
01318     m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
01319     if (!m_Format)
01320         return STATUS_INSUFFICIENT_RESOURCES;
01321 
01322     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
01323 
01324     Port->AddRef();
01325     Filter->AddRef();
01326 
01327     m_Port = Port;
01328     m_Filter = Filter;
01329 
01330     return STATUS_SUCCESS;
01331 }
01332 
01333 
01334 ULONG
01335 NTAPI
01336 CPortPinWaveCyclic::GetCompletedPosition()
01337 {
01338     UNIMPLEMENTED;
01339     return 0;
01340 }
01341 
01342 
01343 ULONG
01344 NTAPI
01345 CPortPinWaveCyclic::GetCycleCount()
01346 {
01347     UNIMPLEMENTED;
01348     return 0;
01349 }
01350 
01351 
01352 ULONG
01353 NTAPI
01354 CPortPinWaveCyclic::GetDeviceBufferSize()
01355 {
01356     return m_CommonBufferSize;
01357 }
01358 
01359 
01360 PVOID
01361 NTAPI
01362 CPortPinWaveCyclic::GetIrpStream()
01363 {
01364     return (PVOID)m_IrpQueue;
01365 }
01366 
01367 
01368 PMINIPORT
01369 NTAPI
01370 CPortPinWaveCyclic::GetMiniport()
01371 {
01372     return (PMINIPORT)m_Miniport;
01373 }
01374 
01375 
01376 NTSTATUS
01377 NewPortPinWaveCyclic(
01378     OUT IPortPinWaveCyclic ** OutPin)
01379 {
01380     CPortPinWaveCyclic * This;
01381 
01382     This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL);
01383     if (!This)
01384         return STATUS_INSUFFICIENT_RESOURCES;
01385 
01386     This->AddRef();
01387 
01388     // store result
01389     *OutPin = (IPortPinWaveCyclic*)This;
01390 
01391     return STATUS_SUCCESS;
01392 }
01393 

Generated on Sun May 27 2012 04:28:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.