/***************************************************************************** * 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; }