我正在尝试修复伪装成虚拟 COM 端口的无响应 USB 设备。手动重新插入工作,但可能有多达 12 个这样的单元。是否有 API 命令可以执行与拔出/重新插入周期等效的编程?
13 回答
使用 Devcon.exe 来“删除”然后“重新扫描”怎么样?
博士
您可以使用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;
}
不幸的是,没有一个我知道。物理拔出 USB 连接会使用上拉电阻执行特定的电子操作,以便设备知道它已拔出。我还没有遇到过试图在没有物理拔出的情况下模拟这种情况的主机。
想法:在设备管理器下,您可以右键单击计算机图标(设备树顶部)并“扫描更改”。我不确定 100%,但我认为如果你“弹出”一个 USB 设备(软件“拔出”等效),然后扫描硬件更改,即使它从未真正离开端口,它也会显示备份。
如果我是对的,您也许可以使用 Microsoft.Win32.Shell 类来模拟打开控制面板 --> 管理工具 --> 设备管理器并运行上下文菜单项。无论如何,值得一试。
我已经看过这个进行自动化测试。我们想出的最佳解决方案似乎是 USB 集线器在消耗过多电量时断开设备的能力。从 USB 的角度来看,USB 主机似乎可以指示集线器这样做。使用 12 台设备,您将拥有集线器,因此我建议调查该路径。
正如Greg Hewgill所说,我认为这是不可能的。
整个 USB 启动的启动由 USB 从设备(在您的情况下是您的设备)触发。USB 主机(PC)可以向设备发送一条消息,告诉它关闭,但一旦完成,就由设备重新启动备份。楼主不能强求。
更糟糕的是,您很可能会发现 USB 设备正在检测插入的插头(通过检测电源线上的 USB 电压)以启动。对于总线供电的设备尤其如此。
听起来您的情况和尝试卸载/重新安装 USB 驱动器的情况有所不同。卸载 USB 驱动器时,没有理由不能在 PC 上保持枚举。您实际上并没有重置 USB 驱动器,只是使其文件系统处于非活动状态。
不久前,我不得不为我的汽车计算机项目做这个。触摸屏驱动程序不喜欢进入休眠状态,当计算机从休眠状态恢复时需要重新插入。我最终解决它的方法是像 DigitalRacer 建议的那样使用 Devcon.exe。然而,诀窍是控制器上的删除/重新扫描不起作用。我必须在设备上游的 HUB 上进行删除/重新扫描(随后断开所有连接的设备)。
这里有一些动手指导:
http://digital.ni.com/public.nsf/allkb/1D120A90884C25AF862573A700602459
这更硬核:
http://support.microsoft.com/kb/311272
我会说使用 devcon.exe 可能会解决一些问题,但不是我的。假设您可以构建一个带有 USB 端口阵列的盒子,其中电源线被 MCU 控制的 FET 中断。MCU 应该说一些基本可靠的东西,比如 RS-232。可能有一个 arduino 板可以简化可怕的硬件工作。
如果您在任何特定主机上拥有多个这些,则可以通过将它们从机器上插入自己的专用 USB 集线器来节省一些时间/挫败感 - 至少只需一根电缆即可拔出/插入重新启动几个设备。
当然,您可能已经想到了这一点。:-)
我们用它来可编程断开 USB 设备。
设备本身可能能够做到这一点(即,执行 USB 断开/重新连接序列)。
您是否联系过设备制造商,或者如果您是制造商,请联系设计它的 EE?
我在设计 USB 嵌入式设备时必须这样做——编程可以通过 USB 完成,但设备必须能够在多个点断开和重新连接才能完成该过程。
除此之外,还有在设备管理器中禁用 USB 主机设备的蛮力方法(我假设这可以在软件中完成)然后重新启用它。
如果不出意外,Phidget 有 USB 控制的继电器板,您可以使用它来将电源或 USB 线本身连接到集线器或单个设备。
-亚当
可以通过编程方式卸载 USB 驱动器,但是,我不知道是否可以通过代码完成重新安装。
在Eject USB disks using C# ( The Code Project ) 中寻找这个:
CM_Request_Device_Eject函数
这是弹出设备(可以弹出的任何设备)的 SetupApi 函数。它需要一个设备实例句柄(或 devInst)作为输入......