如何重新启动USB端口

目录

介绍

背景

使用代码

兴趣点

是什么让它失败


介绍

有时,USB设备会按预期停止工作,重新插入它们会有所帮助。通过代码执行重新插入可能很方便。

如果您想尝试重新启动USB端口是否有帮助,您可以尝试使用我的UsbTreeViewRestartUsbPort

背景

Microsoft表示IOCTL_USB_HUB_CYCLE_PORT重新启动USB端口,从而启动连接设备的重新枚举。

该函数在XP下可用,但通常仅适用于使用Microsoft标准驱动程序运行的集线器。第三方驱动程序通常会返回ERROR_UNKNOWN_FUNCTION

VistaWindows 7下,Windows标准驱动程序不再支持它,它总是以ERROR_NOT_SUPPORTED失败。

Windows 8开始,它再次工作,但与XP相比,需要管理员权限。如果没有管理员权限,它会失败,如在VistaWin7下出现ERROR_NOT_SUPPORTED或自Win10版本1903起出现ERROR_GEN_FAILURE,这两者都非常具有误导性,因为它是一个权限问题。

使用代码

我已将所有内容放在一个函数中,该函数需要USB设备的设备实例ID作为唯一参数。

//--------------------------------------------------------------------------------
// pszUsbDeviceId must be the Device Instance ID of the USB device to restart ----
// returns true on success, false on any failure ---------------------------------
//--------------------------------------------------------------------------------
bool CycleUsbDevice(char* pszUsbDeviceId)
{
  // Step 1: Find the USB device in the device manager
  DEVINST DevInst = 0;
  if ( CR_SUCCESS != CM_Locate_DevNode(&DevInst, pszUsbDeviceId, 0) ) {
    return false; //----
  }

  // Step 2: Determine the USB port number.
  //         Since Vista it can be read reliably from the device location info:
  char szLocation[64] = "";
  DWORD dwType = 0;
  ULONG uLen = sizeof(szLocation);
  if ( CR_SUCCESS != CM_Get_DevNode_Registry_Property(
                       DevInst, CM_DRP_LOCATION_INFORMATION,
                       &dwType, szLocation, &uLen, 0) ) {
    return false; //----
  }

  //       0123456789
  // like "Port_#0004.Hub_#0014"
  if ( 0 != strncmp(szLocation, "Port_#", 6) ) {
    return false; //----
  }

  int PortNumber = atoi(szLocation + 6); // leading zeros are ok with atoi

  // Step 3: The USB hub is the parent device
  DEVINST DevInstHub = 0;
  if ( CR_SUCCESS != CM_Get_Parent(&DevInstHub, DevInst, 0) ) {
    return false; //----
  }

  // Step 4: Request the USB hub's "device interface" aka the "DevicePath"
  char szHubDevPath[MAX_PATH] = "";

  // Get the hub's device instance ID
  char szHubDeviceID[MAX_DEVICE_ID_LEN];
  if ( CR_SUCCESS != CM_Get_Device_ID(
                       DevInstHub,
                       szHubDeviceID, MAX_DEVICE_ID_LEN, 0) ) {
    return false; //----
  }
  // Get the hub's device path (no need for CM_Get_Device_Interface_List_Size
  // since we request a single one rather a list of unknown length)
  if ( CR_SUCCESS != CM_Get_Device_Interface_List(
                       (GUID*)&GUID_DEVINTERFACE_USB_HUB, szHubDeviceID,
                       szHubDevPath, sizeof(szHubDevPath),
                       CM_GET_DEVICE_INTERFACE_LIST_PRESENT) ) {
    return false; //----
  }

  if ( ! szHubDevPath[0] ) {
    return false; //----
  }

  // Step 5: Open the hub
  HANDLE hHub = CreateFile(
                         szHubDevPath,
                         GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                         NULL, OPEN_EXISTING, 0, NULL);

  if ( INVALID_HANDLE_VALUE == hHub ) {
    return false; //----
  }

  // Step 6: Call IOCTL_USB_HUB_CYCLE_PORT
  typedef struct _USB_CYCLE_PORT_PARAMS {
    ULONG ConnectionIndex;
    ULONG StatusReturned;
  } USB_CYCLE_PORT_PARAMS, *PUSB_CYCLE_PORT_PARAMS;

  USB_CYCLE_PORT_PARAMS CyclePortParams  = { PortNumber, 0 }; // in and out

  DWORD dwBytes;
  int res = DeviceIoControl(hHub, IOCTL_USB_HUB_CYCLE_PORT,
                            &CyclePortParams, sizeof(CyclePortParams), 
                            &CyclePortParams, sizeof(CyclePortParams), 
                            &dwBytes, NULL);
  CloseHandle(hHub);
  
  return ( (0 != res) && (0 == CyclePortParams.StatusReturned) );
}
//----------------------------------------------------------------------------------------

兴趣点

Microsoft的IOCTL_USB_HUB_CYCLE_PORT文档是错误的:它说Output buffer: None是错误的。该StatusReturned struct成员得出的结论是,USB_CYCLE_PORT_PARAMS struct用作inout缓冲区。它以这种方式工作,dwBytes之后包含8个,这是预期的sizeof(USB_CYCLE_PORT_PARAMS)

是什么让它失败

与尝试重新启动设备相反,设备管理器IOCTL_USB_HUB_CYCLE_PORT不请求许可,因此没有驱动程序可以否决它,因此它总是成功。

但端口必须连接了USB设备并安装了驱动程序。否则,它会因错误433ERROR_NO_SUCH_DEVICE 或自Windows 10 21H2以来出现错误50ERROR_NOT_SUPPORTED),这再次具有误导性。

Windows 11带有正确的错误1167ERROR_DEVICE_NOT_CONNECTED)。

https://www.codeproject.com/Articles/5363023/How-to-Restart-a-USB-Port

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值