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
412CDevice::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}
0 commit comments