forked from subsurface/subsurface
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli-downloader.cpp
More file actions
128 lines (112 loc) · 4.62 KB
/
cli-downloader.cpp
File metadata and controls
128 lines (112 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// SPDX-License-Identifier: GPL-2.0
#include "qt-models/diveimportedmodel.h"
#include "core/configuredivecomputer.h"
#include "core/downloadfromdcthread.h"
#include "core/subsurfacestartup.h"
#include <QCoreApplication>
#include <QThread>
#include <QDir>
// Expand tilde in filenames
static QString expandTilde(const QString &path)
{
if (path.startsWith("~/")) {
return QDir::homePath() + path.mid(1);
}
return path;
}
// Perform a firmware update from the command line. Returns 0 on success, non-zero on failure.
int cliFirmwareUpdate(const std::string &vendor, const std::string &product, const std::string &device, const std::string &filename, bool force)
{
ConfigureDiveComputer config;
DCDeviceData localData;
// prepare device_data
localData.setVendor(QString::fromStdString(vendor));
localData.setProduct(QString::fromStdString(product));
localData.setDevName(QString::fromStdString(device));
localData.setBluetoothMode(false);
device_data_t *data = localData.internalData();
// Set up the descriptor (needed for dc_open)
QString vendorLower = QString::fromStdString(vendor).toLower();
QString productLower = QString::fromStdString(product).toLower();
data->descriptor = descriptorLookup[vendorLower + productLower];
if (!data->descriptor) {
fprintf(stderr, "Unknown dive computer: %s %s\n", vendor.c_str(), product.c_str());
return 1;
}
// If descriptor not filled yet, call fill_computer_list() in caller before this
QString err = config.dc_open(data);
if (!err.isEmpty()) {
fprintf(stderr, "Failed to open device: %s\n", qPrintable(err));
return 2;
}
// Expand tilde in filename
QString expandedFilename = expandTilde(QString::fromStdString(filename));
// Start firmware update and wait for thread to finish via state changes/signals.
// The ConfigureDiveComputer starts a thread; we'll connect to signals and wait in a local event loop.
bool hadError = false;
QObject::connect(&config, &ConfigureDiveComputer::error, [&hadError](QString e){
fprintf(stderr, "Firmware update error: %s\n", e.toLocal8Bit().constData());
hadError = true;
});
QObject::connect(&config, &ConfigureDiveComputer::message, [](QString m){
fprintf(stdout, "%s\n", m.toLocal8Bit().constData());
});
QObject::connect(&config, &ConfigureDiveComputer::progress, [](int percent){
fprintf(stdout, "Progress: %d%%\r", percent);
fflush(stdout);
});
config.startFirmwareUpdate(expandedFilename, data, force);
// Wait until state becomes DONE or ERRORED
while (config.currentState != ConfigureDiveComputer::DONE && config.currentState != ConfigureDiveComputer::ERRORED) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
QThread::msleep(50);
}
// Let any remaining events be processed (important for thread cleanup)
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
QThread::msleep(100);
// Check if we had errors or if the state indicates failure
if (hadError || config.currentState == ConfigureDiveComputer::ERRORED || !config.lastError.isEmpty()) {
if (!config.lastError.isEmpty()) {
fprintf(stderr, "Firmware update failed: %s\n", qPrintable(config.lastError));
} else if (!hadError) {
fprintf(stderr, "Firmware update failed with unknown error\n");
}
// Don't call dc_close on error - the thread may have already closed it or left it in a bad state
return 3;
}
fprintf(stdout, "\nFirmware update completed successfully\n");
// Don't call dc_close() - the firmware update thread has already closed the device
// Calling it again causes errors like "Failed to receive the echo"
return 0;
}
void cliDownloader(const std::string &vendor, const std::string &product, const std::string &device)
{
DiveImportedModel diveImportedModel;
DiveImportedModel::connect(&diveImportedModel, &DiveImportedModel::downloadFinished, [] {
// do something useful at the end of the download
printf("Finished\n");
});
auto data = diveImportedModel.thread.data();
data->setVendor(QString::fromStdString(vendor));
data->setProduct(QString::fromStdString(product));
data->setBluetoothMode(false);
if (data->vendor() == "Uemis") {
QString devname = QString::fromStdString(device);
int colon = devname.indexOf(QStringLiteral(":\\ (UEMISSDA)"));
if (colon >= 0) {
devname.truncate(colon + 2);
fprintf(stderr, "shortened devname to \"%s\"", qPrintable(devname));
}
data->setDevName(devname);
} else {
data->setDevName(QString::fromStdString(device));
}
// some assumptions - should all be configurable
data->setForceDownload(false);
data->setSaveLog(true);
data->setSaveDump(false);
data->setSyncTime(false);
diveImportedModel.startDownload();
diveImportedModel.waitForDownload();
diveImportedModel.recordDives();
}