diff --git a/vioserial/app/device.cpp b/vioserial/app/device.cpp index 532bbc87d..d3888f6c4 100644 --- a/vioserial/app/device.cpp +++ b/vioserial/app/device.cpp @@ -1,5 +1,13 @@ #include "device.h" #include "assert.h" +#pragma warning(disable : 4201) +#include +#include +#pragma warning(default : 4201) +#include +#include + +const DWORD LOOKUP_PORT_MAX = 32; CDevice::CDevice() { @@ -15,10 +23,11 @@ CDevice::~CDevice() } } -BOOL CDevice::Init(BOOL ovrl, UINT index) +BOOL CDevice::Init(BOOL ovrl, UINT portId) { - PWCHAR DevicePath = NULL; - if ((DevicePath = GetDevicePath(index, (LPGUID)&GUID_VIOSERIAL_PORT)) != NULL) + PWCHAR DevicePath; + std::vector devpathBuf; + if ((DevicePath = GetDevicePath(portId, (LPGUID)&GUID_VIOSERIAL_PORT, devpathBuf)) != NULL) { m_hDevice = CreateFile(DevicePath, GENERIC_WRITE | GENERIC_READ, @@ -35,7 +44,7 @@ BOOL CDevice::Init(BOOL ovrl, UINT index) } } DWORD err = GetLastError(); - printf("Cannot find vioserial device. %S , error = %d\n", DevicePath, err); + printf("Cannot find vioserial device PortId:%u, error: %u\n", portId, err); return FALSE; } @@ -230,7 +239,7 @@ BOOL CDevice::GetInfo(PVOID buf, size_t *size) return res; } -PTCHAR CDevice::GetDevicePath(UINT index, IN LPGUID InterfaceGuid) +PTCHAR CDevice::GetDevicePath(UINT portId, IN LPGUID InterfaceGuid, std::vector &devpathBuf) { HDEVINFO HardwareDeviceInfo; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; @@ -248,44 +257,90 @@ PTCHAR CDevice::GetDevicePath(UINT index, IN LPGUID InterfaceGuid) DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo, 0, InterfaceGuid, index, &DeviceInterfaceData); - - if (bResult == FALSE) - { - printf("Cannot get enumerate device interfaces.\n"); - SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); - return NULL; - } - - SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo, &DeviceInterfaceData, NULL, 0, &RequiredLength, NULL); - - DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, RequiredLength); - - if (DeviceInterfaceDetailData == NULL) + for (DWORD index = 0; index < LOOKUP_PORT_MAX; index++) { - printf("Cannot allocate memory.\n"); - SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); - return NULL; - } + bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo, 0, InterfaceGuid, index, &DeviceInterfaceData); + if (!bResult) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_NO_MORE_ITEMS) + { + printf("EnumDeviceInterfaces stopped at idx %u\n", index); + break; + } + printf("EnumDeviceInterfaces[%u] error: %u\n", index, dwErr); + continue; + } - DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + bResult = SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo, + &DeviceInterfaceData, + NULL, + 0, + &RequiredLength, + NULL); + if (!bResult) + { + DWORD dwErr = GetLastError(); + if (dwErr != ERROR_INSUFFICIENT_BUFFER) + { + printf("SetupDiGetDeviceInterfaceDetail[%u] failed with %u\n", index, dwErr); + continue; + } + } - Length = RequiredLength; + if (devpathBuf.size() < RequiredLength) + { + devpathBuf.resize(RequiredLength); + } + DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)devpathBuf.data(); + DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + Length = RequiredLength; + + bResult = SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo, + &DeviceInterfaceData, + DeviceInterfaceDetailData, + Length, + &RequiredLength, + NULL); + if (!bResult) + { + printf("Cannot get device interface details.\n"); + SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); + return NULL; + } - bResult = SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo, - &DeviceInterfaceData, - DeviceInterfaceDetailData, - Length, - &RequiredLength, - NULL); + std::wstring path(DeviceInterfaceDetailData->DevicePath); + std::wregex regex(L"&\\d+#"); + std::wsmatch wsm; + if (!std::regex_search(path, wsm, regex)) + { + wprintf(L"Failed to parse path: %ls\n", DeviceInterfaceDetailData->DevicePath); + break; + } + // intializing a string without '&' and '#' symbols (ex. "&06#") + // portIdStr will be "06" + std::wstring portIdStr(wsm.str(), 1, wsm.str().length() - 1); + ULONG portIdFromPath; + try + { + portIdFromPath = std::stoi(portIdStr); + } + catch (const std::exception &) + { + wprintf(L"Could not parse port ID from '%ls'. Skipping.\n", portIdStr.c_str()); + continue; + } - if (bResult == FALSE) - { - printf("Cannot get device interface details.\n"); - SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); - LocalFree(DeviceInterfaceDetailData); - return NULL; + if (portIdFromPath == portId) + { + printf("Found vio-serial %u\n", portId); + SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); + return DeviceInterfaceDetailData->DevicePath; + } } - return DeviceInterfaceDetailData->DevicePath; + printf("Cannot find a port with ID:%u\n", portId); + SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); + return NULL; } diff --git a/vioserial/app/device.h b/vioserial/app/device.h index c3627e821..d165b5add 100644 --- a/vioserial/app/device.h +++ b/vioserial/app/device.h @@ -8,20 +8,15 @@ #include #include #include +#include #include "..\sys\public.h" -#pragma warning(disable : 4201) - -#include -#include - -#pragma warning(default : 4201) class CDevice { public: CDevice(); ~CDevice(); - BOOL Init(BOOL ovrl, UINT index); + BOOL Init(BOOL ovrl, UINT portId); BOOL Write(PVOID buf, size_t *size); BOOL WriteEx(PVOID buf, size_t *size); BOOL Read(PVOID buf, size_t *size); @@ -30,7 +25,7 @@ class CDevice protected: HANDLE m_hDevice; - PTCHAR GetDevicePath(UINT index, IN LPGUID InterfaceGuid); + PTCHAR GetDevicePath(UINT portId, IN LPGUID InterfaceGuid, std::vector &devpathBuf); }; #endif diff --git a/vioserial/app/main.cpp b/vioserial/app/main.cpp index b338ced81..ca5607484 100644 --- a/vioserial/app/main.cpp +++ b/vioserial/app/main.cpp @@ -7,6 +7,7 @@ #pragma warning(default : 4201) +static const DWORD LOOKUP_PORT_MAX_ID = 32; static ULONG write_buffer_size = 4096; static BOOL write_send_auto = FALSE; @@ -264,7 +265,7 @@ _cdecl wmain(__in ULONG argc, __in_ecount(argc) PWCHAR argv[]) while (!m_pDev->Init(ovrl, ifIndex)) { ifIndex++; - if (ifIndex >= 4) + if (ifIndex >= LOOKUP_PORT_MAX_ID) { delete m_pDev; return 2;