diff options
| author | Girish Pattabiraman <[email protected]> | 2018-11-12 18:08:19 -0800 |
|---|---|---|
| committer | Adonais Romero González <[email protected]> | 2018-11-12 18:08:19 -0800 |
| commit | 995e20f6dbca7ad10a039fa62a2de69eed092ffc (patch) | |
| tree | 67075f06fd8aaedad732d6c73b682c6e0fda9dba /audio/sysvad/EndpointsCommon/usbhstopo.cpp | |
| parent | c9110a3bc1634a5be8e7922119ad383311104095 (diff) | |
RS5 Updates (#311)
* Format Changes
==============
* Add KSEVENT_PINCAPS_FORMATCHANGE to Bluetooth HFP Endpoints
* Remove 8 bit formats from Bluetooth HFP Endpoints
Name Template
==============
* Bluetooth Endpoints are now based on templates in INF and then customized with endpoints specific data
Sideband Common Interface for future Sideband buses
===================================================
* Add ISidebandDevice
* Add current directory to TabletAudioSample include path. Remove unused compiler flags.
* RS4 bug fixes
* Replace FastMutex with Spinlock for DeviceFormatsAndModes to work well at DISPATCH_LEVEL
* Resync with Microsoft-master branch
* Replace FastMutex with Spinlock for DeviceFormatsAndModes to work well at DISPATCH_LEVEL
* RS5 updates:
- USB Sideband implementation
- Power management options: _USE_IPortClsRuntimePower, _USE_SingleComponentMultiFxStates
Diffstat (limited to 'audio/sysvad/EndpointsCommon/usbhstopo.cpp')
| -rw-r--r-- | audio/sysvad/EndpointsCommon/usbhstopo.cpp | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/audio/sysvad/EndpointsCommon/usbhstopo.cpp b/audio/sysvad/EndpointsCommon/usbhstopo.cpp new file mode 100644 index 00000000..e32f2027 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhstopo.cpp @@ -0,0 +1,538 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhstopo.cpp + +Abstract: + + Implementation of topology miniport for the USB Headset (external). + +--*/ +#ifdef SYSVAD_USB_SIDEBAND + +#pragma warning (disable : 4127) + +#include <sysvad.h> +#include "simple.h" +#include "mintopo.h" +#include "usbhstopo.h" + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsVolumeLevel_BasicSupport +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles basic support for USB Headset ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_VOLUMELEVEL ) + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG cbDescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + ASSERT(PropertyRequest); + + if (PropertyRequest->ValueSize >= cbDescriptionSize) + { + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + ULONG volumeSettingsSize = 0; + PKSPROPERTY_DESCRIPTION volumeSettings; + PKSPROPERTY_DESCRIPTION propDesc; + PSIDEBANDDEVICECOMMON usbHsDevice; + + propDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + volumeSettings = (PKSPROPERTY_DESCRIPTION)usbHsDevice->GetVolumeSettings(miniport->m_DeviceType, &volumeSettingsSize); + ASSERT(volumeSettings != NULL); + ASSERT(volumeSettingsSize != 0); + + ULONG cbFullProperty = volumeSettings->DescriptionSize; + + // if return buffer can hold a range description, return it + if(PropertyRequest->ValueSize >= cbFullProperty) + { + RtlCopyMemory(propDesc, volumeSettings, volumeSettings->DescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbFullProperty; + } + else + { + // otherwise only return description header + RtlCopyMemory(propDesc, volumeSettings, cbDescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbDescriptionSize; + } + } + 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; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsMute_BasicSupport +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles basic support for USB Headset ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MUTE ) + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG cbDescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + ASSERT(PropertyRequest); + + if (PropertyRequest->ValueSize >= cbDescriptionSize) + { + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + ULONG muteSettingsSize = 0; + PKSPROPERTY_DESCRIPTION muteSettings; + PKSPROPERTY_DESCRIPTION propDesc; + PSIDEBANDDEVICECOMMON usbHsDevice; + + propDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + muteSettings = (PKSPROPERTY_DESCRIPTION)usbHsDevice->GetMuteSettings(miniport->m_DeviceType, &muteSettingsSize); + ASSERT(muteSettings != NULL); + ASSERT(muteSettingsSize != 0); + + ULONG cbFullProperty = muteSettings->DescriptionSize; + + // if return buffer can hold mute description, return it + if(PropertyRequest->ValueSize >= cbFullProperty) + { + RtlCopyMemory(propDesc, muteSettings, muteSettings->DescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbFullProperty; + } + else + { + // otherwise only return description header + RtlCopyMemory(propDesc, muteSettings, cbDescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbDescriptionSize; + } + } + 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; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsJackDescription +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION ) + +Arguments: + + PropertyRequest - + + cJackDescriptions - + + JackDescriptions - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + ULONG nPinId = (ULONG)-1; + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + + 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_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) + { + PSIDEBANDDEVICECOMMON usbHsDevice = NULL; + PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value; + PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1); + + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + pMI->Size = cbNeeded; + pMI->Count = 1; + + RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION)); + + pDesc->IsConnected = usbHsDevice->GetConnectionStatus() ? TRUE : FALSE; + + ntStatus = STATUS_SUCCESS; + } + } + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsJackDescription2 +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 ) + +Arguments: + + PropertyRequest - + + cJackDescriptions - + + JackDescriptions - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + ULONG nPinId = (ULONG)-1; + + 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; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsJackContainerId +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_CONTAINERID ) + +Arguments: + + PropertyRequest - + + cJackDescriptions - + + JackDescriptions - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + ULONG nPinId = (ULONG)-1; + + if (PropertyRequest->InstanceSize >= sizeof(ULONG)) + { + nPinId = *(PULONG(PropertyRequest->Instance)); + + // This property is only valid on bridge pins. + 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(GUID); + + 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) + { + PSIDEBANDDEVICECOMMON usbHsDevice = NULL; + + GUID* guid = (GUID *)PropertyRequest->Value; + + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + *guid = usbHsDevice->GetContainerId(miniport->m_DeviceType); + + ntStatus = STATUS_SUCCESS; + } + } + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +PropertyHandler_UsbHsTopoNodeEvent +( + _In_ PPCEVENT_REQUEST EventRequest +) +{ + ASSERT(EventRequest); + + DPF_ENTER(("[%!FUNC!]")); + + // The major target is the object pointer to the topology miniport. + PCMiniportTopology pMiniport = (PCMiniportTopology)EventRequest->MajorTarget; + ASSERT (pMiniport); + + switch (EventRequest->Verb) + { + // Do we support event handling?!? + case PCEVENT_VERB_SUPPORT: + DPF(D_VERBOSE, ("BasicSupport Query for event.")); + break; + + // We should add the event now! + case PCEVENT_VERB_ADD: + DPF(D_VERBOSE, ("Adding event.")); + + // If we have the interface and EventEntry is defined ... + if (EventRequest->EventEntry) + { + pMiniport->AddEventToEventList(EventRequest->EventEntry); + } + else + { + return STATUS_UNSUCCESSFUL; + } + break; + + case PCEVENT_VERB_REMOVE: + // We cannot remove the event but we can stop generating the + // events. However, it also doesn't hurt to always generate them ... + DPF(D_VERBOSE, ("Removing event.")); + break; + + default: + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +#pragma code_seg() +#endif //SYSVAD_USB_SIDEBAND + + |
