From f45f63e7c24131c24a9dce15ecc98be45171e615 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sat, 28 Nov 2009 17:01:46 +0000 Subject: [PATCH] [PORTCLS] - Store KSOBJECT_HEADER as the first member in a struct, which ks can use to access object header. Fixes initialization of ReactOS portcls in WinXP - Partly implement power querying / setting. Fixes bsod when shutting down the system in WinXP with ReactOS portcls - Change the pin state at PASSIVE_LEVEL - Implement IOCTL_KS_RESET for CPinWaveCyclic svn path=/trunk/; revision=44309 --- .../wdm/audio/backpln/portcls/dispatcher.cpp | 118 +++++---- .../wdm/audio/backpln/portcls/dma_slave.cpp | 1 + .../wdm/audio/backpln/portcls/interrupt.cpp | 2 + .../drivers/wdm/audio/backpln/portcls/irp.cpp | 239 +++++++++++++++++- .../wdm/audio/backpln/portcls/irpstream.cpp | 25 +- .../audio/backpln/portcls/pin_wavecyclic.cpp | 218 +++++++++------- .../wdm/audio/backpln/portcls/port_dmus.cpp | 1 + .../wdm/audio/backpln/portcls/private.hpp | 15 +- .../audio/backpln/portcls/propertyhandler.cpp | 7 +- .../wdm/audio/backpln/portcls/undoc.cpp | 71 +++++- 10 files changed, 531 insertions(+), 166 deletions(-) diff --git a/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.cpp b/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.cpp index 81953425c4f..3d2bbb6e018 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.cpp @@ -16,16 +16,16 @@ Dispatch_fnDeviceIoControl( PIRP Irp) { PIO_STACK_LOCATION IoStack; - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); - // access IrpTarget - IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->DeviceIoControl(DeviceObject, Irp); + return DispatchContext->Target->DeviceIoControl(DeviceObject, Irp); } NTSTATUS @@ -35,17 +35,17 @@ Dispatch_fnRead( PIRP Irp) { PIO_STACK_LOCATION IoStack; - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); - // access IrpTarget - IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->Read(DeviceObject, Irp); + return DispatchContext->Target->Read(DeviceObject, Irp); } NTSTATUS @@ -55,17 +55,17 @@ Dispatch_fnWrite( PIRP Irp) { PIO_STACK_LOCATION IoStack; - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); - // access IrpTarget - IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->Write(DeviceObject, Irp); + return DispatchContext->Target->Write(DeviceObject, Irp); } NTSTATUS @@ -75,17 +75,17 @@ Dispatch_fnFlush( PIRP Irp) { PIO_STACK_LOCATION IoStack; - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); - // access IrpTarget - IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->Flush(DeviceObject, Irp); + return DispatchContext->Target->Flush(DeviceObject, Irp); } NTSTATUS @@ -95,17 +95,24 @@ Dispatch_fnClose( PIRP Irp) { PIO_STACK_LOCATION IoStack; - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; + NTSTATUS Status; // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); - - // access IrpTarget - IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext; - + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->Close(DeviceObject, Irp); + Status = DispatchContext->Target->Close(DeviceObject, Irp); + + if (NT_SUCCESS(Status)) + { + KsFreeObjectHeader(DispatchContext->ObjectHeader); + FreeItem(DispatchContext, TAG_PORTCLASS); + } + // done + return Status; } NTSTATUS @@ -115,17 +122,17 @@ Dispatch_fnQuerySecurity( PIRP Irp) { PIO_STACK_LOCATION IoStack; - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); - // access IrpTarget - IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->QuerySecurity(DeviceObject, Irp); + return DispatchContext->Target->QuerySecurity(DeviceObject, Irp); } NTSTATUS @@ -135,17 +142,16 @@ Dispatch_fnSetSecurity( PIRP Irp) { PIO_STACK_LOCATION IoStack; - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); - // access IrpTarget - IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext; - + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->SetSecurity(DeviceObject, Irp); + return DispatchContext->Target->SetSecurity(DeviceObject, Irp); } BOOLEAN @@ -161,13 +167,13 @@ Dispatch_fnFastDeviceIoControl( PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; - // access IrpTarget - IrpTarget = (IIrpTarget *)FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->FastDeviceIoControl(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, IoStatus, DeviceObject); + return DispatchContext->Target->FastDeviceIoControl(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, IoStatus, DeviceObject); } @@ -183,13 +189,13 @@ Dispatch_fnFastRead( PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; - // access IrpTarget - IrpTarget = (IIrpTarget *)FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->FastRead(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); + return DispatchContext->Target->FastRead(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); } BOOLEAN @@ -204,12 +210,12 @@ Dispatch_fnFastWrite( PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { - IIrpTarget * IrpTarget; + PDISPATCH_CONTEXT DispatchContext; - // access IrpTarget - IrpTarget = (IIrpTarget *)FileObject->FsContext; + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)FileObject->FsContext; // let IrpTarget handle request - return IrpTarget->FastWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); + return DispatchContext->Target->FastWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); } static KSDISPATCH_TABLE DispatchTable = @@ -226,7 +232,6 @@ static KSDISPATCH_TABLE DispatchTable = Dispatch_fnFastWrite, }; - NTSTATUS NTAPI NewDispatchObject( @@ -238,14 +243,35 @@ NewDispatchObject( NTSTATUS Status; KSOBJECT_HEADER ObjectHeader; PIO_STACK_LOCATION IoStack; + PDISPATCH_CONTEXT DispatchContext; // get current irp stack location IoStack = IoGetCurrentIrpStackLocation(Irp); - IoStack->FileObject->FsContext = (PVOID)Target; + DispatchContext = (PDISPATCH_CONTEXT)AllocateItem(NonPagedPool, sizeof(DISPATCH_CONTEXT), TAG_PORTCLASS); + if (!DispatchContext) + return STATUS_INSUFFICIENT_RESOURCES; + // allocate object header Status = KsAllocateObjectHeader(&ObjectHeader, CreateItemCount, CreateItem, Irp, &DispatchTable); - DPRINT("KsAllocateObjectHeader result %x\n", Status); + + if (!NT_SUCCESS(Status)) + { + // free dispatch context + FreeItem(DispatchContext, TAG_PORTCLASS); + // done + return Status; + } + + // initialize dispatch context + DispatchContext->ObjectHeader = ObjectHeader; + DispatchContext->Target = Target; + DispatchContext->CreateItem = CreateItem; + + // store dispatch context + IoStack->FileObject->FsContext = DispatchContext; + + DPRINT("KsAllocateObjectHeader result %x Target %p Context %p\n", Status, Target, DispatchContext); return Status; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/dma_slave.cpp b/reactos/drivers/wdm/audio/backpln/portcls/dma_slave.cpp index 47805983fc8..a68e25ea8ef 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/dma_slave.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/dma_slave.cpp @@ -223,6 +223,7 @@ NTAPI CDmaChannelInit::BufferSize() { DPRINT("BufferSize %u\n", m_BufferSize); + PC_ASSERT(m_BufferSize); return m_BufferSize; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp b/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp index 38b5f87aba1..84dd17123b4 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp @@ -231,6 +231,8 @@ CInterruptSync::Connect() if (IsListEmpty(&m_ServiceRoutines)) return STATUS_UNSUCCESSFUL; + DPRINT("Vector %u Level %u Flags %x Affinity %x\n", Descriptor->u.Interrupt.Vector, Descriptor->u.Interrupt.Level, Descriptor->Flags, Descriptor->u.Interrupt.Affinity); + Status = IoConnectInterrupt(&m_Interrupt, IInterruptServiceRoutine, (PVOID)this, diff --git a/reactos/drivers/wdm/audio/backpln/portcls/irp.cpp b/reactos/drivers/wdm/audio/backpln/portcls/irp.cpp index 29fd26c17c3..18a089dadf7 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/irp.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/irp.cpp @@ -12,6 +12,13 @@ #include "private.hpp" +typedef struct +{ + PIRP Irp; + PDEVICE_OBJECT DeviceObject; +}QUERY_POWER_CONTEXT, *PQUERY_POWER_CONTEXT; + + NTSTATUS NTAPI PortClsCreate( @@ -33,7 +40,10 @@ PortClsPnp( NTSTATUS Status; PPCLASS_DEVICE_EXTENSION DeviceExt; PIO_STACK_LOCATION IoStack; + POWER_STATE PowerState; IResourceList* resource_list = NULL; + //ULONG Index; + //PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor; DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension; IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -92,6 +102,14 @@ PortClsPnp( // Assign the resource list to our extension DeviceExt->resources = resource_list; + // store device power state + DeviceExt->DevicePowerState = PowerDeviceD0; + DeviceExt->SystemPowerState = PowerSystemWorking; + + // notify power manager of current state + PowerState = *((POWER_STATE*)&DeviceExt->DevicePowerState); + PoSetPowerState(DeviceObject, DevicePowerState, PowerState); + Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; @@ -103,10 +121,9 @@ PortClsPnp( DeviceExt->resources->Release(); IoDeleteDevice(DeviceObject); - // Do not complete? - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; + // Forward request + Status = PcForwardIrpSynchronous(DeviceObject, Irp); + return PcCompleteIrp(DeviceObject, Irp, Status); case IRP_MN_QUERY_INTERFACE: DPRINT("IRP_MN_QUERY_INTERFACE\n"); @@ -133,21 +150,221 @@ PortClsPnp( return STATUS_UNSUCCESSFUL; } +VOID +CALLBACK +PwrCompletionFunction( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatus) +{ + NTSTATUS Status; + PQUERY_POWER_CONTEXT PwrContext = (PQUERY_POWER_CONTEXT)Context; + + if (NT_SUCCESS(IoStatus->Status)) + { + // forward request to lower device object + Status = PcForwardIrpSynchronous(PwrContext->DeviceObject, PwrContext->Irp); + } + else + { + // failed + Status = IoStatus->Status; + } + + // start next power irp + PoStartNextPowerIrp(PwrContext->Irp); + + // complete request + PwrContext->Irp->IoStatus.Status = Status; + IoCompleteRequest(PwrContext->Irp, IO_NO_INCREMENT); + + // free context + FreeItem(PwrContext, TAG_PORTCLASS); +} + + NTSTATUS NTAPI PortClsPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + PIO_STACK_LOCATION IoStack; + PPCLASS_DEVICE_EXTENSION DeviceExtension; + PQUERY_POWER_CONTEXT PwrContext; + POWER_STATE PowerState; + NTSTATUS Status = STATUS_SUCCESS; + DPRINT("PortClsPower called\n"); - // TODO + // get currrent stack location + IoStack = IoGetCurrentIrpStackLocation(Irp); - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER) + { + // just forward the request + Status = PcForwardIrpSynchronous(DeviceObject, Irp); - return STATUS_SUCCESS; + // start next power irp + PoStartNextPowerIrp(Irp); + + // complete request + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // done + return Status; + } + + + // get device extension + DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + + // get current request type + if (IoStack->Parameters.Power.Type == DevicePowerState) + { + // request for device power state + if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState) + { + // nothing has changed + if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) + { + // only forward query requests + Status = PcForwardIrpSynchronous(DeviceObject, Irp); + } + + // start next power irp + PoStartNextPowerIrp(Irp); + + // complete request + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // done + return Status; + } + + if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) + { + // check if there is a registered adapter power management + if (DeviceExtension->AdapterPowerManagement) + { + // it is query if the change can be changed + PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); + Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState); + + // sanity check + PC_ASSERT(Status == STATUS_SUCCESS); + } + + // only forward query requests + PcForwardIrpSynchronous(DeviceObject, Irp); + + // start next power irp + PoStartNextPowerIrp(Irp); + + // complete request + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // done + return Status; + } + else + { + // set power state + PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); + PoSetPowerState(DeviceObject, DevicePowerState, PowerState); + + // check if there is a registered adapter power management + if (DeviceExtension->AdapterPowerManagement) + { + // notify of a power change state + DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState); + } + + // FIXME call all registered IPowerNotify interfaces via ISubdevice interface + + // store new power state + DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState; + + // complete request + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // done + return Status; + } + } + else + { + // sanity check + PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState); + + if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) + { + // mark irp as pending + IoMarkIrpPending(Irp); + + // allocate power completion context + PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS); + + if (!PwrContext) + { + // no memory + PoStartNextPowerIrp(Irp); + + // complete and forget + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // done + return Status; + } + + // setup power context + PwrContext->Irp = Irp; + PwrContext->DeviceObject = DeviceObject; + + // pass the irp down + PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState); + Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL); + + // check for success + if (!NT_SUCCESS(Status)) + { + // failed + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // done + return Status; + } + + // done + return STATUS_PENDING; + } + else + { + // set power request + DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState; + + // only forward query requests + Status = PcForwardIrpSynchronous(DeviceObject, Irp); + + // start next power irp + PoStartNextPowerIrp(Irp); + + // complete request + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // done + return Status; + } + } } NTSTATUS @@ -200,10 +417,10 @@ PcDispatchIrp( { PIO_STACK_LOCATION IoStack; - DPRINT("PcDispatchIrp called - handling IRP in PortCls\n"); - IoStack = IoGetCurrentIrpStackLocation(Irp); + DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction); + switch ( IoStack->MajorFunction ) { // PortCls diff --git a/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp b/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp index f201db292b8..f80616487e1 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp @@ -145,7 +145,14 @@ CIrpQueue::AddMapping( } // get first stream header - Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + if (Irp->RequestorMode == UserMode) + Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + else + Header = (PKSSTREAM_HEADER)Irp->UserBuffer; + + // sanity check + PC_ASSERT(Header); // calculate num headers NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size; @@ -156,7 +163,8 @@ CIrpQueue::AddMapping( // get first audio buffer Mdl = Irp->MdlAddress; - + // sanity check + PC_ASSERT(Mdl); // store the current stream header Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER] = (PVOID)Header; @@ -166,7 +174,6 @@ CIrpQueue::AddMapping( // store current header index Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0); - NumData = 0; // prepare all headers for(Index = 0; Index < NumHeaders; Index++) @@ -175,7 +182,10 @@ CIrpQueue::AddMapping( PC_ASSERT(Header); PC_ASSERT(Mdl); - Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); + if (Irp->RequestorMode == UserMode) + { + Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); + } if (!Header->Data) { @@ -344,10 +354,13 @@ CIrpQueue::UpdateMapping( return; } - // irp has been processed completly + // irp has been processed completly NumData = 0; - StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer; + if (m_Irp->RequestorMode == KernelMode) + StreamHeader = (PKSSTREAM_HEADER)m_Irp->UserBuffer; + else + StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer; // loop all stream headers for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++) diff --git a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp index f7a7c7f44a8..71e7b33bb66 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp @@ -35,16 +35,11 @@ public: CPortPinWaveCyclic(IUnknown *OuterUnknown){} virtual ~CPortPinWaveCyclic(){} - VOID SetState(KSSTATE State); - protected: VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount); VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount); VOID GeneratePositionEvents(IN ULONGLONG OldOffset, IN ULONGLONG NewOffset); - NTSTATUS NTAPI HandleKsStream(IN PIRP Irp); - NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp); - friend NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); @@ -52,6 +47,7 @@ protected: friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry); friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry); + friend VOID CALLBACK PinSetStateWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context); IPortWaveCyclic * m_Port; IPortFilterWaveCyclic * m_Filter; @@ -82,6 +78,8 @@ protected: KSPIN_LOCK m_EventListLock; LIST_ENTRY m_EventList; + KSRESET m_ResetState; + ULONG m_Delay; LONG m_Ref; @@ -358,6 +356,57 @@ PinWaveCyclicAudioPosition( return STATUS_NOT_SUPPORTED; } +typedef struct +{ + CPortPinWaveCyclic *Pin; + KSSTATE NewState; + PIO_WORKITEM WorkItem; + PIRP Irp; + +}SETPIN_CONTEXT, *PSETPIN_CONTEXT; + +VOID +CALLBACK +PinSetStateWorkerRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) +{ + PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context; + NTSTATUS Status; + + // try set stream + Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState); + + DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status); + if (NT_SUCCESS(Status)) + { + // store new state + PinWorkContext->Pin->m_State = PinWorkContext->NewState; + + if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP) + { + /* FIXME complete pending irps with successfull state */ + PinWorkContext->Pin->m_IrpQueue->CancelBuffers(); + } + //HACK + //PinWorkContext->Pin->m_IrpQueue->CancelBuffers(); + } + + // store result + PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE); + PinWorkContext->Irp->IoStatus.Status = Status; + + // complete irp + IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT); + + // free work item + IoFreeWorkItem(PinWorkContext->WorkItem); + + // free work context + FreeItem(PinWorkContext, TAG_PORTCLASS); + +} + NTSTATUS NTAPI @@ -366,10 +415,10 @@ PinWaveCyclicState( IN PKSIDENTIFIER Request, IN OUT PVOID Data) { - NTSTATUS Status = STATUS_UNSUCCESSFUL; CPortPinWaveCyclic *Pin; PSUBDEVICE_DESCRIPTOR Descriptor; PKSSTATE State = (PKSSTATE)Data; + PSETPIN_CONTEXT PinWorkContext; // get sub device descriptor Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); @@ -387,25 +436,20 @@ PinWaveCyclicState( if (Request->Flags & KSPROPERTY_TYPE_SET) { - // try set stream - Status = Pin->m_Stream->SetState(*State); + PinWorkContext = (PSETPIN_CONTEXT)AllocateItem(NonPagedPool, sizeof(PSETPIN_CONTEXT), TAG_PORTCLASS); + PC_ASSERT(PinWorkContext); - DPRINT("Setting state %u %x\n", *State, Status); - if (NT_SUCCESS(Status)) - { - // store new state - Pin->m_State = *State; + PinWorkContext->WorkItem = IoAllocateWorkItem(IoGetCurrentIrpStackLocation(Irp)->DeviceObject); + PC_ASSERT(PinWorkContext->WorkItem); + // initialize work item context + PinWorkContext->NewState = *State; + PinWorkContext->Pin = Pin; + PinWorkContext->Irp = Irp; - if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP) - { - /* FIXME complete pending irps with successfull state */ - Pin->m_IrpQueue->CancelBuffers(); - } - } + IoMarkIrpPending(Irp); - // store result - Irp->IoStatus.Information = sizeof(KSSTATE); - return Status; + IoQueueWorkItem(PinWorkContext->WorkItem, PinSetStateWorkerRoutine, DelayedWorkQueue, (PVOID)PinWorkContext); + return STATUS_PENDING; } else if (Request->Flags & KSPROPERTY_TYPE_GET) { @@ -413,7 +457,7 @@ PinWaveCyclicState( *State = Pin->m_State; // store result Irp->IoStatus.Information = sizeof(KSSTATE); - + DPRINT1("Getting state %u %x\n", *State, STATUS_SUCCESS); return STATUS_SUCCESS; } @@ -464,7 +508,7 @@ PinWaveCyclicDataFormat( } // new change request - PC_ASSERT(Pin->m_State == KSSTATE_STOP); + PC_ASSERT(Pin->m_State != KSSTATE_RUN); // FIXME queue a work item when Irql != PASSIVE_LEVEL PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); @@ -760,65 +804,6 @@ CPortPinWaveCyclic::NewIrpTarget( return STATUS_UNSUCCESSFUL; } -NTSTATUS -NTAPI -CPortPinWaveCyclic::HandleKsProperty( - IN PIRP Irp) -{ - PKSPROPERTY Property; - NTSTATUS Status; - UNICODE_STRING GuidString; - PIO_STACK_LOCATION IoStack; - - IoStack = IoGetCurrentIrpStackLocation(Irp); - - DPRINT("IPortPinWave_HandleKsProperty entered\n"); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - - Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor); - - if (Status == STATUS_NOT_FOUND) - { - Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; - - RtlStringFromGUID(Property->Set, &GuidString); - DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); - RtlFreeUnicodeString(&GuidString); - } - - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - - return Status; -} - -NTSTATUS -NTAPI -CPortPinWaveCyclic::HandleKsStream( - IN PIRP Irp) -{ - NTSTATUS Status; - ULONG Data = 0; - InterlockedIncrement((PLONG)&m_TotalPackets); - - DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData()); - - Status = m_IrpQueue->AddMapping(Irp, &Data); - - if (NT_SUCCESS(Status)) - { - m_Position.WriteOffset += Data; - - return STATUS_PENDING; - } - - return Status; -} - NTSTATUS NTAPI CPortPinWaveCyclic::DeviceIoControl( @@ -826,14 +811,28 @@ CPortPinWaveCyclic::DeviceIoControl( IN PIRP Irp) { PIO_STACK_LOCATION IoStack; + PKSPROPERTY Property; + UNICODE_STRING GuidString; NTSTATUS Status = STATUS_NOT_SUPPORTED; + ULONG Data = 0; + KSRESET ResetValue; + /* get current irp stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); - if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) { - return HandleKsProperty(Irp); + /* handle property with subdevice descriptor */ + Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor); + + if (Status == STATUS_NOT_FOUND) + { + Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; + + RtlStringFromGUID(Property->Set, &GuidString); + DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); + RtlFreeUnicodeString(&GuidString); + } } else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT) { @@ -846,11 +845,48 @@ CPortPinWaveCyclic::DeviceIoControl( else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE) { /// FIXME - /// handle reset state + Status = KsAcquireResetValue(Irp, &ResetValue); + DPRINT("Status %x Value %u\n", Status, ResetValue); + /* check for success */ + if (NT_SUCCESS(Status)) + { + if (ResetValue == KSRESET_BEGIN) + { + m_IrpQueue->CancelBuffers(); + m_ResetState = KSRESET_BEGIN; + } + else if (ResetValue == KSRESET_END) + { + m_ResetState = KSRESET_END; + } + } } else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) { - return HandleKsStream(Irp); + /* increment total number of packets */ + InterlockedIncrement((PLONG)&m_TotalPackets); + + DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData()); + + /* is the device not currently reset */ + if (m_ResetState == KSRESET_END) + { + /* add the mapping */ + Status = m_IrpQueue->AddMapping(Irp, &Data); + + /* check for success */ + if (NT_SUCCESS(Status)) + { + m_Position.WriteOffset += Data; + Status = STATUS_PENDING; + } + } + else + { + /* reset request is currently in progress */ + Status = STATUS_DEVICE_NOT_READY; + DPRINT1("NotReady\n"); + } } else { @@ -1146,6 +1182,9 @@ CPortPinWaveCyclic::Init( m_Descriptor.EventList = &m_EventList; m_Descriptor.EventListLock = &m_EventListLock; + // initialize reset state + m_ResetState = KSRESET_END; + // release subdevice descriptor Subdevice->Release(); @@ -1183,6 +1222,7 @@ CPortPinWaveCyclic::Init( m_AllocatorFraming.FrameSize = m_FrameSize; m_Stream->Silence(SilenceBuffer, m_FrameSize); + m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize); Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, m_FrameSize, 0, SilenceBuffer); if (!NT_SUCCESS(Status)) @@ -1203,8 +1243,8 @@ CPortPinWaveCyclic::Init( m_Port = Port; m_Filter = Filter; - DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE)); - DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE)); + //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE)); + //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE)); return STATUS_SUCCESS; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.cpp b/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.cpp index 3b8c7cc1929..8c08b1f9c3d 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.cpp @@ -107,6 +107,7 @@ CPortDMus::QueryInterface( if (IsEqualGUIDAligned(refiid, IID_IPortDMus) || IsEqualGUIDAligned(refiid, IID_IPortMidi) || + IsEqualGUIDAligned(refiid, IID_IPort) || IsEqualGUIDAligned(refiid, IID_IUnknown)) { *Output = PVOID(PUNKNOWN((IPortDMus*)this)); diff --git a/reactos/drivers/wdm/audio/backpln/portcls/private.hpp b/reactos/drivers/wdm/audio/backpln/portcls/private.hpp index 45e6092e6e3..17adc4c8af5 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/private.hpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/private.hpp @@ -328,7 +328,10 @@ PcHandleDisableEventWithTable( IN PIRP Irp, IN PSUBDEVICE_DESCRIPTOR Descriptor); - +IIrpTarget * +NTAPI +KsoGetIrpTargetFromIrp( + PIRP Irp); #define DEFINE_KSPROPERTY_CONNECTIONSET(PinSet,\ PropStateHandler, PropDataFormatHandler, PropAllocatorFraming)\ @@ -389,6 +392,9 @@ typedef struct LIST_ENTRY TimerList; KSPIN_LOCK TimerListLock; + DEVICE_POWER_STATE DevicePowerState; + SYSTEM_POWER_STATE SystemPowerState; + } PCLASS_DEVICE_EXTENSION, *PPCLASS_DEVICE_EXTENSION; @@ -406,4 +412,11 @@ typedef struct PVOID Context; }TIMER_CONTEXT, *PTIMER_CONTEXT; +typedef struct +{ + KSOBJECT_HEADER ObjectHeader; + IIrpTarget * Target; + PKSOBJECT_CREATE_ITEM CreateItem; +}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT; + #endif diff --git a/reactos/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp b/reactos/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp index 9a4bbbd8ca0..730cd059a13 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp @@ -183,7 +183,7 @@ PinPropertyHandler( IIrpTarget * IrpTarget; IPort *Port; ISubdevice *SubDevice; - + PDISPATCH_CONTEXT DispatchContext; NTSTATUS Status = STATUS_UNSUCCESSFUL; @@ -193,8 +193,11 @@ PinPropertyHandler( // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); + // get dispatch context + DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; + // Get the IrpTarget - IrpTarget = (IIrpTarget*)IoStack->FileObject->FsContext; + IrpTarget = DispatchContext->Target; PC_ASSERT(IrpTarget); // Get the parent diff --git a/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp b/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp index 21e2bf1ec2d..393e32cf9f4 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp @@ -50,13 +50,13 @@ NTAPI KsoGetIrpTargetFromIrp( PIRP Irp) { - PKSOBJECT_CREATE_ITEM CreateItem; + PIO_STACK_LOCATION IoStack; - // access the create item - CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); + // get current irp stack location + IoStack = IoGetCurrentIrpStackLocation(Irp); // IIrpTarget is stored in Context member - return (IIrpTarget*)CreateItem->Context; + return (IIrpTarget*)IoStack->FileObject->FsContext; } NTSTATUS @@ -110,6 +110,9 @@ PcHandlePropertyWithTable( /* try first KsPropertyHandler */ Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet); + if (Status != STATUS_NOT_FOUND) + return Status; + // get current irp stack location IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -119,7 +122,7 @@ PcHandlePropertyWithTable( // check if this a GUID_NULL request if (Status == STATUS_NOT_FOUND) { - if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE)) + if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE) || !(Property->Property.Flags & KSPROPERTY_TYPE_TOPOLOGY)) return Status; // check if its a request for a topology node @@ -350,16 +353,21 @@ VOID DumpFilterDescriptor( IN PPCFILTER_DESCRIPTOR FilterDescription) { - ULONG Index; + ULONG Index, SubIndex; PPCPROPERTY_ITEM PropertyItem; + PPCEVENT_ITEM EventItem; + PPCNODE_DESCRIPTOR NodeDescriptor; UNICODE_STRING GuidString; - DPRINT("======================\n"); - DPRINT("Descriptor Automation Table%p\n",FilterDescription->AutomationTable); + + + DPRINT1("======================\n"); + DPRINT1("Descriptor Automation Table%p\n",FilterDescription->AutomationTable); if (FilterDescription->AutomationTable) { - DPRINT("FilterPropertiesCount %u FilterPropertySize %u Expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM)); + DPRINT1("FilterPropertiesCount %u FilterPropertySize %u Expected %u Events %u EventItemSize %u expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM), + FilterDescription->AutomationTable->EventCount, FilterDescription->AutomationTable->EventItemSize, sizeof(PCEVENT_ITEM)); if (FilterDescription->AutomationTable->PropertyCount) { PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties; @@ -367,15 +375,56 @@ DumpFilterDescriptor( for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++) { RtlStringFromGUID(*PropertyItem->Set, &GuidString); - DPRINT("Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags); + DPRINT("Property Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags); PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize); } + + EventItem = (PPCEVENT_ITEM)FilterDescription->AutomationTable->Events; + for(Index = 0; Index < FilterDescription->AutomationTable->EventCount; Index++) + { + RtlStringFromGUID(*EventItem->Set, &GuidString); + DPRINT1("EventIndex %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, EventItem->Id, EventItem->Flags); + + EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + FilterDescription->AutomationTable->EventItemSize); + } + } } + if (FilterDescription->Nodes) + { + DPRINT1("NodeCount %u NodeSize %u expected %u\n", FilterDescription->NodeCount, FilterDescription->NodeSize, sizeof(PCNODE_DESCRIPTOR)); + NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes; + for(Index = 0; Index < FilterDescription->NodeCount; Index++) + { + DPRINT("Index %u AutomationTable %p\n", Index, NodeDescriptor->AutomationTable); - DPRINT("======================\n"); + if (NodeDescriptor->AutomationTable) + { + DPRINT1("Index %u EventCount %u\n", Index, NodeDescriptor->AutomationTable->EventCount); + EventItem = (PPCEVENT_ITEM)NodeDescriptor->AutomationTable->Events; + for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->EventCount; SubIndex++) + { + RtlStringFromGUID(*EventItem->Set, &GuidString); + DPRINT1("EventIndex %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, EventItem->Id, EventItem->Flags); + + EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + FilterDescription->AutomationTable->EventItemSize); + } + + } + + + NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize); + } + + + + } + + + + DPRINT1("======================\n"); } NTSTATUS