Index: sources/device/DeviceController.cpp =================================================================== diff -u -r5a4a26f106ba03759e3a89b19690fa678f8a3aca -r7fb3037f90ac302238f618243a137bee1653ca2b --- sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 5a4a26f106ba03759e3a89b19690fa678f8a3aca) +++ sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 7fb3037f90ac302238f618243a137bee1653ca2b) @@ -173,7 +173,7 @@ { // disabled coco begin validated: Needed User Interaction so tested manually // This function cannot be tested on any device other than target - // because only on device the usb is /dev/sdX# and others are mmblk___ + // because only on device the usb is /dev/sdX# and others are mmcblk___ // but on VM and normal Linuxes all drives are /dev/sdX# and cannot be identified as USB. // And the difference between how USB is detected and sd-card is that // for the USB we need to look into /dev/sdX# @@ -244,21 +244,19 @@ */ void DeviceController::usbCheck() { - // disabled coco begin validated: Needed User Interaction so tested manually QString device = ""; usbSpaceCheck(); if (usbSeek(device)) { - if (! _umounted ) { + if (! _umounted ) { // avoid to mount the USB which has just been unmounted usbMount(device); - } else { + } else { // the umount is requested? usbUmount(USB_Mount_Point); } } else { if ( ! _removed ) { usbRemove(); } } - // disabled coco end } /*! @@ -410,29 +408,10 @@ * \param vDevice - USB device to be mounted (e.g. /dev/sda1) * \return true on successful mount */ -bool DeviceController::usbMount(const QString &vDevice) +void DeviceController::usbMount(const QString &vDevice) { - // disabled coco begin validated: This needs user interaction to plug-in the USB device - // has been tested manually - bool ok; - _usbDrive = vDevice.toLatin1().constData(); - ok = ::mount(_usbDrive, USB_Mount_Point, USB_File_System, - MS_SYNCHRONOUS | - MS_NOEXEC | // Disallow program execution - MS_NODEV | - MS_NOSUID , // Setting this option on a file system prevents users from introducing privileged programs onto the system and allowing non-root users to execute them. - "") == 0; - if (ok) { - _mounted = true; - _removed = false; - LOG_DEBUG(QString("USB flash drive %1 has been mounted on %2").arg(vDevice).arg(USB_Mount_Point)); - emit didUSBDriveMount(); - } else { - usbError(vDevice); - } - return ok; + usbMountReq(vDevice); } -// disabled coco end /*! * \brief DeviceController::usbUmount @@ -441,23 +420,10 @@ * \param vDevice - USB device to be unmounted (e.g. /dev/sda1) * \return true on successful unmount */ -bool DeviceController::usbUmount(const QString &vDevice) +void DeviceController::usbUmount(const QString &vDevice) { - // disabled coco begin validated: This needs user interaction to plug-out the USB device - // has been tested manually - bool ok; - ok = ::umount(vDevice.toLatin1().constData()) == 0; - if (ok) { - _mounted = false; - LOG_DEBUG(QString("USB drive %2 unmounted").arg(vDevice)); - emit didUSBDriveUmount(); - } else { - // the error is irrelevant, commented out for now - //usbError(vDevice); - } - return ok; + usbMountReq(vDevice, false); } -// disabled coco end /*! * \brief DeviceController::usbRemove @@ -888,11 +854,6 @@ } ///////////////////////////////////////////// DeviceFactoryReset -/*! - * \brief DeviceController::onAttributeRequest - * \details Calls the FactoryReset script with the model data DeviceFactoryResetRequestData - * \param vData - the model data - */ void DeviceController::onAttributeRequest(const DeviceFactoryResetRequestData &vData) { _deviceFactoryResetRequest._data = vData; @@ -941,11 +902,6 @@ } ///////////////////////////////////////////// DeviceDecommission -/*! - * \brief DeviceController::onAttributeRequest - * \details Calls the decommission script with the model data DeviceDecommissionRequestData - * \param vData - the model data - */ void DeviceController::onAttributeRequest(const DeviceDecommissionRequestData &vData) { _deviceDecommissionRequest._data = vData; @@ -993,3 +949,89 @@ didAttributeResponse(model.data()); LOG_APPED_UI(model.data().mMessage); } + +///////////////////////////////////////////// DeviceUSBMounting +void DeviceController::onAttributeRequest(const DeviceUSBMountRequestData &vData) +{ + Q_UNUSED(vData) + usbMountReq(vData.usbDevice, vData.isMountRequest); +} + +/*! + * \brief DeviceController::usbMountReq + * \details Calls the Usb unmount/mount script + * \param vIsMount - indicate if the request is for mounting or unmounting + * \param vDevice - the path to the USB device + */ +void DeviceController::usbMountReq(const QString &vDevice, bool vIsMount) +{ + qDebug() << __FUNCTION__ << vDevice << vIsMount; + _deviceUSBMountRequest._data.isMountRequest = vIsMount ; + _deviceUSBMountRequest._data.usbDevice = vDevice ; // not necessary, but to be consistent + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, (vIsMount ? USB_Mount : USB_Unmount )), _deviceUSBMountResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processUSBMount.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceUSBMountResponse); + return; + } + + // ----- run the process + int timeout_ms = 5000; + TimedProcess *timedProcess = new TimedProcess(&_processUSBMount, script, timeout_ms, {vDevice, USB_Mount_Point, USB_File_System}); + timedProcess->start(); + + MDeviceUSBMountResponse model; + model._data.mAccepted = false; + model._data.mMessage = vIsMount ? tr("USB unmount started.") : tr("USB mount started"); + didAttributeResponse(model.data()); +} + +/*! + * \brief DeviceController::onProcessFactoryResetExitCode + * \param vExitCode + * \param vStatus + */ +void DeviceController::onProcessUSBMountExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + MDeviceUSBMountResponse model; + QByteArray deviceInfo = _processUSBMount.readAll(); + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processUSBMount.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + didAttributeResponse(model.data()); + + // Re-evaluate the USB space available - need to call this here to avoid + // visual lag caused by waiting to call this function on the timer timeout + usbSpaceCheck(); + + bool ok = ! vStatus; + QString usbDevice = _deviceUSBMountRequest._data.usbDevice; + if(_deviceUSBMountRequest._data.isMountRequest) { // *** USB Mount + if ( ok ) { + _mounted = true; + _removed = false; + LOG_DEBUG(QString("USB flash drive %1 has been mounted on %2").arg(usbDevice).arg(USB_Mount_Point)); + emit didUSBDriveMount(); + } else { + usbError(usbDevice); + } + } else { // *** USB Unmount + if ( ok ) { + _mounted = false; + // _umounted = true; // I think it might be needed, but needs more testing. + LOG_DEBUG(QString("USB drive %2 unmounted").arg(usbDevice)); + emit didUSBDriveUmount(); + } else { + // the error is irrelevant, commented out for now + // usbError(usbDrive); + } + } + + // log error and exit + return; +} Index: sources/device/DeviceController.h =================================================================== diff -u -rfb43510552969e9fb3c3f10ae693ba81ea7e8d52 -r7fb3037f90ac302238f618243a137bee1653ca2b --- sources/device/DeviceController.h (.../DeviceController.h) (revision fb43510552969e9fb3c3f10ae693ba81ea7e8d52) +++ sources/device/DeviceController.h (.../DeviceController.h) (revision 7fb3037f90ac302238f618243a137bee1653ca2b) @@ -100,7 +100,6 @@ bool _mounted = false; bool _umounted = false; bool _removed = false; - const char *_usbDrive = ""; const int _interval = 1000; // in ms const qint8 _minRequiredAvailableSpacePercent = 10; @@ -256,13 +255,13 @@ private: // ----- USB - void usbCheck(); + void usbCheck (); + void usbError (const QString &vDevice ); + void usbMountReq(const QString &vDevice, bool vIsMount = true ); + void usbMount (const QString &vDevice ); + void usbUmount (const QString &vDevice ); + void usbRemove (); - bool usbMount (const QString &vDevice); - bool usbUmount(const QString &vDevice); - void usbRemove(); - void usbError (const QString &vDevice); - void sdcardSpaceCheck(); void usbSpaceCheck(); Index: sources/device/DeviceGlobals.h =================================================================== diff -u -r5a4a26f106ba03759e3a89b19690fa678f8a3aca -r7fb3037f90ac302238f618243a137bee1653ca2b --- sources/device/DeviceGlobals.h (.../DeviceGlobals.h) (revision 5a4a26f106ba03759e3a89b19690fa678f8a3aca) +++ sources/device/DeviceGlobals.h (.../DeviceGlobals.h) (revision 7fb3037f90ac302238f618243a137bee1653ca2b) @@ -172,6 +172,7 @@ DEVICE_DEV_PARENT ( RootSSHAccess ) \ DEVICE_DEV_PARENT ( FactoryReset ) \ DEVICE_DEV_PARENT ( Decommission ) \ + DEVICE_DEV_PARENT ( USBMount ) \ #define DEVICE_DEV_INIT_CONNECTIONS_LIST \ DEVICE_DEV_INIT_CONNECTIONS ( Brightness ) \ @@ -181,6 +182,7 @@ DEVICE_DEV_INIT_CONNECTIONS ( RootSSHAccess ) \ DEVICE_DEV_INIT_CONNECTIONS ( FactoryReset ) \ DEVICE_DEV_INIT_CONNECTIONS ( Decommission ) \ + DEVICE_DEV_INIT_CONNECTIONS ( USBMount ) \ #define DEVICE_DEV_DEFINITION_LIST \ DEVICE_DEV_DEFINITION ( Brightness ) \ @@ -190,6 +192,7 @@ DEVICE_DEV_DEFINITION ( RootSSHAccess ) \ DEVICE_DEV_DEFINITION ( FactoryReset ) \ DEVICE_DEV_DEFINITION ( Decommission ) \ + DEVICE_DEV_DEFINITION ( USBMount ) \ /* ---------------------------- APP */ @@ -210,6 +213,7 @@ DEVICE_APP_BRIDGE_DEFINITION( RootSSHAccess ) \ DEVICE_APP_BRIDGE_DEFINITION( FactoryReset ) \ DEVICE_APP_BRIDGE_DEFINITION( Decommission ) \ + DEVICE_APP_BRIDGE_DEFINITION( USBMount ) \ /* ---------------------------- GUI */ #define DEVICE_GUI_BRIDGE_DEFINITION_LIST \ @@ -236,7 +240,7 @@ DEVICE_VIEW_INIT_CONNECTIONS( BluetoothPairedReset ) \ DEVICE_VIEW_INIT_CONNECTIONS( BluetoothPairedQuery ) \ DEVICE_VIEW_INIT_CONNECTIONS( CryptSetup ) \ - DEVICE_VIEW_INIT_CONNECTIONS( RootSSHAccess ) \ + DEVICE_VIEW_INIT_CONNECTIONS( RootSSHAccess ) \ DEVICE_VIEW_INIT_CONNECTIONS( FactoryReset ) \ DEVICE_VIEW_INIT_CONNECTIONS( Decommission ) \ Index: sources/device/DeviceModels.cpp =================================================================== diff -u -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 -r7fb3037f90ac302238f618243a137bee1653ca2b --- sources/device/DeviceModels.cpp (.../DeviceModels.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) +++ sources/device/DeviceModels.cpp (.../DeviceModels.cpp) (revision 7fb3037f90ac302238f618243a137bee1653ca2b) @@ -252,3 +252,33 @@ lOut: return _data.mAccepted; } + +/*! + * \brief MDeviceUSBMountResponse::fromByteArray + * \details Checks the response and sets up the mode data. + * \param vExitCode - Passed script exit code + * \return true if passed. + */ +bool MDeviceUSBMountResponse::fromByteArray(const QByteArray &vByteArray, int *vExitCode) +{ + // initialize data + int error = 0; + _data.mAccepted = false; + + // check if the vExitCode passed and it has a value other than zero + if ( vExitCode && *vExitCode ){ _data.mReason = Device::DeviceError::eDevice_USBMount_Error; error = *vExitCode; } + else _data.mReason = Device::DeviceError::eDevice_OK; + + // if vExitCode is not zero go to error since the data is no longer valid + if ( _data.mReason ) goto lError; // non-zero Exit code + + // Now everything is good to extract the data + _data.mAccepted = true; + _data.mMessage = QObject::tr("The USB (un)mount Command Complete."); goto lOut ; // normal return + +lError: + _data.mMessage = Device::DeviceError::deviceErrorText(static_cast(_data.mReason), error) + "\n" + vByteArray; + +lOut: + return _data.mAccepted; +} Index: sources/device/DeviceModels.h =================================================================== diff -u -r5a4a26f106ba03759e3a89b19690fa678f8a3aca -r7fb3037f90ac302238f618243a137bee1653ca2b --- sources/device/DeviceModels.h (.../DeviceModels.h) (revision 5a4a26f106ba03759e3a89b19690fa678f8a3aca) +++ sources/device/DeviceModels.h (.../DeviceModels.h) (revision 7fb3037f90ac302238f618243a137bee1653ca2b) @@ -337,9 +337,39 @@ Data data ( ) const { return _data; } bool fromByteArray(const QByteArray &vByteArray, int *vExitCode = nullptr) override; }; -} +// ---------- MDeviceUSBMount ---------- // +/*! + * \brief The MDeviceUSBMountRequest class + * \details The model for the usb unmount/mount script call. + */ +class MDeviceUSBMountRequest : public MDeviceRequestBase { +public: + struct Data { + bool isMountRequest = true; + QString usbDevice = "" ; + } _data; + QString toString() { + return MDeviceRequestBase::toString("UsbMount", { _data.usbDevice, _data.isMountRequest }); + } +}; + +/*! + * \brief The MDeviceUSBMountResponse class + * \details The model for the usb mount/unmount script call returned value / response. + */ +class MDeviceUSBMountResponse : public MDeviceResponseBase { +public: + struct Data : MDeviceResponseBase::Data { + } _data; + QVariantList parameters ( ) const override { return { }; } + QString infoText ( ) const override { return QString("DeviceUsbMount"); } + Data data ( ) const { return _data; } + bool fromByteArray(const QByteArray &vByteArray, int *vExitCode = nullptr) override; +}; +} + typedef Model::MDeviceResponseBase ::Data DeviceResponseBaseData ; typedef Model::MDeviceBrightnessRequest ::Data DeviceBrightnessRequestData ; @@ -362,3 +392,6 @@ typedef Model::MDeviceDecommissionRequest ::Data DeviceDecommissionRequestData ; typedef Model::MDeviceDecommissionResponse::Data DeviceDecommissionResponseData; + +typedef Model::MDeviceUSBMountRequest ::Data DeviceUSBMountRequestData ; +typedef Model::MDeviceUSBMountResponse::Data DeviceUSBMountResponseData; Index: sources/storage/StorageGlobals.cpp =================================================================== diff -u -r1f5b2250ae70d305654d014a9aa1fd8baa29779c -r7fb3037f90ac302238f618243a137bee1653ca2b --- sources/storage/StorageGlobals.cpp (.../StorageGlobals.cpp) (revision 1f5b2250ae70d305654d014a9aa1fd8baa29779c) +++ sources/storage/StorageGlobals.cpp (.../StorageGlobals.cpp) (revision 7fb3037f90ac302238f618243a137bee1653ca2b) @@ -200,4 +200,8 @@ const char *CloudSyncPath = "/var/configurations/CloudSync/credentials/"; + // USB unmount/ mount + const char *USB_Unmount = "usb_unmount.sh"; + const char *USB_Mount = "usb_mount.sh"; + } Index: sources/storage/StorageGlobals.h =================================================================== diff -u -r1f5b2250ae70d305654d014a9aa1fd8baa29779c -r7fb3037f90ac302238f618243a137bee1653ca2b --- sources/storage/StorageGlobals.h (.../StorageGlobals.h) (revision 1f5b2250ae70d305654d014a9aa1fd8baa29779c) +++ sources/storage/StorageGlobals.h (.../StorageGlobals.h) (revision 7fb3037f90ac302238f618243a137bee1653ca2b) @@ -137,4 +137,8 @@ extern const char *CloudSyncPath; + // USB mount/unmount + extern const char *USB_Unmount; + extern const char *USB_Mount; + }