Small compatibility improvements, and added scsi2sd-monitor test program
[SCSI2SD-V6.git] / software / scsi2sd-util / scsi2sd-monitor.cc
1 // Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
2 //
3 // This file is part of SCSI2SD.
4 //
5 // SCSI2SD is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // SCSI2SD is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
17
18
19 // For compilers that support precompilation, includes "wx/wx.h".
20 #include <wx/wxprec.h>
21 #ifndef WX_PRECOMP
22 #include <wx/wx.h>
23 #endif
24
25 #include <wx/filedlg.h>
26 #include <wx/filefn.h>
27 #include <wx/filename.h>
28 #include <wx/log.h>
29 #include <wx/notebook.h>
30 #include <wx/progdlg.h>
31 #include <wx/utils.h>
32 #include <wx/windowptr.h>
33 #include <wx/thread.h>
34
35 #include <zipper.hh>
36
37 #include "ConfigUtil.hh"
38 #include "TargetPanel.hh"
39 #include "SCSI2SD_Bootloader.hh"
40 #include "SCSI2SD_HID.hh"
41 #include "Firmware.hh"
42
43 #include <algorithm>
44 #include <iomanip>
45 #include <vector>
46 #include <set>
47 #include <sstream>
48
49 #if __cplusplus >= 201103L
50 #include <cstdint>
51 #include <memory>
52 using std::shared_ptr;
53 #else
54 #include <stdint.h>
55 #include <tr1/memory>
56 using std::tr1::shared_ptr;
57 #endif
58
59 #define MIN_FIRMWARE_VERSION 0x0400
60
61 using namespace SCSI2SD;
62
63 namespace
64 {
65
66 static uint8_t sdCrc7(uint8_t* chr, uint8_t cnt, uint8_t crc)
67 {
68 uint8_t a;
69 for(a = 0; a < cnt; a++)
70 {
71 uint8_t data = chr[a];
72 uint8_t i;
73 for(i = 0; i < 8; i++)
74 {
75 crc <<= 1;
76 if ((data & 0x80) ^ (crc & 0x80))
77 {
78 crc ^= 0x09;
79 }
80 data <<= 1;
81 }
82 }
83 return crc & 0x7F;
84 }
85
86 class TimerLock
87 {
88 public:
89 TimerLock(wxTimer* timer) :
90 myTimer(timer),
91 myInterval(myTimer->GetInterval())
92 {
93 myTimer->Stop();
94 };
95
96 virtual ~TimerLock()
97 {
98 if (myTimer && myInterval > 0)
99 {
100 myTimer->Start(myInterval);
101 }
102 }
103 private:
104 wxTimer* myTimer;
105 int myInterval;
106 };
107
108 class AppFrame : public wxFrame
109 {
110 public:
111 AppFrame() :
112 wxFrame(NULL, wxID_ANY, "scsi2sd-monitor", wxPoint(50, 50), wxSize(250, 150))
113 {
114 wxFlexGridSizer *fgs = new wxFlexGridSizer(3, 2, 9, 25);
115
116 fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SCSI2SD Device:")));
117 myBoardText = new wxStaticText(this, wxID_ANY, wxT(""));
118 fgs->Add(myBoardText);
119 fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SD Test:")));
120 mySDText = new wxStaticText(this, wxID_ANY, wxT(""));
121 fgs->Add(mySDText);
122 fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SCSI Test:")));
123 mySCSIText = new wxStaticText(this, wxID_ANY, wxT(""));
124 fgs->Add(mySCSIText);
125
126 wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
127 hbox->Add(fgs, 1, wxALL | wxEXPAND, 15);
128 this->SetSizer(hbox);
129 Centre();
130
131 //Fit(); // Needed to reduce window size on Windows
132 //FitInside(); // Needed on Linux to prevent status bar overlap
133
134 myTimer = new wxTimer(this, ID_Timer);
135 myTimer->Start(1000);
136 }
137
138 private:
139 wxTimer* myTimer;
140 shared_ptr<HID> myHID;
141 shared_ptr<Bootloader> myBootloader;
142
143 wxStaticText* myBoardText;
144 wxStaticText* mySDText;
145 wxStaticText* mySCSIText;
146
147 enum
148 {
149 ID_ConfigDefaults = wxID_HIGHEST + 1,
150 ID_Timer
151 };
152
153 void evaluate()
154 {
155 if (myHID)
156 {
157 std::stringstream msg;
158 msg << "Ready, " <<
159 myHID->getFirmwareVersionStr();
160 myBoardText->SetLabelText(msg.str());
161
162
163 std::vector<uint8_t> csd(myHID->getSD_CSD());
164 std::vector<uint8_t> cid(myHID->getSD_CID());
165
166 bool sdGood = false;
167 for (size_t i = 0; i < 16; ++i)
168 {
169 if (csd[i] != 0)
170 {
171 sdGood = true;
172 //break;
173 }
174 }
175
176 sdGood = sdGood &&
177 (sdCrc7(&csd[0], 15, 0) == (csd[15] >> 1)) &&
178 (sdCrc7(&cid[0], 15, 0) == (cid[15] >> 1));
179
180 if (sdGood)
181 {
182 mySDText->SetLabelText("OK");
183 }
184 else
185 {
186 mySDText->SetLabelText("FAIL");
187 }
188
189 if (myHID->scsiSelfTest())
190 {
191 mySCSIText->SetLabelText("OK");
192 }
193 else
194 {
195 mySCSIText->SetLabelText("FAIL");
196 }
197 }
198 else
199 {
200 if (myBootloader)
201 {
202 myBoardText->SetLabelText("Bootloader");
203 }
204 else
205 {
206 myBoardText->SetLabelText("Missing");
207 }
208 mySDText->SetLabelText("-");
209 mySCSIText->SetLabelText("-");
210 }
211 }
212
213 void OnID_Timer(wxTimerEvent& event)
214 {
215 // Check if we are connected to the HID device.
216 // AND/or bootloader device.
217 try
218 {
219 if (myBootloader)
220 {
221 // Verify the USB HID connection is valid
222 if (!myBootloader->ping())
223 {
224 myBootloader.reset();
225 }
226 }
227
228 if (!myBootloader)
229 {
230 myBootloader.reset(Bootloader::Open());
231 }
232
233 if (myHID && !myHID->ping())
234 {
235 // Verify the USB HID connection is valid
236 std::cerr << "RESET!" << std::endl;
237 myHID.reset();
238 }
239
240 if (!myHID)
241 {
242 myHID.reset(HID::Open());
243
244 }
245 }
246 catch (std::runtime_error& e)
247 {
248 std::cerr << e.what() << std::endl;
249 }
250
251 evaluate();
252 }
253
254 // Note: Don't confuse this with the wxApp::OnExit virtual method
255 void OnExitEvt(wxCommandEvent& event)
256 {
257 Close(true);
258 }
259
260 wxDECLARE_EVENT_TABLE();
261 };
262
263 wxBEGIN_EVENT_TABLE(AppFrame, wxFrame)
264 EVT_MENU(wxID_EXIT, AppFrame::OnExitEvt)
265
266 EVT_TIMER(AppFrame::ID_Timer, AppFrame::OnID_Timer)
267
268 wxEND_EVENT_TABLE()
269
270
271
272 class App : public wxApp
273 {
274 public:
275 virtual bool OnInit()
276 {
277 AppFrame* frame = new AppFrame();
278 frame->Show(true);
279 SetTopWindow(frame);
280 return true;
281 }
282 };
283 } // namespace
284
285 // Main Method
286 wxIMPLEMENT_APP(App);
287
288