How to programmatically unplug & replug an arbitrary USB device?
Asked Answered
R

12

39

I'm trying to fix a non-responsive USB device that's masquerading as a virtual COM port. Manual replugging works, but there may be up to 12 of these units. Is there an API command to do the programmatic equivalent of the unplug/replug cycle?

Reading answered 26/9, 2008 at 9:7 Comment(3)
possible duplicate of Safe remove USB-Drive using Win32 API?Frivol
Software like USB Safely Remove is able to replug unplugged USB device by restarting whole USB hub (inlucing other connected devices).Vibrato
Same question on AskUbuntu (of course it's for Ubuntu OS instead of Windows)Noddy
V
9

What about using Devcon.exe to "remove" and then "rescan"?

DR

Vanillin answered 1/4, 2009 at 18:1 Comment(2)
Second this, devcon is a part of the Windows Driver Kit and the source is also provided.Danford
devcon requires administrator privileges.Rationalism
P
4

You can use the C# Hardware Helper Lib and add the ResetDevice function.

public bool ResetDevice( IntPtr hDevInfo, IntPtr devInfoData )  
// Need to add  
// public const int DICS_PROPCHANGE = ((0x00000003));   
// at the public class Native under //PARMS  
int szOfPcp;  
IntPtr ptrToPcp;  
int szDevInfoData;  
IntPtr ptrToDevInfoData;  

Native.SP_PROPCHANGE_PARAMS pcp = new Native.SP_PROPCHANGE_PARAMS();  
pcp.ClassInstallHeader.cbSize = Marshal.SizeOf(typeof(Native.SP_CLASSINSTALL_HEADER));  
pcp.ClassInstallHeader.InstallFunction = Native.DIF_PROPERTYCHANGE;  
pcp.StateChange = Native.DICS_PROPCHANGE; // for reset  
pcp.Scope = Native.DICS_FLAG_CONFIGSPECIFIC;  
pcp.HwProfile = 0;  

szOfPcp = Marshal.SizeOf(pcp);  
ptrToPcp = Marshal.AllocHGlobal(szOfPcp);  
Marshal.StructureToPtr(pcp, ptrToPcp, true);  
szDevInfoData = Marshal.SizeOf(devInfoData);  
ptrToDevInfoData = Marshal.AllocHGlobal(szDevInfoData);  
Marshal.StructureToPtr(devInfoData, ptrToDevInfoData, true);  

bool rslt1 = Native.SetupDiSetClassInstallParams(hDevInfo, ptrToDevInfoData, ptrToPcp,   Marshal.SizeOf(typeof(Native.SP_PROPCHANGE_PARAMS)));  
bool rstl2 = Native.SetupDiCallClassInstaller(Native.DIF_PROPERTYCHANGE, hDevInfo,   ptrToDevInfoData);  

if (rslt1 && rstl2)  
{  
    return true;  
}  
return false;  
}  
Pirzada answered 8/1, 2013 at 13:31 Comment(1)
Unfortunately it works only if the device is not busy. Otherwise it asks for a reboot.Streamer
K
3

Unfortunately, there isn't one that I know of. Physically unplugging the USB connection does specific electronic things with pullup resistors, such that the device knows it's unplugged. I haven't encountered a host that attempts to be able to simulate this condition without physical unplugging.

Karttikeya answered 26/9, 2008 at 9:9 Comment(0)
M
2

Thought: under Device Manager, you can right-click your computer icon (top of the device tree) and "scan for changes". I'm not 100% sure, but I think if you "eject" a USB device (software "unplug" equivalent), then Scan for Hardware Changes, it will show back up even though it never actually left the port.

If I'm right about that, you might be able to use the Microsoft.Win32.Shell class to emulate opening Control Panel --> Administrative Tools --> Device Manager and running the context-menu item. It's worth a shot, anyway.

Melosa answered 3/2, 2009 at 19:30 Comment(0)
C
2

I had to do this for my car computer project a while back. The touchscreen drivers didn't like going into hibernate and needed to be replugged when the computer came back from hibernate. The way I ended up solving it was to use Devcon.exe like DigitalRacer suggested. The trick however, was that remove/rescan on the controller didn't work. I had to do the remove/rescan on a HUB upstream from the device (which subsequently disconnected all attached devices).

Cudgel answered 15/6, 2009 at 14:34 Comment(0)
G
2

For windows 10 devices onward pnputil appears to be the best answer. pnputil is installed in every build of windows.

