mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 04:00:04 +00:00 
			
		
		
		
	Get serial bus reported device description
This commit is contained in:
		
							parent
							
								
									230c96e450
								
							
						
					
					
						commit
						cb14fba3b0
					
				
					 2 changed files with 200 additions and 7 deletions
				
			
		|  | @ -12,8 +12,12 @@ | |||
| 
 | ||||
| #if defined(_WIN32) | ||||
| #   include <Windows.h> | ||||
| #   include <cstdlib> | ||||
| #   include <SetupAPI.h> | ||||
| #   include <initguid.h> | ||||
| #   include <devguid.h> | ||||
| #   include <devpkey.h> | ||||
| #   include <tchar.h> | ||||
| #   include <cstdlib> | ||||
| #endif | ||||
| 
 | ||||
| namespace scwx | ||||
|  | @ -36,9 +40,17 @@ public: | |||
|    ~Impl() = default; | ||||
| 
 | ||||
|    void LogSerialPortInfo(const QSerialPortInfo& info); | ||||
|    void ReadComPortProperties(); | ||||
|    void ReadComPortSettings(); | ||||
|    void RefreshSerialDevices(); | ||||
| 
 | ||||
| #if defined(_WIN32) | ||||
|    static std::string GetDevicePropertyString(HDEVINFO&        deviceInfoSet, | ||||
|                                               SP_DEVINFO_DATA& deviceInfoData, | ||||
|                                               DEVPROPKEY       propertyKey); | ||||
|    static std::string GetRegistryValueDataString(HKEY hKey, LPCTSTR lpValue); | ||||
| #endif | ||||
| 
 | ||||
|    SerialPortDialog*   self_; | ||||
|    QStandardItemModel* model_; | ||||
| 
 | ||||
|  | @ -88,9 +100,70 @@ void SerialPortDialog::Impl::RefreshSerialDevices() | |||
|       LogSerialPortInfo(port); | ||||
|    } | ||||
| 
 | ||||
|    ReadComPortProperties(); | ||||
|    ReadComPortSettings(); | ||||
| } | ||||
| 
 | ||||
| void SerialPortDialog::Impl::ReadComPortProperties() | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|    GUID     classGuid  = GUID_DEVCLASS_PORTS; | ||||
|    PCWSTR   enumerator = nullptr; | ||||
|    HWND     hwndParent = nullptr; | ||||
|    DWORD    flags      = DIGCF_PRESENT; | ||||
|    HDEVINFO deviceInfoSet; | ||||
| 
 | ||||
|    // Retrieve COM port devices
 | ||||
|    deviceInfoSet = | ||||
|       SetupDiGetClassDevs(&classGuid, enumerator, hwndParent, flags); | ||||
|    if (deviceInfoSet == INVALID_HANDLE_VALUE) | ||||
|    { | ||||
|       logger_->error("Error getting COM port devices"); | ||||
|       return; | ||||
|    } | ||||
| 
 | ||||
|    DWORD           memberIndex = 0; | ||||
|    SP_DEVINFO_DATA deviceInfoData {}; | ||||
|    deviceInfoData.cbSize = sizeof(deviceInfoData); | ||||
|    flags                 = 0; | ||||
| 
 | ||||
|    // For each COM port device
 | ||||
