// Fill out your copyright notice in the Description page of Project Settings. #include "SerialPortLibrary.h" #if PLATFORM_WINDOWS #include "Windows/AllowWindowsPlatformTypes.h" #include #include #include "Windows/HideWindowsPlatformTypes.h" #pragma comment(lib, "setupapi.lib") #endif TArray USerialPortLibrary::GetAvailableSerialPorts() { TArray Ports; #if PLATFORM_WINDOWS // Query registry for all COM ports HKEY hKey; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) { DWORD Index = 0; TCHAR ValueName[256]; TCHAR ValueData[256]; DWORD ValueNameSize = 256; DWORD ValueDataSize = 256 * sizeof(TCHAR); DWORD Type; while (RegEnumValue(hKey, Index++, ValueName, &ValueNameSize, nullptr, &Type, (LPBYTE)ValueData, &ValueDataSize) == ERROR_SUCCESS) { Ports.Add(FString(ValueData)); ValueNameSize = 256; ValueDataSize = 256 * sizeof(TCHAR); } RegCloseKey(hKey); } #endif return Ports; } TArray USerialPortLibrary::GetAvailableSerialPortsWithNames() { TArray Ports; #if PLATFORM_WINDOWS // Use SetupAPI to get port + friendly device name HDEVINFO DeviceInfoSet = SetupDiGetClassDevs( nullptr, TEXT("USB"), nullptr, DIGCF_PRESENT | DIGCF_ALLCLASSES ); if (DeviceInfoSet == INVALID_HANDLE_VALUE) return Ports; SP_DEVINFO_DATA DeviceInfoData; DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (DWORD i = 0; SetupDiEnumDeviceInfo(DeviceInfoSet, i, &DeviceInfoData); i++) { TCHAR FriendlyName[256] = {}; TCHAR PortName[256] = {}; // Get friendly name (e.g. "Arduino Uno (COM3)") SetupDiGetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_FRIENDLYNAME, nullptr, (PBYTE)FriendlyName, sizeof(FriendlyName), nullptr); // Get COM port from device registry key HKEY DevKey = SetupDiOpenDevRegKey(DeviceInfoSet, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (DevKey != INVALID_HANDLE_VALUE) { DWORD PortNameSize = sizeof(PortName); RegQueryValueEx(DevKey, TEXT("PortName"), nullptr, nullptr, (LPBYTE)PortName, &PortNameSize); RegCloseKey(DevKey); if (wcslen(PortName) > 0 && wcslen(FriendlyName) > 0) { // Format: "COM3|Arduino Uno (COM3)" FString Entry = FString::Printf(TEXT("%s|%s"), PortName, FriendlyName); Ports.Add(Entry); } } } SetupDiDestroyDeviceInfoList(DeviceInfoSet); #endif return Ports; }