text: /* Copyright (c) Microsoft Corporation. All rights reserved.
     Licensed under the MIT License.
  
  Abstract:
      Implementation of topology miniport for the headphone.
  
  */
  
  //4127: conditional expression is constant
  //4595: illegal inline operator
  #pragma warning (disable : 4127)
  #pragma warning (disable : 4595)
  
  #include "imx_audio.h"
  #include "simple.h"
  #include "mintopo.h"
  #include "speakerhptopo.h"
  #include "speakerhptoptable.h"
  
  
  
  //=============================================================================
  #pragma code_seg("PAGE")
  NTSTATUS
  PropertyHandler_SpeakerHpJackDescription
  ( 
      _In_ PPCPROPERTY_REQUEST PropertyRequest 
  )
  /*++
  
  Routine Description:
  
      Property handler for ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
  
  Arguments:
  
      PropertyRequest - property request
  
  Return Value:
  
      NT status code
  
  --*/
  {
      PAGED_CODE();
  
      ASSERT(PropertyRequest);
  
      DPF_ENTER(("[PropertyHandler_SpeakerHpJackDescription]"));
  
      NTSTATUS                ntStatus = STATUS_INVALID_DEVICE_REQUEST;
      ULONG                   nPinId = (ULONG)-1;
      
      ULONG                   cJackDescriptions = ARRAYSIZE(SpeakerHpJackDescriptions);
      PKSJACK_DESCRIPTION *   JackDescriptions = SpeakerHpJackDescriptions;
  
      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)
                      {
                          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_SpeakerHpJackDescription2
  ( 
      _In_ PPCPROPERTY_REQUEST PropertyRequest 
  )
  /*++
  
  Routine Description:
  
      Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
  
  Arguments:
  
      PropertyRequest - property request
  
  Return Value:
  
      NT status code
  
  --*/
  {
      PAGED_CODE();
  
      ASSERT(PropertyRequest);
  
      DPF_ENTER(("[PropertyHandler_SpeakerHpJackDescription2]"));
  
      NTSTATUS                ntStatus = STATUS_INVALID_DEVICE_REQUEST;
      ULONG                   nPinId = (ULONG)-1;
      
      ULONG                   cJackDescriptions = ARRAYSIZE(SpeakerHpJackDescriptions);
      PKSJACK_DESCRIPTION *   JackDescriptions = SpeakerHpJackDescriptions;
  
      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 
                          //
  						// Dont enable jack detection. Enabling will force the os to use this device as default endpoint.
  						// Instead we want any new audio device thats plugged in to be the default audio device.
                          pDesc->JackCapabilities = 0;
                          
                          ntStatus = STATUS_SUCCESS;
                      }
                  }
              }
          }
      }
  
      return ntStatus;
  }
  
  //=============================================================================
  _Use_decl_annotations_
  NTSTATUS
  PropertyHandler_SpeakerHpTopoFilter
  ( 
      PPCPROPERTY_REQUEST      PropertyRequest 
  )
  /*++
  
  Routine Description:
  
      Redirects property request to miniport object
  
  Arguments:
  
      PropertyRequest - property request
  
  Return Value:
  
      NT status code
  
  --*/
  {
      PAGED_CODE();
  
      ASSERT(PropertyRequest);
  
      DPF_ENTER(("[PropertyHandler_SpeakerHpTopoFilter]"));
  
      // PropertryRequest structure is filled by portcls. 
      // MajorTarget is a pointer to miniport object for miniports.
      //
      NTSTATUS            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
      
      //
      // This line shows how to get a pointer to the miniport topology object.
      //
      PCMiniportTopology  pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
      UNREFERENCED_VAR(pMiniport);
  
      if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
      {
          if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
          {
              ntStatus = PropertyHandler_SpeakerHpJackDescription(PropertyRequest);
          }
          else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
          {
              ntStatus = PropertyHandler_SpeakerHpJackDescription2(PropertyRequest);
          }
      }
  
      return ntStatus;
  }
  
  
  