|    while (SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex++, &deviceInfoData)) | ||||
|    { | ||||
|       DWORD  scope      = DICS_FLAG_GLOBAL; | ||||
|       DWORD  hwProfile  = 0; | ||||
|       DWORD  keyType    = DIREG_DEV; | ||||
|       REGSAM samDesired = KEY_READ; | ||||
|       HKEY   devRegKey  = SetupDiOpenDevRegKey( | ||||
|          deviceInfoSet, &deviceInfoData, scope, hwProfile, keyType, samDesired); | ||||
| 
 | ||||
|       if (devRegKey == INVALID_HANDLE_VALUE) | ||||
|       { | ||||
|          logger_->error("Unable to open device registry key: {}", | ||||
|                         GetLastError()); | ||||
|          continue; | ||||
|       } | ||||
| 
 | ||||
|       // Read Port Name and Device Description
 | ||||
|       std::string portName = | ||||
|          GetRegistryValueDataString(devRegKey, TEXT("PortName")); | ||||
| 
 | ||||
|       if (portName.empty()) | ||||
|       { | ||||
|          // Ignore device without port name
 | ||||
|          continue; | ||||
|       } | ||||
| 
 | ||||
|       std::string busReportedDeviceDesc = GetDevicePropertyString( | ||||
|          deviceInfoSet, deviceInfoData, DEVPKEY_Device_BusReportedDeviceDesc); | ||||
| 
 | ||||
|       logger_->debug("Port: {} ({})", portName, busReportedDeviceDesc); | ||||
| 
 | ||||
|       RegCloseKey(devRegKey); | ||||
|    } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void SerialPortDialog::Impl::ReadComPortSettings() | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|  | @ -126,12 +199,12 @@ void SerialPortDialog::Impl::ReadComPortSettings() | |||
| 
 | ||||
|       // Enumerate each port value
 | ||||
|       while ((status = RegEnumValue(hkResult, | ||||
|                                     dwIndex, | ||||
|                                     dwIndex++, | ||||
|                                     valueName, | ||||
|                                     &valueNameSize, | ||||
|                                     lpReserved, | ||||
|                                     &type, | ||||
|                                     (LPBYTE) &valueData, | ||||
|                                     reinterpret_cast<LPBYTE>(&valueData), | ||||
|                                     &valueDataSize)) == ERROR_SUCCESS || | ||||
|              status == ERROR_MORE_DATA) | ||||
|       { | ||||
|  | @ -176,24 +249,143 @@ void SerialPortDialog::Impl::ReadComPortSettings() | |||
| 
 | ||||
|             std::string portData = buffer; | ||||
| 
 | ||||
|             logger_->debug("Port {} has data \"{}\"", portName, portData); | ||||
|             logger_->debug("Port Settings: {} ({})", portName, portData); | ||||
|          } | ||||
| 
 | ||||
|          valueNameSize = maxValueNameSize; | ||||
|          valueDataSize = sizeof(valueData); | ||||
|          ++dwIndex; | ||||
|       } | ||||
| 
 | ||||
