Skip to content

Commit 991856f

Browse files
authored
BL602 Config/Info Extraction Helper (#169)
* Add BL602 I/O dump analyzer tab * Fix BL602 tab registration * Remove filename-based BL602 detection hints * Calibrate BL602 I/O confidence from dump evidence * Separate BL602 diagnostics from I/O findings * Add hardware-proven BL602 GPIO analysis * Improve BL602 I/O evidence detection and reporting
1 parent 8d81f51 commit 991856f

4 files changed

Lines changed: 3992 additions & 0 deletions

File tree

BK7231Flasher/BK7231Flasher.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@
125125
<Compile Include="FormMain_TuyaConfigExtractor.cs">
126126
<SubType>Form</SubType>
127127
</Compile>
128+
<Compile Include="FormMain_BL602IoExtractor.cs">
129+
<SubType>Form</SubType>
130+
</Compile>
128131
<Compile Include="FormOBKConfig.cs">
129132
<SubType>Form</SubType>
130133
</Compile>
@@ -169,6 +172,7 @@
169172
<Compile Include="Flashers\RTLFlasher.cs" />
170173
<Compile Include="Flashers\SPIFlasher.cs" />
171174
<Compile Include="Flashers\SPIFlasher_Beken.cs" />
175+
<Compile Include="Utils\BL602IoAnalyzer.cs" />
172176
<Compile Include="Utils\TuyaConfig.cs" />
173177
<Compile Include="Utils\RFPartitionUtil.cs" />
174178
<Compile Include="Helpers\RichTextUtil.cs" />

BK7231Flasher/FormMain.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public FormMain()
6666
{
6767
Singleton = this;
6868
InitializeComponent();
69+
InitializeBl602IoExtractorTab();
6970
var version = Assembly.GetExecutingAssembly().GetCustomAttribute<BuildVersion>().Value;
7071
Text += $" (build {(string.IsNullOrWhiteSpace(version) ? "local" : version)})";
7172
}
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
using System;
2+
using System.Drawing;
3+
using System.IO;
4+
using System.Threading.Tasks;
5+
using System.Windows.Forms;
6+
7+
namespace BK7231Flasher
8+
{
9+
public partial class FormMain : Form, ILogListener
10+
{
11+
private TabPage tabPageBl602Io;
12+
private TextBox textBoxBl602IoOutput;
13+
private Button buttonBl602IoOpen;
14+
private Button buttonBl602IoCopy;
15+
private Button buttonBl602IoSave;
16+
private CheckBox checkBoxBl602IoShowDiagnostics;
17+
private CheckBox checkBoxBl602IoDeepScan;
18+
private Label labelBl602IoStatus;
19+
private BL602IoAnalyzer.AnalysisResult lastBl602IoResult;
20+
private string lastBl602IoPath;
21+
22+
private void InitializeBl602IoExtractorTab()
23+
{
24+
tabPageBl602Io = new TabPage
25+
{
26+
Text = "BL602 I/O",
27+
UseVisualStyleBackColor = true,
28+
AllowDrop = true,
29+
Padding = new Padding(8),
30+
};
31+
tabPageBl602Io.DragEnter += TabPageBl602Io_DragEnter;
32+
tabPageBl602Io.DragDrop += TabPageBl602Io_DragDrop;
33+
34+
FlowLayoutPanel commandBar = new FlowLayoutPanel
35+
{
36+
Dock = DockStyle.Top,
37+
Height = 34,
38+
FlowDirection = FlowDirection.LeftToRight,
39+
WrapContents = false,
40+
Padding = new Padding(0),
41+
};
42+
43+
buttonBl602IoOpen = new Button
44+
{
45+
Text = "Open BL602 dump...",
46+
AutoSize = true,
47+
Height = 26,
48+
};
49+
buttonBl602IoOpen.Click += ButtonBl602IoOpen_Click;
50+
51+
buttonBl602IoCopy = new Button
52+
{
53+
Text = "Copy report",
54+
AutoSize = true,
55+
Height = 26,
56+
Enabled = false,
57+
};
58+
buttonBl602IoCopy.Click += ButtonBl602IoCopy_Click;
59+
60+
buttonBl602IoSave = new Button
61+
{
62+
Text = "Save text...",
63+
AutoSize = true,
64+
Height = 26,
65+
Enabled = false,
66+
};
67+
buttonBl602IoSave.Click += ButtonBl602IoSave_Click;
68+
69+
checkBoxBl602IoShowDiagnostics = new CheckBox
70+
{
71+
Text = "Show diagnostics (not I/O assignments)",
72+
AutoSize = true,
73+
Checked = false,
74+
Padding = new Padding(8, 5, 0, 0),
75+
};
76+
checkBoxBl602IoShowDiagnostics.CheckedChanged += CheckBoxBl602IoShowDiagnostics_CheckedChanged;
77+
78+
checkBoxBl602IoDeepScan = new CheckBox
79+
{
80+
Text = "Deep fallback scan (headerless dumps)",
81+
AutoSize = true,
82+
Checked = false,
83+
Padding = new Padding(8, 5, 0, 0),
84+
};
85+
86+
commandBar.Controls.Add(buttonBl602IoOpen);
87+
commandBar.Controls.Add(buttonBl602IoCopy);
88+
commandBar.Controls.Add(buttonBl602IoSave);
89+
commandBar.Controls.Add(checkBoxBl602IoShowDiagnostics);
90+
commandBar.Controls.Add(checkBoxBl602IoDeepScan);
91+
92+
labelBl602IoStatus = new Label
93+
{
94+
Dock = DockStyle.Top,
95+
Height = 28,
96+
TextAlign = ContentAlignment.MiddleLeft,
97+
Text = "Drop a BL602 full flash dump here, or open one. I/O evidence and optional non-assignment diagnostics are reported separately.",
98+
AutoEllipsis = true,
99+
};
100+
101+
textBoxBl602IoOutput = new TextBox
102+
{
103+
Dock = DockStyle.Fill,
104+
Multiline = true,
105+
ReadOnly = true,
106+
WordWrap = false,
107+
ScrollBars = ScrollBars.Both,
108+
Font = new Font(FontFamily.GenericMonospace, 9.0f),
109+
AcceptsTab = true,
110+
};
111+
112+
tabPageBl602Io.Controls.Add(textBoxBl602IoOutput);
113+
tabPageBl602Io.Controls.Add(labelBl602IoStatus);
114+
tabPageBl602Io.Controls.Add(commandBar);
115+
int tuyaConfigTabIndex = tabControl1.TabPages.IndexOf(tabPage2);
116+
TabPage[] trailingTabs = new TabPage[tabControl1.TabPages.Count - tuyaConfigTabIndex];
117+
for (int index = 0; index < trailingTabs.Length; index++)
118+
trailingTabs[index] = tabControl1.TabPages[tuyaConfigTabIndex + index];
119+
foreach (TabPage trailingTab in trailingTabs)
120+
tabControl1.TabPages.Remove(trailingTab);
121+
tabControl1.TabPages.Add(tabPageBl602Io);
122+
tabControl1.TabPages.AddRange(trailingTabs);
123+
}
124+
125+
private void TabPageBl602Io_DragEnter(object sender, DragEventArgs e)
126+
{
127+
if (e.Data != null && e.Data.GetDataPresent(DataFormats.FileDrop))
128+
e.Effect = DragDropEffects.Copy;
129+
}
130+
131+
private async void TabPageBl602Io_DragDrop(object sender, DragEventArgs e)
132+
{
133+
if (e.Data == null || !e.Data.GetDataPresent(DataFormats.FileDrop))
134+
return;
135+
string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
136+
if (files == null || files.Length == 0)
137+
return;
138+
await AnalyseBl602IoFileAsync(files[0]);
139+
}
140+
141+
private async void ButtonBl602IoOpen_Click(object sender, EventArgs e)
142+
{
143+
using (OpenFileDialog dialog = new OpenFileDialog())
144+
{
145+
dialog.Title = "Open BL602 full flash dump";
146+
dialog.Filter = "Binary flash dumps (*.bin;*.img;*.dump)|*.bin;*.img;*.dump|All files (*.*)|*.*";
147+
dialog.FilterIndex = 1;
148+
dialog.RestoreDirectory = true;
149+
if (dialog.ShowDialog(this) == DialogResult.OK)
150+
await AnalyseBl602IoFileAsync(dialog.FileName);
151+
}
152+
}
153+
154+
private void ButtonBl602IoCopy_Click(object sender, EventArgs e)
155+
{
156+
if (!string.IsNullOrEmpty(textBoxBl602IoOutput.Text))
157+
Clipboard.SetText(textBoxBl602IoOutput.Text);
158+
}
159+
160+
private void ButtonBl602IoSave_Click(object sender, EventArgs e)
161+
{
162+
if (string.IsNullOrEmpty(textBoxBl602IoOutput.Text))
163+
return;
164+
using (SaveFileDialog dialog = new SaveFileDialog())
165+
{
166+
dialog.Title = "Save BL602 I/O findings";
167+
dialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
168+
dialog.DefaultExt = "txt";
169+
string baseName = string.IsNullOrWhiteSpace(lastBl602IoPath)
170+
? "BL602_IO_findings"
171+
: Path.GetFileNameWithoutExtension(lastBl602IoPath) + "_IO_findings";
172+
dialog.FileName = baseName + ".txt";
173+
dialog.RestoreDirectory = true;
174+
if (dialog.ShowDialog(this) == DialogResult.OK)
175+
File.WriteAllText(dialog.FileName, textBoxBl602IoOutput.Text);
176+
}
177+
}
178+
179+
private void CheckBoxBl602IoShowDiagnostics_CheckedChanged(object sender, EventArgs e)
180+
{
181+
RenderLastBl602IoResult();
182+
}
183+
184+
private async Task AnalyseBl602IoFileAsync(string fileName)
185+
{
186+
if (string.IsNullOrWhiteSpace(fileName))
187+
return;
188+
189+
SetBl602IoBusy(true, "Reading and analysing " + Path.GetFileName(fileName) + "...");
190+
textBoxBl602IoOutput.Clear();
191+
lastBl602IoResult = null;
192+
lastBl602IoPath = fileName;
193+
194+
try
195+
{
196+
bool deepScan = checkBoxBl602IoDeepScan.Checked;
197+
BL602IoAnalyzer.AnalysisResult result = await Task.Run(() =>
198+
{
199+
byte[] data = File.ReadAllBytes(fileName);
200+
BL602IoAnalyzer.AnalysisOptions options = new BL602IoAnalyzer.AnalysisOptions
201+
{
202+
DeepApplicationScan = deepScan,
203+
IncludeGenericPeripheralClues = true,
204+
};
205+
return BL602IoAnalyzer.Analyze(data, Path.GetFileName(fileName), options);
206+
});
207+
208+
lastBl602IoResult = result;
209+
RenderLastBl602IoResult();
210+
labelBl602IoStatus.Text = string.Format(
211+
"Analysed {0}: {1} DTB(s), {2} I/O finding row(s), {3} diagnostic item(s).",
212+
Path.GetFileName(fileName),
213+
result.Dtbs.Count,
214+
result.Findings.Count,
215+
result.Diagnostics.Count);
216+
}
217+
catch (Exception ex)
218+
{
219+
textBoxBl602IoOutput.Text = "BL602 I/O analysis failed:" + Environment.NewLine + ex;
220+
labelBl602IoStatus.Text = "Analysis failed: " + ex.Message;
221+
}
222+
finally
223+
{
224+
SetBl602IoBusy(false, labelBl602IoStatus.Text);
225+
}
226+
}
227+
228+
private void RenderLastBl602IoResult()
229+
{
230+
if (lastBl602IoResult == null)
231+
return;
232+
textBoxBl602IoOutput.Text = lastBl602IoResult.ToPlainText(checkBoxBl602IoShowDiagnostics.Checked);
233+
buttonBl602IoCopy.Enabled = textBoxBl602IoOutput.TextLength != 0;
234+
buttonBl602IoSave.Enabled = textBoxBl602IoOutput.TextLength != 0;
235+
}
236+
237+
private void SetBl602IoBusy(bool busy, string status)
238+
{
239+
buttonBl602IoOpen.Enabled = !busy;
240+
buttonBl602IoCopy.Enabled = !busy && lastBl602IoResult != null;
241+
buttonBl602IoSave.Enabled = !busy && lastBl602IoResult != null;
242+
checkBoxBl602IoShowDiagnostics.Enabled = !busy;
243+
checkBoxBl602IoDeepScan.Enabled = !busy;
244+
labelBl602IoStatus.Text = status ?? string.Empty;
245+
UseWaitCursor = busy;
246+
}
247+
}
248+
}

0 commit comments

Comments
 (0)