Skip to content

Commit 92aa280

Browse files
Artem Galaburdaasssh52
authored andcommitted
Make GetDevicePath() return path by port id.
Allow open vio-serial port by it's PORT_ID, without calling CreateFile() and IOCTL_GET_INFORMATION for unrelated ports. We can do this, because DevicePath component from SetupDiGetInterfaceDetail already has the port_id part and we can find DevicePath for needed port_id at once. Signed-off-by: Artem Galaburda <[email protected]>
1 parent bd965ef commit 92aa280

File tree

3 files changed

+98
-47
lines changed

3 files changed

+98
-47
lines changed

vioserial/app/device.cpp

Lines changed: 93 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
#include "device.h"
22
#include "assert.h"
3+
#pragma warning(disable : 4201)
4+
#include <setupapi.h>
5+
#include <winioctl.h>
6+
#pragma warning(default : 4201)
7+
#include <string>
8+
#include <regex>
9+
10+
const DWORD LOOKUP_PORT_MAX = 32;
311

412
CDevice::CDevice()
513
{
@@ -15,10 +23,11 @@ CDevice::~CDevice()
1523
}
1624
}
1725

18-
BOOL CDevice::Init(BOOL ovrl, UINT index)
26+
BOOL CDevice::Init(BOOL ovrl, UINT portId)
1927
{
20-
PWCHAR DevicePath = NULL;
21-
if ((DevicePath = GetDevicePath(index, (LPGUID)&GUID_VIOSERIAL_PORT)) != NULL)
28+
PWCHAR DevicePath;
29+
std::vector<uint8_t> devpathBuf;
30+
if ((DevicePath = GetDevicePath(portId, (LPGUID)&GUID_VIOSERIAL_PORT, devpathBuf)) != NULL)
2231
{
2332
m_hDevice = CreateFile(DevicePath,
2433
GENERIC_WRITE | GENERIC_READ,
@@ -35,7 +44,7 @@ BOOL CDevice::Init(BOOL ovrl, UINT index)
3544
}
3645
}
3746
DWORD err = GetLastError();
38-
printf("Cannot find vioserial device. %S , error = %d\n", DevicePath, err);
47+
printf("Cannot find vioserial device PortId:%u, error: %u\n", portId, err);
3948
return FALSE;
4049
}
4150

@@ -230,7 +239,7 @@ BOOL CDevice::GetInfo(PVOID buf, size_t *size)
230239
return res;
231240
}
232241

233-
PTCHAR CDevice::GetDevicePath(UINT index, IN LPGUID InterfaceGuid)
242+
PTCHAR CDevice::GetDevicePath(UINT portId, IN LPGUID InterfaceGuid, std::vector<uint8_t> &devpathBuf)
234243
{
235244
HDEVINFO HardwareDeviceInfo;
236245
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
@@ -248,44 +257,90 @@ PTCHAR CDevice::GetDevicePath(UINT index, IN LPGUID InterfaceGuid)
248257

249258
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
250259

251-
bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo, 0, InterfaceGuid, index, &DeviceInterfaceData);
252-
253-
if (bResult == FALSE)
254-
{
255-
printf("Cannot get enumerate device interfaces.\n");
256-
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
257-
return NULL;
258-
}
259-
260-
SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo, &DeviceInterfaceData, NULL, 0, &RequiredLength, NULL);
261-
262-
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, RequiredLength);
263-
264-
if (DeviceInterfaceDetailData == NULL)
260+
for (DWORD index = 0; index < LOOKUP_PORT_MAX; index++)
265261
{
266-
printf("Cannot allocate memory.\n");
267-
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
268-
return NULL;
269-
}
262+
bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo, 0, InterfaceGuid, index, &DeviceInterfaceData);
263+
if (!bResult)
264+
{
265+
DWORD dwErr = GetLastError();
266+
if (dwErr == ERROR_NO_MORE_ITEMS)
267+
{
268+
printf("EnumDeviceInterfaces stopped at idx %u\n", index);
269+
break;
270+
}
271+
printf("EnumDeviceInterfaces[%u] error: %u\n", index, dwErr);
272+
continue;
273+
}
270274

271-
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
275+
bResult = SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo,
276+
&DeviceInterfaceData,
277+
NULL,
278+
0,
279+
&RequiredLength,
280+
NULL);
281+
if (!bResult)
282+
{
283+
DWORD dwErr = GetLastError();
284+
if (dwErr != ERROR_INSUFFICIENT_BUFFER)
285+
{
286+
printf("SetupDiGetDeviceInterfaceDetail[%u] failed with %u\n", index, dwErr);
287+
continue;
288+
}
289+
}
272290

