Exemple #1
0
/*****************************************************************************
 * CreateMidiFilterFactory()
 *****************************************************************************
 *//*!
 * @brief
 * Filter factory create function.
 * @details
 * Creates a device control filter factory.
 * @return
 * Returns STATUS_SUCCESS if successful. Otherwise, returns an appropriate
 * error code.
 */
NTSTATUS
CreateMidiFilterFactory
(
    IN		PKSDEVICE	KsDevice,
	IN		PWCHAR		RefString,
	IN		PVOID		Parameter1,
	IN		PVOID		Parameter2
)
{
    PAGED_CODE();

    _DbgPrintF(DEBUGLVL_BLAB,("[CMidiFilterFactory::Instantiate]"));

	NTSTATUS ntStatus;

	CMidiFilterFactory * FilterFactory = new(NonPagedPool,'rCcP') CMidiFilterFactory(NULL);

	if (FilterFactory)
	{
		FilterFactory->AddRef();

		ntStatus = FilterFactory->Init(KsDevice, Parameter1, Parameter2);

		PKSFILTER_DESCRIPTOR KsFilterDescriptor = NULL;

		if (NT_SUCCESS(ntStatus))
		{
			ntStatus = FilterFactory->GetFilterDescription(&KsFilterDescriptor);
		}

		if (NT_SUCCESS(ntStatus))
		{
			#define PROXY_CLSID	L"{17CCA71B-ECD7-11D0-B908-00A0C9223196}"

			PKSADAPTER KsAdapter = PKSADAPTER(KsDevice->Context);

			for (ULONG i = 0; i < KsFilterDescriptor->CategoriesCount; i++)
			{
				// Do what normally done by INF AddInterface directive.
				KsAdapter->AddSubDeviceInterface(RefString, KsFilterDescriptor->Categories[i]);

				KsAdapter->SetSubDeviceParameter(RefString, KsFilterDescriptor->Categories[i], L"CLSID", REG_SZ, PROXY_CLSID, sizeof(PROXY_CLSID));
			}

			CMidiFilterFactory::SetupFriendlyName(KsAdapter, KsFilterDescriptor, RefString, Parameter1, Parameter2);

			KsAcquireDevice(KsDevice);

			PKSFILTERFACTORY KsFilterFactory = NULL;

			ntStatus = KsCreateFilterFactory
							(
								KsDevice->FunctionalDeviceObject, 
								KsFilterDescriptor, 
								RefString,
								NULL,
								0,
								CMidiFilterFactory::SleepCallback,
								CMidiFilterFactory::WakeCallback,
								&KsFilterFactory
							);

			if (NT_SUCCESS(ntStatus))
			{
				KsFilterFactory->Context = PVOID(FilterFactory);
			}

			KsReleaseDevice(KsDevice);
		}

		if (NT_SUCCESS(ntStatus))
		{
			//
			// Add the item to the object bag if we were successful. Whenever the device goes 
			// away, the bag is cleaned up and we will be freed.
			//
			// For backwards compatibility with DirectX 8.0, we must grab the device mutex 
			// before doing this.  For Windows XP, this is not required, but it is still safe.
			//
			KsAcquireDevice(KsDevice);

			ntStatus = KsAddItemToObjectBag(KsDevice->Bag, FilterFactory, (PFNKSFREE)CMidiFilterFactory::Destruct);

			KsReleaseDevice(KsDevice);
		}

		if (NT_SUCCESS(ntStatus))
		{
			// Keeping this object...
			FilterFactory->AddRef();
		}

		// Release the private reference.
		FilterFactory->Release();
	}
	else
	{
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }
 
    return ntStatus;
}
NTSTATUS
CCaptureDevice::
PnpStart (
    IN PCM_RESOURCE_LIST TranslatedResourceList,
    IN PCM_RESOURCE_LIST UntranslatedResourceList
    )

/*++

Routine Description:

    Called at Pnp start.  We start up our virtual hardware simulation.

Arguments:

    TranslatedResourceList -
        The translated resource list from Pnp

    UntranslatedResourceList -
        The untranslated resource list from Pnp

Return Value:

    Success / Failure

--*/

