Index: denali.qrc =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- denali.qrc (.../denali.qrc) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ denali.qrc (.../denali.qrc) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -22,6 +22,7 @@ sources/gui/qml/pages/settings/SettingsServicePassword.qml sources/gui/qml/pages/settings/SettingsManufacturingSetup.qml sources/gui/qml/pages/settings/SettingsFactoryReset.qml + sources/gui/qml/pages/settings/SettingsDecommission.qml sources/gui/qml/dialogs/PowerOff.qml Index: scripts/decommission.sh =================================================================== diff -u --- scripts/decommission.sh (revision 0) +++ scripts/decommission.sh (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -0,0 +1,53 @@ +#!/bin/sh +########################################################################### +# +# Copyright (c) 2021-2023 Diality Inc. - All Rights Reserved. +# +# 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 decommission.sh +# +# @author (last) Vy Duong +# @date (last) 26-May-2023 +# @author (original) Vy Duong +# @date (original) 26-May-2023 +# +############################################################################ + +# @details +# This file is called by UI Software to remove and reset the device to a decommissioned state + +LOC_PARTITION="/dev/mmcblk0p7" +LOC_SETTINGS_CONF="/home/root/scripts/settings.conf" #TODO update to reflect real location +LOC_DEFAULT_SETTINGS_CONF="/home/root/scripts/default_settings.conf" #TODO update to reflect real location +LOC_WIFI_CONF="/etc/wpa_supplicant/wpa_supplicant-wlan0.conf" +LOC_BLUETOOTH_CONF="/etc/bluetooth/main.conf" + +# ------------------------------ Remove Wifi Conf +if [ -f $LOC_WIFI_CONF ]; then + rm "$LOC_WIFI_CONF" + echo "Deleted Wifi Conf" +fi + +# ------------------------------ Remove Bluetooth Conf +if [ -f $LOC_BLUETOOTH_CONF ]; then + rm "$LOC_BLUETOOTH_CONF" + echo "Deleted Bluetooth Conf" +fi + +# ------------------------------ Reset Settings Conf +cp $LOC_DEFAULT_SETTINGS_CONF $LOC_SETTINGS_CONF + +# ------------------------------ Remove Logs +rm -rf /media/sd-card/*/* + +# ------------------------------ Format Former Encrypted Partition + +# Assuming the partition is decrypted in advance +#mkfs.ext4 $LOC_PARTITION ## NEED TO Re-eval. since it might ask yes/no...and expect answer..can do force, but dangerous + +# ------------------------------ Remove CloudSync Token +# TODO remove the cloudsync token ? Need additional info on how + +exit 0 Index: sources/device/DeviceController.cpp =================================================================== diff -u -r2038a8a2dcec5a461868b0150ad6fbfc2bfd8707 -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 2038a8a2dcec5a461868b0150ad6fbfc2bfd8707) +++ sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -777,3 +777,56 @@ didAttributeResponse(model.data()); LOG_APPED_UI(model.data().mMessage); } + +///////////////////////////////////////////// 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; + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, Device_Decommission), _deviceDecommissionResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processDecommission.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceDecommissionResponse); + return; + } + + + // ----- run the process + int timeout_ms = 10000; + TimedProcess *timedProcess = new TimedProcess(&_processDecommission, script, timeout_ms); + timedProcess->start(); + + MDeviceDecommissionResponse model; + model._data.mAccepted = false; // will indirectly set the property decommissionEnabled + model._data.mMessage = tr("Decommissioning started."); + didAttributeResponse(model.data()); +} + +/*! + * \brief DeviceController::onProcessDecommissionExitCode + * \param vExitCode + * \param vStatus + */ +void DeviceController::onProcessDecommissionExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + // The Exit code in this script is not used. + // any other checking is done by UI Software at the moment this script is called. + // The only thing matters is the paired device info in text and it will be empty string if error happens. + MDeviceDecommissionResponse model; + QByteArray deviceInfo = _processDecommission.readAll(); + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processDecommission.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + // DEBUG: qDebug() << model._data.mMessage << deviceInfo; + didAttributeResponse(model.data()); + LOG_APPED_UI(model.data().mMessage); +} Index: sources/device/DeviceError.h =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/device/DeviceError.h (.../DeviceError.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/device/DeviceError.h (.../DeviceError.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -64,6 +64,7 @@ eDevice_CryptSetup_Error , eDevice_FactoryReset_Error , + eDevice_Decommission_Error , eDevice_Error_End Index: sources/device/DeviceGlobals.h =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/device/DeviceGlobals.h (.../DeviceGlobals.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/device/DeviceGlobals.h (.../DeviceGlobals.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -176,35 +176,41 @@ DEVICE_DEV_PARENT ( BluetoothPairedQuery ) \ DEVICE_DEV_PARENT ( CryptSetup ) \ DEVICE_DEV_PARENT ( FactoryReset ) \ + DEVICE_DEV_PARENT ( Decommission ) \ #define DEVICE_DEV_INIT_CONNECTIONS_LIST \ DEVICE_DEV_INIT_CONNECTIONS ( Brightness ) \ DEVICE_DEV_INIT_CONNECTIONS ( BluetoothPairedReset ) \ DEVICE_DEV_INIT_CONNECTIONS ( BluetoothPairedQuery ) \ DEVICE_DEV_INIT_CONNECTIONS ( CryptSetup ) \ DEVICE_DEV_INIT_CONNECTIONS ( FactoryReset ) \ + DEVICE_DEV_INIT_CONNECTIONS ( Decommission ) \ #define DEVICE_DEV_DEFINITION_LIST \ DEVICE_DEV_DEFINITION ( Brightness ) \ DEVICE_DEV_DEFINITION ( BluetoothPairedReset ) \ DEVICE_DEV_DEFINITION ( BluetoothPairedQuery ) \ DEVICE_DEV_DEFINITION ( CryptSetup ) \ DEVICE_DEV_DEFINITION ( FactoryReset ) \ + DEVICE_DEV_DEFINITION ( Decommission ) \ + /* ---------------------------- APP */ #define DEVICE_APP_INIT_CONNECTIONS_LIST \ DEVICE_APP_INIT_CONNECTIONS ( Brightness ) \ DEVICE_APP_INIT_CONNECTIONS ( BluetoothPairedReset ) \ DEVICE_APP_INIT_CONNECTIONS ( BluetoothPairedQuery ) \ DEVICE_APP_INIT_CONNECTIONS ( CryptSetup ) \ DEVICE_APP_INIT_CONNECTIONS ( FactoryReset ) \ + DEVICE_APP_INIT_CONNECTIONS ( Decommission ) \ #define DEVICE_APP_BRIDGE_DEFINITION_LIST \ DEVICE_APP_BRIDGE_DEFINITION( Brightness ) \ DEVICE_APP_BRIDGE_DEFINITION( BluetoothPairedReset ) \ DEVICE_APP_BRIDGE_DEFINITION( BluetoothPairedQuery ) \ DEVICE_APP_BRIDGE_DEFINITION( CryptSetup ) \ DEVICE_APP_BRIDGE_DEFINITION( FactoryReset ) \ + DEVICE_APP_BRIDGE_DEFINITION( Decommission ) \ /* ---------------------------- GUI */ #define DEVICE_GUI_BRIDGE_DEFINITION_LIST \ @@ -213,13 +219,15 @@ DEVICE_GUI_BRIDGE_DEFINITION( BluetoothPairedQuery ) \ DEVICE_GUI_BRIDGE_DEFINITION( CryptSetup ) \ DEVICE_GUI_BRIDGE_DEFINITION( FactoryReset ) \ + DEVICE_GUI_BRIDGE_DEFINITION( Decommission ) \ #define DEVICE_GUI_INIT_CONNECTIONS_LIST \ DEVICE_GUI_INIT_CONNECTIONS ( Brightness ) \ DEVICE_GUI_INIT_CONNECTIONS ( BluetoothPairedReset ) \ DEVICE_GUI_INIT_CONNECTIONS ( BluetoothPairedQuery ) \ DEVICE_GUI_INIT_CONNECTIONS ( CryptSetup ) \ DEVICE_GUI_INIT_CONNECTIONS ( FactoryReset ) \ + DEVICE_GUI_INIT_CONNECTIONS ( Decommission ) \ /* ---------------------------- VIEW */ #define DEVICE_VIEW_INIT_CONNECTIONS_LIST \ @@ -228,4 +236,5 @@ DEVICE_VIEW_INIT_CONNECTIONS( BluetoothPairedQuery ) \ DEVICE_VIEW_INIT_CONNECTIONS( CryptSetup ) \ DEVICE_VIEW_INIT_CONNECTIONS( FactoryReset ) \ + DEVICE_VIEW_INIT_CONNECTIONS( Decommission ) \ Index: sources/device/DeviceModels.cpp =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/device/DeviceModels.cpp (.../DeviceModels.cpp) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/device/DeviceModels.cpp (.../DeviceModels.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -221,3 +221,34 @@ lOut: return _data.mAccepted; } + + +/*! + * \brief MDeviceDecommissionResponse::fromByteArray + * \details Checks the response and sets up the mode data. + * \param vExitCode - Passed script exit code + * \return true if passed. + */ +bool MDeviceDecommissionResponse::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_FactoryReset_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 Decommissioning 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 -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/device/DeviceModels.h (.../DeviceModels.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/device/DeviceModels.h (.../DeviceModels.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -254,7 +254,6 @@ class MDeviceFactoryResetRequest : public MDeviceRequestBase { public: struct Data { - QString mCommand = ""; } _data; QString toString() { @@ -264,7 +263,7 @@ /*! * \brief The MDeviceFactoryResetResponse class - * \details The model for the CryptSetup script call returned value / response. + * \details The model for the factory reset script call returned value / response. */ class MDeviceFactoryResetResponse : public MDeviceResponseBase { public: @@ -275,11 +274,39 @@ Data data ( ) const { return _data; } bool fromByteArray(const QByteArray &vByteArray, int *vExitCode = nullptr) override; }; -} +// ---------- MDeviceDecommission ---------- // +/*! + * \brief The MDeviceDecommissionRequest class + * \details The model for the decommission script call. + */ +class MDeviceDecommissionRequest : public MDeviceRequestBase { +public: + struct Data { + } _data; + QString toString() { + return MDeviceRequestBase::toString("DeviceDecommission", { }); + } +}; +/*! + * \brief The MDeviceDecommissionResponse class + * \details The model for the decommission script call returned value / response. + */ +class MDeviceDecommissionResponse : public MDeviceResponseBase { +public: + struct Data : MDeviceResponseBase::Data { + } _data; + QVariantList parameters ( ) const override { return { }; } + QString infoText ( ) const override { return QString("DeviceDecommission"); } + Data data ( ) const { return _data; } + bool fromByteArray(const QByteArray &vByteArray, int *vExitCode = nullptr) override; +}; +} + + typedef Model::MDeviceResponseBase ::Data DeviceResponseBaseData ; typedef Model::MDeviceBrightnessRequest ::Data DeviceBrightnessRequestData ; typedef Model::MDeviceBrightnessResponse::Data DeviceBrightnessResponseData ; @@ -295,3 +322,6 @@ typedef Model::MDeviceFactoryResetRequest ::Data DeviceFactoryResetRequestData ; typedef Model::MDeviceFactoryResetResponse::Data DeviceFactoryResetResponseData; + +typedef Model::MDeviceDecommissionRequest ::Data DeviceDecommissionRequestData ; +typedef Model::MDeviceDecommissionResponse::Data DeviceDecommissionResponseData; Index: sources/device/DeviceView.cpp =================================================================== diff -u -rc849da4382b19f1e0cf36c39e7975b337bf6bec0 -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/device/DeviceView.cpp (.../DeviceView.cpp) (revision c849da4382b19f1e0cf36c39e7975b337bf6bec0) +++ sources/device/DeviceView.cpp (.../DeviceView.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -169,3 +169,31 @@ DeviceFactoryResetRequestData data; emit didAttributeRequest(data); } + +// ================================================= Decommission +void VDevice::doInitDecommission() { + // Nothing for now. +} + +void VDevice::onAttributeResponse(const DeviceDecommissionResponseData &vData) { + qDebug() << "HERE Response " << Q_FUNC_INFO << " accepted: "<< vData.mAccepted << vData.mReason; + // this has to be called to let Gui to set to old value that device controller provided. + status(vData.mMessage); + + // Either the script exited successfully or the script failed and the reason is provided + decommissionEnabled(vData.mAccepted || (!vData.mAccepted && vData.mReason!=0)); + + accepted(vData.mAccepted); + reason (vData.mReason ); + + // has to be the last one + response(true); +} + +void VDevice::decommissionRequest(const QString &vCommand) { + Q_UNUSED(vCommand) + // DEBUG : qDebug() << "HERE Request" << vCommand; + DeviceDecommissionRequestData data; + emit didAttributeRequest(data); +} + Index: sources/device/DeviceView.h =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/device/DeviceView.h (.../DeviceView.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/device/DeviceView.h (.../DeviceView.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -53,6 +53,9 @@ ATTRIBUTE ( QString , factoryReset , "", FactoryReset ) PROPERTY ( bool , factoryResetEnabled , true ) + ATTRIBUTE ( QString , decommission , "", Decommission ) + PROPERTY ( bool , decommissionEnabled , true ) + VIEW_DEC_CLASS(VDevice) }; } Index: sources/gui/qml/pages/settings/SettingsDecommission.qml =================================================================== diff -u --- sources/gui/qml/pages/settings/SettingsDecommission.qml (revision 0) +++ sources/gui/qml/pages/settings/SettingsDecommission.qml (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -0,0 +1,47 @@ +/*! + * + * Copyright (c) 2021-2023 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 SettingsDecommission.qml + * \author (last) Vy Duong + * \date (last) 09-Jun-2023 + * \author (original) Vy Duong + * \date (original) 09-Jun-2023 + * + */ + +// Qt +import QtQuick 2.12 + +// Qml imports +import "qrc:/globals" +import "qrc:/pages" +import "qrc:/components" + +/*! + * \brief SettingsDecommission is the screen + * which asks for confirmation of performing a factory reset and doing it if confirmed + */ +UserConfirmation{ id: _root + title : qsTr("Device Decommissioning") + message : vDevice.factoryResetEnabled ? qsTr("Do you want to perform a decommissioning of this device?") + : qsTr("Decommissioning...") + itemIndex : SettingsStack.Decommission + notificationText : vDevice.status + + confirmVisible : true + confirmEnabled : vDevice.decommissionEnabled + onConfirmClicked : { + vDevice.decommission = "start" + + // restore the binding; notificationText will now be bind to vDevice.status and correctly update + _root.notificationText = Qt.binding(function(){return vDevice.status}) + } + + backVisible : true + backEnabled : vDevice.decommissionEnabled + onBackClicked : _root.notificationText = "" // Note: breaks binding of notificationText property +} Index: sources/gui/qml/pages/settings/SettingsStack.qml =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/gui/qml/pages/settings/SettingsStack.qml (.../SettingsStack.qml) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/gui/qml/pages/settings/SettingsStack.qml (.../SettingsStack.qml) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -54,7 +54,8 @@ DeviceConfiguration , DeviceRegistration , SWUpdate , - FactoryReset + FactoryReset , + Decommission } property var itemsText : [ qsTr("Information" ), // Information @@ -72,6 +73,7 @@ qsTr("Device Registration" ), // DeviceRegistration qsTr("Software Update" ), // SWUpdate qsTr("Factory Reset" ), // FactoryReset + qsTr("Decommission" ), // Decommission ] property var itemsEnabled : [ true , // Information @@ -89,6 +91,7 @@ true , // DeviceRegistration false , // SWUpdate serviceMode , // FactoryReset + serviceMode , // Decommission ] property var itemsVisible : [ true , // Information @@ -106,6 +109,7 @@ _GuiView.manufactMode && serviceMode , // DeviceRegistration // && serviceMode added to make sure the service mode is confirmed by HD false /* serviceMode phase 1 */ , // SWUpdate _GuiView.manufactMode && serviceMode , // FactoryReset + _GuiView.manufactMode && serviceMode , // Decommission ] SettingsHome { id : _settingsHome @@ -173,6 +177,10 @@ push( _serviceFactoryReset ) break + case SettingsStack.Decommission: + push( _serviceDecommission ) + break + default: console.debug("Unknown Index", vIndex) break @@ -192,6 +200,7 @@ SettingsDeviceRegistration { id: _settingsDeviceRegistration } SettingsServicePassword { id: _servicePassword } SettingsFactoryReset { id: _serviceFactoryReset } + SettingsDecommission { id: _serviceDecommission } function gotoServiceMode( vservice ) { if ( ! _servicePassword.isPassword_Accepted ) return Index: sources/model/MModel.h =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/model/MModel.h (.../MModel.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/model/MModel.h (.../MModel.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -288,6 +288,8 @@ REGISTER_METATYPE( DeviceCryptSetupResponseData ) \ REGISTER_METATYPE( DeviceFactoryResetRequestData) \ REGISTER_METATYPE( DeviceFactoryResetResponseData) \ + REGISTER_METATYPE( DeviceDecommissionRequestData) \ + REGISTER_METATYPE( DeviceDecommissionResponseData) \ /* Settings */ \ REGISTER_METATYPE( SettingsData ) \ REGISTER_METATYPE( WifiNetworkData ) \ Index: sources/storage/StorageGlobals.cpp =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/storage/StorageGlobals.cpp (.../StorageGlobals.cpp) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/storage/StorageGlobals.cpp (.../StorageGlobals.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -166,4 +166,7 @@ // Factory Reset const char *Factory_Reset = "factory_reset.sh"; + // Device Decommissioning + const char *Device_Decommission = "decommission.sh"; + } Index: sources/storage/StorageGlobals.h =================================================================== diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6 --- sources/storage/StorageGlobals.h (.../StorageGlobals.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db) +++ sources/storage/StorageGlobals.h (.../StorageGlobals.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6) @@ -119,4 +119,8 @@ // Factory Reset extern const char *Factory_Reset; + + // Device Decommissioning + extern const char *Device_Decommission; + }