273-
Length = RequiredLength;
291+
if (devpathBuf.size() < RequiredLength)
292+
{
293+
devpathBuf.resize(RequiredLength);
294+
}
295+
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)devpathBuf.data();
296+
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
297+
298+
Length = RequiredLength;
299+
300+
bResult = SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo,
301+
&DeviceInterfaceData,
302+
DeviceInterfaceDetailData,
303+
Length,
304+
&RequiredLength,
305+
NULL);
306+
if (!bResult)
307+
{
308+
printf("Cannot get device interface details.\n");
309+
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
310+
return NULL;
311+
}
274312

275-
bResult = SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo,
276-
&DeviceInterfaceData,
277-
DeviceInterfaceDetailData,
278-
Length,
279-
&RequiredLength,
280-
NULL);
313+
std::wstring path(DeviceInterfaceDetailData->DevicePath);
314+
std::wregex regex(L"&\\d+#");
315+
std::wsmatch wsm;
316+
if (!std::regex_search(path, wsm, regex))
317+
{
318+
wprintf(L"Failed to parse path: %ls\n", DeviceInterfaceDetailData->DevicePath);
319+
break;
320+
}
321+
// intializing a string without '&' and '#' symbols (ex. "&06#")
322+
// portIdStr will be "06"
323+
std::wstring portIdStr(wsm.str(), 1, wsm.str().length() - 1);
324+
ULONG portIdFromPath;
325+
try
326+
{
327+
portIdFromPath = std::stoi(portIdStr);
328+
}
329+
catch (const std::exception &)
330+
{
331+
wprintf(L"Could not parse port ID from '%ls'. Skipping.\n", portIdStr.c_str());
332+
continue;
333+
}
281334

282-
if (bResult == FALSE)
283-
{
284-
printf("Cannot get device interface details.\n");
285-
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
286-
LocalFree(DeviceInterfaceDetailData);
287-
return NULL;
335+
if (portIdFromPath == portId)
336+
{
337+
printf("Found vio-serial %u\n", portId);
338+
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
339+
return DeviceInterfaceDetailData->DevicePath;
340+
}
288341
}
289342

290-
return DeviceInterfaceDetailData->DevicePath;
343+
printf("Cannot find a port with ID:%u\n", portId);
344+
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
345+
return NULL;
291346
}

vioserial/app/device.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,15 @@
88
#include <stdio.h>
99
#include <string.h>
1010
#include <conio.h>
11+
#include <vector>
1112
#include "..\sys\public.h"
12-
#pragma warning(disable : 4201)
13-
14-
#include <setupapi.h>
15-
#include <winioctl.h>
16-
17-
#pragma warning(default : 4201)
1813

1914
class CDevice
2015
{
2116
public:
2217
CDevice();
2318
~CDevice();
24-
BOOL Init(BOOL ovrl, UINT index);
19+
BOOL Init(BOOL ovrl, UINT portId);
2520
BOOL Write(PVOID buf, size_t *size);
2621
BOOL WriteEx(PVOID buf, size_t *size);
2722
BOOL Read(PVOID buf, size_t *size);
@@ -30,7 +25,7 @@ class CDevice
3025

3126
protected:
3227
HANDLE m_hDevice;
33-
PTCHAR GetDevicePath(UINT index, IN LPGUID InterfaceGuid);
28+
PTCHAR GetDevicePath(UINT portId, IN LPGUID InterfaceGuid, std::vector<uint8_t> &devpathBuf);
3429
};
3530

3631
#endif

vioserial/app/main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#pragma warning(default : 4201)
99

10+
static const DWORD LOOKUP_PORT_MAX_ID = 32;
1011
static ULONG write_buffer_size = 4096;
1112
static BOOL write_send_auto = FALSE;
1213

@@ -264,7 +265,7 @@ _cdecl wmain(__in ULONG argc, __in_ecount(argc) PWCHAR argv[])
264265
while (!m_pDev->Init(ovrl, ifIndex))
265266
{
266267
ifIndex++;
267-
if (ifIndex >= 4)
268+
if (ifIndex >= LOOKUP_PORT_MAX_ID)
268269
{
269270
delete m_pDev;
270271
return 2;

0 commit comments

Comments
 (0)