{

    PAGED_CODE();

    //
    // Normally, we'd do things here like parsing the resource lists and
    // connecting our interrupt.  Since this is a simulation, there isn't
    // much to parse.  The parsing and connection should be the same as
    // any WDM driver.  The sections that will differ are illustrated below
    // in setting up a simulated DMA.
    //

    NTSTATUS Status = STATUS_SUCCESS;

    if (!m_Device -> Started) {
        // Create the Filter for the device
        KsAcquireDevice(m_Device);
        Status = KsCreateFilterFactory( m_Device->FunctionalDeviceObject,
                                        &CaptureFilterDescriptor,
                                        L"GLOBAL",
                                        NULL,
                                        KSCREATE_ITEM_FREEONSTOP,
                                        NULL,
                                        NULL,
                                        NULL );
        KsReleaseDevice(m_Device);

    }
    //
    // By PnP, it's possible to receive multiple starts without an intervening
    // stop (to reevaluate resources, for example).  Thus, we only perform
    // creations of the simulation on the initial start and ignore any 
    // subsequent start.  Hardware drivers with resources should evaluate
    // resources and make changes on 2nd start.
    //
    if (NT_SUCCESS(Status) && (!m_Device -> Started)) {

        m_HardwareSimulation = new (NonPagedPool) CHardwareSimulation (this);
        if (!m_HardwareSimulation) {
            //
            // If we couldn't create the hardware simulation, fail.
            //
            Status = STATUS_INSUFFICIENT_RESOURCES;
    
        } else {
            Status = KsAddItemToObjectBag (
                m_Device -> Bag,
                reinterpret_cast <PVOID> (m_HardwareSimulation),
                reinterpret_cast <PFNKSFREE> (CHardwareSimulation::Cleanup)
                );

            if (!NT_SUCCESS (Status)) {
                delete m_HardwareSimulation;
            }
        }
#if defined(_X86_)
        //
        // DMA operations illustrated in this sample are applicable only for 32bit platform.
        //
        INTERFACE_TYPE InterfaceBuffer;
        ULONG InterfaceLength;
        DEVICE_DESCRIPTION DeviceDescription;

        if (NT_SUCCESS (Status)) {
            //
            // Set up DMA...
            //
            // Ordinarilly, we'd be using InterfaceBuffer or 
            // InterfaceTypeUndefined if !NT_SUCCESS (IfStatus) as the 
            // InterfaceType below; however, for the purposes of this sample, 
            // we lie and say we're on the PCI Bus.  Otherwise, we're using map
            // registers on x86 32 bit physical to 32 bit logical and this isn't
            // what I want to show in this sample.
            //
            //
            // NTSTATUS IfStatus = 

            IoGetDeviceProperty (
                m_Device -> PhysicalDeviceObject,
                DevicePropertyLegacyBusType,
                sizeof (INTERFACE_TYPE),
                &InterfaceBuffer,
                &InterfaceLength
                );

            //
            // Initialize our fake device description.  We claim to be a 
            // bus-mastering 32-bit scatter/gather capable piece of hardware.
            //
            DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
            DeviceDescription.DmaChannel = ((ULONG) ~0);
            DeviceDescription.InterfaceType = PCIBus;
            DeviceDescription.DmaWidth = Width32Bits;
            DeviceDescription.DmaSpeed = Compatible;
            DeviceDescription.ScatterGather = TRUE;
            DeviceDescription.Master = TRUE;
            DeviceDescription.Dma32BitAddresses = TRUE;
            DeviceDescription.AutoInitialize = FALSE;
            DeviceDescription.MaximumLength = (ULONG) -1;
    
            //
            // Get a DMA adapter object from the system.
            //
            m_DmaAdapterObject = IoGetDmaAdapter (
                m_Device -> PhysicalDeviceObject,
                &DeviceDescription,
                &m_NumberOfMapRegisters
                );
    
            if (!m_DmaAdapterObject) {
                Status = STATUS_UNSUCCESSFUL;
            }
    
        }
    
        if (NT_SUCCESS (Status)) {
            //
            // Initialize our DMA adapter object with AVStream.  This is 
            // **ONLY** necessary **IF** you are doing DMA directly into
            // capture buffers as this sample does.  For this,
            // KSPIN_FLAG_GENERATE_MAPPINGS must be specified on a queue.
            //
    
            //
            // The (1 << 20) below is the maximum size of a single s/g mapping
            // that this hardware can handle.  Note that I have pulled this
            // number out of thin air for the "fake" hardware.
            //
            KsDeviceRegisterAdapterObject (
                m_Device,
                m_DmaAdapterObject,
                (1 << 20),
                sizeof (KSMAPPING)
                );
    
        }
#endif
    }
    
    return Status;

}
NTSTATUS
CCaptureDevice::
PnpStart (
    _In_ PCM_RESOURCE_LIST TranslatedResourceList,
    _In_ PCM_RESOURCE_LIST UntranslatedResourceList
)

