2016-04-15 3 views
2

Я использую функции API-интерфейса, чтобы найти устройство USB, а затем использовать файл createfile для связи с ним. то есть с помощью SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces, SetupDiGetDeviceInterfaceDetail и т. д.Как определить скорость USB в Windows

Я хотел бы иметь возможность определить, подключено ли устройство на скорости USB2 или скорости USB3, т.е. SuperSpeed ​​или нет

Как это сделать через API Windows?

ответ

0

Я думаю, вам придется попробовать WinUSB в ссылке есть пример кода обнаружения скорости USB. Если вам нужно описание WinUSB, вы найдете его here.

+0

Устройство, с которым я разговариваю, не является устройством WinUSB.sys. Разве нет более общего способа определения этого? – MrMoDoJoJr

0

Это то, с чем я столкнулся. Это запутанно. Возможно, нет более простого способа:

#include "stdafx.h" 

#include <Windows.h> 
#include <Setupapi.h> 
#include <winusb.h> 

#undef LowSpeed 
#include <Usbioctl.h> 

#include <iostream> 
#include <string> 
#include <memory> 
#include <vector> 

class Usb_Device 
{ 
private: 
    std::wstring _driverKey; 
    char _speed; 

public: 
    Usb_Device(int adapterNumber, std::wstring devicePath, char speed); 

    virtual char GetSpeed(std::wstring driverKey); 
}; 

class Usb_Hub : public Usb_Device 
{ 
private: 
    bool _isRootHub; 
    std::wstring _deviceDescription; 
    std::wstring _devicePath; 

    std::vector<std::unique_ptr<Usb_Device>> _devices; 

public: 
    Usb_Hub(std::wstring devicePath, char speed); 

    virtual char GetSpeed(std::wstring driverKey) override; 
}; 

class Usb_Controller 
{ 
private: 

    GUID _interfaceClassGuid; 
    std::wstring _devicePath; 
    std::wstring _deviceDescription; 
    std::wstring _driverKey; 

    std::vector<std::unique_ptr<Usb_Device>> _devices; 

public: 
    Usb_Controller(); 

    char GetSpeed(std::wstring driverKey); 
}; 

static std::unique_ptr<Usb_Device> BuildDevice(int portCount, std::wstring devicePath) 
{ 
    std::unique_ptr<Usb_Device> ret; 

    HANDLE handle = INVALID_HANDLE_VALUE; 

    DWORD bytes = -1; 
    DWORD bytesReturned = -1; 
    BOOL isConnected = FALSE; 
    char speed; 

    // Open a handle to the Hub device 
    handle = CreateFile(devicePath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); 
    if (handle != INVALID_HANDLE_VALUE) 
    { 
     bytes = sizeof(USB_NODE_CONNECTION_INFORMATION_EX); 
     PUSB_NODE_CONNECTION_INFORMATION_EX nodeConnection = (PUSB_NODE_CONNECTION_INFORMATION_EX)(new char[bytes]); 

     nodeConnection->ConnectionIndex = portCount; 

     if (DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, nodeConnection, bytes, nodeConnection, bytes, &bytesReturned, 0)) 
     { 
      isConnected = nodeConnection->ConnectionStatus == USB_CONNECTION_STATUS::DeviceConnected; 
      speed = nodeConnection->Speed; 
     } 

     if (isConnected) 
     { 
      if (nodeConnection->DeviceDescriptor.bDeviceClass == 0x09 /*HubDevice*/) 
      { 
       bytes = sizeof(USB_NODE_CONNECTION_NAME); 
       PUSB_NODE_CONNECTION_NAME nodeConnectionName = (PUSB_NODE_CONNECTION_NAME)(new char[bytes]); 
       nodeConnectionName->ConnectionIndex = portCount; 

       if (DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_NAME, nodeConnectionName, bytes, nodeConnectionName, bytes, &bytesReturned, 0)) 
       { 
        bytes = nodeConnectionName->ActualLength; 
        delete[] nodeConnectionName; 

        nodeConnectionName = (PUSB_NODE_CONNECTION_NAME)(new char[bytes]); 
        nodeConnectionName->ConnectionIndex = portCount; 

        if (DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_NAME, nodeConnectionName, bytes, nodeConnectionName, bytes, &bytesReturned, 0)) 
        { 
         std::wstring name = std::wstring(L"\\\\?\\") + std::wstring(nodeConnectionName->NodeName); 
         ret = std::unique_ptr<Usb_Device>(new Usb_Hub(name, speed)); 
        } 
       } 

       delete[] nodeConnectionName; 
      } 
      else 
      { 
       ret = std::unique_ptr<Usb_Device>(new Usb_Device(portCount, devicePath, speed)); 
      } 
     } 
     else 
     { 
      // Chuck this device 
     } 

     delete[] nodeConnection; 
     CloseHandle(handle); 
    } 

    return ret; 
} 

