Windows 에서 개발 하는 과정에서 COM port 를 찾는 방법은 여러가지가 있긴 합니다만, 명확히 USB 나 Bluetooth 와 같은 기기들이 연결 되었을 때 이것을 다 찾아 내는 방법은 애매한 경우가 더러 있습니다.
저의 경우는 기존에 SetupDiEnumDeviceInterfaces() 를 사용한 방법을 쓰다가, Windows 10 으로 올린 다음 부터 USB 장치로 인식한 COM port 가 검색이 되질 않아 좀 더 애를 먹었습니다만, 간단히 GUID 를 GUID_DEVINTERFACE_COMPORT 로 쓰던걸 GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR 로 변경하기만 해도 문제가 해결 되었습니다.
각 GUI 는 다음과 같은 값을 가집니다. (mingw-w64 의 경우 winioctl.h 에 이 내용이 있습니다)
GUID_DEVINTERFACE_COMPORT = 0x86e0d1e0,0x8089,0x11d0,0x9c,0xe4,0x08,0x00,0x3e,0x30,0x1f,0x73
GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR = 0x4D36E978,0xE325,0x11CE,0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18
그리고 이것을 아래와 같이 응용 할 수 있습니다.
GUID* guidDev = (GUID*) &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR;
HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DETAIL_DATA* pDetData = NULL;
hDevInfo = SetupDiGetClassDevs( guidDev,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
if( hDevInfo == INVALID_HANDLE_VALUE )
{
errorstring = TEXT("SetupDiGetClassDevs return INVALID_HANDLE_VALUE");
return;
}
BOOL bOk = TRUE;
SP_DEVICE_INTERFACE_DATA ifcData;
DWORD dwDetDataSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + DEVICE_INFO_SZ;
pDetData = (SP_DEVICE_INTERFACE_DETAIL_DATA*)new char[dwDetDataSize];
if ( pDetData == NULL )
return;
ifcData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
pDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
for( int cnt=0; cnt<256; cnt++ )
{
bOk = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guidDev, cnt, &ifcData);
if ( bOk == TRUE )
{
⁄⁄ Got a device. Get the details.
SP_DEVINFO_DATA devdata = {sizeof(SP_DEVINFO_DATA)};
bOk = SetupDiGetDeviceInterfaceDetail( hDevInfo,
&ifcData,
pDetData,
dwDetDataSize,
NULL,
&devdata );
if ( bOk == TRUE )
{
TSTRING strDevPath = pDetData->DevicePath;
wchar_t fname[256] = {0};
wchar_t desc[256] = {0};
BOOL bSuccess = SetupDiGetDeviceRegistryProperty( hDevInfo,
&devdata,
SPDRP_FRIENDLYNAME,
NULL,
(PBYTE)fname,
256,
NULL );
bSuccess = bSuccess &&
SetupDiGetDeviceRegistryProperty( hDevInfo,
&devdata,
SPDRP_DEVICEDESC,
NULL,
(PBYTE)desc,
256,
NULL );
bool bUsbDevice = false;
if ( ( wcsstr( desc, L"USB" ) != NULL ) || ( wcsstr( fname, L"USB" ) != NULL ) )
{
bUsbDevice = true;
}
if ( bSuccess == TRUE )
{
#ifdef DEBUG
wprintf( L"%S[%03d] %S (%S)\n",
L"COM Port",
cnt,
(wchar_t*)fname,
(wchar_t*)desc );
#endif ⁄⁄ DEBUG
serialportinfo si;
si.isUSBdev = bUsbDevice;
si.devpath = ConvertFromUnicode( strDevPath.c_str() );
si.friendlyname = ConvertFromUnicode( fname );
si.description = ConvertFromUnicode( desc );
string::size_type postkf = si.friendlyname.find("(");
string::size_type postke = si.friendlyname.find_last_of(")");
string::size_type lentk = postke - postkf - 1;
string portn = si.friendlyname.substr( postkf + 1, lentk );
si.portname = portn;
serialports.push_back( si );
}
}
else
{
errorstring = TEXT("SetupDiGetDeviceInterfaceDetail failed.");
throw errorstring;
}
}
else
{
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_ITEMS)
{
errorstring = TEXT("SetupDiEnumDeviceInterfaces failed.");
throw errorstring;
}
}
}
if (pDetData != NULL)
delete [] (char*)pDetData;
if (hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);
혹시 저와 같이 이 일로 하루를 버린 경우가 계시다면 조속히 해결 할 수 있는 방법으로 사용하시길 바랍니다.
이걸 몰라서 엄청 해매었습니다.. 망할 MSDN ...