/*++

Routine Description:

    Called at Pnp start.  We start up our  hardware simulation.

Arguments:

    TranslatedResourceList -
        The translated resource list from Pnp

    UntranslatedResourceList -
        The untranslated resource list from Pnp

Return Value:

    Success / Failure

--*/

{

    PAGED_CODE();

    //
    // Normally, we'd do things here like parsing the resource lists and
    // connecting our interrupt.  Since this is a simulation, there isn't
    // much to parse.  The parsing and connection should be the same as
    // any WDM driver.  The sections that will differ are illustrated below
    // in setting up a simulated DMA.
    //

    NTSTATUS Status = STATUS_SUCCESS;

    //
    // By PnP, it's possible to receive multiple starts without an intervening
    // stop (to reevaluate resources, for example).  Thus, we only perform
    // creations of the simulation on the initial start and ignore any
    // subsequent start.  Hardware drivers with resources should evaluate
    // resources and make changes on 2nd start.
    //
    // Walk the list of descriptors and enumerate the h/w sims described.
    //

    if (!m_Device -> Started)
    {
        // Create the Filter for the device
        for( size_t i=0; i<m_FilterDescriptorCount; i++ )
        {
            PKSFILTERFACTORY FilterFactory=nullptr;
            IFFAILED_EXIT(
                KsCreateFilterFactory( m_Device->FunctionalDeviceObject,
                                       m_Context[i].Descriptor,
                                       m_Context[i].Name,
                                       NULL,
                                       KSCREATE_ITEM_FREEONSTOP,
                                       NULL,
                                       NULL,
                                       &FilterFactory )
            );

            // Set primary camera to its interface, this allows device to be queried by GUID
            if( FilterFactory )
            {
                PKSDEVICE_PROFILE_INFO pDeviceProfiles = nullptr;
                UINT32 uiProfileCount = 0;
                PUNICODE_STRING SymbolicLinkName = KsFilterFactoryGetSymbolicLink(FilterFactory);
                BOOL fFrontCamera = FALSE;
                ACPI_PLD_V2_BUFFER pld = {0};
                pld.Revision = 2;
                pld.Panel = m_Context[i].AcpiPosition;
                pld.Rotation = m_Context[i].AcpiRotation;
                static
                const
                GUID FFC_Filter = {STATIC_FrontCamera_Filter};

                IFFAILED_EXIT(
                    IoSetDeviceInterfacePropertyData(SymbolicLinkName,
                                                     &DEVPKEY_Device_PhysicalDeviceLocation,
                                                     LOCALE_NEUTRAL,
                                                     PLUGPLAY_PROPERTY_PERSISTENT,
                                                     DEVPROP_TYPE_BINARY,
                                                     sizeof(pld),
                                                     (PVOID)&pld)
                );

                if( m_Context[i].Descriptor->ReferenceGuid &&
                    IsEqualGUID(*(m_Context[i].Descriptor->ReferenceGuid), FFC_Filter))
                {
                    fFrontCamera = TRUE;
                }

                // Publish our profile here.
                uiProfileCount = InitializeDeviceProfiles(fFrontCamera, &pDeviceProfiles);
                if( uiProfileCount > 0 && pDeviceProfiles != nullptr)
                {
                    if( NT_SUCCESS(KsInitializeDeviceProfile(FilterFactory)) )
                    {
                        for( UINT32 j=0; j<uiProfileCount; j++ )
                        {
                            if( !NT_SUCCESS(KsPublishDeviceProfile(FilterFactory, &pDeviceProfiles[j])) )
                            {
                                // Bail...
                                break;
                            }
                        }
                        if( !NT_SUCCESS(KsPersistDeviceProfile(FilterFactory)) )
                        {
                            // Trace here?
                        }
                    }

                    ExFreePool(pDeviceProfiles);
                    pDeviceProfiles = NULL;
                }
                else
                {
                    IFFAILED_EXIT(STATUS_INSUFFICIENT_RESOURCES);
                }
            }

            //  On a real device this object would be constructed whenever the sensor hardware is ready...
            m_Sensor[i] = CreateSensor( m_Context[i].Descriptor );
            if( !m_Sensor[i] )
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }

            IFFAILED_EXIT(m_Sensor[i]->Initialize());

            m_Sensor[i]->SetMountingOrientation( m_Context[i].AcpiRotation );
        }
    }

done:
    if( !NT_SUCCESS(Status) )
    {
        //  Free any sensor objects we created during this failed attempt.
        for( size_t i=0; i<m_FilterDescriptorCount; i++ )
        {
            SAFE_DELETE( m_Sensor[i] );
        }
    }
    return Status;
}