|       RegCloseKey(hkResult); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       logger_->warn("Could not open COM port settings registry key: {}", | ||||
|                     status); | ||||
|       logger_->error("Could not open COM port settings registry key: {}", | ||||
|                      status); | ||||
|    } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| #if defined(_WIN32) | ||||
| std::string | ||||
| SerialPortDialog::Impl::GetDevicePropertyString(HDEVINFO&        deviceInfoSet, | ||||
|                                                 SP_DEVINFO_DATA& deviceInfoData, | ||||
|                                                 DEVPROPKEY       propertyKey) | ||||
| { | ||||
|    std::string devicePropertyString {}; | ||||
| 
 | ||||
|    DEVPROPTYPE        propertyType = 0; | ||||
|    std::vector<TCHAR> propertyBuffer {}; | ||||
|    DWORD              requiredSize = 0; | ||||
|    DWORD              flags        = 0; | ||||
| 
 | ||||
|    BOOL status = SetupDiGetDeviceProperty(deviceInfoSet, | ||||
|                                           &deviceInfoData, | ||||
|                                           &propertyKey, | ||||
|                                           &propertyType, | ||||
|                                           nullptr, | ||||
|                                           0, | ||||
|                                           &requiredSize, | ||||
|                                           flags); | ||||
| 
 | ||||
|    if (requiredSize > 0) | ||||
|    { | ||||
|       propertyBuffer.reserve(requiredSize / sizeof(TCHAR)); | ||||
| 
 | ||||
|       status = SetupDiGetDeviceProperty( | ||||
|          deviceInfoSet, | ||||
|          &deviceInfoData, | ||||
|          &propertyKey, | ||||
|          &propertyType, | ||||
|          reinterpret_cast<PBYTE>(propertyBuffer.data()), | ||||
|          static_cast<DWORD>(propertyBuffer.capacity() * sizeof(TCHAR)), | ||||
|          &requiredSize, | ||||
|          flags); | ||||
|    } | ||||
| 
 | ||||
|    if (status && requiredSize > 0) | ||||
|    { | ||||
|       errno_t     error; | ||||
|       std::size_t returnValue; | ||||
| 
 | ||||
|       devicePropertyString.resize(requiredSize / sizeof(TCHAR)); | ||||
| 
 | ||||
|       if ((error = wcstombs_s(&returnValue, | ||||
|                               devicePropertyString.data(), | ||||
|                               devicePropertyString.size(), | ||||
|                               propertyBuffer.data(), | ||||
|                               _TRUNCATE)) != 0) | ||||
|       { | ||||
|          logger_->error("Error converting device property string: {}", | ||||
|                         returnValue); | ||||
|          devicePropertyString.clear(); | ||||
|       } | ||||
|       else if (!devicePropertyString.empty()) | ||||
|       { | ||||
|          // Remove trailing null
 | ||||
|          devicePropertyString.erase(devicePropertyString.size() - 1); | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    return devicePropertyString; | ||||
| } | ||||
| 
 | ||||
| std::string SerialPortDialog::Impl::GetRegistryValueDataString(HKEY    hKey, | ||||
|                                                                LPCTSTR lpValue) | ||||
| { | ||||
|    std::string dataString {}; | ||||
| 
 | ||||
|    LPCTSTR lpSubKey = nullptr; | ||||
|    DWORD   dwFlags  = RRF_RT_REG_SZ; // Restrict type to REG_SZ
 | ||||
|    DWORD   dwType; | ||||
| 
 | ||||
|    std::vector<TCHAR> dataBuffer {}; | ||||
|    DWORD              dataBufferSize = 0; | ||||
| 
 | ||||
|    LSTATUS status = RegGetValue( | ||||
|       hKey, lpSubKey, lpValue, dwFlags, &dwType, nullptr, &dataBufferSize); | ||||
| 
 | ||||
|    if (status == ERROR_SUCCESS && dataBufferSize > 0) | ||||
|    { | ||||
|       dataBuffer.reserve(dataBufferSize / sizeof(TCHAR)); | ||||
| 
 | ||||
|       status = RegGetValue(hKey, | ||||
|                            lpSubKey, | ||||
|                            lpValue, | ||||
|                            dwFlags, | ||||
|                            &dwType, | ||||
|                            reinterpret_cast<PVOID>(dataBuffer.data()), | ||||
|                            &dataBufferSize); | ||||
|    } | ||||
| 
 | ||||
|    if (status == ERROR_SUCCESS && dataBufferSize > 0) | ||||
|    { | ||||
|       errno_t     error; | ||||
|       std::size_t returnValue; | ||||
| 
 | ||||
|       dataString.resize(dataBufferSize / sizeof(TCHAR)); | ||||
| 
 | ||||
|       if ((error = wcstombs_s(&returnValue, | ||||
|                               dataString.data(), | ||||
|                               dataString.size(), | ||||
|                               dataBuffer.data(), | ||||
|                               _TRUNCATE)) != 0) | ||||
|       { | ||||
|          logger_->error("Error converting registry value data string: {}", | ||||
|                         returnValue); | ||||
|          dataString.clear(); | ||||
|       } | ||||
|       else if (!dataString.empty()) | ||||
|       { | ||||
|          // Remove trailing null
 | ||||
|          dataString.erase(dataString.size() - 1); | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    return dataString; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| } // namespace ui
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat