diff --git a/src/display_device/session.cpp b/src/display_device/session.cpp index af66232a7ff..a1392149724 100644 --- a/src/display_device/session.cpp +++ b/src/display_device/session.cpp @@ -509,8 +509,17 @@ namespace display_device { const std::string vdd_identifier = config::video.vdd_reuse ? "shared_vdd" // 固定标识符,所有客户端共用同一GUID : current_client_id; // 为每个客户端生成不同GUID - vdd_utils::create_vdd_monitor(vdd_identifier, hdr_brightness, physical_size); - std::this_thread::sleep_for(200ms); + if (!vdd_utils::create_vdd_monitor(vdd_identifier, hdr_brightness, physical_size)) { + BOOST_LOG(error) << "创建虚拟显示器失败(驱动报告错误),尝试恢复"; + if (!try_recover_vdd_device(current_client_id, session.client_name, hdr_brightness, device_zako)) { + BOOST_LOG(error) << "VDD设备最终初始化失败"; + vdd_utils::disable_enable_vdd(); + return; + } + } + else { + std::this_thread::sleep_for(200ms); + } } // Wait for device to be ready @@ -622,11 +631,15 @@ namespace display_device { auto devices = display_device::enum_available_devices(); if (devices.empty()) { BOOST_LOG(info) << "无头主机检测:未找到显示设备,自动创建基地显示器"; - create_vdd_monitor(""); - constexpr int max_attempts = 5; - constexpr auto wait_time = std::chrono::milliseconds(233); - for (int i = 0; i < max_attempts && !is_display_on(); ++i) { - std::this_thread::sleep_for(wait_time); + if (!create_vdd_monitor("")) { + BOOST_LOG(error) << "无头主机自动创建显示器失败"; + } + else { + constexpr int max_attempts = 5; + constexpr auto wait_time = std::chrono::milliseconds(233); + for (int i = 0; i < max_attempts && !is_display_on(); ++i) { + std::this_thread::sleep_for(wait_time); + } } } } diff --git a/src/display_device/vdd_utils.cpp b/src/display_device/vdd_utils.cpp index 0b0f79b3de8..b0bcd6ed335 100644 --- a/src/display_device/vdd_utils.cpp +++ b/src/display_device/vdd_utils.cpp @@ -141,7 +141,7 @@ namespace display_device { } bool - execute_pipe_command(const wchar_t *pipe_name, const wchar_t *command, std::string *response, bool *timed_out) { + execute_pipe_command(const wchar_t *pipe_name, const wchar_t *command, std::string *response, bool *timed_out, DWORD read_timeout_ms) { auto hPipe = connect_to_pipe_with_retry(pipe_name); if (hPipe == INVALID_HANDLE_VALUE) { BOOST_LOG(error) << "连接MTT虚拟显示管道失败,已重试多次"; @@ -180,6 +180,7 @@ namespace display_device { } // 读取响应 + const DWORD effective_read_timeout = (read_timeout_ms > 0) ? read_timeout_ms : kPipeTimeoutMs; bool read_timed_out = false; if (response) { char buffer[kPipeBufferSize]; @@ -190,7 +191,7 @@ namespace display_device { return false; } - DWORD waitResult = WaitForSingleObject(overlapped.hEvent, kPipeTimeoutMs); + DWORD waitResult = WaitForSingleObject(overlapped.hEvent, effective_read_timeout); if (waitResult == WAIT_OBJECT_0 && GetOverlappedResult(hPipe, &overlapped, &bytesRead, FALSE)) { buffer[bytesRead] = '\0'; *response = std::string(buffer, bytesRead); @@ -322,14 +323,16 @@ namespace display_device { } // 尝试发送命令(带GUID或不带GUID) + // 使用更长的读取超时,因为新版驱动会在管道中等待CCD系统就绪 + constexpr DWORD kCreateMonitorReadTimeoutMs = 20000; bool read_timed_out = false; - bool success = execute_pipe_command(kVddPipeName, command.c_str(), &response, &read_timed_out); + bool success = execute_pipe_command(kVddPipeName, command.c_str(), &response, &read_timed_out, kCreateMonitorReadTimeoutMs); // 如果带GUID的命令失败,降级为不带GUID的命令(兼容旧版驱动) if (!success && !guid_str.empty()) { BOOST_LOG(warning) << "带GUID的命令失败,尝试降级为不带GUID的命令"; read_timed_out = false; - success = execute_pipe_command(kVddPipeName, L"CREATEMONITOR", &response, &read_timed_out); + success = execute_pipe_command(kVddPipeName, L"CREATEMONITOR", &response, &read_timed_out, kCreateMonitorReadTimeoutMs); } if (!success) { @@ -340,7 +343,23 @@ namespace display_device { #if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1 system_tray::update_vdd_menu(); #endif - BOOST_LOG(info) << "创建虚拟显示器完成,响应: " << response << " [return=" << (read_timed_out ? 1 : 0) << "]"; + + // 解析驱动响应:OK = CCD已就绪, OK_PENDING = 创建成功但CCD未就绪, FAIL = 创建失败 + if (response == "FAIL") { + BOOST_LOG(error) << "驱动端报告虚拟显示器创建失败"; + return false; + } + + if (response == "OK") { + BOOST_LOG(info) << "创建虚拟显示器完成,驱动确认CCD已就绪"; + } + else if (response == "OK_PENDING") { + BOOST_LOG(warning) << "创建虚拟显示器完成,但CCD系统尚未就绪(驱动等待超时)"; + } + else { + // 旧版驱动不返回响应(read_timed_out=true),视为成功 + BOOST_LOG(info) << "创建虚拟显示器完成,响应: " << response << " [return=" << (read_timed_out ? 1 : 0) << "]"; + } return true; } diff --git a/src/display_device/vdd_utils.h b/src/display_device/vdd_utils.h index a91939cf3d2..08369c66d78 100644 --- a/src/display_device/vdd_utils.h +++ b/src/display_device/vdd_utils.h @@ -67,7 +67,7 @@ namespace display_device::vdd_utils { connect_to_pipe_with_retry(const wchar_t *pipe_name, int max_retries = 3); bool - execute_pipe_command(const wchar_t *pipe_name, const wchar_t *command, std::string *response = nullptr, bool *timed_out = nullptr); + execute_pipe_command(const wchar_t *pipe_name, const wchar_t *command, std::string *response = nullptr, bool *timed_out = nullptr, DWORD read_timeout_ms = 0); // 驱动重载函数 bool