C++ 如何以编程方式拔出和重新插入任意 USB 设备?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/138394/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:08:53  来源:igfitidea点击:

How to programmatically unplug & replug an arbitrary USB device?

c++winapiusbusbserial

提问by

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?

我正在尝试修复伪装成虚拟 COM 端口的无响应 USB 设备。手动重新插入工作,但可能有多达 12 个这样的单元。是否有一个 API 命令来执行拔出/重新插入周期的编程等效?

回答by

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

使用 Devcon.exe“删除”然后“重新扫描”怎么样?

DR

DR

回答by shahar_m

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

您可以使用C# Hardware Helper Lib并添加ResetDevice 函数

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;  
}  

回答by Greg Hewgill

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.

不幸的是,没有一个我知道。物理上拔下 USB 连接会使用上拉电阻执行特定的电子操作,以便设备知道它已拔下。我还没有遇到过试图在不拔掉物理插头的情况下模拟这种情况的主机。

回答by Coderer

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.

想法:在设备管理器下,您可以右键单击您的计算机图标(设备树的顶部)并“扫描更改”。我不是 100% 确定,但我认为如果你“弹出”一个 USB 设备(软件“拔出”等效),然后扫描硬件更改,它会显示回来,即使它从未真正离开过端口。

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.

如果我是对的,您也许可以使用 Microsoft.Win32.Shell 类来模拟打开控制面板 --> 管理工具 --> 设备管理器并运行上下文菜单项。无论如何,这值得一试。

回答by Andrew Edgecombe

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

正如Greg Hewgill所说,我认为这是不可能的。

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.

整个 USB 启动的启动由 USB 从设备(在您的情况下是您的设备)触发。USB 主机(PC)可以向设备发送消息告诉它关闭,但是一旦完成,就由设备重新启动。主机不能强迫它。

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.

更糟糕的是,您很可能会发现 USB 设备正在检测插入的插头(通过检测电源线上的 USB 电压)以启动。对于总线供电的设备尤其如此。



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.

这听起来与您的情况和尝试卸载/重新安装 USB 驱动器的情况有所不同。当 USB 驱动器被卸载时,没有理由不能在 PC 上保持枚举。您实际上并没有重置 USB 驱动器,只是使其文件系统处于非活动状态。

回答by MSalters

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.

我已经看过这个用于自动化测试。我们提出的最佳解决方案似乎是 USB 集线器能够在设备消耗过多电量时断开设备连接。从 USB 的角度来看,似乎 USB 主机可能会指示集线器这样做。使用 12 台设备,您将拥有集线器,因此我建议调查该路径。

回答by Dolphin

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).

不久前,我不得不为我的汽车计算机项目执行此操作。触摸屏驱动程序不喜欢进入休眠状态,需要在计算机从休眠状态恢复时重新插入。我最终解决它的方法是像 DigitalRacer 建议的那样使用 Devcon.exe。然而,诀窍是控制器上的删除/重新扫描不起作用。我不得不在设备上游的集线器上进行删除/重新扫描(随后断开了所有连接的设备)。

回答by NoJoshua

Here's some hands on guidance:

以下是一些指导:

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

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

This is more hardcore:

这是更硬核:

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

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.

我会说使用 devcon.exe 可能会解决一些问题,但不是我的。假设您可以构建一个带有 USB 端口阵列的盒子,其中电源线被 MCU 控制的 FET 中断。MCU 应该谈论一些基本和可靠的东西,比如 RS-232。可能有一个 arduino 板可以简化可怕的硬件工作。

回答by Ilya

We used thisto programmable disconnect usb devices.

我们用来可编程断开 USB 设备。

回答by Adam Davis

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

设备本身可能能够做到这一点(即,执行 USB 断开/重新连接序列)。

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

您是否联系过设备制造商,或者如果您是制造商,则是设计它的 EE?

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.

我在设计 USB 嵌入式设备时必须这样做 - 可以通过 USB 完成编程,但该设备必须能够在多个点断开连接并重新连接才能完成该过程。

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.

除此之外,还有在设备管理器中禁用 USB 主机设备的蛮力方法(我认为这可以在软件中完成)然后重新启用它。

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.

如果不出意外,Phidg​​et 有 USB 控制的继电器板,您可以使用它来将电源或 USB 线本身连接到集线器或单个设备。

-Adam

-亚当