diff --git a/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c index 52d6fa36cdb..bd85b964d47 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c @@ -86,14 +86,14 @@ IPortFilterWaveCyclic_fnNewIrpTarget( ISubdevice * ISubDevice; NTSTATUS Status; IPortPinWaveCyclic * Pin; - SUBDEVICE_DESCRIPTOR * Descriptor; PKSPIN_CONNECT ConnectDetails; - IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface; ASSERT(This->Port); + DPRINT("IPortFilterWaveCyclic_fnNewIrpTarget entered\n"); + Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice); if (!NT_SUCCESS(Status)) return STATUS_UNSUCCESSFUL; diff --git a/reactos/drivers/wdm/audio/backpln/portcls/guids.c b/reactos/drivers/wdm/audio/backpln/portcls/guids.c index 4b19072e4be..e846ba69482 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/guids.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/guids.c @@ -60,6 +60,7 @@ const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, { const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}}; +const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; /// /// undocumented guids diff --git a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c index 1595c2a1d72..5b6fe0df67f 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c @@ -9,6 +9,12 @@ typedef struct IPortWaveCyclic * Port; IPortFilterWaveCyclic * Filter; KSPIN_DESCRIPTOR * KsPinDescriptor; + PMINIPORTWAVECYCLIC Miniport; + PSERVICEGROUP ServiceGroup; + PDMACHANNEL DmaChannel; + PMINIPORTWAVECYCLICSTREAM Stream; + KSSTATE State; + PKSDATAFORMAT Format; }IPortPinWaveCyclicImpl; @@ -165,6 +171,139 @@ IPortPinWaveCyclic_fnNewIrpTarget( return STATUS_UNSUCCESSFUL; } +NTSTATUS +NTAPI +IPortPinWaveCyclic_HandleKsProperty( + IN IPortPinWaveCyclic * iface, + IN PIRP Irp) +{ + PKSPROPERTY Property; + NTSTATUS Status; + UNICODE_STRING GuidString; + PIO_STACK_LOCATION IoStack; + IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface; + + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT1("IPortPinWave_HandleKsProperty entered\n"); + + if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY)) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + return STATUS_INVALID_PARAMETER; + } + + Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; + + if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Connection)) + { + if (Property->Id == KSPROPERTY_CONNECTION_STATE) + { + PKSSTATE State = (PKSSTATE)Irp->UserBuffer; + + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTATE)) + { + Irp->IoStatus.Information = sizeof(KSSTATE); + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + return STATUS_BUFFER_TOO_SMALL; + } + + if (Property->Id & KSPROPERTY_TYPE_SET) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + if (This->Stream) + { + Status = This->Stream->lpVtbl->SetState(This->Stream, *State); + + DPRINT1("Setting state %x\n", Status); + if (NT_SUCCESS(Status)) + { + This->State = *State; + Irp->IoStatus.Information = sizeof(KSSTATE); + Irp->IoStatus.Status = Status; + return Status; + } + Irp->IoStatus.Status = Status; + } + return Irp->IoStatus.Status; + } + else if (Property->Id & KSPROPERTY_TYPE_GET) + { + *State = This->State; + Irp->IoStatus.Information = sizeof(KSSTATE); + Irp->IoStatus.Status = STATUS_SUCCESS; + return STATUS_SUCCESS; + } + } + else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT) + { + PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer; + if (Property->Id & KSPROPERTY_TYPE_SET) + { + PKSDATAFORMAT NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); + if (!NewDataFormat) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_NO_MEMORY; + return STATUS_NO_MEMORY; + } + RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize); + + if (This->Stream) + { + Status = This->Stream->lpVtbl->SetFormat(This->Stream, DataFormat); + if (NT_SUCCESS(Status)) + { + if (This->Format) + ExFreePoolWithTag(This->Format, TAG_PORTCLASS); + This->Format = NewDataFormat; + Irp->IoStatus.Information = DataFormat->FormatSize; + Irp->IoStatus.Status = STATUS_SUCCESS; + return STATUS_SUCCESS; + } + } + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; + } + else if (Property->Id & KSPROPERTY_TYPE_GET) + { + PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer; + if (!This->Format) + { + DPRINT1("No format\n"); + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; + } + if (This->Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength) + { + Irp->IoStatus.Information = This->Format->FormatSize; + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + return STATUS_BUFFER_TOO_SMALL; + } + + RtlMoveMemory(DataFormat, This->Format, This->Format->FormatSize); + Irp->IoStatus.Information = DataFormat->FormatSize; + Irp->IoStatus.Status = STATUS_SUCCESS; + return STATUS_SUCCESS; + } + } + } + RtlStringFromGUID(&Property->Set, &GuidString); + + DPRINT1("Unhandeled property Set %S Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); + DbgBreakPoint(); + RtlFreeUnicodeString(&GuidString); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + return STATUS_NOT_IMPLEMENTED; +} + + /* * @unimplemented */ @@ -181,11 +320,10 @@ IPortPinWaveCyclic_fnDeviceIoControl( IoStack = IoGetCurrentIrpStackLocation(Irp); - DPRINT1("IPortPinWaveCyclic_fnDeviceIoControl\n"); + DPRINT1("IPortPinWaveCyclic_fnDeviceIoControl %x %x\n",IoStack->Parameters.DeviceIoControl.IoControlCode, IOCTL_KS_PROPERTY); if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) { - /// FIXME - /// handle property event + return IPortPinWaveCyclic_HandleKsProperty(iface, Irp); } else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT) { @@ -365,6 +503,8 @@ IPortPinWaveCyclic_fnInit( IN KSPIN_CONNECT * ConnectDetails, IN KSPIN_DESCRIPTOR * KsPinDescriptor) { + NTSTATUS Status; + PKSDATAFORMAT DataFormat; IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface; Port->lpVtbl->AddRef(Port); @@ -373,6 +513,42 @@ IPortPinWaveCyclic_fnInit( This->Port = Port; This->Filter = Filter; This->KsPinDescriptor = KsPinDescriptor; + This->Miniport = GetWaveCyclicMiniport(Port); + + DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1); + + DPRINT("IPortPinWaveCyclic_fnInit entered\n"); + + This->Format = ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); + if (!This->Format) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize); + + Status = This->Miniport->lpVtbl->NewStream(This->Miniport, + &This->Stream, + NULL, + NonPagedPool, + FALSE, //FIXME + ConnectDetails->PinId, + This->Format, + &This->DmaChannel, + &This->ServiceGroup); + + DPRINT("IPortPinWaveCyclic_fnInit Status %x\n", Status); + + if (!NT_SUCCESS(Status)) + return Status; + + Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup, + (PSERVICESINK)&This->lpVtblServiceSink); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to add pin to service group\n"); + return Status; + } + + This->State = KSSTATE_STOP; return STATUS_SUCCESS; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_midi.c b/reactos/drivers/wdm/audio/backpln/portcls/port_midi.c index 7fcfe5dfbd2..c068a3a3308 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_midi.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_midi.c @@ -172,7 +172,6 @@ IPortMidi_fnInit( /* increment reference on miniport adapter */ Miniport->lpVtbl->AddRef(Miniport); - DbgBreakPoint(); Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &ServiceGroup); if (!NT_SUCCESS(Status)) { @@ -182,8 +181,6 @@ IPortMidi_fnInit( return Status; } - DPRINT1("IMiniportMidi sucessfully init\n"); - /* get the miniport device descriptor */ Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor); if (!NT_SUCCESS(Status)) diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c b/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c index 8a6931e48ba..8de27c2c2c4 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c @@ -17,6 +17,12 @@ typedef struct PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor; }IPortTopologyImpl; +typedef struct +{ + PIRP Irp; + IIrpTarget *Filter; + +}PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT; static GUID InterfaceGuids[2] = { @@ -432,6 +438,43 @@ static ISubdeviceVtbl vt_ISubdeviceVtbl = ISubDevice_fnPinCount }; +VOID +NTAPI +CreatePinWorkerRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) +{ + NTSTATUS Status; + IIrpTarget *Pin; + PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context; + + DPRINT("CreatePinWorkerRoutine called\n"); + + Status = WorkerContext->Filter->lpVtbl->NewIrpTarget(WorkerContext->Filter, + &Pin, + NULL, + NULL, + NonPagedPool, + DeviceObject, + WorkerContext->Irp, + NULL); + + DPRINT("CreatePinWorkerRoutine Status %x\n", Status); + + if (NT_SUCCESS(Status)) + { + /* create the dispatch object */ + Status = NewDispatchObject(WorkerContext->Irp, Pin); + DPRINT("Pin %p\n", Pin); + } + + DPRINT1("CreatePinWorkerRoutine completing irp\n"); + WorkerContext->Irp->IoStatus.Status = Status; + WorkerContext->Irp->IoStatus.Information = 0; + IoCompleteRequest(WorkerContext->Irp, IO_SOUND_INCREMENT); +} + + NTSTATUS NTAPI PcCreateItemDispatch( @@ -521,7 +564,6 @@ PcCreateItemDispatch( Status = NewDispatchObject(Irp, Filter); DPRINT1("Filter %p\n", Filter); - DbgBreakPoint(); } else { @@ -534,6 +576,34 @@ PcCreateItemDispatch( if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN))) { /* try to create new pin */ + + if (KeGetCurrentIrql() >= APC_LEVEL) + { + PPIN_WORKER_CONTEXT Context = AllocateItem(NonPagedPool, sizeof(PIN_WORKER_CONTEXT), TAG_PORTCLASS); + if (!Context) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + return STATUS_INSUFFICIENT_RESOURCES; + } + Context->Filter = Filter; + Context->Irp = Irp; + + PIO_WORKITEM WorkItem = IoAllocateWorkItem(DeviceObject); + if (!WorkItem) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + return STATUS_INSUFFICIENT_RESOURCES; + } + + IoQueueWorkItem(WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context); + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_PENDING; + IoMarkIrpPending(Irp); + return STATUS_PENDING; + } + Create.CreateItemsCount = 1; Create.CreateItemsList = (PKSOBJECT_CREATE_ITEM)(IoStack->FileObject->FileName.Buffer + (wcslen(KS_NAME_PIN) + 1)); @@ -553,7 +623,8 @@ PcCreateItemDispatch( } } } - + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = Status; return Status; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c index 45a3c3f32dd..4c0ccec9039 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c @@ -709,6 +709,14 @@ static ISubdeviceVtbl vt_ISubdeviceVtbl = }; +///-------------------------------------------------------------- +PMINIPORTWAVECYCLIC +GetWaveCyclicMiniport( + IN IPortWaveCyclic* iface) +{ + IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl *)iface; + return This->pMiniport; +} //--------------------------------------------------------------- // IPortWaveCyclic constructor diff --git a/reactos/drivers/wdm/audio/backpln/portcls/private.h b/reactos/drivers/wdm/audio/backpln/portcls/private.h index f6a5f40efec..1e09b88ba49 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/private.h +++ b/reactos/drivers/wdm/audio/backpln/portcls/private.h @@ -94,7 +94,15 @@ NewDispatchObject( IN PIRP Irp, IN IIrpTarget * Target); -PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag); +PMINIPORTWAVECYCLIC +GetWaveCyclicMiniport( + IN IPortWaveCyclic* iface); + +PVOID +AllocateItem( + IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag); VOID FreeItem(