/*! * * Copyright (c) 2021 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 VUIPowerOnSelfTest.cpp * \author (last) Peter Lucia * \date (last) 21-May-2021 * \author (original) Peter Lucia * \date (original) 21-May-2021 * */ #include "VUIPowerOnSelfTest.h" // Qt #include #include #include // Project #include "FileHandler.h" #include "Compatible.h" using namespace View; using namespace Storage; VUIPowerOnSelfTest::VUIPowerOnSelfTest(QObject *parent) : QObject(parent) { initConnections(); powerOnSelfTests(); } void VUIPowerOnSelfTest::initConnections() { // incoming ACTION_VIEW_CONNECTION(HDRequestVersionsData) // outgoing ADJUST_VIEW_CONNECTION(AdjustUIPostFinalResultRequestData); ADJUST_VIEW_CONNECTION(AdjustUIPostReportVersionRequestData); } /*! * \brief VUIPowerOnSelfTest::powerOnSelfTests * Kicks off the UI power on self tests */ void VUIPowerOnSelfTest::powerOnSelfTests() { AdjustUIPostFinalResultRequestData data; // assume success then set to 0 if there are any failures data.mResult = 1; if (!selfTestFileSystem()) data.mResult = 0; if (!selfTestTouchScreenDriver()) data.mResult = 0; if (!selfTestWifiDriver()) data.mResult = 0; if (!selfTestCANDriver()) data.mResult = 0; if (!selfTestBluetoothDriver()) data.mResult = 0; if (!selfTestRTCClock()) data.mResult = 0; emit didAdjustment(data); } /*! * \brief VUIPostSingleResult::sha256 * Gets the Sha256 checksum for the specified file * \param fileName - the file we want the sha256 hash for * \return The hash result */ QString VUIPowerOnSelfTest::sha256(const QString &vFilename) { QFile f(vFilename); if (f.open(QFile::ReadOnly)) { QCryptographicHash hash(QCryptographicHash::Sha256); hash.addData(f.readAll()); f.close(); return hash.result().toHex(); } return QString(); } /*! * \brief VUIPostSingleResult::selfTestApplicationBinary * Tests that the filesystem checksums are correct */ bool VUIPowerOnSelfTest::selfTestFileSystem() { QJsonObject obj; if (!FileHandler::read(Path_FileSystem_Checksums, obj)) return false; bool result = true; for (const QString& path : obj.keys()) { QString calculatedChecksum = sha256(path); if ( calculatedChecksum != obj.value(path).toString()) { LOG_DEBUG(QString("Invalid checksum detected: %1").arg(path)); result = false; } else { LOG_DEBUG(QString("Checksum verified: %1").arg(path)); } } return result; } /*! * \brief VUIPostSingleResult::selfTestTouchScreenDriver * Tests that the touch screen driver is loaded correctly */ bool VUIPowerOnSelfTest::selfTestTouchScreenDriver() { bool result = true; if (!checkFileForRegularExpression(Path_Modules_Check, QRegularExpression(".*ft5x06_ts.*"))) { LOG_DEBUG("Touch screen driver is not loaded"); result = false; } else LOG_DEBUG("Touch screen driver is loaded"); if (!checkFileForRegularExpression(Path_Touchscreen_Check, QRegularExpression("Could not detect touch screen"))) { LOG_DEBUG("Touch screen is not physically connected."); result = false; } else LOG_DEBUG("Touch screen has been detected."); return result; } /*! * \brief VUIPowerOnSelfTest::checkFileForRegularExpression * Checks that the provided expression can be found in the specified file * \param vRegExp - the regular expression to search the file with for a match * \return true if found, false otherwise */ bool VUIPowerOnSelfTest::checkFileForRegularExpression(const QString &vFilePath, const QRegularExpression vRegExp) { QString content; if (!FileHandler::read(vFilePath, content)) { LOG_DEBUG(QString("Could not read %1!").arg(vFilePath)); return false; } QStringList lines = content.split("\n"); for (const QString &line : lines) { if (vRegExp.match(line).hasMatch()) { return true; } } return false; } /*! * \brief VUIPostSingleResult::selfTestWifiDriver * Tests that the Wi-Fi driver is correctly loaded */ bool VUIPowerOnSelfTest::selfTestWifiDriver() { // check that wpa_supplicant exists bool result = checkFileForRegularExpression(Path_Modules_Check, QRegularExpression(".*wlan.*")); if (result) LOG_DEBUG("Wifi driver is loaded."); else LOG_DEBUG("Wifi driver is not loaded."); return result; } /*! * \brief VUIPostSingleResult::selfTestBluetoothDriver * Tests that the bluetooth driver is correctly loaded */ bool VUIPowerOnSelfTest::selfTestBluetoothDriver() { bool result = true; if (!checkFileForRegularExpression(Path_Bluetooth_Check, QRegularExpression(".*Powered: yes.*"))) { LOG_DEBUG("Bluetooth driver was not initialized"); result = false; } if (!checkFileForRegularExpression(Path_Bluetooth_Check, QRegularExpression(".*Pairable: yes.*"))) { LOG_DEBUG("Bluetooth controller cannot pair"); result = false; } return result; } /*! * \brief VUIPostSingleResult::selfTestCANDriver * Tests that the CAN driver is correctly loaded */ bool VUIPowerOnSelfTest::selfTestCANDriver() { bool result = checkFileForRegularExpression(Path_Modules_Check, QRegularExpression(".*mcp25xxfd.*")); if (result) LOG_DEBUG("CAN driver is loaded."); else LOG_DEBUG("CAN driver is not loaded."); return result; } /*! * \brief VUIPostSingleResult::selfTestClockSpeed * Test that the clock speed can be read and is within spec */ bool VUIPowerOnSelfTest::selfTestRTCClock() { QString content; if (!FileHandler::read(Path_RTC_Check, content)) { LOG_DEBUG(QString("Could not read %1!").arg(Path_RTC_Check)); return false; } QStringList lines = content.split("\n", QString::SkipEmptyParts); QList times; for (const QString &line : lines) { bool ok = false; double tm = line.toDouble(&ok); if (ok) times.append(tm); } if (times.length() == 2) { double diff = times.at(1) - times.at(0); if ((diff > 0) && (diff < (1.0 + _rtc_tolerance))) { LOG_DEBUG("RTC Clock speed check passed."); return true; } } LOG_DEBUG("RTC Clock speed check failed."); return false; } /*! * \brief VUIPowerOnSelfTest::onActionReceive * Called when the HD requests the UI version * Sends the UI version to the HD for the version compatibility check */ void VUIPowerOnSelfTest::onActionReceive(const HDRequestVersionsData &) { AdjustUIPostReportVersionRequestData data; data.mMajor = QString(VER_MAJOR).toUInt(); data.mMinor = QString(VER_MINOR).toUInt(); data.mMicro = QString(VER_MICRO).toUInt(); data.mBuild = QString(VER_REVIS).toUInt(); data.mCompat = QString(SW_COMPATIBILITY_REV).toUInt(); LOG_DEBUG(QString("Reporting the UI version: Major %1 " "Minor: %2 " "Micro: %3 " "Build: %4 " "Compat: %5 ") .arg(data.mMajor) .arg(data.mMinor) .arg(data.mMicro) .arg(data.mBuild) .arg(data.mCompat)); emit didAdjustment(data); }