From 4023159b470a3de6b4bd66a9023757ae4dfcd2a5 Mon Sep 17 00:00:00 2001 From: chenjiangqun Date: Wed, 13 May 2026 11:33:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=80=E6=96=B0code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WinISP/BaseClass/GraphicCardI2CCtrl.cs | 47 +- .../WinISP/BaseClass/MTKDebugCmd.cs | 64 +- .../WinISP/FormISP_MSI.cs | 659 +++++++++++------- .../WinISP/WinISP.csproj | 13 +- .../WinISP/frmISP.cs | 343 ++++++--- 5 files changed, 777 insertions(+), 349 deletions(-) diff --git a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs index 053a1a0..8f18f6f 100644 --- a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs +++ b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs @@ -83,6 +83,40 @@ namespace WinISP.BaseClass CreateGraphicsCardCtrl(); } + public void ReCreateGraphicCardCtrl(GPUTypes type) + { + FreeGraphicsCardCtrl(); + + try + { + switch (type) + { + case GPUTypes.AMD: + pGraphicCardCtrl = CreateGraphicCardCtrl((int)GPUTypes.AMD); + break; + + case GPUTypes.NVIDIA: + pGraphicCardCtrl = CreateGraphicCardCtrl((int)GPUTypes.NVIDIA); + break; + + case GPUTypes.INTEL: + pGraphicCardCtrl = CreateGraphicCardCtrl((int)GPUTypes.INTEL); + break; + + default: + pGraphicCardCtrl = CreateGraphicCardCtrl(); + break; + } + + if (pGraphicCardCtrl != IntPtr.Zero) + _IsInit = true; + } + catch (Exception e) + { + frmISP.WriteLog("ReCreateGraphicCardCtrl(" + type.ToString() + ") Exception: " + e.Message, "debug"); + } + } + private void CreateGraphicsCardCtrl() { // Declare an instance of the CallBack delegate. @@ -106,7 +140,7 @@ namespace WinISP.BaseClass } catch (Exception e) { - System.Windows.Forms.MessageBox.Show(e.Message); + frmISP.WriteLog("CreateGraphicCardCtrl Exception: " + e.Message, "debug"); } } @@ -247,8 +281,17 @@ namespace WinISP.BaseClass { if (_IsInit == true) return true; - else + if (pGraphicCardCtrl == IntPtr.Zero) + return false; + try + { return InitGraphicCardCtrl(pGraphicCardCtrl); + } + catch (Exception e) + { + frmISP.WriteLog("Init() Exception: " + e.Message, "debug"); + return false; + } } public GRAPHIC_CARD GetGraphicCardType diff --git a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/MTKDebugCmd.cs b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/MTKDebugCmd.cs index 835538c..7fe420a 100644 --- a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/MTKDebugCmd.cs +++ b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/MTKDebugCmd.cs @@ -47,9 +47,7 @@ namespace MTK for (int i = 3; i < wrBuf.Length; ++i) strData += wrBuf[i].ToString("X2") + " "; - if (ret) - WinISP.frmISP.WriteLog("[Write DDC]" + strData, "debug"); - else + if (!ret) WinISP.frmISP.WriteLog("[Write DDC Fail]" + strData, "debug"); return ret; @@ -60,38 +58,48 @@ namespace MTK string strData = ""; for (int i = 0; i < data.Length; ++i) strData += data[i].ToString("X2") + " "; - if (!DDC_Write(data)) - return null; - - WinIOLib.DelayUs(delayTime); - - const Byte dest = 0x6F; - Byte[] wrCmds = { dest }; - Byte[] recvBuf = new Byte[recvLen]; - strData = ""; - if (_i2cCtrl.ReadData(recvBuf, wrCmds) == true) + const int maxNullRetryCnt = 3; + for (int retry = 0; retry <= maxNullRetryCnt; retry++) { - for (int i = 0; i < recvBuf.Length; ++i) - strData += recvBuf[i].ToString("X2") + " "; - - if ((recvBuf[0] != 0x6E) || (recvBuf[1] <= 0x80)) - { - WinISP.frmISP.WriteLog("[Read DDC Fail]" + strData + " I2C Format Error!", "debug"); + if (!DDC_Write(data)) return null; + + WinIOLib.DelayUs(delayTime * (retry + 1)); + + const Byte dest = 0x6F; + Byte[] wrCmds = { dest }; + Byte[] recvBuf = new Byte[recvLen]; + strData = ""; + if (_i2cCtrl.ReadData(recvBuf, wrCmds) == true) + { + for (int i = 0; i < recvBuf.Length; ++i) + strData += recvBuf[i].ToString("X2") + " "; + + if ((recvBuf[0] == 0x6E) && (recvBuf[1] == 0x80)) + { + if (retry < maxNullRetryCnt) + continue; + + WinISP.frmISP.WriteLog("[Read DDC Fail]" + strData + " DDC null response timeout.", "debug"); + return null; + } + + if ((recvBuf[0] != 0x6E) || (recvBuf[1] < 0x80)) + { + WinISP.frmISP.WriteLog("[Read DDC Fail]" + strData + " I2C Format Error!", "debug"); + return null; + } + + return recvBuf; } else { - WinISP.frmISP.WriteLog("[Read DDC]" + strData, "debug"); - return recvBuf; + WinISP.frmISP.WriteLog("[Read DDC Fail]", "debug"); + return null; } } - else - { - for (int i = 0; i < recvBuf.Length; ++i) - strData += recvBuf[i].ToString("X2") + " "; - WinISP.frmISP.WriteLog("[Read DDC Fail]", "debug"); - return null; - } + + return null; } private static Byte CalCheckSum(Byte[] data, int startIdx = 0) diff --git a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs index 586a38c..e17f7b8 100644 --- a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs +++ b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs @@ -39,14 +39,14 @@ namespace WinISP private string _u8ModelName = String.Empty; private string _u8PanelName = String.Empty; private string _panelTypeName = String.Empty; - private string _u8FWVersion = String.Empty; + private string _u8FWVersion = String.Empty; private string _chipName = String.Empty; private string _u8ChipName = String.Empty; private string _u8BoardName = String.Empty; - //private string _monitorModelName = String.Empty; - //private string _monitorChipName = String.Empty; - //private string _monitorPanelName = String.Empty; - //private string _monitorBoardName = String.Empty; + private string _monitorModelName = String.Empty; + private string _monitorChipName = String.Empty; + private string _monitorPanelName = String.Empty; + private string _monitorBoardName = String.Empty; private string _fwModelName = String.Empty; private string _fwChipName = String.Empty; private string _fwPanelName = String.Empty; @@ -69,11 +69,13 @@ namespace WinISP private const int MonitorChipNameLength = 20; private const int MonitorPanelNameLength = 30; private const int MonitorBoardNameLength = 20; + private const string PlaceholderMonitorModelName = "MST9U6_PanelCMIM236HGJ_L21"; + private const string LegacyMonitorModelName = "MAG 321UPD E14"; private const byte MS_GET_MODEL_NAME = 0x36; private const byte MS_GET_CHIP_NAME = 0x41; private const byte MS_GET_PANEL_NAME = 0x42; private const byte MS_GET_BOARD_NAME = 0x45; - private const byte MS_GET_FW_VERSION = 0x47; + private const byte MS_GET_FW_VERSION = 0x47; private string _fwVersionFromDDC = String.Empty; object _lockObj = new object(); int _numberOfMonitors; @@ -271,7 +273,7 @@ namespace WinISP if (display) MessageBox.Show(msg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } - /// + /// /// Send a 2-byte DDC command and parse the ASCII string returned by the monitor firmware. /// recv layout: [hdr0][hdr1][char0][char1]...[\0] /// @@ -341,7 +343,21 @@ namespace WinISP for (int i = 0; i < retryCount; i++) { if (string.IsNullOrWhiteSpace(_fwModelName)) - _fwModelName = DDC_GetMonitorName(MS_GET_MODEL_NAME); + { + string rawModel = DDC_GetMonitorName(MS_GET_MODEL_NAME); + if (string.Equals(NormalizeMonitorInfo(rawModel), PlaceholderMonitorModelName, StringComparison.OrdinalIgnoreCase)) + { + WriteLog("Placeholder model detected, applying legacy field remapping", "debug"); + _fwModelName = LegacyMonitorModelName; + _fwChipName = "MST9U"; + _fwPanelName = "Panel_SG315GD01_2_eDP"; + _fwVersionFromDDC = "FW.033"; + } + else + { + _fwModelName = NormalizeMonitorModelName(rawModel); + } + } if (string.IsNullOrWhiteSpace(_fwChipName)) _fwChipName = DDC_GetMonitorName(MS_GET_CHIP_NAME); if (string.IsNullOrWhiteSpace(_fwPanelName)) @@ -378,43 +394,57 @@ namespace WinISP return String.IsNullOrWhiteSpace(value) ? String.Empty : value.Trim(); } - //private bool IsModelNameMatch(string u8Model_Name) - //{ - // string monitorValue = NormalizeMonitorInfo(_monitorModelName); - // if (String.IsNullOrEmpty(monitorValue)) - // return true; + private string NormalizeMonitorModelName(string value) + { + string normalizedValue = NormalizeMonitorInfo(value); + if (string.Equals(normalizedValue, PlaceholderMonitorModelName, StringComparison.OrdinalIgnoreCase)) + return LegacyMonitorModelName; - // return string.Equals(monitorValue, NormalizeMonitorInfo(u8Model_Name), StringComparison.Ordinal); - //} - //private bool IsChipNameMatch(string u8Chi_pName) - //{ - // string monitorValue = NormalizeMonitorInfo(_monitorChipName); - // if (String.IsNullOrEmpty(monitorValue)) - // return true; + return normalizedValue; + } - // return string.Equals(monitorValue, NormalizeMonitorInfo(u8Chi_pName), StringComparison.Ordinal); - //} - //private bool IsPanelNameMatch(string u8Panel_Name) - //{ - // string monitorValue = NormalizeMonitorInfo(_monitorPanelName); - // if (String.IsNullOrEmpty(monitorValue)) - // return true; + private string GetModelMismatchMessage(string monitorModelName, string binModelName) + { + return "Model not match."; + } - // return string.Equals(monitorValue, NormalizeMonitorInfo(u8Panel_Name), StringComparison.Ordinal); - //} - //private bool IsBoardNameMatch(string u8Board_Name) - //{ - // string monitorValue = NormalizeMonitorInfo(_monitorBoardName); - // string binValue = NormalizeMonitorInfo(u8Board_Name); + private bool IsModelNameMatch(string u8Model_Name) + { + string monitorValue = NormalizeMonitorModelName(_monitorModelName); + if (String.IsNullOrEmpty(monitorValue)) + return true; - // if (!String.IsNullOrEmpty(monitorValue)) - // return string.Equals(monitorValue, binValue, StringComparison.Ordinal); + return string.Equals(monitorValue, NormalizeMonitorInfo(u8Model_Name), StringComparison.Ordinal); + } + private bool IsChipNameMatch(string u8Chi_pName) + { + string monitorValue = NormalizeMonitorInfo(_monitorChipName); + if (String.IsNullOrEmpty(monitorValue)) + return true; - // if (binValue.Length < 4) - // return false; + return string.Equals(monitorValue, NormalizeMonitorInfo(u8Chi_pName), StringComparison.Ordinal); + } + private bool IsPanelNameMatch(string u8Panel_Name) + { + string monitorValue = NormalizeMonitorInfo(_monitorPanelName); + if (String.IsNullOrEmpty(monitorValue)) + return true; - // return binValue[0] == 'F' && binValue[1] == 'W' && binValue[2] == '.' && binValue[3] == '0'; - //} + return string.Equals(monitorValue, NormalizeMonitorInfo(u8Panel_Name), StringComparison.Ordinal); + } + private bool IsBoardNameMatch(string u8Board_Name) + { + string monitorValue = NormalizeMonitorInfo(_monitorBoardName); + string binValue = NormalizeMonitorInfo(u8Board_Name); + + if (!String.IsNullOrEmpty(monitorValue)) + return string.Equals(monitorValue, binValue, StringComparison.Ordinal); + + if (binValue.Length < 4) + return false; + + return binValue[0] == 'F' && binValue[1] == 'W' && binValue[2] == '.' && binValue[3] == '0'; + } private void btnLoadFile_Click(object sender, EventArgs e) { @@ -433,24 +463,28 @@ namespace WinISP tsslFilePath.Text = fi.Name; tsslFileSize.Text = InitBinaryFile(_binFilePath).Length.ToString(); - // 解析bin文件中的u8ModelName、u8PanelName、u8BoardName、u8ChipName + // 解析bin文件中的u8ModelName、u8ChipName、u8PanelName、u8FWVersion const long infoAddr = 0x0041380; const int modenameLen = 20; // 每个名字最大长度 const int chipnameLen = 20; const int panelnameLen = 30; - const int boardnameLen = 20; - const int totalLen = modenameLen + chipnameLen + panelnameLen + boardnameLen; + const int fwversionLen = 20; + const int totalLen = modenameLen + chipnameLen + panelnameLen + fwversionLen; byte[] infoBytes = ReadBinSection(_binFilePath, infoAddr, totalLen); if (infoBytes.Length < totalLen) throw new InvalidDataException("Bin metadata section is shorter than expected."); _u8ModelName = Encoding.ASCII.GetString(infoBytes, 0, modenameLen).TrimEnd('\0'); _u8ChipName = Encoding.ASCII.GetString(infoBytes, modenameLen, chipnameLen).TrimEnd('\0'); _u8PanelName = Encoding.ASCII.GetString(infoBytes, modenameLen + chipnameLen, panelnameLen).TrimEnd('\0'); - _u8BoardName = Encoding.ASCII.GetString(infoBytes, modenameLen + chipnameLen + panelnameLen, boardnameLen).TrimEnd('\0'); - SetStatusMsg("Read Bin OK. Model: " + _u8ModelName + ", Chip: " + _u8ChipName + ", Panel: " + _u8PanelName + ", Board: " + _u8BoardName); + _u8FWVersion = Encoding.ASCII.GetString(infoBytes, modenameLen + chipnameLen + panelnameLen, fwversionLen).TrimEnd('\0'); + _u8BoardName = String.Empty; + frmISP.WriteLog("BIN parsed: Model=[" + _u8ModelName + "] Chip=[" + _u8ChipName + "] Panel=[" + _u8PanelName + "] FW=[" + _u8FWVersion + "]", "debug"); + // SetStatusMsg("Read Bin OK. Model: " + _u8ModelName + ", Chip: " + _u8ChipName + ", Panel: " + _u8PanelName + ", FW: " + _u8FWVersion); } catch (Exception ex) { + frmISP.WriteLog("btnLoadFile_Click exception: " + ex.GetType().Name + ": " + ex.Message, "debug"); + MessageBox.Show(this, "加载文件失败: " + ex.GetType().Name + "\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); SetStatusMsg("Could not read file from disk.", true); } @@ -459,74 +493,114 @@ namespace WinISP if (flashSectorInfo != null && flashSectorInfo.Count > 0) flashSectorInfo.Clear(); - // Re-connect after loading a new bin (原 frmISP 调用 btnConnect.PerformClick()) - Connect(); + // 已连接时跳过重连,避免DDC偶发握手失败触发错误弹窗 + if (!IsConnect) + Connect(); + + if (IsConnect) + { + string verifyErr; + if (!ValidateMonitorVsBin(out verifyErr)) + { + SetStatusMsg(verifyErr, true); + SetStatusMsg("Please select a F/W file."); + } + else + { + SetStatusMsg("BIN loaded. Ready to upgrade."); + } + } } } - //private void QueryConnectedMonitorInfo() - //{ - // // 读取显示器端信息(芯片名、面板名、板卡名、型号名) - // try - // { - // // 型号名 - // { - // Byte[] cmd = { MStarCommand, CmdGetModelName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorModelNameLength + 2) - // _monitorModelName = Encoding.ASCII.GetString(recv, 2, MonitorModelNameLength).TrimEnd('\0'); - // else - // _monitorModelName = string.Empty; - // } + private void QueryConnectedMonitorInfo() + { + // 读取显示器端信息(芯片名、面板名、板卡名、型号名) + try + { + bool legacyRemapped = false; - // // 芯片名 - // { - // Byte[] cmd = { MStarCommand, CmdGetChipName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorChipNameLength + 2) - // _monitorChipName = Encoding.ASCII.GetString(recv, 2, MonitorChipNameLength).TrimEnd('\0'); - // else - // _monitorChipName = string.Empty; - // } - // // 面板名 - // { - // Byte[] cmd = { MStarCommand, CmdGetPanelName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorPanelNameLength + 2) - // _monitorPanelName = Encoding.ASCII.GetString(recv, 2, MonitorPanelNameLength).TrimEnd('\0'); - // else - // _monitorPanelName = string.Empty; - // } - // // 板卡名 - // { - // Byte[] cmd = { MStarCommand, CmdGetBoardName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorBoardNameLength + 2) - // _monitorBoardName = Encoding.ASCII.GetString(recv, 2, MonitorBoardNameLength).TrimEnd('\0'); - // else - // _monitorBoardName = string.Empty; - // } + // 型号名 + { + Byte[] cmd = { MStarCommand, CmdGetModelName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorModelNameLength + 2) + { + string rawModelName = Encoding.ASCII.GetString(recv, 2, MonitorModelNameLength).TrimEnd('\0'); + if (string.Equals(rawModelName.Trim(), PlaceholderMonitorModelName, StringComparison.OrdinalIgnoreCase)) + { + legacyRemapped = true; + _monitorModelName = LegacyMonitorModelName; + _monitorChipName = "MST9U"; + _monitorPanelName = "Panel_SG315GD01_2_eDP"; + WriteLog("Placeholder model detected, legacy remapping: " + rawModelName + " -> " + _monitorModelName + ", Chip=MST9U, Panel=Panel_SG315GD01_2_eDP", "debug"); + } + else + { + _monitorModelName = NormalizeMonitorModelName(rawModelName); + } + } + else + _monitorModelName = string.Empty; + } - // //DDC_GetModelName(ref _monitorModelName); - // // 日志打印 - // WriteLog($"MonitorModelName={_monitorModelName}", "debug"); - // WriteLog($"MonitorChipName={_monitorChipName}", "debug"); - // WriteLog($"MonitorPanelName={_monitorPanelName}", "debug"); - // WriteLog($"MonitorBoardName={_monitorBoardName}", "debug"); - // } - // catch (Exception ex) - // { - // WriteLog("QueryConnectedMonitorInfo Exception: " + ex.Message, "debug"); - // } - //} + // 芯片名 + if (!legacyRemapped) + { + Byte[] cmd = { MStarCommand, CmdGetChipName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorChipNameLength + 2) + _monitorChipName = Encoding.ASCII.GetString(recv, 2, MonitorChipNameLength).TrimEnd('\0'); + else + _monitorChipName = string.Empty; + } + // 面板名 + if (!legacyRemapped) + { + Byte[] cmd = { MStarCommand, CmdGetPanelName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorPanelNameLength + 2) + _monitorPanelName = Encoding.ASCII.GetString(recv, 2, MonitorPanelNameLength).TrimEnd('\0'); + else + _monitorPanelName = string.Empty; + } + // 板卡名 + { + Byte[] cmd = { MStarCommand, CmdGetBoardName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorBoardNameLength + 2) + _monitorBoardName = Encoding.ASCII.GetString(recv, 2, MonitorBoardNameLength).TrimEnd('\0'); + else + _monitorBoardName = string.Empty; + } - //private void ClearConnectedMonitorInfo() - //{ - // _monitorModelName = string.Empty; - // _monitorChipName = string.Empty; - // _monitorPanelName = string.Empty; - // _monitorBoardName = string.Empty; - //} + // 日志打印 + WriteLog("MonitorModelName=" + _monitorModelName, "debug"); + WriteLog("MonitorChipName=" + _monitorChipName, "debug"); + WriteLog("MonitorPanelName=" + _monitorPanelName, "debug"); + WriteLog("MonitorBoardName=" + _monitorBoardName, "debug"); + } + catch (Exception ex) + { + WriteLog("QueryConnectedMonitorInfo Exception: " + ex.Message, "debug"); + } + } + + private void ClearConnectedMonitorInfo() + { + _monitorModelName = string.Empty; + _monitorChipName = string.Empty; + _monitorPanelName = string.Empty; + _monitorBoardName = string.Empty; + } void Connect(int delayTime = 0) { @@ -565,21 +639,67 @@ namespace WinISP // DDC2CI_SetR2Reset51Flag(0x01); Byte chipType = 0; IsConnect = false; - int retry = 0; MTKDebugCmd.DDC_Write(buf); //if (IsConnect) { //WriteLog("IsConnect = true", "debug"); btnAuto.Enabled = true; - SetStatusMsg("Please select a F/W file."); + if (String.IsNullOrEmpty(_binFilePath)) + SetStatusMsg("Please select a F/W file."); + else + SetStatusMsg("BIN loaded. Ready to upgrade."); String nameFromGPU = ""; List list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + frmISP.WriteLog("InitConnectedMonitor count = " + list.Count, "debug"); + + if (list.Count == 0 && ((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType == GraphicCardI2CCtrl.GRAPHIC_CARD.AMD) + { + frmISP.WriteLog("InitConnectedMonitor = 0 on AMD auto-detect, trying forced NVIDIA controller ...", "debug"); + ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(GraphicCardI2CCtrl.GPUTypes.NVIDIA); + WinIOLib.DelayMs(300); + if (_simI2cCtrl.Init()) + { + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + frmISP.WriteLog("InitConnectedMonitor after forced NVIDIA count = " + list.Count, "debug"); + } + + if (list.Count == 0) + { + frmISP.WriteLog("Forced NVIDIA controller did not find monitors, restoring auto-detect controller ...", "debug"); + ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(); + WinIOLib.DelayMs(300); + if (_simI2cCtrl.Init()) + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + } + } + + // NVIDIA DP AUX channel may not be ready on first launch – retry with delay. + { + int mntRetry = 0; + while (list.Count == 0 && mntRetry++ < 3) + { + frmISP.WriteLog("InitConnectedMonitor = 0, waiting 1500ms before retry " + mntRetry + " ...", "debug"); + WinIOLib.DelayMs(1500); + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + frmISP.WriteLog("InitConnectedMonitor retry " + mntRetry + " count = " + list.Count, "debug"); + } + // If all retries exhausted and still no monitor, recreate the GPU control and try once more. + if (list.Count == 0) + { + frmISP.WriteLog("InitConnectedMonitor still 0 – calling ReCreateGraphicCardCtrl ...", "debug"); + ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(); + WinIOLib.DelayMs(1500); + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + frmISP.WriteLog("InitConnectedMonitor after ReCreate count = " + list.Count, "debug"); + } + } for (int idxDisp = 0; idxDisp < list.Count; idxDisp++) { + int retry = 0; // Reset retry counter for each monitor index nameFromGPU = list[idxDisp].ToUpper(); - frmISP.WriteLog("nameFromGPU = " + nameFromGPU, "debug"); + frmISP.WriteLog("nameFromGPU[" + idxDisp + "] = " + nameFromGPU, "debug"); _selectedMonitorIndex = idxDisp; ((GraphicCardI2CCtrl)_simI2cCtrl).SetConnectedMonitorIndex((Byte)idxDisp); @@ -587,21 +707,33 @@ namespace WinISP { IsConnect = DDC_CheckMTKDevice(ref chipType); } + frmISP.WriteLog("idxDisp=" + idxDisp + " IsConnect=" + IsConnect + " chipType=" + chipType, "debug"); if (IsConnect == true) { break; } } - // 自动读取显示器信息 - //QueryConnectedMonitorInfo(); + // Intel IGCL and AMD can complete the FE handshake but still time out on optional + // identity queries during connect. Skip those reads here so connect stays usable. + if ((((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.AMD)) + { + QueryConnectedMonitorInfo(); + } + else + { + ClearConnectedMonitorInfo(); + frmISP.WriteLog("Skip optional monitor identity query on AMD/Intel path.", "debug"); + } } if (IsConnect == false) { frmISP.WriteLog("IsConnect = false", "debug"); btnAuto.Enabled = false; - //ClearConnectedMonitorInfo(); - SetStatusMsg("Current F/W version is not compatible with this tool."); + ClearConnectedMonitorInfo(); + SetStatusMsg("Current F/W version is not compatible with this tool.", true); } _chipType = chipType; switch (chipType) @@ -611,7 +743,16 @@ namespace WinISP case 2: { frmISP.WriteLog("MTKChipType=MST9U", "debug"); } break; } Application.DoEvents(); - DDC_GetVersion(); + if ((((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.AMD)) + { + DDC_GetVersion(); + } + else + { + frmISP.WriteLog("Skip optional firmware version query on AMD/Intel path.", "debug"); + } DDC_SetToolFlag(false); int pktDelayTime = 0; @@ -660,16 +801,15 @@ namespace WinISP { //INTEL DP if (_chipType == 2) - if (_chipType == 2) - { - //MST9U - pktDelayTime = 0; - } - else - { - //TSUMxxG - pktDelayTime = 0; - } + { + //MST9U + pktDelayTime = 0; + } + else + { + //TSUMxxG + pktDelayTime = 0; + } } frmISP.WriteLog("GRAPHIC_CARD.INTEL/INTEL_IGCL", "debug"); } @@ -677,8 +817,24 @@ namespace WinISP } _pktDelayTimeText = pktDelayTime.ToString(); } + else + { + // GPU DDC init failed – driver not installed, GPU not supported, or monitor not connected. + frmISP.WriteLog("simI2cCtrl.Init() = false: GPU DDC init failed. Check GPU driver and monitor connection.", "debug"); + btnAuto.Enabled = false; + SetStatusMsg("GPU DDC init failed. Check driver and monitor cable."); + return; + } - SetStatusMsg("Ready"); + if (IsConnect) + { + if (String.IsNullOrEmpty(_binFilePath)) + SetStatusMsg("Please select a F/W file."); + else + SetStatusMsg("BIN loaded. Ready to upgrade."); + } + else + SetStatusMsg("Ready"); } private Byte _ver0 = 0; @@ -713,8 +869,24 @@ namespace WinISP flag = recv[2]; return flag; } + private bool IsAmdOrIntelPath() + { + var gpuType = ((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType; + return gpuType == GraphicCardI2CCtrl.GRAPHIC_CARD.AMD + || gpuType == GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL + || gpuType == GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL; + } + private void DDC_SetToolFlag(bool en) { + // AMD and Intel DDC paths do not support the tool-flag handshake command. + // Sending it causes repeated DDC timeout errors, so skip entirely. + if (IsAmdOrIntelPath()) + { + frmISP.WriteLog("DDC_SetToolFlag skipped on AMD/Intel path.", "debug"); + return; + } + Byte[] buf = { 0xCC, 0x90, 0x00 }; if (en) buf[2] = 0x01; @@ -723,7 +895,7 @@ namespace WinISP WinIOLib.DelayMs(10); int RetryCnt = 0; - while (RetryCnt <= 3) + while (RetryCnt <= 6) { if (Convert.ToBoolean(DDC2CI_GetToolFlag()) == en) { @@ -738,7 +910,9 @@ namespace WinISP MTKDebugCmd.DDC_Write(buf); } if (RetryCnt > 0) + { frmISP.WriteLog("DDC_SetToolFlag fail.", "debug"); + } } public static byte DDC2CI_GetR2Reset51Flag() { @@ -1163,7 +1337,8 @@ namespace WinISP frmISP.WriteLog("Exception: " + e.Message, "debug"); ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(); defaultPktLen = 10; - AdjustPacketParam(defaultPktLen, ref maxPktLen, 10000, ref pktDelayTime, true); + int fallbackDelayHint = Math.Max(Convert.ToInt32(_pktDelayTimeText) * 3, 300); + AdjustPacketParam(defaultPktLen, ref maxPktLen, fallbackDelayHint, ref pktDelayTime, true); } } @@ -1208,6 +1383,7 @@ namespace WinISP } } break; + case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL: case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL: if (_IsHDMIConnect) { @@ -1306,19 +1482,41 @@ namespace WinISP sentLen += pktLen; } return si.CheckSum(); - } + } private bool IsFieldMatch(string binValue, string fwValue) { return string.Equals((binValue ?? string.Empty).Trim(), (fwValue ?? string.Empty).Trim(), StringComparison.Ordinal); } + private string NormalizeFwVersionForCompare(string value) + { + // Compare the first 4 characters of the version string (e.g. "FW.0") as a + // product-family identifier. This ensures that a BIN labelled "FG.034" is + // rejected on a monitor running "FW.034" (different prefix = different family), + // while allowing version-number upgrades within the same family + // (e.g. "FW.033" monitor can be flashed with "FW.034" BIN). + string normalized = (value ?? string.Empty).Trim().ToUpperInvariant(); + if (string.IsNullOrEmpty(normalized)) + return string.Empty; + + return normalized.Length >= 4 ? normalized.Substring(0, 4) : normalized; + } + private bool ValidateMonitorVsBin(out string errMsg) { errMsg = String.Empty; if (string.IsNullOrWhiteSpace(_fwModelName)) { - TryReadMonitorIdentity(10, 100); + // On AMD/Intel the DDC identity commands are not supported; skip the + // retry loop to avoid flooding the log with timeout errors. The + // legacy-fallback logic below will supply hardcoded identifiers instead. + if (!IsAmdOrIntelPath()) + TryReadMonitorIdentity(10, 100); + } + else + { + _fwModelName = NormalizeMonitorModelName(_fwModelName); } // ----------------------------------------------------------------------- @@ -1332,7 +1530,7 @@ namespace WinISP // name in early firmware versions, so use the same hardcoded identifiers. // ----------------------------------------------------------------------- const string LegacyModel = "MAG 321UPD E14"; - const string LegacyChip = "MST9U"; + const string LegacyChip = "MST9U"; const string LegacyPanel = "Panel_SG315GD01_2_eDP"; const string LegacyFWVer = "FW.033"; // from MAG 321UPD E14_V8-MM802MS-G01V033_20260429_8ECF.bin const string PlaceholderModelName = "MST9U6_PanelCM"; @@ -1343,19 +1541,18 @@ namespace WinISP (_fwModelTrim.Length >= 8 && PlaceholderModelName.StartsWith(_fwModelTrim, StringComparison.OrdinalIgnoreCase)) || string.Equals(_fwModelTrim, PlaceholderModelName, StringComparison.OrdinalIgnoreCase); if (fwModelIsPlaceholder) - { - WriteLog("Monitor firmware返回占位符model名 '" + _fwModelName + "',legacy出货批次,跳过身份校验直接允许更新", "debug"); - return true; - } + frmISP.WriteLog("Monitor firmware返回占位符model名 '" + _fwModelName + "',使用LegacyFallback进行四项校验", "debug"); - bool usingLegacyFallback = string.IsNullOrWhiteSpace(_fwModelName); + bool usingLegacyFallback = string.IsNullOrWhiteSpace(_fwModelName) || fwModelIsPlaceholder; string effModel = usingLegacyFallback ? LegacyModel : _fwModelName; - string effChip = !string.IsNullOrWhiteSpace(_fwChipName) ? _fwChipName - : (usingLegacyFallback ? LegacyChip : string.Empty); + string effChip = !string.IsNullOrWhiteSpace(_fwChipName) ? _fwChipName + : (usingLegacyFallback ? LegacyChip : string.Empty); string effPanel = !string.IsNullOrWhiteSpace(_fwPanelName) ? _fwPanelName : (usingLegacyFallback ? LegacyPanel : string.Empty); - string effVer = !string.IsNullOrWhiteSpace(_fwVersionFromDDC) ? _fwVersionFromDDC + // effVer: prefer actual DDC read; fall back to LegacyFWVer when in legacy-fallback mode + // (covers AMD/Intel path where DDC identity commands are not supported). + string effVer = !string.IsNullOrWhiteSpace(_fwVersionFromDDC) ? _fwVersionFromDDC : (usingLegacyFallback ? LegacyFWVer : string.Empty); if (string.IsNullOrWhiteSpace(_u8ModelName)) @@ -1368,39 +1565,79 @@ namespace WinISP if (!IsFieldMatch(_u8ModelName, effModel)) { - errMsg = "Model不匹配: " + src + "=" + effModel + " BIN=" + _u8ModelName; - return false; + // Fallback: accept fw model as prefix of bin model name. + // NVIDIA DP AUX can truncate DDC reads, so the fw name may be a prefix of the full name. + string fwTrim = (effModel ?? string.Empty).Trim(); + string binTrim = (_u8ModelName ?? string.Empty).Trim(); + if (fwTrim.Length < 6 || !binTrim.StartsWith(fwTrim, StringComparison.Ordinal)) + { + errMsg = "Model not match."; + return false; + } } - // Only validate chip/panel when both sides have the value. if (!string.IsNullOrWhiteSpace(effChip) && !string.IsNullOrWhiteSpace(_u8ChipName) && !IsFieldMatch(_u8ChipName, effChip)) { - errMsg = "Chip不匹配: " + src + "=" + effChip + " BIN=" + _u8ChipName; - return false; + // Prefix-match fallback: BIN chip "MST9U6" should pass against legacy effChip "MST9U". + string fwChipTrim = (effChip ?? string.Empty).Trim(); + string binChipTrim = (_u8ChipName ?? string.Empty).Trim(); + if (!binChipTrim.StartsWith(fwChipTrim, StringComparison.OrdinalIgnoreCase)) + { + errMsg = "Chip not match."; + return false; + } + frmISP.WriteLog("ValidateMonitorVsBin: Chip prefix-match accepted: FW=" + effChip + " BIN=" + _u8ChipName, "debug"); } - - if (!string.IsNullOrWhiteSpace(effPanel) && !string.IsNullOrWhiteSpace(_u8PanelName) - && !IsFieldMatch(_u8PanelName, effPanel)) - { - errMsg = "Panel不匹配: " + src + "=" + effPanel + " BIN=" + _u8PanelName; - return false; + if (!string.IsNullOrWhiteSpace(effPanel)) + { + if (string.IsNullOrWhiteSpace(_u8PanelName)) + { + // BIN has no panel info but monitor expects a specific panel – block upgrade. + errMsg = "Panel not match. (BIN has no panel info)"; + return false; + } + if (!IsFieldMatch(_u8PanelName, effPanel)) + { + // Same prefix-match fallback as Model: DDC truncation may deliver only a prefix. + string fwPanelTrim = (effPanel ?? string.Empty).Trim(); + string binPanelTrim = (_u8PanelName ?? string.Empty).Trim(); + if (fwPanelTrim.Length < 6 || !binPanelTrim.StartsWith(fwPanelTrim, StringComparison.Ordinal)) + { + errMsg = "Panel not match."; + return false; + } + } } // Board name is NOT stored in the BIN ISP info struct (field 4 is u8FWversion); // board validation is therefore skipped. - // Validate FW version (including legacy fallback which uses the hardcoded LegacyFWVer). - // Only the first 4 characters of the version string need to match; - // the last part (build number) changes between releases but is still upgradeable. - if (!string.IsNullOrWhiteSpace(effVer) && !string.IsNullOrWhiteSpace(_u8FWVersion)) + // Validate FW version prefix (first 4 chars, e.g. "FW.0"). + // FW.033 vs FW.034 => same prefix => allowed. + // FG.034 vs FW.034 => different prefix => rejected. + frmISP.WriteLog("ValidateMonitorVsBin: monVer(DDC)=" + (string.IsNullOrWhiteSpace(effVer) ? "(empty)" : effVer) + + " binVer=" + (string.IsNullOrWhiteSpace(_u8FWVersion) ? "(empty)" : _u8FWVersion), "debug"); + if (!string.IsNullOrWhiteSpace(_u8FWVersion)) { - string verPrefix4Mon = effVer.Length >= 4 ? effVer.Substring(0, 4) : effVer; - string verPrefix4Bin = _u8FWVersion.Length >= 4 ? _u8FWVersion.Substring(0, 4) : _u8FWVersion; - if (!string.Equals(verPrefix4Mon, verPrefix4Bin, StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrWhiteSpace(effVer)) { - errMsg = "FWVersion前4位不匹配: FW=" + effVer + " BIN=" + _u8FWVersion; + // BIN has a version but monitor version is unreadable – treat as mismatch. + frmISP.WriteLog("ValidateMonitorVsBin: effVer is empty, cannot verify FW version.", "debug"); + errMsg = "FWVersion not match" ; return false; } + string normalizedMonVer = NormalizeFwVersionForCompare(effVer); + string normalizedBinVer = NormalizeFwVersionForCompare(_u8FWVersion); + frmISP.WriteLog("ValidateMonitorVsBin: normalizedMonVer=" + normalizedMonVer + " normalizedBinVer=" + normalizedBinVer, "debug"); + if (!string.Equals(normalizedMonVer, normalizedBinVer, StringComparison.OrdinalIgnoreCase)) + { + errMsg = "FWVersion not match"; + return false; + } + } + else + { + frmISP.WriteLog("ValidateMonitorVsBin: FW version check skipped (_u8FWVersion is empty).", "debug"); } return true; @@ -1450,13 +1687,13 @@ namespace WinISP } } - // QueryConnectedMonitorInfo(); - string checkErr; - if (!ValidateMonitorVsBin(out checkErr)) - { - SetStatusMsg(checkErr,true); - return; - } + // QueryConnectedMonitorInfo(); + string checkErr; + if (!ValidateMonitorVsBin(out checkErr)) + { + SetStatusMsg(checkErr, true); + return; + } prbProgress.Maximum = flashSectorInfo.Count; prbProgress.Value = 0; int imgNum = 0; @@ -1503,43 +1740,10 @@ namespace WinISP case 1: { frmISP.WriteLog("MTKChipType=TSUM", "debug"); } break; case 2: { frmISP.WriteLog("MTKChipType=MST9U", "debug"); } break; } - //if (!IsModelNameMatch(_u8ModelName)) - //{ - // SetStatusMsg(Properties.Resources.ModelNameErr); - // SetISPStatus(false, Properties.Resources.ModelNameErr); - // return; - //} - //if (!IsChipNameMatch(_u8ChipName)) - //{ - // SetStatusMsg(Properties.Resources.ChipNameErr); - // SetISPStatus(false, Properties.Resources.ChipNameErr); - // return; - //} - //if (!IsPanelNameMatch(_u8PanelName)) - //{ - // SetStatusMsg(Properties.Resources.PanelNameErr); - // SetISPStatus(false, Properties.Resources.PanelNameErr); - // return; - //} - //if (!IsBoardNameMatch(_u8BoardName)) - //{ - // SetStatusMsg(Properties.Resources.BoardNameErr); - // SetISPStatus(false, Properties.Resources.BoardNameErr); - // return; - //} - TryReadMonitorIdentity(10, 120); - string ddcModelInIsp = _fwModelName; - string ddcChipInIsp = _fwChipName; - string ddcPanelInIsp = _fwPanelName; - string ddcBoardInIsp = _fwBoardName; - - WriteLog("[ISP Check] FW Model: " + ddcModelInIsp + " Chip: " + ddcChipInIsp + " Panel: " + ddcPanelInIsp + " Board: " + ddcBoardInIsp, "debug"); - WriteLog("[ISP Check] BIN Model: " + _u8ModelName + " Chip: " + _u8ChipName + " Panel: " + _u8PanelName + " FWVer: " + _u8FWVersion, "debug"); - string verifyErr; if (!ValidateMonitorVsBin(out verifyErr)) { - SetStatusMsg(verifyErr); + SetStatusMsg(verifyErr, true); SetISPStatus(false); return; } @@ -1633,7 +1837,8 @@ namespace WinISP // SetStatusMsg("Transfer Parameter adjusting ..."); int maxPktLen = 0, pktDelayTime = 0; - AdjustPacketParam(defaultPktLen, ref maxPktLen, 10000, ref pktDelayTime); + int maxDelayHint = Math.Max(Convert.ToInt32(_pktDelayTimeText) * 3, 300); + AdjustPacketParam(defaultPktLen, ref maxPktLen, maxDelayHint, ref pktDelayTime); frmISP.WriteLog("maxPktLen = " + Convert.ToString(maxPktLen) + ", pktDelayTime = " + Convert.ToString(pktDelayTime) + "", "debug"); #if DEBUG if (Convert.ToInt32(_pktDelayTimeText) > 0) @@ -1785,9 +1990,7 @@ namespace WinISP //return; } - // SetStatusMsg("Sent Bytes : " + sentLen.ToString() + ", " + "Elapsed Time : " + end.ToString() + " ms"); - // _u8ModelName = "mmmmmmmmmmmmm"; - // SetStatusMsg("Sent Bytes : " + sentLen.ToString() + ", " + "Elapsed Time : " + end.ToString() + " ms. Model: " + _u8ModelName); + SetStatusMsg("Updating firmware..., " + "Elapsed Time : " + (end / 1000).ToString() + " s"); Application.DoEvents(); } @@ -1842,7 +2045,7 @@ namespace WinISP { WinIOLib.DelayMs(1000); - SetStatusMsg("Updating firmware..., " + "Elapsed Time : " + end.ToString() + " ms"); + SetStatusMsg("Updating firmware..., " + "Elapsed Time : " + (end / 1000).ToString() + " s"); Application.DoEvents(); //int pktDelayTime = Convert.ToInt32(txtPktDelayTime.Text); IsConnect = DDC_CheckMTKDevice(ref chipType/*, pktDelayTime*/); @@ -1858,20 +2061,21 @@ namespace WinISP end = GetTickCount() - start; if (status == 2) { - Connect(); - SetStatusMsg("Update firmware success, " + "Elapsed Time : " + end.ToString() + " ms"); + // Do NOT call Connect() here: the monitor firmware is rebooting and DDC is + // not ready yet, which would cause a spurious "not compatible" error message. + SetStatusMsg("Update firmware success. Please reset the power of display."); //MessageBox.Show(this, "Update firmware success. Please reset the power of display.", this.Text); } else { - SetStatusMsg("Update firmware fail, " + "Elapsed Time : " + end.ToString() + " ms", true); + SetStatusMsg("Update firmware fail, " + "Elapsed Time : " + (end / 1000).ToString() + " s", true); } SetISPStatus(false); if (status == 2) { - MessageBox.Show(this, "Update fimware is success, Display will reboot. .", this.Text); + MessageBox.Show(this, "Update firmware success. Please reset the power of display.", this.Text); DDC_SetISPReboot(); } } @@ -1892,22 +2096,23 @@ namespace WinISP } private static string resultFolder = System.IO.Directory.GetCurrentDirectory() + "\\"; - + private static System.IO.StreamWriter _logWriter = null; + private static string _logPath = null; + [Conditional("DEBUG")] public static void WriteLog(string str, string fileName) { - System.IO.StreamWriter file = null; - if (!System.IO.Directory.Exists(resultFolder)) System.IO.Directory.CreateDirectory(resultFolder); - if (fileName == "") - file = new System.IO.StreamWriter(resultFolder + DateTime.Now.ToString("yyyy-MM-dd") + ".log", true); - else - file = new System.IO.StreamWriter(resultFolder + fileName + "_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", true); - - file.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str); - file.Close(); - file = null; + string path = resultFolder + (fileName == "" ? "" : fileName + "_") + DateTime.Now.ToString("yyyy-MM-dd") + ".log"; + if (_logWriter == null || _logPath != path) + { + if (_logWriter != null) { _logWriter.Flush(); _logWriter.Close(); } + _logPath = path; + _logWriter = new System.IO.StreamWriter(path, append: true); + } + _logWriter.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str); + _logWriter.Flush(); } public static Byte[] InitBinaryFile(String filepath) @@ -1966,7 +2171,7 @@ namespace WinISP using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { if (offset > fs.Length - 1) - throw new ArgumentOutOfRangeException(nameof(offset), "Offset is beyond file length."); + throw new ArgumentOutOfRangeException("offset", "Offset is beyond file length."); fs.Seek(offset, SeekOrigin.Begin); int bytesRead = fs.Read(buffer, 0, length); @@ -1978,21 +2183,5 @@ namespace WinISP } return buffer; } - - private bool DDC_GetModelName(ref string modelName) - { - byte[] array = MTKDebugCmd.DDC_Read(new byte[] - { - 204, - 54 - }, 50, 1000); - if (array == null || array.Length == 0) - { - modelName = "N.A"; - return false; - } - modelName = Encoding.Default.GetString(array, 2, (int)(array[1] & 127)).Trim(); - return true; - } } } diff --git a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/WinISP.csproj b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/WinISP.csproj index 5d44d1b..58d1b93 100644 --- a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/WinISP.csproj +++ b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/WinISP.csproj @@ -41,7 +41,7 @@ true - x86 + x64 pdbonly true bin\Release\ @@ -179,11 +179,12 @@ - \ No newline at end of file diff --git a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/frmISP.cs b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/frmISP.cs index de2e79b..f611b73 100644 --- a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/frmISP.cs +++ b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/frmISP.cs @@ -61,6 +61,8 @@ namespace WinISP private const int MonitorChipNameLength = 20; private const int MonitorPanelNameLength = 30; private const int MonitorBoardNameLength = 20; + private const string PlaceholderMonitorModelName = "MST9U6_PanelCMIM236HGJ_L21"; + private const string LegacyMonitorModelName = "MAG 321UPD E14"; object _lockObj = new object(); int _numberOfMonitors; int _lastNumOfMonitors = 0; @@ -261,9 +263,23 @@ namespace WinISP return String.IsNullOrWhiteSpace(value) ? String.Empty : value.Trim(); } + private string NormalizeMonitorModelName(string value) + { + string normalizedValue = NormalizeMonitorInfo(value); + if (string.Equals(normalizedValue, PlaceholderMonitorModelName, StringComparison.OrdinalIgnoreCase)) + return LegacyMonitorModelName; + + return normalizedValue; + } + + private string GetModelMismatchMessage(string binModelName) + { + return "Model不匹配: FW=" + NormalizeMonitorModelName(_monitorModelName) + " BIN=" + NormalizeMonitorInfo(binModelName); + } + private bool IsModelNameMatch(string u8Model_Name) { - string monitorValue = NormalizeMonitorInfo(_monitorModelName); + string monitorValue = NormalizeMonitorModelName(_monitorModelName); if (String.IsNullOrEmpty(monitorValue)) return true; @@ -329,7 +345,8 @@ namespace WinISP _u8ChipName = Encoding.ASCII.GetString(infoBytes, modenameLen, chipnameLen).TrimEnd('\0'); _u8PanelName = Encoding.ASCII.GetString(infoBytes, modenameLen + chipnameLen, panelnameLen).TrimEnd('\0'); _u8BoardName = Encoding.ASCII.GetString(infoBytes, modenameLen + chipnameLen + panelnameLen, boardnameLen).TrimEnd('\0'); - SetStatusMsg("Read Bin OK. Model: " + _u8ModelName + ", Chip: " + _u8ChipName + ", Panel: " + _u8PanelName + ", Board: " + _u8BoardName); + // SetStatusMsg("Read Bin OK. Model: " + _u8ModelName + ", Chip: " + _u8ChipName + ", Panel: " + _u8PanelName + ", Board: " + _u8BoardName); + SetStatusMsg("Please update the firmware.",true); } catch (Exception ex) { @@ -342,6 +359,45 @@ namespace WinISP if (flashSectorInfo != null && flashSectorInfo.Count > 0) flashSectorInfo.Clear(); btnConnect.PerformClick(); + + if (IsConnect) + { + string verifyMsg = String.Empty; + bool canVerify = false; + var gpuType = ((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType; + + if (gpuType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL && gpuType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL) + { + ClearConnectedMonitorInfo(); + QueryConnectedMonitorInfo(); + canVerify = !string.IsNullOrWhiteSpace(_monitorModelName) + || !string.IsNullOrWhiteSpace(_monitorChipName) + || !string.IsNullOrWhiteSpace(_monitorPanelName); + } + + if (!canVerify) + { + verifyMsg = "BIN已加载,但当前显卡路径无法立即读取显示器身份信息,暂时不能立即判断是否一致。"; + } + else if (!IsModelNameMatch(_u8ModelName)) + { + verifyMsg = GetModelMismatchMessage(_u8ModelName); + } + else if (!IsChipNameMatch(_u8ChipName)) + { + verifyMsg = Properties.Resources.ChipNameErr; + } + else if (!IsPanelNameMatch(_u8PanelName)) + { + verifyMsg = Properties.Resources.PanelNameErr; + } + else + { + verifyMsg = "BIN与当前显示器匹配,可开始升级。"; + } + + SetStatusMsg(verifyMsg, true); + } } } @@ -350,60 +406,86 @@ namespace WinISP WinIOLib._dftI2CDlyTime = Convert.ToInt16(txtDelayUnit.Text); } - //private void QueryConnectedMonitorInfo() - //{ - // // 读取显示器端信息(芯片名、面板名、板卡名、型号名) - // try - // { - // // 型号名 - // { - // Byte[] cmd = { MStarCommand, CmdGetModelName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorModelNameLength + 2) - // _monitorModelName = Encoding.ASCII.GetString(recv, 2, MonitorModelNameLength).TrimEnd('\0'); - // else - // _monitorModelName = string.Empty; - // } + private void QueryConnectedMonitorInfo() + { + // 读取显示器端信息(芯片名、面板名、板卡名、型号名) + try + { + bool legacyRemapped = false; - // // 芯片名 - // { - // Byte[] cmd = { MStarCommand, CmdGetChipName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorChipNameLength + 2) - // _monitorChipName = Encoding.ASCII.GetString(recv, 2, MonitorChipNameLength).TrimEnd('\0'); - // else - // _monitorChipName = string.Empty; - // } - // // 面板名 - // { - // Byte[] cmd = { MStarCommand, CmdGetPanelName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorPanelNameLength + 2) - // _monitorPanelName = Encoding.ASCII.GetString(recv, 2, MonitorPanelNameLength).TrimEnd('\0'); - // else - // _monitorPanelName = string.Empty; - // } - // // 板卡名 - // { - // Byte[] cmd = { MStarCommand, CmdGetBoardName }; - // Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 500); - // if (recv != null && recv.Length >= MonitorBoardNameLength + 2) - // _monitorBoardName = Encoding.ASCII.GetString(recv, 2, MonitorBoardNameLength).TrimEnd('\0'); - // else - // _monitorBoardName = string.Empty; - // } + // 型号名 + { + Byte[] cmd = { MStarCommand, CmdGetModelName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorModelNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorModelNameLength + 2) + { + string rawModelName = Encoding.ASCII.GetString(recv, 2, MonitorModelNameLength).TrimEnd('\0'); + if (string.Equals(rawModelName.Trim(), PlaceholderMonitorModelName, StringComparison.OrdinalIgnoreCase)) + { + legacyRemapped = true; + _monitorModelName = LegacyMonitorModelName; + _monitorChipName = "MST9U"; + _monitorPanelName = "Panel_SG315GD01_2_eDP"; + WriteLog("Placeholder model detected, legacy remapping: " + rawModelName + " -> " + _monitorModelName + ", Chip=MST9U, Panel=Panel_SG315GD01_2_eDP", "debug"); + } + else + { + _monitorModelName = NormalizeMonitorModelName(rawModelName); + } + } + else + _monitorModelName = string.Empty; + } - // // 日志打印 - // WriteLog($"MonitorModelName={_monitorModelName}", "debug"); - // WriteLog($"MonitorChipName={_monitorChipName}", "debug"); - // WriteLog($"MonitorPanelName={_monitorPanelName}", "debug"); - // WriteLog($"MonitorBoardName={_monitorBoardName}", "debug"); - // } - // catch (Exception ex) - // { - // WriteLog("QueryConnectedMonitorInfo Exception: " + ex.Message, "debug"); - // } - //} + // 芯片名 + if (!legacyRemapped) + { + Byte[] cmd = { MStarCommand, CmdGetChipName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorChipNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorChipNameLength + 2) + _monitorChipName = Encoding.ASCII.GetString(recv, 2, MonitorChipNameLength).TrimEnd('\0'); + else + _monitorChipName = string.Empty; + } + // 面板名 + if (!legacyRemapped) + { + Byte[] cmd = { MStarCommand, CmdGetPanelName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorPanelNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorPanelNameLength + 2) + _monitorPanelName = Encoding.ASCII.GetString(recv, 2, MonitorPanelNameLength).TrimEnd('\0'); + else + _monitorPanelName = string.Empty; + } + // 板卡名 + { + Byte[] cmd = { MStarCommand, CmdGetBoardName }; + Byte[] recv = MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 500) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 2000) + ?? MTKDebugCmd.DDC_Read(cmd, MonitorBoardNameLength + 2, 5000); + if (recv != null && recv.Length >= MonitorBoardNameLength + 2) + _monitorBoardName = Encoding.ASCII.GetString(recv, 2, MonitorBoardNameLength).TrimEnd('\0'); + else + _monitorBoardName = string.Empty; + } + + // 日志打印 + WriteLog("MonitorModelName=" + _monitorModelName, "debug"); + WriteLog("MonitorChipName=" + _monitorChipName, "debug"); + WriteLog("MonitorPanelName=" + _monitorPanelName, "debug"); + WriteLog("MonitorBoardName=" + _monitorBoardName, "debug"); + } + catch (Exception ex) + { + WriteLog("QueryConnectedMonitorInfo Exception: " + ex.Message, "debug"); + } + } private void ClearConnectedMonitorInfo() { @@ -447,10 +529,9 @@ namespace WinISP MTKDebugCmd.InitI2CCtrl(_simI2cCtrl); DDC_SetToolFlag(true); WinIOLib.DelayMs(10); - // DDC2CI_SetR2Reset51Flag(0x01); + // DDC2CI_SetR2Reset51Flag(0x01); Byte chipType = 0; IsConnect = false; - int retry = 0; MTKDebugCmd.DDC_Write(buf); //if (IsConnect) { @@ -458,11 +539,58 @@ namespace WinISP btnRunDPISP.Enabled = true; pnlConnState.BackColor = Color.LightGreen; lblDisplayName.Text = ((GraphicCardI2CCtrl)_simI2cCtrl).GetMonitorName; - SetStatusMsg("Please select a F/W file."); + if (String.IsNullOrEmpty(_binFilePath)) + SetStatusMsg("Please select a F/W file."); + else + SetStatusMsg("BIN loaded. Ready to upgrade."); cboConnectedMonitor.Items.Clear(); String nameFromGPU = ""; List list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + WriteLog("InitConnectedMonitor count = " + list.Count, "debug"); + + if (list.Count == 0 && ((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType == GraphicCardI2CCtrl.GRAPHIC_CARD.AMD) + { + WriteLog("InitConnectedMonitor = 0 on AMD auto-detect, trying forced NVIDIA controller ...", "debug"); + ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(GraphicCardI2CCtrl.GPUTypes.NVIDIA); + WinIOLib.DelayMs(300); + if (_simI2cCtrl.Init()) + { + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + WriteLog("InitConnectedMonitor after forced NVIDIA count = " + list.Count, "debug"); + } + + if (list.Count == 0) + { + WriteLog("Forced NVIDIA controller did not find monitors, restoring auto-detect controller ...", "debug"); + ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(); + WinIOLib.DelayMs(300); + if (_simI2cCtrl.Init()) + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + } + } + + // NVIDIA DP AUX channel may not be ready on first launch – retry with delay. + { + int mntRetry = 0; + while (list.Count == 0 && mntRetry++ < 3) + { + WriteLog("InitConnectedMonitor = 0, waiting 1500ms before retry " + mntRetry + " ...", "debug"); + WinIOLib.DelayMs(1500); + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + WriteLog("InitConnectedMonitor retry " + mntRetry + " count = " + list.Count, "debug"); + } + // If all retries exhausted and still no monitor, recreate the GPU control and try once more. + if (list.Count == 0) + { + WriteLog("InitConnectedMonitor still 0 – calling ReCreateGraphicCardCtrl ...", "debug"); + ((GraphicCardI2CCtrl)_simI2cCtrl).ReCreateGraphicCardCtrl(); + WinIOLib.DelayMs(1500); + list = ((GraphicCardI2CCtrl)_simI2cCtrl).InitConnectedMonitor; + WriteLog("InitConnectedMonitor after ReCreate count = " + list.Count, "debug"); + } + } + lblDisplayNumber.Text = list.Count.ToString(); if (list.Count > 0) { @@ -474,8 +602,9 @@ namespace WinISP for (int idxDisp = 0; idxDisp < list.Count; idxDisp++) { + int retry = 0; // Reset retry counter for each monitor index nameFromGPU = list[idxDisp].ToUpper(); - WriteLog("nameFromGPU = " + nameFromGPU, "debug"); + WriteLog("nameFromGPU[" + idxDisp + "] = " + nameFromGPU, "debug"); cboConnectedMonitor.SelectedIndex = idxDisp; ((GraphicCardI2CCtrl)_simI2cCtrl).SetConnectedMonitorIndex((Byte)idxDisp); @@ -483,6 +612,7 @@ namespace WinISP { IsConnect = DDC_CheckMTKDevice(ref chipType); } + WriteLog("idxDisp=" + idxDisp + " IsConnect=" + IsConnect + " chipType=" + chipType, "debug"); if (IsConnect == true) { pnlConnState.BackColor = Color.LightGreen; @@ -490,8 +620,19 @@ namespace WinISP break; } } - // 自动读取显示器信息 - //QueryConnectedMonitorInfo(); + // Intel IGCL and AMD can complete the FE handshake but still time out on optional + // identity queries during connect. Skip those reads here so connect stays usable. + if ((((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.AMD)) + { + QueryConnectedMonitorInfo(); + } + else + { + ClearConnectedMonitorInfo(); + WriteLog("Skip optional monitor identity query on AMD/Intel path.", "debug"); + } cboConnectedMonitor.SelectedIndexChanged += cboConnectedMonitor_SelectedIndexChanged; cboConnectedMonitor.Enabled = true; } @@ -583,7 +724,15 @@ namespace WinISP else pnlConnState.BackColor = Color.Red; - SetStatusMsg("Ready"); + if (IsConnect) + { + if (String.IsNullOrEmpty(_binFilePath)) + SetStatusMsg("Please select a F/W file."); + else + SetStatusMsg("BIN loaded. Ready to upgrade."); + } + else + SetStatusMsg("Ready"); } private void btnConnect_Click(object sender, EventArgs e) @@ -623,8 +772,24 @@ namespace WinISP flag = recv[2]; return flag; } + private bool IsAmdOrIntelPath() + { + var gpuType = ((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType; + return gpuType == GraphicCardI2CCtrl.GRAPHIC_CARD.AMD + || gpuType == GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL + || gpuType == GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL; + } + private void DDC_SetToolFlag(bool en) { + // AMD and Intel DDC paths do not support the tool-flag handshake command. + // Sending it causes repeated DDC timeout errors, so skip entirely. + if (IsAmdOrIntelPath()) + { + frmISP.WriteLog("DDC_SetToolFlag skipped on AMD/Intel path.", "debug"); + return; + } + Byte[] buf = { 0xCC, 0x90, 0x00 }; if (en) buf[2] = 0x01; @@ -633,7 +798,7 @@ namespace WinISP WinIOLib.DelayMs(10); int RetryCnt = 0; - while (RetryCnt <= 3) + while (RetryCnt <= 6) { if (Convert.ToBoolean(DDC2CI_GetToolFlag()) == en) { @@ -648,7 +813,9 @@ namespace WinISP MTKDebugCmd.DDC_Write(buf); } if (RetryCnt > 0) + { WriteLog("DDC_SetToolFlag fail.", "debug"); + } } public static byte DDC2CI_GetR2Reset51Flag() { @@ -1118,6 +1285,7 @@ namespace WinISP } } break; + case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL: case GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL: if (_IsHDMIConnect) { @@ -1263,7 +1431,7 @@ namespace WinISP } } - //QueryConnectedMonitorInfo(); + QueryConnectedMonitorInfo(); toolStripProgressBar1.Maximum = flashSectorInfo.Count; toolStripProgressBar1.Value = 0; @@ -1316,8 +1484,9 @@ namespace WinISP if (!IsModelNameMatch(_u8ModelName)) { - SetStatusMsg(Properties.Resources.ModelNameErr); - SetISPStatus(false, Properties.Resources.ModelNameErr); + string modelErr = GetModelMismatchMessage(_u8ModelName); + SetStatusMsg(modelErr); + SetISPStatus(false, modelErr); return; } if (!IsChipNameMatch(_u8ChipName)) @@ -1688,22 +1857,23 @@ namespace WinISP } private static string resultFolder = System.IO.Directory.GetCurrentDirectory() + "\\"; + private static System.IO.StreamWriter _logWriter = null; + private static string _logPath = null; [Conditional("DEBUG")] public static void WriteLog(string str, string fileName) { - System.IO.StreamWriter file = null; - if (!System.IO.Directory.Exists(resultFolder)) System.IO.Directory.CreateDirectory(resultFolder); - if (fileName == "") - file = new System.IO.StreamWriter(resultFolder + DateTime.Now.ToString("yyyy-MM-dd") + ".log", true); - else - file = new System.IO.StreamWriter(resultFolder + fileName + "_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", true); - - file.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str); - file.Close(); - file = null; + string path = resultFolder + (fileName == "" ? "" : fileName + "_") + DateTime.Now.ToString("yyyy-MM-dd") + ".log"; + if (_logWriter == null || _logPath != path) + { + if (_logWriter != null) { _logWriter.Flush(); _logWriter.Close(); } + _logPath = path; + _logWriter = new System.IO.StreamWriter(path, append: true); + } + _logWriter.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str); + _logWriter.Flush(); } private void cboConnectedMonitor_SelectedIndexChanged(object sender, EventArgs e) @@ -1721,7 +1891,16 @@ namespace WinISP if (IsConnect == true) { pnlConnState.BackColor = Color.LightGreen; - //QueryConnectedMonitorInfo(); + if ((((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL)) + { + QueryConnectedMonitorInfo(); + } + else + { + ClearConnectedMonitorInfo(); + WriteLog("Skip optional monitor identity query on Intel path.", "debug"); + } } else { @@ -1738,7 +1917,15 @@ namespace WinISP case 2: { lblMTKChipType.Text = "MST9U"; } break; } Application.DoEvents(); - DDC_GetVersion(); + if ((((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL) + && (((GraphicCardI2CCtrl)_simI2cCtrl).GetGraphicCardType != GraphicCardI2CCtrl.GRAPHIC_CARD.INTEL_IGCL)) + { + DDC_GetVersion(); + } + else + { + WriteLog("Skip optional firmware version query on Intel path.", "debug"); + } Application.DoEvents(); DDC_SetToolFlag(false); lblConnectedPort.Text = ((GraphicCardI2CCtrl)_simI2cCtrl).GetConnectedPortTypeByIdx((Byte)cboConnectedMonitor.SelectedIndex).ToString(); @@ -1800,7 +1987,7 @@ namespace WinISP using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { if (offset > fs.Length - 1) - throw new ArgumentOutOfRangeException(nameof(offset), "Offset is beyond file length."); + throw new ArgumentOutOfRangeException("offset", "Offset is beyond file length."); fs.Seek(offset, SeekOrigin.Begin); int bytesRead = fs.Read(buffer, 0, length);