Usb_Controller::Usb_Controller() 
{ 
    BOOL success = TRUE; 
    for (int index = 0; success; index++) 
    { 
     GUID guid; 
     HRESULT hr = CLSIDFromString(L"{3abf6f2d-71c4-462a-8a92-1e6861e6af27}", (LPCLSID)&guid); 

     unsigned char* ptr = new unsigned char[2048]; // Should really do two calls, but that's more effort 

     HDEVINFO deviceInfoHandle = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 

     // Create a device interface data structure 
     SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 }; 
     deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 

     // Start the enumeration. 
     success = SetupDiEnumDeviceInterfaces(deviceInfoHandle, 0, &guid, index, &deviceInterfaceData); 
     if (success) 
     { 
      _interfaceClassGuid = deviceInterfaceData.InterfaceClassGuid; 

      // Build a DevInfo data structure. 
      SP_DEVINFO_DATA deviceInfoData = { 0 }; 
      deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 

      // Now we can get some more detailed informations. 
      DWORD nRequiredSize = 0; 

      SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterfaceData, 0, 0, &nRequiredSize, 0); 
      if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) 
      { 
       PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(new char[nRequiredSize]); 
       memset(deviceInterfaceDetailData, 0, nRequiredSize); 
       deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 

       if (SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterfaceData, deviceInterfaceDetailData, nRequiredSize, &nRequiredSize, &deviceInfoData)) 
       { 
        _devicePath = deviceInterfaceDetailData->DevicePath; 

        // Get the device description and driver key name. 
        DWORD requiredSize = 0; 
        DWORD regType = REG_SZ; 

        if (SetupDiGetDeviceRegistryProperty(deviceInfoHandle, &deviceInfoData, SPDRP_DEVICEDESC, &regType, ptr, 2048, &requiredSize)) 
        { 
         _deviceDescription = reinterpret_cast<wchar_t*>(ptr); 
        } 

        if (SetupDiGetDeviceRegistryProperty(deviceInfoHandle, &deviceInfoData, SPDRP_DRIVER, &regType, ptr, 2048, &requiredSize)) 
        { 
         _driverKey = reinterpret_cast<wchar_t*>(ptr); 
        } 
       } 

       delete[] deviceInterfaceDetailData; 
      } 

      SetupDiDestroyDeviceInfoList(deviceInfoHandle); 

      std::unique_ptr<Usb_Device> hub(new Usb_Hub(_devicePath, -1)); 
      _devices.push_back(std::move(hub)); 
     } 
     else 
     { 
      success = false; 
     } 

     delete[] ptr; 
    } 
} 

char Usb_Controller::GetSpeed(std::wstring driverKey) 
{ 
    char speed = -1; 

    for (auto it = _devices.begin(); it != _devices.end() && speed == -1; ++it) 
    { 
     if (*it != nullptr) 
     { 
      speed = (*it)->GetSpeed(driverKey); 
     } 
    } 

    return speed; 
} 