Commands for restarting

pnputil /restart-device "device-instance-ID"

or

pnputil /disable-device "device-instance-ID"

pnputil /enable-device "device-instance-ID"

Find USB Device

with every usb device there are generally more than one device instance ID associated with it. You need to get one instance ID first

  • Open "Device Manager" window
  • Go to the "Universal Serial Bus Controllers" drop down
  • Right Click on one of the "USB Composite Devices" and select "Properties"
  • Select the "Details" tab on the window
  • Then on the property dropdown list select "Device Instance Path". This will show you a device instance ID.
  • You'll need to plug and unplug your usb device, compare device instance IDs and by process of elimination determine which of the devices is the one you want.

Using this device instance ID you can now search for all device instance IDs by using the VID value

Device Instance ID Example
USB\VID_045E&PID_097D&MI_02\7&28580E27&0&0002

VID value for search
VID_045E

Powershell Command to search for all device instance IDs

Get-WmiObject Win32_PnPEntity | Where-Object {$_.PNPDeviceID -like "*VID_045E*"} | Select-Object Caption, PNPDeviceID

This should give a list of all device instance IDs associated with your USB device. Selecting the correct device to restart isn't obvious and friendly warning you can cause some issues by selecting the wrong ID. But if you figure out the correct ID then this should work for you.

Gosser answered 16/2, 2023 at 10:48 Comment(0)
J
1

As Greg Hewgill said, I don't think that it's possible.

Initiation of the whole usb startup is triggered by the usb slave (in your case your device). The usb host (the pc) can send a message to the device to tell it to shut down, but once it's done that it's up to the device to start back up again. The host can't force it to.

To make matters worse you'll quite possibly find that the usb device is detecting the plug being inserted (by detecting the usb voltage on the power lines) to start up. This is particularly true of bus powered devices.


It sounds like there are differences from your situation and the case of trying to unmount/remount usb drives. When the usb drive is unmounted there is no reason that it can't stay enumerated on the pc. You're not actually reseting the usb drive, just making it's filesystem inactive.

Jauch answered 26/9, 2008 at 10:46 Comment(0)
K
1

I've looked at this for automated tests. The best solution we came up with seems to be the ability of USB hubs to disconnect devices when they draw too much power. From a USB pserspective, it appears the USB host may instruct a hub to do so. With 12 devices, you will have hubs, so I'd suggest to investigate that path.

Knutson answered 26/9, 2008 at 11:27 Comment(0)
A
1

Here's some hands on guidance:

http://digital.ni.com/public.nsf/allkb/1D120A90884C25AF862573A700602459

This is more hardcore:

http://support.microsoft.com/kb/311272

I'd say that using devcon.exe may solve some problems, not mine though. Suppose that you can build a box with arrays of USB-ports, where the power line is interrupted with FETs controlled by a MCU. The MCU should talk something basic and reliable, like RS-232. There might be an arduino board that simplifies the scary hardware work.

Aston answered 29/6, 2012 at 14:45 Comment(0)
E
0

If you have more than one of these on any particular host machine, you might save some time/frustration by plugging them into their own dedicated USB hub out from the machine - at least it's only one cable to unplug/plug to restart a couple of devices at a time.

You've probably thought of that, of course. :-)

Euhemerism answered 26/9, 2008 at 9:12 Comment(0)
H
0

The device itself may be able to do this (ie, perform a USB disconnect/reconnect sequence).

Have you contacted the device manufacturer, or if you are the manufacturer, the EE's that designed it?

I had to do this when I designed a USB embedded device - programming could be accomplished through USB, but the device had to be able to disconnect and reconnect at several points to complete the process.

Beyond that there's the brute force method of disabling the USB host device in device manager (I assume this can be done in software) and then re-enabling it.

If nothing else, Phidget has USB controlled relay boards which you can use to connect power or the USB lines themselves to hubs or individual devices.

-Adam

Hydride answered 3/2, 2009 at 19:41 Comment(0)
C
-1

In Eject USB disks using C# (The Code Project) look for this:

CM_Request_Device_Eject function

This is the SetupApi function that ejects a device (any device that can be ejected). It takes a device instance handle (or devInst) as input...

Chagres answered 26/9, 2008 at 9:21 Comment(1)
Can a device that's "...masquerading as a virtual com port." be ejected?Jauch

© 2022 - 2024 — McMap. All rights reserved.