diff --git a/downloadthread.cpp b/downloadthread.cpp index aee6a94..10b427b 100644 --- a/downloadthread.cpp +++ b/downloadthread.cpp @@ -91,8 +91,24 @@ size_t DownloadThread::_curl_header_callback( void *ptr, size_t size, size_t nme return len; } +QByteArray DownloadThread::_fileGetContentsTrimmed(const QString &filename) +{ + QByteArray result; + QFile f(filename); + + if (f.exists() && f.open(f.ReadOnly)) + { + result = f.readAll().trimmed(); + f.close(); + } + + return result; +} + bool DownloadThread::_openAndPrepareDevice() { + emit preparationStatusUpdate(tr("opening drive")); + if (_filename.startsWith("/dev/")) { unmount_disk(_filename.constData()); @@ -203,11 +219,65 @@ bool DownloadThread::_openAndPrepareDevice() } #endif +#ifdef Q_OS_LINUX + /* Optional optimizations for Linux */ + + if (_filename.startsWith("/dev/")) + { + QString devname = _filename.mid(5); + + /* On some internal SD card readers CID/CSD is available, print it for debugging purposes */ + QByteArray cid = _fileGetContentsTrimmed("/sys/block/"+devname+"/device/cid"); + QByteArray csd = _fileGetContentsTrimmed("/sys/block/"+devname+"/device/csd"); + if (!cid.isEmpty()) + qDebug() << "SD card CID:" << cid; + if (!csd.isEmpty()) + qDebug() << "SD card CSD:" << csd; + + QByteArray discardmax = _fileGetContentsTrimmed("/sys/block/"+devname+"/queue/discard_max_bytes"); + + if (discardmax.isEmpty() || discardmax == "0") + { + qDebug() << "BLKDISCARD not supported"; + } + else + { + /* DISCARD/TRIM the SD card */ + uint64_t devsize, range[2]; + int fd = _file.handle(); + + if (::ioctl(fd, BLKGETSIZE64, &devsize) == -1) { + qDebug() << "Error getting device/sector size with BLKGETSIZE64 ioctl():" << strerror(errno); + } + else + { + qDebug() << "Try to perform TRIM/DISCARD on device"; + range[0] = 0; + range[1] = devsize; + emit preparationStatusUpdate(tr("discarding existing data on drive")); + _timer.start(); + if (::ioctl(fd, BLKDISCARD, &range) == -1) + { + qDebug() << "BLKDISCARD failed."; + } + else + { + qDebug() << "BLKDISCARD successful. Discarding took" << _timer.elapsed() / 1000 << "seconds"; + } + } + } + } +#endif + #ifndef Q_OS_WIN // Zero out MBR qint64 knownsize = _file.size(); QByteArray emptyMB(1024*1024, 0); + emit preparationStatusUpdate(tr("zeroing out first and last MB of drive")); + qDebug() << "Zeroing out first and last MB of drive"; + _timer.start(); + if (!_file.write(emptyMB.data(), emptyMB.size()) || !_file.flush()) { emit error(tr("Write error while zero'ing out MBR")); @@ -229,36 +299,10 @@ bool DownloadThread::_openAndPrepareDevice() } emptyMB.clear(); _file.seek(0); + qDebug() << "Done zeroing out start and end of drive. Took" << _timer.elapsed() / 1000 << "seconds"; #endif #ifdef Q_OS_LINUX - /* Optional optimizations for Linux */ - - /* See if we can DISCARD/TRIM the SD card */ - uint64_t devsize, range[2]; - int fd = _file.handle(); - - if (::ioctl(fd, BLKGETSIZE64, &devsize) == -1) { - qDebug() << "Error getting device/sector size with BLKGETSIZE64 ioctl():" << strerror(errno); - } - else - { - int secsize; - ::ioctl(fd, BLKSSZGET, &secsize); - qDebug() << "Sector size:" << secsize << "Device size:" << devsize; - - qDebug() << "Try to perform TRIM/DISCARD on device"; - range[0] = 0; - range[1] = devsize; - if (::ioctl(fd, BLKDISCARD, &range) == -1) - { - qDebug() << "BLKDISCARD not supported"; - } - else - { - qDebug() << "BLKDISCARD successful"; - } - } _sectorsStart = _sectorsWritten(); #endif @@ -303,6 +347,7 @@ void DownloadThread::run() if (!_proxy.isEmpty()) curl_easy_setopt(_c, CURLOPT_PROXY, _proxy.constData()); + emit preparationStatusUpdate(tr("starting download")); _timer.start(); CURLcode ret = curl_easy_perform(_c); diff --git a/downloadthread.h b/downloadthread.h index 2f46b95..37f52a8 100644 --- a/downloadthread.h +++ b/downloadthread.h @@ -126,6 +126,7 @@ signals: void error(QString msg); void cacheFileUpdated(QByteArray sha256); void finalizing(); + void preparationStatusUpdate(QString msg); protected: virtual void run(); @@ -140,6 +141,7 @@ protected: void _writeCache(const char *buf, size_t len); qint64 _sectorsWritten(); void _closeFiles(); + QByteArray _fileGetContentsTrimmed(const QString &filename); /* * libcurl callbacks diff --git a/imagewriter.cpp b/imagewriter.cpp index 6c2aef6..57b8adf 100644 --- a/imagewriter.cpp +++ b/imagewriter.cpp @@ -201,6 +201,8 @@ void ImageWriter::startWrite() connect(_thread, SIGNAL(success()), SLOT(onSuccess())); connect(_thread, SIGNAL(error(QString)), SLOT(onError(QString))); + connect(_thread, SIGNAL(finalizing()), SLOT(onFinalizing())); + connect(_thread, SIGNAL(preparationStatusUpdate(QString)), SLOT(onPreparationStatusUpdate(QString))); _thread->setVerifyEnabled(_verifyEnabled); _thread->setUserAgent(QString("Mozilla/5.0 rpi-imager/%1").arg(constantVersion()).toUtf8()); @@ -252,6 +254,7 @@ void ImageWriter::startWrite() _thread->start(); } + _dlnow = 0; _verifynow = 0; _polltimer.start(PROGRESS_UPDATE_INTERVAL); } @@ -403,6 +406,11 @@ void ImageWriter::onFinalizing() emit finalizing(); } +void ImageWriter::onPreparationStatusUpdate(QString msg) +{ + emit preparationStatusUpdate(msg); +} + void ImageWriter::openFileDialog() { #ifndef QT_NO_WIDGETS diff --git a/imagewriter.h b/imagewriter.h index f0c6131..10fb143 100644 --- a/imagewriter.h +++ b/imagewriter.h @@ -99,6 +99,7 @@ signals: void cancelled(); void finalizing(); void networkOnline(); + void preparationStatusUpdate(QVariant msg); protected slots: @@ -112,6 +113,7 @@ protected slots: void onCacheFileUpdated(QByteArray sha256); void onFinalizing(); void onTimeSyncReply(QNetworkReply *reply); + void onPreparationStatusUpdate(QString msg); protected: QUrl _src, _repo; diff --git a/localfileextractthread.cpp b/localfileextractthread.cpp index cc5081e..0ac86a3 100644 --- a/localfileextractthread.cpp +++ b/localfileextractthread.cpp @@ -31,6 +31,7 @@ void LocalFileExtractThread::run() if (isImage() && !_openAndPrepareDevice()) return; + emit preparationStatusUpdate(tr("opening image file")); _timer.start(); _inputfile.setFileName( QUrl(_url).toLocalFile() ); if (!_inputfile.open(_inputfile.ReadOnly)) diff --git a/main.cpp b/main.cpp index 3c4f690..5587e4e 100644 --- a/main.cpp +++ b/main.cpp @@ -158,6 +158,7 @@ int main(int argc, char *argv[]) QObject *qmlwindow = engine.rootObjects().value(0); qmlwindow->connect(&imageWriter, SIGNAL(downloadProgress(QVariant,QVariant)), qmlwindow, SLOT(onDownloadProgress(QVariant,QVariant))); qmlwindow->connect(&imageWriter, SIGNAL(verifyProgress(QVariant,QVariant)), qmlwindow, SLOT(onVerifyProgress(QVariant,QVariant))); + qmlwindow->connect(&imageWriter, SIGNAL(preparationStatusUpdate(QVariant)), qmlwindow, SLOT(onPreparationStatusUpdate(QVariant))); qmlwindow->connect(&imageWriter, SIGNAL(error(QVariant)), qmlwindow, SLOT(onError(QVariant))); qmlwindow->connect(&imageWriter, SIGNAL(success()), qmlwindow, SLOT(onSuccess())); qmlwindow->connect(&imageWriter, SIGNAL(fileSelected(QVariant)), qmlwindow, SLOT(onFileSelected(QVariant))); diff --git a/main.qml b/main.qml index 816b39f..ea87424 100644 --- a/main.qml +++ b/main.qml @@ -749,7 +749,7 @@ ApplicationWindow { cancelwritebutton.enabled = true cancelwritebutton.visible = true cancelverifybutton.enabled = true - progressText.text = qsTr("Writing... %1%").arg("0") + progressText.text = qsTr("Preparing to write..."); progressText.visible = true progressBar.visible = true progressBar.indeterminate = true @@ -831,6 +831,10 @@ ApplicationWindow { } } + function onPreparationStatusUpdate(msg) { + progressText.text = qsTr("Preparing to write... (%1)").arg(msg) + } + function resetWriteButton() { progressText.visible = false progressBar.visible = false