Usb_Hub::Usb_Hub(std::wstring devicePath, char speed) : 
    Usb_Device(-1, devicePath, speed) 
{ 
    HANDLE handle1 = INVALID_HANDLE_VALUE; 
    HANDLE handle2 = INVALID_HANDLE_VALUE; 
    _deviceDescription = L"Standard-USB-Hub"; 
    _devicePath = devicePath; 

    DWORD bytesReturned = -1; 
    DWORD bytes = -1; 

    BOOL success = TRUE; 

    // Open a handle to the host controller. 
    handle1 = CreateFile(devicePath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); 
    if (handle1 != INVALID_HANDLE_VALUE) 
    { 
     USB_ROOT_HUB_NAME rootHubName; 
     memset(&rootHubName, 0, sizeof(USB_ROOT_HUB_NAME)); 

     // Get the root hub name. 
     if (DeviceIoControl(handle1, IOCTL_USB_GET_ROOT_HUB_NAME, nullptr, 0, &rootHubName, sizeof(USB_ROOT_HUB_NAME), &bytesReturned, 0)) 
     { 
      if (rootHubName.ActualLength > 0) 
      { 
       PUSB_ROOT_HUB_NAME actualRootHubName = (PUSB_ROOT_HUB_NAME)(new char[rootHubName.ActualLength]); 

       if (DeviceIoControl(handle1, IOCTL_USB_GET_ROOT_HUB_NAME, nullptr, 0, actualRootHubName, rootHubName.ActualLength, &bytesReturned, 0)) 
       { 
        _isRootHub = true; 
        _deviceDescription = L"RootHub"; 
        _devicePath = std::wstring(L"\\\\?\\") + std::wstring(actualRootHubName->RootHubName); 
       } 

       delete[] actualRootHubName; 
      } 
     } 

     // Now let's open the hub (based upon the hub name we got above). 
     int PortCount = 0; 
     handle2 = CreateFile(_devicePath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); 
     if (handle2 != INVALID_HANDLE_VALUE) 
     { 
      bytes = sizeof(USB_NODE_INFORMATION); 
      PUSB_NODE_INFORMATION nodeInfo = (PUSB_NODE_INFORMATION)(new char[bytes]); 
      memset(nodeInfo, 0, sizeof(USB_NODE_INFORMATION)); 

      nodeInfo->NodeType = USB_HUB_NODE::UsbHub; 

      // Get the hub information. 
      if (DeviceIoControl(handle2, IOCTL_USB_GET_NODE_INFORMATION, nodeInfo, bytes, nodeInfo, bytes, &bytesReturned, 0)) 
      { 
       DWORD d = GetLastError(); 

       PortCount = nodeInfo->u.HubInformation.HubDescriptor.bNumberOfPorts; 
      } 

      delete[] nodeInfo; 

      CloseHandle(handle2); 
     } 

     CloseHandle(handle1); 

     for (int index = 1; index <= PortCount; index++) 
     { 
      std::unique_ptr<Usb_Device> device = BuildDevice(index, _devicePath); 
      _devices.push_back(std::move(device)); 
     } 
    } 
    else 
    { 
     success = FALSE; 
    } 
} 

char Usb_Hub::GetSpeed(std::wstring driverKey) 
{ 
    char speed = Usb_Device::GetSpeed(driverKey); 

    if (speed == -1) 
    { 
     for (auto it = _devices.begin(); it != _devices.end() && speed == -1; ++it) 
     { 
      if (*it != nullptr) 
      { 
       speed = (*it)->GetSpeed(driverKey); 
      } 
     } 
    } 

    return speed; 
} 

Usb_Device::Usb_Device(int adapterNumber, std::wstring devicePath, char speed) 
{ 
    _speed = speed; 

    HANDLE handle = CreateFile(devicePath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); 
    if (handle != INVALID_HANDLE_VALUE) 
    { 
     // Get the Driver Key Name (usefull in locating a device) 
     DWORD bytesReturned = -1; 
     DWORD bytes = sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); 
     PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKey = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)(new char[bytes]); 

     driverKey->ConnectionIndex = adapterNumber; 

     // Use an IOCTL call to request the Driver Key Name 
     if (DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, driverKey, bytes, driverKey, bytes, &bytesReturned, 0)) 
     { 
      bytes = driverKey->ActualLength; 
      delete[] driverKey; 

      driverKey = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)(new char[bytes]); 
      driverKey->ConnectionIndex = adapterNumber; 

      if (DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, driverKey, bytes, driverKey, bytes, &bytesReturned, 0)) 
      { 
       _driverKey = driverKey->DriverKeyName; 
      } 
     } 

     delete[] driverKey; 

     CloseHandle(handle); 
    } 
} 

