//============================================================================= 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 < ARRAYSIZE(JackDescriptions)) && (JackDescriptions[nPinId] != NULL)) { 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; RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION)); ntStatus = STATUS_SUCCESS; } } } } } return ntStatus; }
NTSTATUS PropertyHandler_CpuResources ( _In_ PPCPROPERTY_REQUEST PropertyRequest ) /*++ Routine Description: Processes KSPROPERTY_AUDIO_CPURESOURCES Arguments: PropertyRequest - property request structure. Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[%s]",__FUNCTION__)); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(ULONG)); if (NT_SUCCESS(ntStatus)) { *(PULONG(PropertyRequest->Value)) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU; PropertyRequest->ValueSize = sizeof(ULONG); } } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandler_BasicSupport ( PropertyRequest, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, VT_UI4 ); } return ntStatus; } // PropertyHandlerCpuResources
//============================================================================= NTSTATUS CMiniportTopology::PropertyHandlerMuxSource(IN PPCPROPERTY_REQUEST PropertyRequest) /*++ Routine Description: PropertyHandler for KSPROPERTY_AUDIO_MUX_SOURCE. Arguments: PropertyRequest - property request structure Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[%s]",__FUNCTION__)); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; // // Validate node // This property is only valid for WAVEIN_MUX node. // // TODO if (WAVEIN_MUX == PropertyRequest->Node) { if (PropertyRequest->ValueSize >= sizeof(ULONG)) { PULONG pulMuxValue = PULONG(PropertyRequest->Value); if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *pulMuxValue = m_AdapterCommon->MixerMuxRead(); PropertyRequest->ValueSize = sizeof(ULONG); ntStatus = STATUS_SUCCESS; } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { m_AdapterCommon->MixerMuxWrite(*pulMuxValue); ntStatus = STATUS_SUCCESS; } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandler_BasicSupport(PropertyRequest, KSPROPERTY_TYPE_ALL, VT_I4); } } else { DPF(D_TERSE, ("[PropertyHandlerMuxSource - Invalid parameter]")); ntStatus = STATUS_INVALID_PARAMETER; } } return ntStatus; } // PropertyHandlerMuxSource
//============================================================================= NTSTATUS CMiniportTopology::PropertyHandlerVolume(IN PPCPROPERTY_REQUEST PropertyRequest) /*++ Routine Description: Property handler for KSPROPERTY_AUDIO_VOLUMELEVEL Arguments: PropertyRequest - property request structure Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[%s]",__FUNCTION__)); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; LONG lChannel; PULONG pulVolume; if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandlerBasicSupportVolume(PropertyRequest); } else { // volume value is a ULONG, instance is the channel number ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(ULONG), sizeof(LONG)); if (NT_SUCCESS(ntStatus)) { lChannel = * (PLONG (PropertyRequest->Instance)); pulVolume = PULONG (PropertyRequest->Value); if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *pulVolume = m_AdapterCommon->MixerVolumeRead(PropertyRequest->Node, lChannel); PropertyRequest->ValueSize = sizeof(ULONG); } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { m_AdapterCommon->MixerVolumeWrite(PropertyRequest->Node, lChannel, *pulVolume); } } else { DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus)); } } return ntStatus; } // PropertyHandlerVolume
//============================================================================= NTSTATUS CMiniportTopology::PropertyHandlerDevSpecific(IN PPCPROPERTY_REQUEST PropertyRequest) /*++ Routine Description: Property handler for KSPROPERTY_AUDIO_DEV_SPECIFIC Arguments: PropertyRequest - property request structure Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[%s]",__FUNCTION__)); NTSTATUS ntStatus = STATUS_SUCCESS; if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { if (DEV_SPECIFIC_VT_BOOL == PropertyRequest->Node ) { ntStatus = PropertyHandler_BasicSupport(PropertyRequest,KSPROPERTY_TYPE_ALL,VT_BOOL); } else { ULONG ExpectedSize = sizeof( KSPROPERTY_DESCRIPTION ) + sizeof( KSPROPERTY_MEMBERSHEADER ) + sizeof( KSPROPERTY_BOUNDS_LONG ); DWORD ulPropTypeSetId; if( DEV_SPECIFIC_VT_I4 == PropertyRequest->Node ) { ulPropTypeSetId = VT_I4; } else if ( DEV_SPECIFIC_VT_UI4 == PropertyRequest->Node ) { ulPropTypeSetId = VT_UI4; } else { ulPropTypeSetId = VT_ILLEGAL; ntStatus = STATUS_INVALID_PARAMETER; } if( NT_SUCCESS(ntStatus)) { if ( !PropertyRequest->ValueSize ) { PropertyRequest->ValueSize = ExpectedSize; ntStatus = STATUS_BUFFER_OVERFLOW; } else if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION)) { // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it // PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); PropDesc->AccessFlags = KSPROPERTY_TYPE_ALL; PropDesc->DescriptionSize = ExpectedSize; PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; PropDesc->PropTypeSet.Id = ulPropTypeSetId; PropDesc->PropTypeSet.Flags = 0; PropDesc->MembersListCount = 0; PropDesc->Reserved = 0; if ( PropertyRequest->ValueSize >= ExpectedSize ) { // Extra information to return PropDesc->MembersListCount = 1; PKSPROPERTY_MEMBERSHEADER MembersHeader = ( PKSPROPERTY_MEMBERSHEADER )( PropDesc + 1); MembersHeader->MembersFlags = KSPROPERTY_MEMBER_RANGES; MembersHeader->MembersCount = 1; MembersHeader->MembersSize = sizeof( KSPROPERTY_BOUNDS_LONG ); MembersHeader->Flags = 0; PKSPROPERTY_BOUNDS_LONG PeakMeterBounds = (PKSPROPERTY_BOUNDS_LONG)( MembersHeader + 1); if(VT_I4 == ulPropTypeSetId ) { PeakMeterBounds->SignedMinimum = 0; PeakMeterBounds->SignedMaximum = 0x7fffffff; } else { PeakMeterBounds->UnsignedMinimum = 0; PeakMeterBounds->UnsignedMaximum = 0xffffffff; } // set the return value size PropertyRequest->ValueSize = ExpectedSize; } else { // No extra information to return. PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); } ntStatus = STATUS_SUCCESS; } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) { // if return buffer can hold a ULONG, return the access flags // *(PULONG(PropertyRequest->Value)) = KSPROPERTY_TYPE_ALL; PropertyRequest->ValueSize = sizeof(ULONG); ntStatus = STATUS_SUCCESS; } else { PropertyRequest->ValueSize = 0; ntStatus = STATUS_BUFFER_TOO_SMALL; } } } } else { // switch on node id switch( PropertyRequest->Node ) { case DEV_SPECIFIC_VT_BOOL: PBOOL pbDevSpecific; ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(BOOL), 0); if (NT_SUCCESS(ntStatus)) { pbDevSpecific = PBOOL (PropertyRequest->Value); if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *pbDevSpecific = m_AdapterCommon->bDevSpecificRead(); PropertyRequest->ValueSize = sizeof(BOOL); } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { m_AdapterCommon->bDevSpecificWrite(*pbDevSpecific); } else { ntStatus = STATUS_INVALID_PARAMETER; } } break; case DEV_SPECIFIC_VT_I4: INT* piDevSpecific; ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(int), 0); if (NT_SUCCESS(ntStatus)) { piDevSpecific = PINT (PropertyRequest->Value); if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *piDevSpecific = m_AdapterCommon->iDevSpecificRead(); PropertyRequest->ValueSize = sizeof(int); } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { m_AdapterCommon->iDevSpecificWrite(*piDevSpecific); } else { ntStatus = STATUS_INVALID_PARAMETER; } } break; case DEV_SPECIFIC_VT_UI4: UINT* puiDevSpecific; ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(UINT), 0); if (NT_SUCCESS(ntStatus)) { puiDevSpecific = PUINT (PropertyRequest->Value); if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *puiDevSpecific = m_AdapterCommon->uiDevSpecificRead(); PropertyRequest->ValueSize = sizeof(UINT); } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { m_AdapterCommon->uiDevSpecificWrite(*puiDevSpecific); } else { ntStatus = STATUS_INVALID_PARAMETER; } } break; default: ntStatus = STATUS_INVALID_PARAMETER; break; } if( !NT_SUCCESS(ntStatus)) { DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus)); } } return ntStatus; } // PropertyHandlerDevSpecific
//============================================================================= NTSTATUS CMiniportTopology::PropertyHandlerBasicSupportVolume(IN PPCPROPERTY_REQUEST PropertyRequest) /*++ Routine Description: Handles BasicSupport for Volume nodes. Arguments: PropertyRequest - property request structure Return Value: NT status code. --*/ { PAGED_CODE(); NTSTATUS ntStatus = STATUS_SUCCESS; ULONG cbFullProperty = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG); if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) { PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); PropDesc->AccessFlags = KSPROPERTY_TYPE_ALL; PropDesc->DescriptionSize = cbFullProperty; PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; PropDesc->PropTypeSet.Id = VT_I4; PropDesc->PropTypeSet.Flags = 0; PropDesc->MembersListCount = 1; PropDesc->Reserved = 0; // if return buffer can also hold a range description, return it too if(PropertyRequest->ValueSize >= cbFullProperty) { // fill in the members header PKSPROPERTY_MEMBERSHEADER Members = PKSPROPERTY_MEMBERSHEADER(PropDesc + 1); Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES; Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG); Members->MembersCount = 1; Members->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL; // fill in the stepped range PKSPROPERTY_STEPPING_LONG Range = PKSPROPERTY_STEPPING_LONG(Members + 1); Range->Bounds.SignedMaximum = 0x00000000; // 0 dB Range->Bounds.SignedMinimum = -96 * 0x10000; // -96 dB Range->SteppingDelta = 0x08000; // .5 dB Range->Reserved = 0; // set the return value size PropertyRequest->ValueSize = cbFullProperty; } else { PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); } } else if(PropertyRequest->ValueSize >= sizeof(ULONG)) { // if return buffer can hold a ULONG, return the access flags PULONG AccessFlags = PULONG(PropertyRequest->Value); PropertyRequest->ValueSize = sizeof(ULONG); *AccessFlags = KSPROPERTY_TYPE_ALL; } else { PropertyRequest->ValueSize = 0; ntStatus = STATUS_BUFFER_TOO_SMALL; } return ntStatus; } // PropertyHandlerBasicSupportVolume
NTSTATUS PropertyHandler_PeakMeter2 ( _In_ PADAPTERCOMMON AdapterCommon, _In_ PPCPROPERTY_REQUEST PropertyRequest, _In_ ULONG MaxChannels ) /*++ Routine Description: Property handler for KSPROPERTY_AUDIO_PEAKMETER2 Arguments: AdapterCommon - interface to the common adapter object. PropertyRequest - property request structure. MaxChannels - # of supported channels. Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[%s]",__FUNCTION__)); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; ULONG ulChannel; PLONG plSample; if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandler_BasicSupportPeakMeter2( PropertyRequest, MaxChannels); } else { ntStatus = ValidatePropertyParams ( PropertyRequest, sizeof(LONG), // sample value is a LONG sizeof(ULONG) // instance is the channel number ); if (NT_SUCCESS(ntStatus)) { ulChannel = * (PULONG (PropertyRequest->Instance)); plSample = PLONG (PropertyRequest->Value); if (ulChannel >= MaxChannels && ulChannel != ALL_CHANNELS_ID) { ntStatus = STATUS_INVALID_PARAMETER; } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *plSample = PEAKMETER_NORMALIZE_IN_RANGE( AdapterCommon->MixerPeakMeterRead ( PropertyRequest->Node, ulChannel == ALL_CHANNELS_ID ? 0 : ulChannel )); PropertyRequest->ValueSize = sizeof(ULONG); } } if (!NT_SUCCESS(ntStatus)) { DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus)); } } return ntStatus; } // PropertyHandlerVolume
NTSTATUS PropertyHandler_Mute ( _In_ PADAPTERCOMMON AdapterCommon, _In_ PPCPROPERTY_REQUEST PropertyRequest, _In_ ULONG MaxChannels ) /*++ Routine Description: Property handler for KSPROPERTY_AUDIO_MUTE Arguments: AdapterCommon - interface to the common adapter object. PropertyRequest - property request structure. MaxChannels - # of supported channels. Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[%s]",__FUNCTION__)); NTSTATUS ntStatus; ULONG ulChannel; PBOOL pfMute; if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandler_BasicSupportMute( PropertyRequest, MaxChannels); } else { ntStatus = ValidatePropertyParams ( PropertyRequest, sizeof(BOOL), sizeof(ULONG) ); if (NT_SUCCESS(ntStatus)) { ulChannel = * (PULONG (PropertyRequest->Instance)); pfMute = PBOOL (PropertyRequest->Value); if (ulChannel >= MaxChannels && ulChannel != ALL_CHANNELS_ID) { ntStatus = STATUS_INVALID_PARAMETER; } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *pfMute = AdapterCommon->MixerMuteRead ( PropertyRequest->Node, ulChannel == ALL_CHANNELS_ID ? 0 : ulChannel ); PropertyRequest->ValueSize = sizeof(BOOL); } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { if (ALL_CHANNELS_ID == ulChannel) { for (ULONG i=0; i<ulChannel; ++i) { AdapterCommon->MixerMuteWrite ( PropertyRequest->Node, i, (*pfMute) ? TRUE : FALSE ); } } else { AdapterCommon->MixerMuteWrite ( PropertyRequest->Node, ulChannel, (*pfMute) ? TRUE : FALSE ); } } } if (!NT_SUCCESS(ntStatus)) { DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus)); } } return ntStatus; } // PropertyHandlerMute
NTSTATUS PropertyHandler_BasicSupportPeakMeter2 ( _In_ PPCPROPERTY_REQUEST PropertyRequest, _In_ ULONG MaxChannels ) /*++ Routine Description: Handles BasicSupport for peak meter nodes. Arguments: PropertyRequest - property request structure. MaxChannels - # of supported channels. Return Value: NT status code. --*/ { PAGED_CODE(); NTSTATUS ntStatus = STATUS_SUCCESS; ULONG cbFullProperty = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG) * MaxChannels; ASSERT(MaxChannels > 0); if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) { PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); PropDesc->AccessFlags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT; PropDesc->DescriptionSize = cbFullProperty; PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; PropDesc->PropTypeSet.Id = VT_I4; PropDesc->PropTypeSet.Flags = 0; PropDesc->MembersListCount = 1; PropDesc->Reserved = 0; // if return buffer can also hold a range description, return it too if(PropertyRequest->ValueSize >= cbFullProperty) { // fill in the members header PKSPROPERTY_MEMBERSHEADER Members = PKSPROPERTY_MEMBERSHEADER(PropDesc + 1); Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES; Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG); Members->MembersCount = MaxChannels; Members->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL; // fill in the stepped range PKSPROPERTY_STEPPING_LONG Range = PKSPROPERTY_STEPPING_LONG(Members + 1); for (ULONG i=0; i<MaxChannels; ++i) { Range[i].Bounds.SignedMaximum = PEAKMETER_SIGNED_MAXIMUM; Range[i].Bounds.SignedMinimum = PEAKMETER_SIGNED_MINIMUM; Range[i].SteppingDelta = PEAKMETER_STEPPING_DELTA; Range[i].Reserved = 0; } // set the return value size PropertyRequest->ValueSize = cbFullProperty; } else { PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); } } else if(PropertyRequest->ValueSize >= sizeof(ULONG)) { // if return buffer can hold a ULONG, return the access flags PULONG AccessFlags = PULONG(PropertyRequest->Value); PropertyRequest->ValueSize = sizeof(ULONG); *AccessFlags = KSPROPERTY_TYPE_ALL; } else { PropertyRequest->ValueSize = 0; ntStatus = STATUS_BUFFER_TOO_SMALL; } return ntStatus; } // PropertyHandlerBasicSupportVolume
NTSTATUS PropertyHandler_BasicSupport ( _In_ PPCPROPERTY_REQUEST PropertyRequest, _In_ ULONG Flags, _In_ DWORD PropTypeSetId ) /*++ Routine Description: Default basic support handler. Basic processing depends on the size of data. For ULONG it only returns Flags. For KSPROPERTY_DESCRIPTION, the structure is filled. Arguments: PropertyRequest - Flags - Support flags. PropTypeSetId - PropTypeSetId Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(Flags & KSPROPERTY_TYPE_BASICSUPPORT); NTSTATUS ntStatus = STATUS_INVALID_PARAMETER; if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION)) { // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it // PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); PropDesc->AccessFlags = Flags; PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); if (VT_ILLEGAL != PropTypeSetId) { PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; PropDesc->PropTypeSet.Id = PropTypeSetId; } else { PropDesc->PropTypeSet.Set = GUID_NULL; PropDesc->PropTypeSet.Id = 0; } PropDesc->PropTypeSet.Flags = 0; PropDesc->MembersListCount = 0; PropDesc->Reserved = 0; PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); ntStatus = STATUS_SUCCESS; } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) { // if return buffer can hold a ULONG, return the access flags // *(PULONG(PropertyRequest->Value)) = Flags; PropertyRequest->ValueSize = sizeof(ULONG); ntStatus = STATUS_SUCCESS; } else { PropertyRequest->ValueSize = 0; ntStatus = STATUS_BUFFER_TOO_SMALL; } return ntStatus; } // PropertyHandler_BasicSupport
NTSTATUS PropertyHandler_BthHfpMicVolumeLevel ( _In_ PPCPROPERTY_REQUEST PropertyRequest ) /*++ Routine Description: Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_VOLUMELEVEL ) Arguments: PropertyRequest - Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(PropertyRequest); DPF_ENTER(("[PropertyHandler_BthHfpMicVolumeLevel]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; PBTHHFPDEVICECOMMON bthHfpDevice = NULL; ULONG channel = (ULONG)-1; bthHfpDevice = miniport->GetBthHfpDevice(); // weak ref. ASSERT(bthHfpDevice != NULL); if (bthHfpDevice->IsVolumeSupported() == FALSE) { ntStatus = miniport->PropertyHandlerGeneric(PropertyRequest); } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { ntStatus = PropertyHandler_BthHfpVolumeLevel_BasicSupport(PropertyRequest); } else if (PropertyRequest->InstanceSize >= sizeof(ULONG)) { // Instance is the channel #, Bluetooth HFP supports mono streams. channel = *(PULONG(PropertyRequest->Instance)); if (channel == 0) { ULONG cbNeeded = sizeof(LONG); if (PropertyRequest->ValueSize == 0) { PropertyRequest->ValueSize = cbNeeded; ntStatus = STATUS_BUFFER_OVERFLOW; } else if (PropertyRequest->ValueSize < cbNeeded) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { LONG* volume = (LONG*)PropertyRequest->Value; if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *volume = bthHfpDevice->GetMicVolume(); ntStatus = STATUS_SUCCESS; } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { ntStatus = bthHfpDevice->SetMicVolume(*volume); } } } } return ntStatus; }
//============================================================================= NTSTATUS PropertyHandler_MicInJackDescription2 ( _In_ PPCPROPERTY_REQUEST PropertyRequest ) /*++ Routine Description: Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 ) Arguments: PropertyRequest - Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(PropertyRequest); DPF_ENTER(("[PropertyHandler_MicInJackDescription2]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; ULONG nPinId = (ULONG)-1; ULONG cJackDescriptions = ARRAYSIZE(MicInJackDescriptions); PKSJACK_DESCRIPTION * JackDescriptions = MicInJackDescriptions; if (PropertyRequest->InstanceSize >= sizeof(ULONG)) { nPinId = *(PULONG(PropertyRequest->Instance)); if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL)) { 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_DESCRIPTION2); 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_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI+1); pMI->Size = cbNeeded; pMI->Count = 1; RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2)); // // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether // the jack is currently active, streaming, idle, or hardware not ready. // pDesc->DeviceStateInfo = 0; // // From MSDN: // "If an audio device lacks jack presence detection, the IsConnected member of // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the // ambiguity that results from this dual meaning of the TRUE value for IsConnected, // a client application can call IKsJackDescription2::GetJackDescription2 to read // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint // does in fact support jack presence detection. In that case, the return value of // the IsConnected member can be interpreted to accurately reflect the insertion status // of the jack." // // Bit definitions: // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY // pDesc->JackCapabilities = JACKDESC2_PRESENCE_DETECT_CAPABILITY; ntStatus = STATUS_SUCCESS; } } } } } return ntStatus; }