Page 1 of 1

USB Power Management query

Posted: Mon Nov 19, 2018 6:23 am
by ozzie
When viewing the properties of USB Hubs in Windows Device Manager, under Power Management the checkbox 'allow the computer to turn off this device to save power' is set by default. This sometimes causes a problem when an audio interface device is connected to that USB hub, especially if the computer is left idle for a long time but with the audio playback program loaded and ready to go.

Is there some Windows API I can call from PureBasic to at least check the state of this property in all USB hubs? I could then warn the user if the property is set.

Re: USB Power Management query

Posted: Mon Nov 19, 2018 6:46 am
by RASHAD
Hi
Run as Admin

Code: Select all

Procedure USB_CB(hwnd, uMsg, wParam, lParam)
 result = #PB_ProcessPureBasicEvents
    Select uMsg
      Case #WM_DEVICECHANGE
        Select wParam
          Case #DBT_DEVICEARRIVAL
              MessageRequester("USB Status :","USB Device Inserted",#PB_MessageRequester_Ok)
                
          Case #DBT_DEVICEREMOVECOMPLETE
              MessageRequester("USB Status :","USB Device Removed",#PB_MessageRequester_Ok)
                
          Case #DBT_CONFIGCHANGED
              MessageRequester("USB Status :","USB Device Configuration Changed",#PB_MessageRequester_Ok)
              
          Case #DBT_DEVICETYPESPECIFIC
          
          Case #DBT_QUERYCHANGECONFIG            
                
          EndSelect
   EndSelect
ProcedureReturn result 
EndProcedure

OpenWindow(0,0,0,300,300,"Test",#PB_Window_SystemMenu| #PB_Window_Minimize)

SetWindowCallback(@USB_CB())

Repeat
  Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Quit = 1
   EndSelect
Until Quit = 1

Re: USB Power Management query

Posted: Mon Nov 19, 2018 8:00 am
by ozzie
Thanks, RASHAD. That code detects when a USB device is connected or disconnected, but what I'm looking for is to know whether or not the Power Management is set to turn off power to the hub (for a device that's already connected). On further investigation I've found there's a Power Plan setting for 'Selective Suspend'. But I can't find any reference to a Windows API that will return the current setting of that either.

Re: USB Power Management query

Posted: Mon Nov 19, 2018 8:52 pm
by breeze4me
try this.

Code: Select all

;Getting current USB power state
;https://stackoverflow.com/questions/51725639/getting-current-usb-power-state

#DIGCF_PRESENT = $00000002
#DIGCF_ALLCLASSES = $00000004
#DIGCF_PROFILE = $00000008
#DIGCF_DEVICEINTERFACE = $00000010

#SPDRP_DEVICE_POWER_DATA = $0000001E
#SPDRP_FRIENDLYNAME = $0000000C
#SPDRP_DEVICEDESC = 0
;#SPDRP_DRIVER = $00000009

#POWER_SYSTEM_MAXIMUM = 7

Enumeration
  #PowerDeviceUnspecified
  #PowerDeviceD0
  #PowerDeviceD1
  #PowerDeviceD2
  #PowerDeviceD3
EndEnumeration




Structure SP_DEVINFO_DATA Align #PB_Structure_AlignC
  cbSize.l
  ClassGuid.GUID
  DevInst.l
  Reserved.i
EndStructure


Structure CM_POWER_DATA
  PD_Size.l
  PD_MostRecentPowerState.l                     ;DEVICE_POWER_STATE
  PD_Capabilities.l
  PD_D1Latency.l
  PD_D2Latency.l
  PD_D3Latency.l
  PD_PowerStateMapping.l[#POWER_SYSTEM_MAXIMUM] ;DEVICE_POWER_STATE
  PD_DeepestSystemWake.l                        ;SYSTEM_POWER_STATE
EndStructure

Procedure.s GUIDtoString(*guid)
  Protected res.s{48}
  
  If StringFromGUID2_(*guid, @res, 40)
    ProcedureReturn res
  EndIf
  
EndProcedure


Define Text.s{1024}

Define PowerData.CM_POWER_DATA\PD_Size = SizeOf(CM_POWER_DATA)

;hDevinfo = SetupDiGetClassDevs_(?GUID_DEVINTERFACE_USB_DEVICE, 0, 0, #DIGCF_PRESENT | #DIGCF_DEVICEINTERFACE)
hDevinfo = SetupDiGetClassDevs_(?GUID_DEVINTERFACE_USB_HUB, 0, 0, #DIGCF_PRESENT | #DIGCF_DEVICEINTERFACE)

If hDevinfo <> #INVALID_HANDLE_VALUE
  
  Define di.SP_DEVINFO_DATA\cbSize = SizeOf(SP_DEVINFO_DATA)
  
  Repeat
    
    If SetupDiEnumDeviceInfo_(hDevinfo, idx, di) = 0 And GetLastError_() = #ERROR_NO_MORE_ITEMS
      Break
    Else
      
      ;If SetupDiGetDeviceRegistryProperty_(hDevinfo, di, #SPDRP_FRIENDLYNAME, @PropertyRegDataType, @Text, 1020, 0)
      If SetupDiGetDeviceRegistryProperty_(hDevinfo, di, #SPDRP_DEVICEDESC, @PropertyRegDataType, @Text, 1020, 0)
        Debug Text
      EndIf
      
      If SetupDiGetDeviceRegistryProperty_(hDevinfo, di, #SPDRP_DEVICE_POWER_DATA, @PropertyRegDataType, @PowerData, SizeOf(CM_POWER_DATA), 0)
        Debug GUIDtoString(di\ClassGuid)
        
        ;USB Device Power States
        ;https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/comparing-usb-device-states-to-wdm-device-states
        ;https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/device-power-states
        
        Select PowerData\PD_MostRecentPowerState
          Case #PowerDeviceD0
            Debug "D0 - The working state. The device is fully powered."
            
          Case #PowerDeviceD1, #PowerDeviceD2
            Debug "D1/D2 - The intermediate sleep states. These states allow the device to be armed for remote wakeup."
            
          Case #PowerDeviceD3
            Debug "D3 - The deepest sleep state. Devices in state D3 cannot be armed for remote wakeup."
            
          Default
            Debug "#PowerDeviceUnspecified"
            
        EndSelect
        
        Debug "-------------------------------------"
        
      EndIf
      
    EndIf
    
    idx + 1
    
  ForEver
  
  SetupDiDestroyDeviceInfoList_(hDevinfo)
EndIf



DataSection
  
  GUID_DEVINTERFACE_USB_DEVICE: ; {A5DCBF10-6530-11D2-901F-00C04FB951ED}
  Data.l $A5DCBF10
  Data.w $6530, $11D2
  Data.b $90, $1F, $00, $C0, $4F, $B9, $51, $ED
  
  
  GUID_DEVINTERFACE_USB_HUB: ; {F18A0E88-C30C-11D0-8815-00A0C906BED8}
  Data.l $F18A0E88
  Data.w $C30C, $11D0
  Data.b $88, $15, $00, $A0, $C9, $06, $BE, $D8
  
EndDataSection

Re: USB Power Management query

Posted: Tue Nov 20, 2018 3:28 am
by ozzie
Thanks - that's just what I need! The links are also helpful.