char Usb_Device::GetSpeed(std::wstring driverKey) 
{ 
    return _speed; 
} 

int main() 
{ 
    Usb_Controller controller; 

    GUID guid; 
    HRESULT hr = CLSIDFromString(L"{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}", (LPCLSID)&guid); 

    HDEVINFO deviceInfoHandle = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 

    if (deviceInfoHandle != INVALID_HANDLE_VALUE) 
    { 
     int deviceIndex = 0; 
     while (true) 
     { 
      SP_DEVICE_INTERFACE_DATA deviceInterface = { 0 }; 
      deviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 

      if (SetupDiEnumDeviceInterfaces(deviceInfoHandle, 0, &guid, deviceIndex, &deviceInterface)) 
      { 
       DWORD cbRequired = 0; 

       SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface, 0, 0, &cbRequired, 0); 
       if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) 
       { 
        PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(new char[cbRequired]); 
        memset(deviceInterfaceDetail, 0, cbRequired); 
        deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 

        if (!SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface, deviceInterfaceDetail, cbRequired, &cbRequired, 0)) 
        { 
         deviceIndex++; 
         continue; 
        } 

        // Initialize the structure before using it. 
        memset(deviceInterfaceDetail, 0, cbRequired); 
        deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 

        // Call the API a second time to retrieve the actual 
        // device path string. 
        BOOL status = SetupDiGetDeviceInterfaceDetail(
         deviceInfoHandle, // Handle to device information set 
         &deviceInterface,  // Pointer to current node in devinfo set 
         deviceInterfaceDetail, // Pointer to buffer to receive device path 
         cbRequired, // Length of user-allocated buffer 
         &cbRequired, // Pointer to arg to receive required buffer length 
         NULL);  // Not interested in additional data 

        BOOL success = TRUE; 
        for (int i = 0; success; i++) 
        { 
         SP_DEVINFO_DATA deviceInterfaceData = { 0 }; 
         deviceInterfaceData.cbSize = sizeof(SP_DEVINFO_DATA); 

         // Start the enumeration. 
         success = SetupDiEnumDeviceInfo(deviceInfoHandle, i, &deviceInterfaceData); 

         DWORD RequiredSize = 0; 
         DWORD regType = REG_SZ; 
         unsigned char* ptr = new unsigned char[2048]; 
         if (SetupDiGetDeviceRegistryProperty(deviceInfoHandle, &deviceInterfaceData, SPDRP_DRIVER, &regType, ptr, 2048, &RequiredSize)) 
         { 
          char speed = controller.GetSpeed(reinterpret_cast<wchar_t*>(ptr)); 
          std::wcout << std::wstring(reinterpret_cast<wchar_t*>(ptr)) << std::endl; 
          std::wcout << L"Speed: " << (int)speed << std::endl; 
         } 

         delete[] ptr; 
        } 

        auto hDeviceHandle = CreateFile(
         deviceInterfaceDetail->DevicePath, 
         GENERIC_READ | GENERIC_WRITE, 
         FILE_SHARE_READ | FILE_SHARE_WRITE, 
         NULL, 
         OPEN_EXISTING, 
         FILE_FLAG_OVERLAPPED, 
         NULL); 

        CloseHandle(hDeviceHandle); 

        delete[] deviceInterfaceDetail; 
       } 
      } 
      else 
      { 
       break; 
      } 

      ++deviceIndex; 
     } 

     SetupDiDestroyDeviceInfoList(deviceInfoHandle); 
    } 

    return 0; 
} 
Смежные вопросы