/*! * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, * IN PART OR IN WHOLE, * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * file usbwatcher.cpp * date 12/31/2019 * author Behrouz NematiPour * */ #include "usbwatcher.h" // Linux #include #include // Qt #include #include // Project #include "storageglobals.h" #include "logger.h" #include "applicationcontroller.h" // namespace using namespace Storage; USBWatcher::USBWatcher(QObject *parent) : QObject(parent) { startTimer(_checkInterval); } bool USBWatcher::init() { // runs in main thread Q_ASSERT_X(QThread::currentThread() == qApp->thread() , "_USBWatcher::init", "The Class initialization must be done in Main Thread" ); _USBWatcher_Thread.setObjectName("USB Watcher Thread"); connect(qApp, &QApplication::aboutToQuit, this, &USBWatcher::quit); _USBWatcher_Thread.start(); moveToThread(&_USBWatcher_Thread); // runs in USBWatcher thread initConnections(); return true; } void USBWatcher::quit() { // runs in Logger thread moveToThread(qApp->thread()); // runs in main thread _USBWatcher_Thread.quit(); _USBWatcher_Thread.wait(); } void USBWatcher::initConnections() { connect(&_ApplicationController, SIGNAL(didUSBDriveUmount()), this , SLOT( onUSBDriveUmount())); } bool USBWatcher::isMounted() const { return _mounted; } bool USBWatcher::isUmounted() const { return _umounted; } bool USBWatcher::usbSeek(QString &vDevice) { PRINT_THREAD_NAME; QString device = ""; for (char a = 'a'; a <= 'z'; a++) { device = QString("/dev/sd%1%2").arg(a).arg('1'); if (QFileInfo::exists(device)) { vDevice = device; return true; // application is deciding on the first existing drive } } vDevice = device; return false; } void USBWatcher::timerEvent(QTimerEvent *) { PRINT_THREAD_NAME; usbcheck(); } void USBWatcher::usbcheck() { PRINT_THREAD_NAME; QString device = ""; if (usbSeek(device)) { if (! _umounted ) { usbMount(device); } else { usbUmount(USB_Mount_Point); } } else { if ( ! _removed ) { usbRemove(); } } } void USBWatcher::usbError(const QString &vDevice) { QString error; static QString lastError; switch (errno) { case EBUSY: error = tr("%1 - Device or resource busy (%2)").arg(errno).arg(vDevice); _mounted = true; break; default: error = tr("%1 - %2 (%3 , %4)").arg(errno).arg(strerror(errno)).arg(vDevice).arg(USB_Mount_Point); break; } if (error != lastError) { LOG_ERROR(error); lastError = error; } } void USBWatcher::onUSBDriveUmount() { _umounted = true; } bool USBWatcher::usbMount(const QString &vDevice) { PRINT_THREAD_NAME; bool ok; _usbDrive = vDevice.toLatin1().constData(); ok = mount(_usbDrive, USB_Mount_Point, USB_File_System, 0, "") == 0; if (ok) { _mounted = true; _removed = false; LOG_EVENT(tr("USB flash drive %1 has been mounted on %2").arg(vDevice).arg(USB_Mount_Point)); emit didUSBDriveMount(); } else { usbError(vDevice); } return ok; } bool USBWatcher::usbUmount(const QString &vDevice) { PRINT_THREAD_NAME; bool ok; ok = umount(vDevice.toLatin1().constData()) == 0; if (ok) { _mounted = false; LOG_EVENT(tr("USB drive unmounted")); emit didUSBDriveUmount(); } else { // the error is irrelevant, commented out for now //usbError(vDevice); } return ok; } void USBWatcher::usbRemove() { PRINT_THREAD_NAME; usbUmount(USB_Mount_Point); _umounted = false; _removed = true; LOG_EVENT(tr("USB drive removed")); emit didUSBDriveRemove(); }