Sample Code
Windows Driver Samples/ Microsoft Virtual Audio Device Driver Sample/ C++/ micarray/ mintopo.cpp/
/*++ Copyright (c) 1997-2000 Microsoft Corporation All Rights Reserved Module Name: mintopo.cpp Abstract: Implementation of topology miniport. --*/ #pragma warning (disable : 4127) #include <msvad.h> #include <common.h> #include "micarray.h" #include "minwave.h" #include "mintopo.h" #include "toptable.h" /********************************************************************* * Topology/Wave bridge connection * * * * +------+ +------+ * * | Topo | | Wave | * * | | | | * * Jack --->|0 1|===>|0 1|---> Capture Host Pin * * | | | | * * +------+ +------+ * *********************************************************************/ PHYSICALCONNECTIONTABLE TopologyPhysicalConnections = { (ULONG)-1, // ulTopologyIn KSPIN_TOPO_BRIDGE, // ulTopologyOut KSPIN_WAVE_BRIDGE, // ulWaveIn (ULONG)-1 // ulWaveOut }; #pragma code_seg("PAGE") //============================================================================= NTSTATUS CreateMiniportTopologyMSVAD ( OUT PUNKNOWN * Unknown, IN REFCLSID, IN PUNKNOWN UnknownOuter OPTIONAL, _When_((PoolType & NonPagedPoolMustSucceed) != 0, __drv_reportError("Must succeed pool allocations are forbidden. " "Allocation failures cause a system crash")) IN POOL_TYPE PoolType ) /*++ Routine Description: Creates a new topology miniport. Arguments: Unknown - RefclsId - UnknownOuter - PoolType - Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(Unknown); STD_CREATE_BODY(CMiniportTopology, Unknown, UnknownOuter, PoolType); } // CreateMiniportTopologyMSVAD //============================================================================= CMiniportTopology::~CMiniportTopology ( void ) /*++ Routine Description: Topology miniport destructor Arguments: Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[CMiniportTopology::~CMiniportTopology]")); } // ~CMiniportTopology //============================================================================= NTSTATUS CMiniportTopology::DataRangeIntersection ( _In_ ULONG PinId, _In_ PKSDATARANGE ClientDataRange, _In_ PKSDATARANGE MyDataRange, _In_ ULONG OutputBufferLength, _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength) PVOID ResultantFormat OPTIONAL, _Out_ PULONG ResultantFormatLength ) /*++ Routine Description: The DataRangeIntersection function determines the highest quality intersection of two data ranges. Arguments: PinId - Pin for which data intersection is being determined. ClientDataRange - Pointer to KSDATARANGE structure which contains the data range submitted by client in the data range intersection property request. MyDataRange - Pin's data range to be compared with client's data range. OutputBufferLength - Size of the buffer pointed to by the resultant format parameter. ResultantFormat - Pointer to value where the resultant format should be returned. ResultantFormatLength - Actual length of the resultant format that is placed at ResultantFormat. This should be less than or equal to OutputBufferLength. Return Value: NT status code. --*/ { PAGED_CODE(); return CMiniportTopologyMSVAD::DataRangeIntersection ( PinId, ClientDataRange, MyDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength ); } // DataRangeIntersection //============================================================================= STDMETHODIMP CMiniportTopology::GetDescription ( _Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor ) /*++ Routine Description: The GetDescription function gets a pointer to a filter description. It provides a location to deposit a pointer in miniport's description structure. This is the placeholder for the FromNode or ToNode fields in connections which describe connections to the filter's pins. Arguments: OutFilterDescriptor - Pointer to the filter description. Return Value: NT status code. --*/ { PAGED_CODE(); return CMiniportTopologyMSVAD::GetDescription(OutFilterDescriptor); } // GetDescription //============================================================================= STDMETHODIMP CMiniportTopology::Init ( _In_ PUNKNOWN UnknownAdapter, _In_ PRESOURCELIST ResourceList, _In_ PPORTTOPOLOGY Port_ ) /*++ Routine Description: The Init function initializes the miniport. Callers of this function should run at IRQL PASSIVE_LEVEL Arguments: UnknownAdapter - A pointer to the Iuknown interface of the adapter object. ResourceList - Pointer to the resource list to be supplied to the miniport during initialization. The port driver is free to examine the contents of the ResourceList. The port driver will not be modify the ResourceList contents. Port - Pointer to the topology port object that is linked with this miniport. Return Value: NT status code. --*/ { UNREFERENCED_PARAMETER(ResourceList); PAGED_CODE(); ASSERT(UnknownAdapter); ASSERT(Port_); DPF_ENTER(("[CMiniportTopology::Init]")); NTSTATUS ntStatus; ntStatus = CMiniportTopologyMSVAD::Init ( UnknownAdapter, Port_ ); if (NT_SUCCESS(ntStatus)) { m_FilterDescriptor = &MiniportFilterDescriptor; } return ntStatus; } // Init //============================================================================= STDMETHODIMP CMiniportTopology::NonDelegatingQueryInterface ( _In_ REFIID Interface, _COM_Outptr_ PVOID * Object ) /*++ Routine Description: QueryInterface for MiniportTopology Arguments: Interface - GUID of the interface Object - interface object to be returned. Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(Object); if (IsEqualGUIDAligned(Interface, IID_IUnknown)) { *Object = PVOID(PUNKNOWN(this)); } else if (IsEqualGUIDAligned(Interface, IID_IMiniport)) { *Object = PVOID(PMINIPORT(this)); } else if (IsEqualGUIDAligned(Interface, IID_IMiniportTopology)) { *Object = PVOID(PMINIPORTTOPOLOGY(this)); } else { *Object = NULL; } if (*Object) { // We reference the interface for the caller. PUNKNOWN(*Object)->AddRef(); return(STATUS_SUCCESS); } return(STATUS_INVALID_PARAMETER); } // NonDelegatingQueryInterface //============================================================================= NTSTATUS CMiniportTopology::PropertyHandlerMicArrayGeometry ( IN PPCPROPERTY_REQUEST PropertyRequest ) /*++ Routine Description: Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY ) Arguments: PropertyRequest - Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(PropertyRequest); DPF_ENTER(("[PropertyHandlerMicArrayGeometry]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; ULONG nPinId = (ULONG)-1; if (PropertyRequest->InstanceSize >= sizeof(ULONG)) { nPinId = *(PULONG(PropertyRequest->Instance)); if (nPinId == KSPIN_TOPO_MIC_ELEMENTS) { if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandler_BasicSupport ( PropertyRequest, KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET, VT_ILLEGAL ); } else { ULONG cElements = 2; ULONG cbNeeded = FIELD_OFFSET(KSAUDIO_MIC_ARRAY_GEOMETRY, KsMicCoord) + cElements * sizeof(KSAUDIO_MICROPHONE_COORDINATES); if (PropertyRequest->ValueSize == 0) { PropertyRequest->ValueSize = cbNeeded; ntStatus = STATUS_BUFFER_OVERFLOW; } else if (PropertyRequest->ValueSize < cbNeeded) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { PKSAUDIO_MIC_ARRAY_GEOMETRY pMAG = (PKSAUDIO_MIC_ARRAY_GEOMETRY)PropertyRequest->Value; // fill in mic array geometry fields pMAG->usVersion = 0x0100; // Version of Mic array specification (0x0100) pMAG->usMicArrayType = (USHORT)KSMICARRAY_MICARRAYTYPE_LINEAR; // Type of Mic Array pMAG->wVerticalAngleBegin = -7854; // Work Volume Vertical Angle Begin (-45 degrees) pMAG->wVerticalAngleEnd = 7854; // Work Volume Vertical Angle End (+45 degrees) pMAG->wHorizontalAngleBegin = -7854; // Work Volume HorizontalAngle Begin (-45 degrees) pMAG->wHorizontalAngleEnd = 7854; // Work Volume HorizontalAngle End (+45 degrees) pMAG->usFrequencyBandLo = 100; // Low end of Freq Range pMAG->usFrequencyBandHi = 8000; // High end of Freq Range pMAG->usNumberOfMicrophones = 2; // Count of microphone coordinate structures to follow. pMAG->KsMicCoord[0].usType = (USHORT)KSMICARRAY_MICTYPE_CARDIOID; pMAG->KsMicCoord[0].wXCoord = 0; pMAG->KsMicCoord[0].wYCoord = -100; // mic elements are 200 mm apart; pMAG->KsMicCoord[0].wZCoord = 0; pMAG->KsMicCoord[0].wVerticalAngle = 0; pMAG->KsMicCoord[0].wHorizontalAngle = 0; pMAG->KsMicCoord[1].usType = (USHORT)KSMICARRAY_MICTYPE_CARDIOID; pMAG->KsMicCoord[1].wXCoord = 0; pMAG->KsMicCoord[1].wYCoord = 100; // mic elements are 200 mm apart pMAG->KsMicCoord[1].wZCoord = 0; pMAG->KsMicCoord[1].wVerticalAngle = 0; pMAG->KsMicCoord[1].wHorizontalAngle = 0; ntStatus = STATUS_SUCCESS; } } } } } return ntStatus; } //============================================================================= NTSTATUS CMiniportTopology::PropertyHandlerJackDescription ( IN PPCPROPERTY_REQUEST PropertyRequest ) /*++ Routine Description: Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION ) Arguments: PropertyRequest - Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(PropertyRequest); DPF_ENTER(("[PropertyHandlerJackDescription]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; ULONG nPinId = (ULONG)-1; if (PropertyRequest->InstanceSize >= sizeof(ULONG)) { nPinId = *(PULONG(PropertyRequest->Instance)); if (nPinId == KSPIN_TOPO_MIC_ELEMENTS) { if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandler_BasicSupport ( PropertyRequest, KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET, VT_ILLEGAL ); } else { ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION); if (PropertyRequest->ValueSize == 0) { PropertyRequest->ValueSize = cbNeeded; ntStatus = STATUS_BUFFER_OVERFLOW; } else if (PropertyRequest->ValueSize < cbNeeded) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value; PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1); pMI->Size = cbNeeded; pMI->Count = 1; pDesc->ChannelMapping = 0; // Don't specify channel mask for array mic pDesc->Color = 0x00000000; // Black. This is an integrated device pDesc->ConnectionType = eConnTypeUnknown; // Integrated. pDesc->GeoLocation = eGeoLocInsideMobileLid; pDesc->GenLocation = eGenLocPrimaryBox; pDesc->PortConnection = ePortConnIntegratedDevice; pDesc->IsConnected = TRUE; // This is an integrated device, so it's always "connected" ntStatus = STATUS_SUCCESS; } } } } } return ntStatus; } //============================================================================= NTSTATUS PropertyHandler_TopoFilter ( IN PPCPROPERTY_REQUEST PropertyRequest ) /*++ Routine Description: Redirects property request to miniport object Arguments: PropertyRequest - Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(PropertyRequest); DPF_ENTER(("[PropertyHandler_TopoFilter]")); // PropertryRequest structure is filled by portcls. // MajorTarget is a pointer to miniport object for miniports. // NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Audio) && (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY)) { ntStatus = pMiniport->PropertyHandlerMicArrayGeometry ( PropertyRequest ); } else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack) && (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)) { ntStatus = pMiniport->PropertyHandlerJackDescription ( PropertyRequest ); } return ntStatus; } // PropertyHandler_TopoFilter //============================================================================= NTSTATUS PropertyHandler_Topology ( IN PPCPROPERTY_REQUEST PropertyRequest ) /*++ Routine Description: Redirects property request to miniport object Arguments: PropertyRequest - Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(PropertyRequest); DPF_ENTER(("[PropertyHandler_Topology]")); // PropertryRequest structure is filled by portcls. // MajorTarget is a pointer to miniport object for miniports. // PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; return pMiniport->PropertyHandlerGeneric(PropertyRequest); } // PropertyHandler_Topology #pragma code_seg()
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials