3

I'm working on software that interacts with a custom USB device. The device presents itself as a HID device and the software interacts with it via File I/O.

Due to changes in Windows 8.1 the OS keeps restarting the device and this is causing problems in the software.

According to this Knowledge Base article: http://support.microsoft.com/kb/2900614, Microsoft recommends disabling the Enhanced Power Management feature for a USB device if it is having this problem and after doing so manually the problem does go away.

Now, I'd like to modify the installer of the software to disable this setting for all of our devices, not just for a specific device instance.

Is there a way to accomplish that? Either via a Windows API call, or through a registry setting that would affect all instances of a particular ProductID / VendorID combination?

E.g. I'd like to modify all instances under:

  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_11AE&PID_07CE

Including any future instances that may be connected to the system, after the installer executes.

Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151

3 Answers3

3

Here is a sample script I wrote to disable power management on all Datalogic-brand USB devices (vendor ID 0x05F9). You can probably just change the "VID_05F9&" in the conditional down in the For Each loop to make it match the keys you need to modify. Note that the necessary UAC elevation is handled as well.

'Filename: USBPMFIX.VBS
'Author:   Matthew Mellon <mmellon@ecrs.com>
'Date:     2014-12-12
'Desc:     Disables enhanced power management on all Datalogic USB devices.
'License:  This source code is released into the public domain.    

'Checks if the script is running elevated (UAC)
function isElevated
  Set shell = CreateObject("WScript.Shell")
  Set whoami = shell.Exec("whoami /groups")
  Set whoamiOutput = whoami.StdOut
  strWhoamiOutput = whoamiOutput.ReadAll

  If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then 
    isElevated = True
  Else
      isElevated = False
  End If
end function

'Re-runs the process prompting for priv elevation on re-run
sub uacPrompt

  'Check if we need to run in C or W script
  interpreter = "wscript.exe"
  If Instr(1, WScript.FullName, "CScript", vbTextCompare) = 0 Then
    interpreter = "wscript.exe"
  else
    interpreter = "cscript.exe"
  end if

  'Start a new instance with an elevation prompt first
  Set shellApp = CreateObject("Shell.Application")
  shellApp.ShellExecute interpreter, Chr(34) & WScript.ScriptFullName & Chr(34) & " uac", "", "runas", 1

  'End the non-elevated instance
  WScript.Quit
end sub

if not isElevated Then uacPrompt

Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."

Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
 strComputer & "\root\default:StdRegProv")

strKeyPath = "SYSTEM\CurrentControlSet\Enum\USB"
objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys

For Each Subkey in arrSubKeys
  If Left(Subkey,9) = "VID_05F9&" And Left(Right(Subkey,6),5) = "&MI_0" Then
    strKeyPath = "SYSTEM\CurrentControlSet\Enum\USB\"+Subkey
    objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrInnerSubKeys
    For Each InnerSubkey in arrInnerSubKeys
      strFullKey = "SYSTEM\CurrentControlSet\Enum\USB\"+Subkey+"\"+InnerSubkey+"\Device Parameters"
      objReg.SetDWORDValue HKEY_LOCAL_MACHINE, strFullKey, "EnhancedPowerManagementEnabled", 0
    Next   
  End If
Next
0

You should be able to use the Registry Functions to go through and dynamically change the keys that are causing your problem. I haven't done it before but I think you could add this in as an install step in a custom INF for your device to ensure it happens on each installation of a new device.

I don't know if you have control over the device firmware but you might be able to change the descriptors so that it tells the OS up front it doesn't support power management like suspend or remote wakeup.

Preston
  • 2,543
  • 1
  • 17
  • 26
  • `I think you could add this in as an install step in a custom INF for your device to ensure it happens on each installation of a new device.` - that's what I'm looking for. Any idea how to do that exactly, or where to find relevant documentation for that? – Mike Dinescu Apr 20 '14 at 21:56
  • on second thought, the device is an HID device and it doesn't have any custom drivers (or INF file). Windows detects it as a generic HID and happily sets it up with the generic HID driver. So the INF solution won't work. – Mike Dinescu Apr 21 '14 at 15:12
  • You can still provide an INF for your device though, take a look at [this post](http://stackoverflow.com/questions/19401162/inf-file-for-hid-device-setting-name-and-icon). In your custom INF you would want to provide an `AddReg` section to add in the registry keys per your settings, [documented here](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546320(v=vs.85).aspx). – Preston Apr 21 '14 at 15:41
0

One more option is to add MS OS Descriptor to the device firmware. You can modify registry properties that you need thru that descriptor. All necessary info can be found in the spec. Here is how such descriptor may look like.

const uint8_t msOs20DescriptorSet[10 + 76 + 6] =
{
    //
    // Microsoft OS 2.0 Descriptor Set Header
    //
    0x0A, 0x00,             // wLength - 10 bytes
    0x00, 0x00,             // wDescriptorType, MSOS20_SET_HEADER_DESCRIPTOR
    0x00, 0x00, 0x03, 0x06, // dwWindowsVersion – 0x06030000 for Windows Blue
    0x5C, 0x00,             // wTotalLength – 92 bytes

    //
    // Microsoft OS 2.0 Registry Value Feature Descriptor
    //
    0x4C, 0x00, // wLength - 76 bytes
    0x04, 0x00, // wDescriptorType – 4 for Registry Property
    0x04, 0x00, // wPropertyDataType - 4 for REG_DWORD
    0x3E, 0x00, // wPropertyNameLength – 62 bytes
    'E', 0, // Property Name - EnhancedPowerManagementEnabled
    'n', 0,
    'h', 0,
    'a', 0,
    'n', 0,
    'c', 0,
    'e', 0,
    'd', 0,
    'P', 0,
    'o', 0,
    'w', 0,
    'e', 0,
    'r', 0,
    'M', 0,
    'a', 0,
    'n', 0,
    'a', 0,
    'g', 0,
    'e', 0,
    'm', 0,
    'e', 0,
    'n', 0,
    't', 0,
    'E', 0,
    'n', 0,
    'a', 0,
    'b', 0,
    'l', 0,
    'e', 0,
    'd', 0,
    0, 0,
    0x04, 0x00,             // wPropertyDataLength – 4 bytes
    0x00, 0x00, 0x00, 0x00,  // PropertyData - 0x00000000

    // Microsoft OS 2.0 vendor revision descriptor
    0x06, 0x00, // wLength - 6 bytes
    0x08, 0x00, // wDescriptorType, MS_OS_20_FEATURE_VENDOR_REVISION
    0x01, 0x00, /* VendorRevision, if this value changes between enumerations the registry 
    property descriptors will be updated in registry during that enumeration. */
};
emblink
  • 1
  • 2