comparison OSTC4Operations.cpp @ 12:ac837fe1d590

Switch implementation for reqex class and added RFCOMM as label for Bluetooth based connection by Linux
author Ideenmodellierer
date Mon, 12 Jan 2026 13:58:41 +0000
parents fc91c3e09285
children e47e0f59101d
comparison
equal deleted inserted replaced
11:6fba58c4964b 12:ac837fe1d590
32 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 // THE POSSIBILITY OF SUCH DAMAGE. 34 // THE POSSIBILITY OF SUCH DAMAGE.
35 // 35 //
36 ////////////////////////////////////////////////////////////////////////////// 36 //////////////////////////////////////////////////////////////////////////////
37 #include "OSTC4Operations.h"
38 #include <QRegularExpression>
37 #include <QSettings> 39 #include <QSettings>
38 #include <QRegularExpression> 40
39 #include "OSTC4Operations.h" 41 #include "Utils/Exception.h"
40
41
42 #include "Utils/Log.h" 42 #include "Utils/Log.h"
43 #include "Utils/Exception.h"
44 #include "Utils/ProgressEvent.h" 43 #include "Utils/ProgressEvent.h"
45 44
46 extern QSettings* settings; 45 extern QSettings *settings;
47 46
48 #define FIRMWARE_BLOCK 0x40 // 64 bytes 47 #define FIRMWARE_BLOCK 0x40 // 64 bytes
49 #define FIRMWARE_BLOCK_DELAY 15 // 15 msec. 48 #define FIRMWARE_BLOCK_DELAY 15 // 15 msec.
50 #define FIRMWARE_BLOCK_FAST 0x300 // 4096 bytes 49 #define FIRMWARE_BLOCK_FAST 0x300 // 4096 bytes
51 50
52 ////////////////////////////////////////////////////////////////////////////// 51 //////////////////////////////////////////////////////////////////////////////
53 52
54 QSize OSTC4Operations::nameSize() const 53 QSize OSTC4Operations::nameSize() const
55 { 54 {
77 features |= BLUETOOTH; 76 features |= BLUETOOTH;
78 features |= VPM_MODEL; 77 features |= VPM_MODEL;
79 features |= SIGNAL_CHECK; 78 features |= SIGNAL_CHECK;
80 features |= ICON; 79 features |= ICON;
81 80
82 return features; 81 return features;
83 } 82 }
84 83
85 QString OSTC4Operations::firmwareTemplate() const 84 QString OSTC4Operations::firmwareTemplate() const
86 { 85 {
87 return "ostc4*.bin"; 86 return "ostc4*.bin";
103 return QRegExp("COM.*", Qt::CaseSensitive); 102 return QRegExp("COM.*", Qt::CaseSensitive);
104 #endif 103 #endif
105 } 104 }
106 #endif 105 #endif
107 106
108
109 QRegularExpression OSTC4Operations::portTemplate() const 107 QRegularExpression OSTC4Operations::portTemplate() const
110 { 108 {
111 #if defined(Q_OS_MAC) 109 #if defined(Q_OS_MAC)
112 return QRegularExpression("tty[.]OSTC4-.*", 110 return QRegularExpression("tty[.]OSTC4-.*", QRegularExpression::CaseInsensitiveOption);
113 QRegularExpression::CaseInsensitiveOption);
114 #elif defined(Q_OS_LINUX) 111 #elif defined(Q_OS_LINUX)
115 // Debian, Ubuntu, RedHat, CentOS, SUSE 112 // Debian, Ubuntu, RedHat, CentOS, SUSE
116 return QRegularExpression("ttyUSB.*"); // default: case-sensitive 113 return QRegularExpression("^(rfcomm.*|ttyUSB.*)$");
117 #elif defined(Q_OS_WIN) 114 #elif defined(Q_OS_WIN)
118 return QRegularExpression("COM.*"); // default: case-sensitive 115 return QRegularExpression("COM.*"); // default: case-sensitive
119 #endif 116 #endif
120 } 117 }
121 ////////////////////////////////////////////////////////////////////////////// 118 //////////////////////////////////////////////////////////////////////////////
122 119
123 void OSTC4Operations::getIdentity() 120 void OSTC4Operations::getIdentity()
124 { 121 {
125 descriptionString.clear(); 122 descriptionString.clear();
126 123
127 LOG_TRACE("Getting model..."); 124 LOG_TRACE("Getting model...");
128 HardwareDescriptor hw = hardwareDescriptor(); 125 HardwareDescriptor hw = hardwareDescriptor();
129 if( hw != HW_OSTC4 ) 126 if (hw != HW_OSTC4)
130 LOG_THROW("Not an OSTC4/5."); 127 LOG_THROW("Not an OSTC4/5.");
131 128
132 LOG_TRACE("Getting identity..."); 129 LOG_TRACE("Getting identity...");
133 getCommonIdentity(); 130 getCommonIdentity();
134 131
135 //---- Main firmware ----------------------------------------------------- 132 //---- Main firmware -----------------------------------------------------
136 QString mainFW; 133 QString mainFW;
137 { 134 {
138 unsigned char echo = retryCommand(_serial, 'k'); // 0x69 OSTC4 FW Details. 135 unsigned char echo = retryCommand(_serial, 'k'); // 0x69 OSTC4 FW Details.
139 if( echo != 'k' ) 136 if (echo != 'k')
140 LOG_THROW("Bad firmware details."); 137 LOG_THROW("Bad firmware details.");
141 138
142 unsigned char reply[4+1]; 139 unsigned char reply[4 + 1];
143 _serial.writeByte(0xFF); // Main firmware 140 _serial.writeByte(0xFF); // Main firmware
144 _serial.readBlock(reply, sizeof reply); 141 _serial.readBlock(reply, sizeof reply);
145 if( reply[4] != 0x4D ) 142 if (reply[4] != 0x4D)
146 LOG_THROW("Bad main firmware reply."); 143 LOG_THROW("Bad main firmware reply.");
147 144
148 mainFW = QString::asprintf("%d.%02d.%02d%s", reply[0], reply[1], reply[2], reply[3] ? "beta" : ""); 145 mainFW = QString::asprintf("%d.%02d.%02d%s",
146 reply[0],
147 reply[1],
148 reply[2],
149 reply[3] ? "beta" : "");
149 } 150 }
150 151
151 //---- RTE firmware ------------------------------------------------------ 152 //---- RTE firmware ------------------------------------------------------
152 QString rteFW; 153 QString rteFW;
153 { 154 {
154 unsigned char echo = retryCommand(_serial, 'k'); // 0x69 OSTC4 FW Details. 155 unsigned char echo = retryCommand(_serial, 'k'); // 0x69 OSTC4 FW Details.
155 if( echo != 'k' ) 156 if (echo != 'k')
156 LOG_THROW("Bad firmware details."); 157 LOG_THROW("Bad firmware details.");
157 158
158 unsigned char reply[4+1]; 159 unsigned char reply[4 + 1];
159 _serial.writeByte(0xFE); // RTE firmware 160 _serial.writeByte(0xFE); // RTE firmware
160 _serial.readBlock(reply, sizeof reply); 161 _serial.readBlock(reply, sizeof reply);
161 if( reply[4] != 0x4D ) 162 if (reply[4] != 0x4D)
162 LOG_THROW("Bad RTE firmware reply."); 163 LOG_THROW("Bad RTE firmware reply.");
163 164
164 rteFW = QString::asprintf("%d.%02d.%02d%s", reply[0], reply[1], reply[2], reply[3] ? "beta" : ""); 165 rteFW = QString::asprintf("%d.%02d.%02d%s",
166 reply[0],
167 reply[1],
168 reply[2],
169 reply[3] ? "beta" : "");
165 } 170 }
166 171
167 //---- Font Package ------------------------------------------------------ 172 //---- Font Package ------------------------------------------------------
168 QString fontPKG; 173 QString fontPKG;
169 { 174 {
170 unsigned char echo = retryCommand(_serial, 'k'); // 0x69 OSTC4 FW Details. 175 unsigned char echo = retryCommand(_serial, 'k'); // 0x69 OSTC4 FW Details.
171 if( echo != 'k' ) 176 if (echo != 'k')
172 LOG_THROW("Bad firmware details."); 177 LOG_THROW("Bad firmware details.");
173 178
174 unsigned char reply[4+1]; 179 unsigned char reply[4 + 1];
175 _serial.writeByte(0x10); // Font Package 180 _serial.writeByte(0x10); // Font Package
176 _serial.readBlock(reply, sizeof reply); 181 _serial.readBlock(reply, sizeof reply);
177 if( reply[4] != 0x4D ) 182 if (reply[4] != 0x4D)
178 LOG_THROW("Bad Font package reply."); 183 LOG_THROW("Bad Font package reply.");
179 184
180 fontPKG = QString::asprintf("%d.%02d.%02d%s", reply[0], reply[1], reply[2], reply[3] ? "beta" : ""); 185 fontPKG = QString::asprintf("%d.%02d.%02d%s",
186 reply[0],
187 reply[1],
188 reply[2],
189 reply[3] ? "beta" : "");
181 } 190 }
182 191
183 //---- OSTC4 specific description ---------------------------------------- 192 //---- OSTC4 specific description ----------------------------------------
184 descriptionString = QString("%1 #%2, fw %3 (main %4/RTE %5/Font %6), %7") 193 descriptionString = QString("%1 #%2, fw %3 (main %4/RTE %5/Font %6), %7")
185 .arg(model()) 194 .arg(model())
186 .arg(serialNumber(), 4, 10, QChar('0')) 195 .arg(serialNumber(), 4, 10, QChar('0'))
187 .arg( QString::asprintf("%d.%02d", firmware() / 100, firmware() % 100)) 196 .arg(QString::asprintf("%d.%02d", firmware() / 100, firmware() % 100))
188 .arg( mainFW ) 197 .arg(mainFW)
189 .arg( rteFW ) 198 .arg(rteFW)
190 .arg( fontPKG ) 199 .arg(fontPKG)
191 .arg( QString::fromLatin1((char*)(computerText), 60) 200 .arg(QString::fromLatin1((char *) (computerText), 60)
192 .replace(QChar('\0'), "") 201 .replace(QChar('\0'), "")
193 .trimmed() ); 202 .trimmed());
194 203
195 LOG_INFO("Found " << descriptionString); 204 LOG_INFO("Found " << descriptionString);
196 } 205 }
197 206
198 ////////////////////////////////////////////////////////////////////////////// 207 //////////////////////////////////////////////////////////////////////////////
199 208
200 OSTC4Operations::OSTC4Operations() 209 OSTC4Operations::OSTC4Operations()
201 : fileChecksum(0,0) 210 : fileChecksum(0, 0)
202 { 211 {
203 emulatorName = "OSTC4/5"; 212 emulatorName = "OSTC4/5";
204 m_crcWrapper = new CrcWrapper(nullptr); 213 m_crcWrapper = new CrcWrapper(nullptr);
205 } 214 }
206 215
214 openFirmware(fileName, false); 223 openFirmware(fileName, false);
215 224
216 LOG_INFO("Please wait for OSTC4/5 to complete installation..."); 225 LOG_INFO("Please wait for OSTC4/5 to complete installation...");
217 } 226 }
218 227
219 #define SWAP4BYTES(x) \ 228 #define SWAP4BYTES(x) \
220 uint( (((x) & 0x000000FF) << 24) \ 229 uint((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) \
221 | (((x) & 0x0000FF00) << 8) \ 230 | (((x) & 0xFF000000) >> 24))
222 | (((x) & 0x00FF0000) >> 8) \
223 | (((x) & 0xFF000000) >> 24))
224 231
225 void OSTC4Operations::setIcons(const QString &fileName) 232 void OSTC4Operations::setIcons(const QString &fileName)
226 { 233 {
227 int size; 234 int size;
228 int blockSize; 235 int blockSize;
238 uint32_t height = 0; 245 uint32_t height = 0;
239 246
240 blockSize = FIRMWARE_BLOCK; 247 blockSize = FIRMWARE_BLOCK;
241 transferDelay = FIRMWARE_BLOCK_DELAY; 248 transferDelay = FIRMWARE_BLOCK_DELAY;
242 249
243 try 250 try {
244 {
245 bmp = std::make_unique<BmpToArray>(fileName); 251 bmp = std::make_unique<BmpToArray>(fileName);
246 } 252 } catch (const std::exception &e) {
247 catch (const std::exception& e)
248 {
249 std::cerr << "Fehler beim Laden: " << e.what() << '\n'; 253 std::cerr << "Fehler beim Laden: " << e.what() << '\n';
250 } 254 }
251 255
252 QByteArray bin = bmp->getTransferBytes(); 256 QByteArray bin = bmp->getTransferBytes();
253 bmp->getImageXY(&width, &height); 257 bmp->getImageXY(&width, &height);
254 258
255 if(bin.size() < 0x20000 - 12) /* max bin size - header */ 259 if (bin.size() < 0x20000 - 12) /* max bin size - header */
256 { 260 {
257 buf3offset[0] = 0x20; 261 buf3offset[0] = 0x20;
258 buf3offset[1] = 0x00; 262 buf3offset[1] = 0x00;
259 buf3offset[2] = 0x00; 263 buf3offset[2] = 0x00;
260 buf3offset[3] = 0x00; 264 buf3offset[3] = 0x00;
263 bufVersion[2] = 0; 267 bufVersion[2] = 0;
264 bufVersion[3] = 0; 268 bufVersion[3] = 0;
265 269
266 header.type = 0x20; 270 header.type = 0x20;
267 /* original header shallnot be modifieded => split image size information into 5 bytes */ 271 /* original header shallnot be modifieded => split image size information into 5 bytes */
268 header.dummy5 = width; /* low byte */ 272 header.dummy5 = width; /* low byte */
269 header.dummy6 = height; /* low byte */ 273 header.dummy6 = height; /* low byte */
270 header.dummy7 = (width >> 8) & 0x0000000F; /* shifted high nibble */ 274 header.dummy7 = (width >> 8) & 0x0000000F; /* shifted high nibble */
271 header.dummy7 |= (height >> 4) & 0x000000F0; /* shifted high nibble */ 275 header.dummy7 |= (height >> 4) & 0x000000F0; /* shifted high nibble */
272 276
273 header.length = SWAP4BYTES(bin.size()); 277 header.length = SWAP4BYTES(bin.size());
274 header.checksum = bin.size() + (256*256*256*header.type) + (256*256* header.dummy5) + (256*header.dummy6) + header.dummy7; 278 header.checksum = bin.size() + (256 * 256 * 256 * header.type) + (256 * 256 * header.dummy5)
275 279 + (256 * header.dummy6) + header.dummy7;
276 checksum = SWAP4BYTES(m_crcWrapper->CRC_CalcBlockCRC(reinterpret_cast<uint32_t*>(bin.data()), bin.size() / 4)); 280
281 checksum = SWAP4BYTES(
282 m_crcWrapper->CRC_CalcBlockCRC(reinterpret_cast<uint32_t *>(bin.data()),
283 bin.size() / 4));
277 284
278 //---- Upload icon ----------------------------------------------- 285 //---- Upload icon -----------------------------------------------
279 const int steps = 3 + (bin.size()+blockSize-1) / blockSize; 286 const int steps = 3 + (bin.size() + blockSize - 1) / blockSize;
280 int step = 0; 287 int step = 0;
281 PROGRESS(step++, steps); 288 PROGRESS(step++, steps);
282 289
283 LOG_INFO(QString(" uploading icon size %1 bytes").arg(bin.size())); 290 LOG_INFO(QString(" uploading icon size %1 bytes").arg(bin.size()));
284 writeText( QString("Upload Icon") ); 291 writeText(QString("Upload Icon"));
285 292
286 //---- Command 293 //---- Command
287 PROGRESS(step++, steps); 294 PROGRESS(step++, steps);
288 echo = retryCommand(_serial, 'o'); // 0x6F upload icon 295 echo = retryCommand(_serial, 'o'); // 0x6F upload icon
289 if( echo != 'o' ) 296 if (echo != 'o')
290 LOG_THROW("Bad OSTC4/5 icon upload."); 297 LOG_THROW("Bad OSTC4/5 icon upload.");
291 298
292 //---- Header 299 //---- Header
293 PROGRESS(step++, steps); 300 PROGRESS(step++, steps);
294 _serial.writeBlock((uchar*)&header, sizeof header); 301 _serial.writeBlock((uchar *) &header, sizeof header);
295 _serial.sleep(500); 302 _serial.sleep(500);
296 //---- Data 303 //---- Data
297 for(int len = 0x00000; len < bin.size(); len += blockSize) 304 for (int len = 0x00000; len < bin.size(); len += blockSize) {
298 { 305 if (transferDelay) {
299 if(transferDelay) 306 _serial.sleep(transferDelay); // 15 msec between 64B blocks...
300 {
301 _serial.sleep(transferDelay); // 15 msec between 64B blocks...
302 } 307 }
303 PROGRESS(step++, steps); 308 PROGRESS(step++, steps);
304 309
305 size = qMin(blockSize, 310 size = qMin(blockSize, bin.size() - len);
306 bin.size() - len);
307 311
308 LOG_TRACE("Fill " << size); 312 LOG_TRACE("Fill " << size);
309 _serial.writeBlock((uchar*)bin.data()+len, (unsigned int)size); 313 _serial.writeBlock((uchar *) bin.data() + len, (unsigned int) size);
310 } 314 }
311 _serial.writeBlock((uchar*)&checksum, 4); 315 _serial.writeBlock((uchar *) &checksum, 4);
312 PROGRESS(steps, steps); // 100% 316 PROGRESS(steps, steps); // 100%
313 317
314 //---- Wait acknowledge ---------------------------------------------- 318 //---- Wait acknowledge ----------------------------------------------
315 PROGRESS_THROTTLE(); 319 PROGRESS_THROTTLE();
316 320
317 for(int wait=0; wait<2*60; ++wait) // Up to 2 min... 321 for (int wait = 0; wait < 2 * 60; ++wait) // Up to 2 min...
318 { 322 {
319 try { 323 try {
320 unsigned char reply = _serial.readByte(); 324 unsigned char reply = _serial.readByte();
321 if( reply == 0x4D ) 325 if (reply == 0x4D)
322 break; 326 break;
323 } 327 } catch (const ReadTimeout &) {
324 catch( const ReadTimeout&) {}
325 } 328 }
329 }
326 330
327 LOG_INFO(" icon uploaded."); 331 LOG_INFO(" icon uploaded.");
328 } 332 } else {
329 else
330 {
331 LOG_THROW("Image to large. Must be < 128k."); 333 LOG_THROW("Image to large. Must be < 128k.");
332 } 334 }
333 PROGRESS_RESET(); 335 PROGRESS_RESET();
334 } 336 }
335
336
337 337
338 ////////////////////////////////////////////////////////////////////////////// 338 //////////////////////////////////////////////////////////////////////////////
339 ////////////////////////////////////////////////////////////////////////////// 339 //////////////////////////////////////////////////////////////////////////////
340 /// FIRMWARE UPGRADE /// 340 /// FIRMWARE UPGRADE ///
341 ////////////////////////////////////////////////////////////////////////////// 341 //////////////////////////////////////////////////////////////////////////////
355 int size; 355 int size;
356 int blockSize; 356 int blockSize;
357 int transferDelay; 357 int transferDelay;
358 358
359 // Previous trial failed ? 359 // Previous trial failed ?
360 if( _file.isOpen() ) _file.close(); 360 if (_file.isOpen())
361 _file.close();
361 362
362 _file.setFileName(fileName); 363 _file.setFileName(fileName);
363 if( ! _file.open(QIODevice::ReadOnly) ) 364 if (!_file.open(QIODevice::ReadOnly))
364 LOG_THROW( "Cannot open BIN file " << fileName ); 365 LOG_THROW("Cannot open BIN file " << fileName);
365
366 366
367 // Get settings to overwrite version check 367 // Get settings to overwrite version check
368 forceFirmwareUpdate = settings->value("OSTC/forceFirmwareUpdate", false).toBool(); 368 forceFirmwareUpdate = settings->value("OSTC/forceFirmwareUpdate", false).toBool();
369 forceRTEUpdate = settings->value("OSTC/forceRTEUpdate", false).toBool(); 369 forceRTEUpdate = settings->value("OSTC/forceRTEUpdate", false).toBool();
370 forceFontlibUpdate = settings->value("OSTC/forceFontlibUpdate", false).toBool(); 370 forceFontlibUpdate = settings->value("OSTC/forceFontlibUpdate", false).toBool();
371 371
372 useFastMode = settings->value("OSTC/useFastMode", false).toBool(); 372 useFastMode = settings->value("OSTC/useFastMode", false).toBool();
373 373
374 //---- Check consistency ------------------------------------------------- 374 //---- Check consistency -------------------------------------------------
375 fileChecksum.reset(0, 0); 375 fileChecksum.reset(0, 0);
376 for(int part=1; part<4; ++part) 376 for (int part = 1; part < 4; ++part) {
377 {
378 // Less than 3 parts ? 377 // Less than 3 parts ?
379 if( (_file.size() - _file.pos()) < 16 ) 378 if ((_file.size() - _file.pos()) < 16)
380 break; 379 break;
381 380
382 if( dryRun ) 381 if (dryRun)
383 LOG_TRACE("Checking part " << part <<"..."); 382 LOG_TRACE("Checking part " << part << "...");
384 383
385 FirmwareOSTC4 header; 384 FirmwareOSTC4 header;
386 QByteArray bin; 385 QByteArray bin;
387 loadFirmwarePart(header, bin, part, dryRun); 386 loadFirmwarePart(header, bin, part, dryRun);
388 387
389 QString name = QString::asprintf("%s v%d.%02d.%02d%s", 388 QString name = QString::asprintf("%s v%d.%02d.%02d%s",
390 header.type==0x10 ? "Font" 389 header.type == 0x10 ? "Font"
391 : header.type==0xFF ? "FW " 390 : header.type == 0xFF ? "FW "
392 : header.type==0xFE ? "RTE " 391 : header.type == 0xFE ? "RTE "
393 : "??? ", 392 : "??? ",
394 header.version.x, header.version.y, header.version.z, 393 header.version.x,
395 header.version.beta ? " beta" : ""); 394 header.version.y,
395 header.version.z,
396 header.version.beta ? " beta" : "");
396 397
397 //---- On first pass, just check file structure ---------------------- 398 //---- On first pass, just check file structure ----------------------
398 if( dryRun ) 399 if (dryRun)
399 continue; 400 continue;
400 401
401 //---- On second pass, do upload new stuff --------------------------- 402 //---- On second pass, do upload new stuff ---------------------------
402 if( _connectMode != SERVICE_MODE ) 403 if (_connectMode != SERVICE_MODE)
403 connectServiceMode(); 404 connectServiceMode();
404 if( _connectMode != SERVICE_MODE ) 405 if (_connectMode != SERVICE_MODE)
405 LOG_THROW("Cannot connect OSTC 4/5 service mode..."); 406 LOG_THROW("Cannot connect OSTC 4/5 service mode...");
406 407
407 //---- Check if needed ? --------------------------------------------- 408 //---- Check if needed ? ---------------------------------------------
408 LOG_TRACE("Check part " << part << " is needed ?"); 409 LOG_TRACE("Check part " << part << " is needed ?");
409 unsigned char echo = retryCommand(_serial, 'k'); // 0x6B OSTC4 FW Details. 410 unsigned char echo = retryCommand(_serial, 'k'); // 0x6B OSTC4 FW Details.
410 if( echo != 'k' ) 411 if (echo != 'k')
411 LOG_THROW("Bad firmware details."); 412 LOG_THROW("Bad firmware details.");
412 413
413 unsigned char reply[4+1]; 414 unsigned char reply[4 + 1];
414 _serial.writeByte(header.type); // type of firmware part 415 _serial.writeByte(header.type); // type of firmware part
415 _serial.readBlock(reply, sizeof reply); 416 _serial.readBlock(reply, sizeof reply);
416 if( reply[4] != 0x4C ) // SERVICE MODE only. 417 if (reply[4] != 0x4C) // SERVICE MODE only.
417 LOG_THROW("Bad firmware reply."); 418 LOG_THROW("Bad firmware reply.");
418 419
419 if(((reply[0] *100 + reply[1] * 10 + reply[2]) > 151 ) && (header.type==0xFF)) /* suitable firmware version? First supported in 1.5.2 */ 420 if (((reply[0] * 100 + reply[1] * 10 + reply[2]) > 151)
421 && (header.type == 0xFF)) /* suitable firmware version? First supported in 1.5.2 */
420 { 422 {
421 firmwareSupportFastMode = true; 423 firmwareSupportFastMode = true;
422 } 424 }
423 425
424 if(( header.version.x == reply[0] 426 if ((header.version.x == reply[0] && header.version.y == reply[1]
425 && header.version.y == reply[1] 427 && header.version.z == reply[2])
426 && header.version.z == reply[2] ) 428 && (!(forceFirmwareUpdate && header.type == 0xFF))
427 && (!(forceFirmwareUpdate && header.type==0xFF)) 429 && (!(forceRTEUpdate && header.type == 0xFE))
428 && (!(forceRTEUpdate && header.type==0xFE)) 430 && (!(forceFontlibUpdate && header.type == 0x10))) {
429 && (!(forceFontlibUpdate && header.type==0x10))
430 )
431 {
432 LOG_INFO(" part " << part << ": " << name << " already up-to-date."); 431 LOG_INFO(" part " << part << ": " << name << " already up-to-date.");
433 continue; 432 continue;
434 } 433 }
435 if((useFastMode) && (firmwareSupportFastMode)) /* is fast mode supported ? */ 434 if ((useFastMode) && (firmwareSupportFastMode)) /* is fast mode supported ? */
436 { 435 {
437 blockSize = FIRMWARE_BLOCK_FAST; 436 blockSize = FIRMWARE_BLOCK_FAST;
438 transferDelay = 1; 437 transferDelay = 1;
439 } 438 } else {
440 else {
441 blockSize = FIRMWARE_BLOCK; 439 blockSize = FIRMWARE_BLOCK;
442 transferDelay = FIRMWARE_BLOCK_DELAY; 440 transferDelay = FIRMWARE_BLOCK_DELAY;
443 } 441 }
444 //---- Upload firwmare ----------------------------------------------- 442 //---- Upload firwmare -----------------------------------------------
445 const int steps = 3 + (bin.size()+blockSize-1) / blockSize; 443 const int steps = 3 + (bin.size() + blockSize - 1) / blockSize;
446 int step = 0; 444 int step = 0;
447 PROGRESS(step++, steps); 445 PROGRESS(step++, steps);
448 446
449 LOG_INFO(" uploading part " << part 447 LOG_INFO(" uploading part " << part << ": " << name << "...");
450 << ": " << name 448 writeText(QString("Upload Part %1").arg(part));
451 << "...");
452 writeText( QString("Upload Part %1").arg(part) );
453 449
454 //---- Command 450 //---- Command
455 PROGRESS(step++, steps); 451 PROGRESS(step++, steps);
456 echo = retryCommand(_serial, 's'); // 0x73 OSTC4 FW Upgrade 452 echo = retryCommand(_serial, 's'); // 0x73 OSTC4 FW Upgrade
457 if( echo != 's' ) 453 if (echo != 's')
458 LOG_THROW("Bad OSTC4/5 FW upgrade commande."); 454 LOG_THROW("Bad OSTC4/5 FW upgrade commande.");
459 455
460 //---- Header 456 //---- Header
461 PROGRESS(step++, steps); 457 PROGRESS(step++, steps);
462 _serial.writeBlock((uchar*)&header, sizeof header); 458 _serial.writeBlock((uchar *) &header, sizeof header);
463 _serial.sleep(500); 459 _serial.sleep(500);
464 //---- Data 460 //---- Data
465 for(int len = 0x00000; len < bin.size(); len += blockSize) 461 for (int len = 0x00000; len < bin.size(); len += blockSize) {
466 { 462 if (transferDelay) {
467 if(transferDelay) 463 _serial.sleep(transferDelay); // 15 msec between 64B blocks...
468 {
469 _serial.sleep(transferDelay); // 15 msec between 64B blocks...
470 } 464 }
471 PROGRESS(step++, steps); 465 PROGRESS(step++, steps);
472 466
473 size = qMin(blockSize, 467 size = qMin(blockSize, bin.size() - len);
474 bin.size() - len);
475 468
476 LOG_TRACE("Fill " << size); 469 LOG_TRACE("Fill " << size);
477 _serial.writeBlock((uchar*)bin.data()+len, (unsigned int)size); 470 _serial.writeBlock((uchar *) bin.data() + len, (unsigned int) size);
478 } 471 }
479 472
480 PROGRESS(steps, steps); // 100% 473 PROGRESS(steps, steps); // 100%
481 474
482 //---- Wait acknowledge ---------------------------------------------- 475 //---- Wait acknowledge ----------------------------------------------
483 // RTE seems to miss the acknowledge byte ... 476 // RTE seems to miss the acknowledge byte ...
484 if( header.type != 0xFE ) { 477 if (header.type != 0xFE) {
485 PROGRESS_THROTTLE(); 478 PROGRESS_THROTTLE();
486 479
487 for(int wait=0; wait<2*60; ++wait) // Up to 2 min... 480 for (int wait = 0; wait < 2 * 60; ++wait) // Up to 2 min...
488 { 481 {
489 try { 482 try {
490 unsigned char reply = _serial.readByte(); 483 unsigned char reply = _serial.readByte();
491 if( reply == 0x4C ) 484 if (reply == 0x4C)
492 break; 485 break;
486 } catch (const ReadTimeout &) {
493 } 487 }
494 catch( const ReadTimeout&) {}
495 } 488 }
496 } 489 }
497 490
498 LOG_INFO(" part " << part << ": " << name << " uploaded."); 491 LOG_INFO(" part " << part << ": " << name << " uploaded.");
499 } 492 }
500 493
501 //---- Done -------------------------------------------------------------- 494 //---- Done --------------------------------------------------------------
502 // Low-level close, to avoid trying to send a 0xFF byte... 495 // Low-level close, to avoid trying to send a 0xFF byte...
503 if( !dryRun ) { 496 if (!dryRun) {
504 disconnect(true); 497 disconnect(true);
505 } 498 }
506 499
507 PROGRESS_RESET(); 500 PROGRESS_RESET();
508 501
509 //---- Check FILE checksum on first pass --------------------------------- 502 //---- Check FILE checksum on first pass ---------------------------------
510 if( dryRun ) { 503 if (dryRun) {
511 uint expected; 504 uint expected;
512 if( 4 != _file.read((char*)&expected, sizeof expected) ) 505 if (4 != _file.read((char *) &expected, sizeof expected))
513 LOG_THROW("Missing file checksum."); 506 LOG_THROW("Missing file checksum.");
514 507
515 uint checksum = fileChecksum.a() | (fileChecksum.b() << 16); 508 uint checksum = fileChecksum.a() | (fileChecksum.b() << 16);
516 509
517 if( checksum != expected ) 510 if (checksum != expected)
518 LOG_ERROR( QString::asprintf("File checksum ERROR: expected = %04X, actual = %04X", expected, checksum) ); 511 LOG_ERROR(QString::asprintf("File checksum ERROR: expected = %04X, actual = %04X",
519 else if( dryRun ) 512 expected,
520 LOG_TRACE( QString::asprintf("File checksum = %04X (OK)", checksum) ); 513 checksum));
521 514 else if (dryRun)
522 if( ! _file.atEnd() ) 515 LOG_TRACE(QString::asprintf("File checksum = %04X (OK)", checksum));
516
517 if (!_file.atEnd())
523 LOG_THROW("Extra data after last block."); 518 LOG_THROW("Extra data after last block.");
524 } 519 }
525 520
526 _file.close(); 521 _file.close();
527 } 522 }
528 523
529 ////////////////////////////////////////////////////////////////////////////// 524 //////////////////////////////////////////////////////////////////////////////
530 525
531 void OSTC4Operations::loadFirmwarePart(FirmwareOSTC4& header, 526 void OSTC4Operations::loadFirmwarePart(FirmwareOSTC4 &header, QByteArray &bin, int part, bool dryRun)
532 QByteArray& bin,
533 int part,
534 bool dryRun)
535 { 527 {
536 memset(&header, 0, sizeof header); 528 memset(&header, 0, sizeof header);
537 529
538 //---- Read part header and check consistency ---------------------------- 530 //---- Read part header and check consistency ----------------------------
539 if( sizeof header != _file.read((char*)&header, sizeof header) ) 531 if (sizeof header != _file.read((char *) &header, sizeof header))
540 LOG_THROW("EOF in header."); 532 LOG_THROW("EOF in header.");
541 fileChecksum.add(&header, sizeof header); 533 fileChecksum.add(&header, sizeof header);
542 534
543 uint checksum = SWAP4BYTES(header.length) 535 uint checksum = SWAP4BYTES(header.length) + SWAP4BYTES(*(uint *) &header.type);
544 + SWAP4BYTES(*(uint*)&header.type); 536 if (checksum != header.checksum)
545 if( checksum != header.checksum ) 537 LOG_THROW(
546 LOG_THROW( QString::asprintf("Inconsistent header (%04X != %04X).", checksum, header.checksum) ); 538 QString::asprintf("Inconsistent header (%04X != %04X).", checksum, header.checksum));
547 539
548 if( SWAP4BYTES(header.length) > (1024 * 1024) || (SWAP4BYTES(header.length) % 4) ) 540 if (SWAP4BYTES(header.length) > (1024 * 1024) || (SWAP4BYTES(header.length) % 4))
549 LOG_THROW("Inconsistent header (part=" << part << ", size=" << SWAP4BYTES(header.length) << ")."); 541 LOG_THROW("Inconsistent header (part=" << part << ", size=" << SWAP4BYTES(header.length)
550 542 << ").");
551 if( dryRun ) 543
552 switch( header.type ) { 544 if (dryRun)
553 case 0x10: LOG_TRACE("... font"); break; 545 switch (header.type) {
554 case 0xFF: LOG_TRACE("... firmware"); break; 546 case 0x10:
555 case 0xFE: LOG_TRACE("... RTE"); break; 547 LOG_TRACE("... font");
548 break;
549 case 0xFF:
550 LOG_TRACE("... firmware");
551 break;
552 case 0xFE:
553 LOG_TRACE("... RTE");
554 break;
556 default: 555 default:
557 // LOG_THROW("Inconsistent header (part=" << part << ", type=0x" << QString::asprintf(int(header.type), 16) << ")."); 556 // LOG_THROW("Inconsistent header (part=" << part << ", type=0x" << QString::asprintf(int(header.type), 16) << ").");
558 LOG_THROW("Inconsistent header (part=" << part << ", type=0x" << QString::asprintf("Value = %d", header.type) << ")."); 557 LOG_THROW("Inconsistent header (part=" << part << ", type=0x"
558 << QString::asprintf("Value = %d", header.type)
559 << ").");
559 break; 560 break;
560 } 561 }
561 562
562 if( dryRun ) 563 if (dryRun)
563 LOG_TRACE("... version " << QString::asprintf("%d.%02d.%02d.%s", 564 LOG_TRACE("... version " << QString::asprintf("%d.%02d.%02d.%s",
564 header.version.x, header.version.y, header.version.z, 565 header.version.x,
565 header.version.beta ? " beta" : "")); 566 header.version.y,
567 header.version.z,
568 header.version.beta ? " beta" : ""));
566 569
567 //---- Read Binary Data -------------------------------------------------- 570 //---- Read Binary Data --------------------------------------------------
568 if( dryRun ) 571 if (dryRun)
569 LOG_TRACE("... size " << SWAP4BYTES(header.length) << " bytes."); 572 LOG_TRACE("... size " << SWAP4BYTES(header.length) << " bytes.");
570 bin.resize(SWAP4BYTES(header.length) + 4); 573 bin.resize(SWAP4BYTES(header.length) + 4);
571 assert((uint)bin.size() == SWAP4BYTES(header.length) + 4); 574 assert((uint) bin.size() == SWAP4BYTES(header.length) + 4);
572 575
573 if( bin.size() != _file.read(bin.data(), bin.size()) ) 576 if (bin.size() != _file.read(bin.data(), bin.size()))
574 LOG_THROW("EOF in data."); 577 LOG_THROW("EOF in data.");
575 578
576 if( dryRun ) 579 if (dryRun)
577 LOG_TRACE("... checksum " << QString::asprintf("%08x", 580 LOG_TRACE("... checksum " << QString::asprintf("%08x",
578 *(uint*)(bin.data() + SWAP4BYTES(header.length)))); 581 *(uint *) (bin.data()
582 + SWAP4BYTES(header.length))));
579 fileChecksum.add(bin); 583 fileChecksum.add(bin);
580 } 584 }
581 585
582 void OSTC4Operations::getSignal() 586 void OSTC4Operations::getSignal()
583 { 587 {
584 char buffer[60]; 588 char buffer[60];
585 memset(buffer, 0, sizeof buffer); 589 memset(buffer, 0, sizeof buffer);
586 unsigned char echo = retryCommand(_serial, 'l'); // 0x6c request bluetooth signal 590 unsigned char echo = retryCommand(_serial, 'l'); // 0x6c request bluetooth signal
587 if( echo != 0x6C ) 591 if (echo != 0x6C)
588 LOG_THROW("Bad text reply (1)" << echo); 592 LOG_THROW("Bad text reply (1)" << echo);
589 593
590 _serial.sleep(1000); 594 _serial.sleep(1000);
591 595
592 unsigned char ok = _serial.readByte(); 596 unsigned char ok = _serial.readByte();
593 if( ok != 0x4D ) // DOWNLOAD mode only. 597 if (ok != 0x4D) // DOWNLOAD mode only.
594 LOG_THROW("Bad clock reply (2)"); 598 LOG_THROW("Bad clock reply (2)");
595 } 599 }
596 600
597 601 void OSTC4Operations::getAllHeader(unsigned char *pBuffer)
598 void OSTC4Operations::getAllHeader(unsigned char* pBuffer)
599 { 602 {
600 unsigned char index = 0; 603 unsigned char index = 0;
601 char buffer[60]; 604 char buffer[60];
602 memset(buffer, 0, sizeof buffer); 605 memset(buffer, 0, sizeof buffer);
603 606
604 if( _connectMode != SERVICE_MODE ) 607 if (_connectMode != SERVICE_MODE)
605 connectServiceMode(); 608 connectServiceMode();
606 if( _connectMode != SERVICE_MODE ) 609 if (_connectMode != SERVICE_MODE)
607 LOG_THROW("Cannot connect OSTC4 service mode..."); 610 LOG_THROW("Cannot connect OSTC4 service mode...");
608 611
609
610 unsigned char echo = retryCommand(_serial, 0x85); // 0x85 request all headers (dump) 612 unsigned char echo = retryCommand(_serial, 0x85); // 0x85 request all headers (dump)
611 if( echo != 0x85 ) 613 if (echo != 0x85)
612 LOG_THROW("Bad text reply (1)" << echo); 614 LOG_THROW("Bad text reply (1)" << echo);
613 615
614 _serial.sleep(1000); 616 _serial.sleep(1000);
615 617
616 for(index = 0; index < 8; index++) // Expect 8 blocks a 0x8000 618 for (index = 0; index < 8; index++) // Expect 8 blocks a 0x8000
617 { 619 {
618 _serial.readBlock(pBuffer + (index * 0x8000), 0x8000); 620 _serial.readBlock(pBuffer + (index * 0x8000), 0x8000);
619 LOG_INFO((".")); 621 LOG_INFO(("."));
620 } 622 }
621 *(pBuffer + (index * 0x8000)) = _serial.readByte(); // get lastdiveID 623 *(pBuffer + (index * 0x8000)) = _serial.readByte(); // get lastdiveID
622 LOG_INFO(QString::asprintf("%d",*(pBuffer + (index * 0x8000)))); 624 LOG_INFO(QString::asprintf("%d", *(pBuffer + (index * 0x8000))));
623 unsigned char ok = _serial.readByte(); 625 unsigned char ok = _serial.readByte();
624 if( ok != 0x4C ) //Service mode only. 626 if (ok != 0x4C) //Service mode only.
625 LOG_THROW("Bad clock reply (2)"); 627 LOG_THROW("Bad clock reply (2)");
626 } 628 }
627 629
628 void OSTC4Operations::writeAllHeader(unsigned char* pBuffer) 630 void OSTC4Operations::writeAllHeader(unsigned char *pBuffer)
629 { 631 {
630 unsigned char index = 0; 632 unsigned char index = 0;
631 char buffer[60]; 633 char buffer[60];
632 memset(buffer, 0, sizeof buffer); 634 memset(buffer, 0, sizeof buffer);
633 635
634 if( _connectMode != SERVICE_MODE ) 636 if (_connectMode != SERVICE_MODE)
635 connectServiceMode(); 637 connectServiceMode();
636 if( _connectMode != SERVICE_MODE ) 638 if (_connectMode != SERVICE_MODE)
637 LOG_THROW("Cannot connect OSTC4 service mode..."); 639 LOG_THROW("Cannot connect OSTC4 service mode...");
638 640
639
640 unsigned char echo = retryCommand(_serial, 0x86); // 0x86 request all headers (dump) 641 unsigned char echo = retryCommand(_serial, 0x86); // 0x86 request all headers (dump)
641 if( echo != 0x86 ) 642 if (echo != 0x86)
642 LOG_THROW("Bad text reply (1)" << echo); 643 LOG_THROW("Bad text reply (1)" << echo);
643 644
644 _serial.sleep(1000); 645 _serial.sleep(1000);
645 646
646 for(index = 0; index < 8; index++) // Expect 8 blocks a 0x8000 647 for (index = 0; index < 8; index++) // Expect 8 blocks a 0x8000
647 { 648 {
648 _serial.writeBlock(pBuffer + (index * 0x8000), 0x8000); 649 _serial.writeBlock(pBuffer + (index * 0x8000), 0x8000);
649 LOG_INFO((".")); 650 LOG_INFO(("."));
650 } 651 }
651 _serial.writeByte(*(pBuffer + (index * 0x8000))); // write lastdiveID 652 _serial.writeByte(*(pBuffer + (index * 0x8000))); // write lastdiveID
652 653
653 unsigned char ok = _serial.readByte(); 654 unsigned char ok = _serial.readByte();
654 if( ok != 0x4C ) //Service mode only. 655 if (ok != 0x4C) //Service mode only.
655 LOG_THROW("Bad clock reply (2)"); 656 LOG_THROW("Bad clock reply (2)");
656 } 657 }
657 658
658 void OSTC4Operations::getAllSamples(unsigned char* pBuffer) 659 void OSTC4Operations::getAllSamples(unsigned char *pBuffer)
659 { 660 {
660 unsigned short index = 0; 661 unsigned short index = 0;
661 char buffer[60]; 662 char buffer[60];
662 memset(buffer, 0, sizeof buffer); 663 memset(buffer, 0, sizeof buffer);
663 664
664 if( _connectMode != SERVICE_MODE ) 665 if (_connectMode != SERVICE_MODE)
665 connectServiceMode(); 666 connectServiceMode();
666 if( _connectMode != SERVICE_MODE ) 667 if (_connectMode != SERVICE_MODE)
667 LOG_THROW("Cannot connect OSTC4 service mode..."); 668 LOG_THROW("Cannot connect OSTC4 service mode...");
668 669
669
670 unsigned char echo = retryCommand(_serial, 0x88); // 0x88 request all samples (dump) 670 unsigned char echo = retryCommand(_serial, 0x88); // 0x88 request all samples (dump)
671 if( echo != 0x88 ) 671 if (echo != 0x88)
672 LOG_THROW("Bad text reply (1)" << echo); 672 LOG_THROW("Bad text reply (1)" << echo);
673 673
674 _serial.sleep(500); 674 _serial.sleep(500);
675 675
676 for(index = 0; index < 384; index++) // Expect 8 blocks a 0x8000 676 for (index = 0; index < 384; index++) // Expect 8 blocks a 0x8000
677 { 677 {
678 _serial.readBlock(pBuffer + (index * 0x8000), 0x8000); 678 _serial.readBlock(pBuffer + (index * 0x8000), 0x8000);
679 LOG_INFO(QString::asprintf("%d",index)); 679 LOG_INFO(QString::asprintf("%d", index));
680 } 680 }
681 _serial.readBlock(pBuffer + (index * 0x8000), 4); // get lastdiveID 681 _serial.readBlock(pBuffer + (index * 0x8000), 4); // get lastdiveID
682 unsigned char ok = _serial.readByte(); 682 unsigned char ok = _serial.readByte();
683 if( ok != 0x4C ) //Service mode only. 683 if (ok != 0x4C) //Service mode only.
684 LOG_THROW("Bad clock reply (2)"); 684 LOG_THROW("Bad clock reply (2)");
685 } 685 }
686 686
687 687 void OSTC4Operations::writeAllSamples(unsigned char *pBuffer)
688 void OSTC4Operations::writeAllSamples(unsigned char* pBuffer)
689 { 688 {
690 unsigned short index = 0; 689 unsigned short index = 0;
691 char buffer[60]; 690 char buffer[60];
692 memset(buffer, 0, sizeof buffer); 691 memset(buffer, 0, sizeof buffer);
693 692
694 if( _connectMode != SERVICE_MODE ) 693 if (_connectMode != SERVICE_MODE)
695 connectServiceMode(); 694 connectServiceMode();
696 if( _connectMode != SERVICE_MODE ) 695 if (_connectMode != SERVICE_MODE)
697 LOG_THROW("Cannot connect OSTC4 service mode..."); 696 LOG_THROW("Cannot connect OSTC4 service mode...");
698 697
699
700 unsigned char echo = retryCommand(_serial, 0x89); // 0x88 request all samples (dump) 698 unsigned char echo = retryCommand(_serial, 0x89); // 0x88 request all samples (dump)
701 if( echo != 0x89 ) 699 if (echo != 0x89)
702 LOG_THROW("Bad text reply (1)" << echo); 700 LOG_THROW("Bad text reply (1)" << echo);
703 701
704 _serial.sleep(500); 702 _serial.sleep(500);
705 703
706 for(index = 0; index < 384; index++) // Expect 8 blocks a 0x8000 384 704 for (index = 0; index < 384; index++) // Expect 8 blocks a 0x8000 384
707 { 705 {
708 _serial.writeBlock((const unsigned char*)(pBuffer + (index * 0x8000)), 0x8000); 706 _serial.writeBlock((const unsigned char *) (pBuffer + (index * 0x8000)), 0x8000);
709 LOG_INFO(QString::asprintf("%d",index)); 707 LOG_INFO(QString::asprintf("%d", index));
710 } 708 }
711 _serial.writeBlock(pBuffer + (index * 0x8000), 4); // set lastdiveID 709 _serial.writeBlock(pBuffer + (index * 0x8000), 4); // set lastdiveID
712 unsigned char ok = _serial.readByte(); 710 unsigned char ok = _serial.readByte();
713 if( ok != 0x4C ) //Service mode only. 711 if (ok != 0x4C) //Service mode only.
714 LOG_THROW("Bad clock reply (2)"); 712 LOG_THROW("Bad clock reply (2)");
715 } 713 }
716 714
717 ////////////////////////////////////////////////////////////////////////////// 715 //////////////////////////////////////////////////////////////////////////////