M module-bsp/board/linux/usb_cdc/usb_cdc.cpp => module-bsp/board/linux/usb_cdc/usb_cdc.cpp +23 -8
@@ 10,7 10,12 @@ namespace bsp
int fd;
xQueueHandle USBReceiveQueue;
- void usbCDCReceive(void *)
+ void usbDeviceTask(void *ptr)
+ {
+ usbCDCReceive(ptr);
+ }
+
+ int usbCDCReceive(void *)
{
LOG_INFO("[ServiceDesktop:BSP_Driver] Start reading on fd:%d", fd);
uint8_t inputData[SERIAL_BUFFER_LEN];
@@ 51,20 56,25 @@ namespace bsp
}
}
- void *usbInit(xQueueHandle receiveQueue)
+ int usbInit(xQueueHandle receiveQueue, USBDeviceListener *)
{
fd = 0;
fd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if (fd == -1) {
- return (nullptr);
+ LOG_ERROR("bsp::usbInit Failed to open /dev/ptmx, can't allocate new pseudo terminal");
+ return -1;
}
grantpt(fd);
unlockpt(fd);
char *pts_name = ptsname(fd);
- LOG_INFO("[ServiceDesktop:BSP_Driver] VCOMAPPInit linux ptsname: %s", pts_name);
+ if (pts_name == nullptr) {
+ LOG_ERROR("bsp::usbInit ptsname returned NULL, no pseudo terminal allocated");
+ return -1;
+ }
+ LOG_INFO("bsp::usbInit linux ptsname: %s", pts_name);
struct termios newtio;
memset(&newtio, 0, sizeof(newtio));
struct termios oldtio;
@@ 86,13 96,18 @@ namespace bsp
xTaskHandle taskHandleReceive;
USBReceiveQueue = receiveQueue;
- BaseType_t task_error = xTaskCreate(
- usbCDCReceive, "USBLinuxReceive", SERIAL_BUFFER_LEN * 8, (void *)1, tskIDLE_PRIORITY, &taskHandleReceive);
+ BaseType_t task_error = xTaskCreate(&bsp::usbDeviceTask,
+ "USBLinuxReceive",
+ SERIAL_BUFFER_LEN * 8,
+ nullptr,
+ tskIDLE_PRIORITY,
+ &taskHandleReceive);
if (task_error != pdPASS) {
- LOG_ERROR("[ServiceDesktop:BSP_Driver] Failed to start freertos USB_Linux_Receive");
+ LOG_ERROR("bsp::usbInit Failed to start freertos USB_Linux_Receive");
+ return -1;
}
- return (&fd);
+ return 0;
}
} // namespace bsp
M module-bsp/board/rt1051/bsp/usb => module-bsp/board/rt1051/bsp/usb +1 -1
@@ 1,1 1,1 @@
-Subproject commit 7061a014757a5dc3b6d9207a7408d5e3f8591bab
+Subproject commit 9b7a0a468b28c185d94024823f844b2d64dc6efe
M module-bsp/bsp/usb/usb.hpp => module-bsp/bsp/usb/usb.hpp +12 -7
@@ 14,15 14,20 @@ extern "C"
#include <string.h>
#include <unistd.h>
-#define SERIAL_TRANSMISSION_START 0x02
-#define SERIAL_TRANSMISSION_END 0x03
-#define SERIAL_SHELL_START 0x33
-#define SERIAL_BAUDRATE 115200
-#define SERIAL_BUFFER_LEN 512 // this matches the buffer length in rt1051 cdc implementaion
+inline constexpr auto SERIAL_BUFFER_LEN = 512;
+inline constexpr auto SERIAL_BAUDRATE = 115200;
namespace bsp
{
- void *usbInit(xQueueHandle);
- void usbCDCReceive(void *ptr);
+ class USBDeviceListener {
+ public:
+ virtual bool getRawMode() const noexcept{
+ return false;
+ }
+ virtual void rawDataReceived(void *dataPtr, uint32_t dataLen) = 0;
+ };
+
+ int usbInit(xQueueHandle, USBDeviceListener *deviceListener = nullptr);
+ int usbCDCReceive(void *ptr);
int usbCDCSend(std::string *sendMsg);
} // namespace bsp
M module-services/service-desktop/CMakeLists.txt => module-services/service-desktop/CMakeLists.txt +1 -0
@@ 18,6 18,7 @@ set(SOURCES
endpoints/restore/RestoreEndpoint.cpp
endpoints/update/UpdateEndpoint.cpp
endpoints/update/UpdateMuditaOS.cpp
+ endpoints/filesystem/FilesystemEndpoint.cpp
parser/ParserUtils.cpp
parser/ParserFSM.cpp
M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +10 -5
@@ 36,11 36,17 @@ ServiceDesktop::~ServiceDesktop()
sys::ReturnCodes ServiceDesktop::InitHandler()
{
desktopWorker = std::make_unique<WorkerDesktop>(this);
- desktopWorker->init(
- {{desktopWorker->RECEIVE_QUEUE_BUFFER_NAME, sizeof(std::string), sdesktop::cdc_queue_len},
- {desktopWorker->SEND_QUEUE_BUFFER_NAME, sizeof(std::string *), sdesktop::cdc_queue_object_size}});
- desktopWorker->run();
+ const bool ret = desktopWorker->init(
+ {{sdesktop::RECEIVE_QUEUE_BUFFER_NAME, sizeof(std::string), sdesktop::cdc_queue_len},
+ {sdesktop::SEND_QUEUE_BUFFER_NAME, sizeof(std::string *), sdesktop::cdc_queue_object_size}});
+ if (ret == false) {
+ LOG_ERROR("!!! service-desktop InitHandler failed to initialize worker, service-desktop won't work");
+ return sys::ReturnCodes::Failure;
+ }
+ else {
+ desktopWorker->run();
+ }
connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) {
auto request = static_cast<sdesktop::developerMode::DeveloperModeRequest *>(msg);
if (request->event != nullptr) {
@@ 104,7 110,6 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
return std::make_shared<sys::ResponseMessage>();
});
- vfs.updateTimestamp();
return (sys::ReturnCodes::Success);
}
M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +164 -26
@@ 1,9 1,11 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include "service-desktop/ServiceDesktop.hpp"
#include "service-desktop/WorkerDesktop.hpp"
#include "parser/MessageHandler.hpp"
#include "parser/ParserFSM.hpp"
+#include "endpoints/Context.hpp"
#include <bsp/usb/usb.hpp>
#include <log/log.hpp>
@@ 13,55 15,191 @@
#include <map>
#include <vector>
-bool WorkerDesktop::handleMessage(uint32_t queueID)
+inline constexpr auto uploadFailedMessage = "file upload terminated before all data transferred";
+
+WorkerDesktop::WorkerDesktop(sys::Service *ownerServicePtr)
+ : sys::Worker(ownerServicePtr), ownerService(ownerServicePtr), parser(ownerServicePtr), fileDes(nullptr)
{
+ transferTimer =
+ std::make_unique<sys::Timer>("WorkerDesktop file upload", ownerServicePtr, sdesktop::file_transfer_timeout);
+ transferTimer->connect([=](sys::Timer &) { timerHandler(); });
+}
- QueueHandle_t queue = queues[queueID];
+bool WorkerDesktop::init(std::list<sys::WorkerQueueInfo> queues)
+{
+ Worker::init(queues);
- std::string qname = queueNameMap[queue];
- LOG_INFO("[ServiceDesktop:Worker] Received data from queue: %s", qname.c_str());
+ receiveQueue = Worker::getQueueByName(sdesktop::RECEIVE_QUEUE_BUFFER_NAME);
+ parserFSM::MessageHandler::sendQueue = Worker::getQueueByName(sdesktop::SEND_QUEUE_BUFFER_NAME);
- static std::string receiveMsg;
- static std::string *sendMsg;
+ return (bsp::usbInit(receiveQueue, this) < 0) ? false : true;
+}
- if (qname == SERVICE_QUEUE_NAME) {
- LOG_ERROR("[ServiceDesktop:Worker] Service Queue invoked but not implemented!");
+bool WorkerDesktop::deinit(void)
+{
+ LOG_DEBUG("deinit");
+
+ if (fileDes != nullptr) {
+ LOG_DEBUG("deinit close opened fileDes");
+ fclose(fileDes);
}
- if (qname == RECEIVE_QUEUE_BUFFER_NAME) {
- if (xQueueReceive(queue, &receiveMsg, 0) != pdTRUE)
- return false;
+ Worker::deinit();
- parser.processMessage(receiveMsg);
- }
+ LOG_DEBUG("deinit end");
+ return true;
+}
+
+bool WorkerDesktop::handleMessage(uint32_t queueID)
+{
+ QueueHandle_t queue = queues[queueID];
- // TODO: Consider moving sendBuffer receive to bsp driver
- if (qname == SEND_QUEUE_BUFFER_NAME) {
- if (xQueueReceive(queue, &sendMsg, 0) != pdTRUE)
+ std::string qname = queueNameMap[queue];
+ LOG_INFO("handleMessage received data from queue: %s", qname.c_str());
+ static std::string *sendMsg = nullptr;
+ static std::string receivedMsg;
+
+ if (qname == sdesktop::RECEIVE_QUEUE_BUFFER_NAME) {
+ if (xQueueReceive(queue, &receivedMsg, 0) != pdTRUE) {
+ LOG_ERROR("handleMessage failed to receive from \"%s\"", sdesktop::RECEIVE_QUEUE_BUFFER_NAME);
+ return false;
+ }
+ else {
+ parser.processMessage(receivedMsg);
+ }
+ }
+ else if (qname == sdesktop::SEND_QUEUE_BUFFER_NAME) {
+ if (xQueueReceive(queue, &sendMsg, 0) != pdTRUE) {
+ LOG_ERROR("handleMessage xQueueReceive failed for %s size %d bytes",
+ sdesktop::SEND_QUEUE_BUFFER_NAME,
+ static_cast<unsigned int>(sendMsg->length()));
return false;
+ }
+ else {
+ LOG_DEBUG("handeMessage sending %d bytes using usbCDCSend", static_cast<unsigned int>(sendMsg->length()));
+ }
bsp::usbCDCSend(sendMsg);
}
+ else {
+ LOG_INFO("handeMessage got message on an unhandled queue");
+ }
return true;
}
-bool WorkerDesktop::init(std::list<sys::WorkerQueueInfo> queues)
+sys::ReturnCodes WorkerDesktop::startDownload(const std::filesystem::path &destinationPath, uint32_t fileSize)
{
- Worker::init(queues);
+ filePath = destinationPath;
+ fileDes = fopen(filePath.c_str(), "w");
- if ((bsp::usbInit(Worker::getQueueByName(WorkerDesktop::RECEIVE_QUEUE_BUFFER_NAME)) == nullptr)) {
- LOG_ERROR("won't start desktop service without serial port");
- return false;
+ if (fileDes == nullptr)
+ return sys::ReturnCodes::Failure;
+
+ if (fileSize <= 0)
+ return sys::ReturnCodes::Failure;
+
+ transferTimer->start();
+
+ writeFileSizeExpected = fileSize;
+ rawModeEnabled = true;
+
+ LOG_DEBUG("startDownload all checks passed starting download");
+ return sys::ReturnCodes::Success;
+}
+
+void WorkerDesktop::stopTransfer(const TransferFailAction action)
+{
+ LOG_DEBUG("stopTransfer %s",
+ action == TransferFailAction::removeDesitnationFile ? "remove desination file" : "do nothing");
+ parser.setState(parserFSM::State::NoMsg);
+ rawModeEnabled = false;
+
+ parserFSM::Context responseContext;
+ responseContext.setResponseStatus((action == TransferFailAction::removeDesitnationFile)
+ ? parserFSM::http::Code::NotAcceptable
+ : parserFSM::http::Code::Accepted);
+ responseContext.setEndpoint(parserFSM::EndpointType::filesystemUpload);
+ json11::Json responseJson = json11::Json::object{{parserFSM::json::fileSize, std::to_string(writeFileDataWritten)},
+ {parserFSM::json::fileName, filePath.filename().c_str()}};
+ responseContext.setResponseBody(responseJson);
+
+ // close the file descriptor
+ fclose(fileDes);
+
+ // stop the timeout timer
+ transferTimer->stop();
+
+ // reset all counters
+ writeFileSizeExpected = 0;
+ writeFileDataWritten = 0;
+
+ if (action == TransferFailAction::removeDesitnationFile) {
+ if (remove(filePath.c_str()) != 0) {
+ LOG_ERROR("stopTransfer can't delete file(requested) %s", filePath.c_str());
+ }
}
- parserFSM::MessageHandler::sendQueue = Worker::getQueueByName(WorkerDesktop::SEND_QUEUE_BUFFER_NAME);
+ parserFSM::MessageHandler::putToSendQueue(responseContext.createSimpleResponse());
+}
- return true;
+void WorkerDesktop::rawDataReceived(void *dataPtr, uint32_t dataLen)
+{
+ if (getRawMode()) {
+ transferTimer->reload();
+
+ if (dataPtr == nullptr || dataLen == 0) {
+ LOG_ERROR("transferDataReceived invalid data");
+ return;
+ }
+
+ const uint32_t bytesWritten = fwrite(dataPtr, 1, dataLen, fileDes);
+
+ if (bytesWritten != dataLen) {
+ LOG_ERROR("transferDataReceived vfs write failed bytesWritten=%" PRIu32 " != dataLen=%" PRIu32,
+ bytesWritten,
+ dataLen);
+ return;
+ }
+
+ writeFileDataWritten += dataLen;
+
+ if (writeFileDataWritten >= writeFileSizeExpected) {
+ LOG_INFO("transferDataReceived all data transferred, stop now");
+ stopTransfer(TransferFailAction::doNothing);
+ }
+ }
+ else {
+ LOG_DEBUG("transferDataReceived not in a transfer state");
+ }
}
-bool WorkerDesktop::deinit(void)
+void WorkerDesktop::timerHandler()
{
- Worker::deinit();
- return true;
+ LOG_DEBUG("timeout timer: run");
+
+ if (getRawMode()) {
+ LOG_DEBUG("timeout timer: stopping transfer");
+ uploadFileFailedResponse();
+ stopTransfer(TransferFailAction::removeDesitnationFile);
+ }
+}
+
+bool WorkerDesktop::getRawMode() const noexcept
+{
+ return rawModeEnabled;
+}
+
+void WorkerDesktop::uploadFileFailedResponse()
+{
+ LOG_ERROR("Upload file failed, timeout");
+ parserFSM::Context responseContext;
+ responseContext.setResponseStatus(parserFSM::http::Code::InternalServerError);
+ responseContext.setEndpoint(parserFSM::EndpointType::filesystemUpload);
+
+ json11::Json responseJson = json11::Json::object{
+ {parserFSM::json::status, uploadFailedMessage},
+ };
+ responseContext.setResponseBody(responseJson);
+ parserFSM::MessageHandler::putToSendQueue(responseContext.createSimpleResponse());
}
M module-services/service-desktop/endpoints/Context.hpp => module-services/service-desktop/endpoints/Context.hpp +4 -4
@@ 97,6 97,10 @@ namespace parserFSM
{
responseContext.status = status;
}
+ auto setEndpoint(EndpointType endpointTypeToSet)
+ {
+ endpoint = endpointTypeToSet;
+ }
auto setResponseBody(json11::Json respBody)
{
responseContext.body = respBody;
@@ 109,10 113,6 @@ namespace parserFSM
{
return endpoint;
}
- void setEndpoint(EndpointType newEndpoint)
- {
- endpoint = newEndpoint;
- }
auto getUuid() -> uint32_t
{
return uuid;
M module-services/service-desktop/endpoints/EndpointFactory.hpp => module-services/service-desktop/endpoints/EndpointFactory.hpp +6 -2
@@ 7,11 7,13 @@
#include "Service/Service.hpp"
#include "backup/BackupEndpoint.hpp"
+#include "deviceInfo/DeviceInfoEndpoint.hpp"
+#include "update/UpdateEndpoint.hpp"
+#include "filesystem/FilesystemEndpoint.hpp"
+#include "factoryReset/FactoryResetEndpoint.hpp"
#include "calllog/CalllogEndpoint.hpp"
#include "contacts/ContactsEndpoint.hpp"
#include "developerMode/DeveloperModeEndpoint.hpp"
-#include "deviceInfo/DeviceInfoEndpoint.hpp"
-#include "factoryReset/FactoryResetEndpoint.hpp"
#include "messages/MessagesEndpoint.hpp"
#include "restore/RestoreEndpoint.hpp"
#include "update/UpdateEndpoint.hpp"
@@ 27,6 29,8 @@ class EndpointFactory
switch (context.getEndpoint()) {
case EndpointType::update:
return std::make_unique<UpdateEndpoint>(ownerServicePtr);
+ case EndpointType::filesystemUpload:
+ return std::make_unique<FilesystemEndpoint>(ownerServicePtr);
case EndpointType::backup:
return std::make_unique<BackupEndpoint>(ownerServicePtr);
case EndpointType::deviceInfo:
A module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp => module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp +71 -0
@@ 0,0 1,71 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "FilesystemEndpoint.hpp"
+#include "service-desktop/DesktopMessages.hpp"
+#include "service-desktop/ServiceDesktop.hpp"
+#include <module-vfs/include/user/purefs/filesystem_paths.hpp>
+
+auto FilesystemEndpoint::handle(Context &context) -> void
+{
+ LOG_DEBUG("handle");
+ switch (context.getMethod()) {
+ case http::Method::post:
+ run(context);
+ break;
+ default:
+ break;
+ }
+}
+static bool isWritable(const fs::path file)
+{
+ auto lamb = [](vfs::FILE *stream) { vfs.fclose(stream); };
+
+ std::unique_ptr<vfs::FILE, decltype(lamb)> sf(vfs.fopen(file.c_str(), "w"), lamb);
+
+ if (sf.get() != nullptr) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+auto FilesystemEndpoint::run(Context &context) -> sys::ReturnCodes
+{
+ LOG_DEBUG("running");
+ sys::ReturnCodes returnCode = sys::ReturnCodes::Failure;
+ std::string cmd = context.getBody()[parserFSM::json::filesystem::command].string_value();
+
+ context.setResponseBody(
+ json11::Json::object({{json::status, std::to_string(static_cast<int>(sys::ReturnCodes::Failure))}}));
+
+ auto owner = static_cast<ServiceDesktop *>(ownerServicePtr);
+
+ if (cmd == parserFSM::json::filesystem::commands::download) {
+ fs::path filePath = context.getBody()[parserFSM::json::fileName].string_value();
+ fs::path tmpFilePath = purefs::dir::getUpdatesOSPath() / filePath;
+
+ uint32_t fileSize = context.getBody()[parserFSM::json::fileSize].int_value();
+
+ LOG_DEBUG("got owner, file %s", tmpFilePath.c_str());
+
+ if (isWritable(tmpFilePath)) {
+ LOG_INFO("download %" PRIu32 " bytes to: %s", fileSize, tmpFilePath.c_str());
+
+ if (owner->desktopWorker->startDownload(tmpFilePath, fileSize) == sys::ReturnCodes::Success) {
+ context.setResponseStatus(parserFSM::http::Code::Accepted);
+ returnCode = sys::ReturnCodes::Success;
+ }
+ }
+ else {
+ LOG_ERROR("download command failed, can't write %" PRIu32 " bytes to: %s", fileSize, tmpFilePath.c_str());
+ }
+ }
+ else {
+ LOG_ERROR("unknown command: %s", cmd.c_str());
+ }
+
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return returnCode;
+}<
\ No newline at end of file
A module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.hpp => module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.hpp +19 -0
@@ 0,0 1,19 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <module-services/service-desktop/endpoints/Endpoint.hpp>
+#include "Service/Service.hpp"
+
+using namespace parserFSM;
+
+class FilesystemEndpoint : public Endpoint
+{
+ public:
+ FilesystemEndpoint(sys::Service *ownerServicePtr) : Endpoint(ownerServicePtr)
+ {}
+ auto handle(Context &context) -> void override;
+ auto run(Context &context) -> sys::ReturnCodes;
+ auto getUpdates(Context &context) -> sys::ReturnCodes;
+};
M module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +147 -91
@@ 17,6 17,9 @@
#if defined(TARGET_RT1051)
#include <board/cross/eMMC/eMMC.hpp>
+#include "bsp/watchdog/watchdog.hpp"
+#include "vfs_globals.hpp"
+#include <module-vfs/include/user/purefs/filesystem_paths.hpp>
#endif
#include <array>
@@ 56,13 59,15 @@ updateos::UpdateError UpdateMuditaOS::setUpdateFile(fs::path updateFileToUse)
totalBytes = vfs.filelength(updateTar.stream);
}
else {
- informError("UpdateMuditaOS::setUpdateFile can't open TAR file %s", updateFile.c_str());
- return updateos::UpdateError::CantOpenUpdateFile;
+ return informError(updateos::UpdateError::CantOpenUpdateFile,
+ "UpdateMuditaOS::setUpdateFile can't open TAR file %s",
+ updateFile.c_str());
}
}
else {
- informError("UpdateMuditaOS::setUpdateFile %s does not exist", updateFile.c_str());
- return updateos::UpdateError::CantOpenUpdateFile;
+ return informError(updateos::UpdateError::CantOpenUpdateFile,
+ "UpdateMuditaOS::setUpdateFile %s does not exist",
+ updateFile.c_str());
}
status = updateos::UpdateState::UpdateFileSet;
@@ 75,52 80,47 @@ updateos::UpdateError UpdateMuditaOS::runUpdate()
updateos::UpdateError err = prepareTempDirForUpdate();
if (err != updateos::UpdateError::NoError) {
- informError("runUpdate can't prepare temp directory for update");
- return err;
+ return informError(err, "runUpdate can't prepare temp directory for update");
}
informDebug("Unpacking update");
if ((err = unpackUpdate()) == updateos::UpdateError::NoError) {
- informUpdate("Unpacked");
+ informUpdate(status, "Unpacked");
}
else {
- informError("%s can't be unpacked", updateFile.c_str());
- return err;
+ return informError(err, "%s can't be unpacked", updateFile.c_str());
}
if ((err = verifyChecksums()) == updateos::UpdateError::NoError) {
- informUpdate("Verify checksums");
+ informUpdate(status, "Verify checksums");
}
else {
- informError("Checksum verification failed");
- return err;
+ return informError(err, "Checksum verification failed");
}
if ((err = verifyVersion()) == updateos::UpdateError::NoError) {
- informUpdate("Verify version");
+ informUpdate(status, "Verify version");
}
else {
- informError("Can't verify version");
- return err;
+ return informError(err, "Can't verify version");
}
if ((err = updateBootloader()) == updateos::UpdateError::NoError) {
- informUpdate("Update bootloader");
+ informUpdate(status, "Update bootloader");
}
else {
- informError("Failed to update the bootloader");
- return err;
+ return informError(err, "Failed to update the bootloader");
}
if ((err = prepareRoot()) == updateos::UpdateError::NoError) {
- informUpdate("Ready for reset");
+ informUpdate(status, "Ready for reset");
}
else {
- informError("Can't prepare root dir for reset");
+ informError(err, "Can't prepare root dir for reset");
}
if ((err = cleanupAfterUpdate()) != updateos::UpdateError::NoError) {
- informError("runUpdate cleanupAfterUpdate failed, resetting anyway");
+ informError(err, "runUpdate cleanupAfterUpdate failed, resetting anyway");
}
// reboot always
@@ 141,14 141,16 @@ updateos::UpdateError UpdateMuditaOS::unpackUpdate()
if (tarHeader.type == MTAR_TDIR) {
fs::path tmpPath = getUpdateTmpChild(tarHeader.name);
if (vfs.mkdir(tmpPath.c_str()) != 0) {
- informError("unpackUpdate failed to create %s when extracting update tar", tmpPath.c_str());
- return (updateos::UpdateError::CantCreateExtractedFile);
+ return informError(updateos::UpdateError::CantCreateExtractedFile,
+ "unpackUpdate failed to create %s when extracting update tar",
+ tmpPath.c_str());
}
}
else {
if (unpackFileToTemp(tarHeader, &fileCRC32) == false) {
- informError("unpackUpdate failed to extract update file %s", tarHeader.name);
- return (updateos::UpdateError::CantCreateExtractedFile);
+ return informError(updateos::UpdateError::CantCreateExtractedFile,
+ "unpackUpdate failed to extract update file %s",
+ tarHeader.name);
}
filesInUpdatePackage.emplace_back(FileInfo(tarHeader, fileCRC32));
}
@@ 169,8 171,9 @@ updateos::UpdateError UpdateMuditaOS::verifyChecksums()
vfs::FILE *fpChecksums = vfs.fopen(checksumsFile.c_str(), "r");
if (fpChecksums == nullptr) {
- informError("verifyChecksums can't open checksums file %s", checksumsFile.c_str());
- return updateos::UpdateError::CantOpenChecksumsFile;
+ return informError(updateos::UpdateError::CantOpenChecksumsFile,
+ "verifyChecksums can't open checksums file %s",
+ checksumsFile.c_str());
}
while (!vfs.eof(fpChecksums)) {
@@ 184,9 187,12 @@ updateos::UpdateError UpdateMuditaOS::verifyChecksums()
getChecksumInfo(line, filePath, &fileCRC32);
unsigned long computedCRC32 = getExtractedFileCRC32(filePath);
if (computedCRC32 != fileCRC32) {
- informError("verifyChecksums %s crc32 match FAIL %lX != %lX", filePath.c_str(), fileCRC32, computedCRC32);
vfs.fclose(fpChecksums);
- return updateos::UpdateError::VerifyChecksumsFailure;
+ return informError(updateos::UpdateError::VerifyChecksumsFailure,
+ "verifyChecksums %s crc32 match FAIL %lX != %lX",
+ filePath.c_str(),
+ fileCRC32,
+ computedCRC32);
}
}
vfs.fclose(fpChecksums);
@@ 198,16 204,17 @@ updateos::UpdateError UpdateMuditaOS::verifyVersion()
status = updateos::UpdateState::VersionVerificiation;
if (!vfs.fileExists(getUpdateTmpChild(updateos::file::version).c_str())) {
- informError("verifyVersion %s does not exist", getUpdateTmpChild(updateos::file::version).c_str());
- return updateos::UpdateError::VerifyVersionFailure;
+ return informError(updateos::UpdateError::VerifyVersionFailure,
+ "verifyVersion %s does not exist",
+ getUpdateTmpChild(updateos::file::version).c_str());
}
std::string versionJsonString = vfs.loadFileAsString(getUpdateTmpChild(updateos::file::version));
std::string parserError;
json11::Json updateVersionInformation = json11::Json::parse(versionJsonString, parserError);
if (parserError != "") {
- informUpdate("verifyVersion parse json error: %s", parserError.c_str());
- return updateos::UpdateError::VerifyVersionFailure;
+ return informError(
+ updateos::UpdateError::VerifyVersionFailure, "verifyVersion parse json error: %s", parserError.c_str());
}
else {
}
@@ 269,24 276,34 @@ updateos::UpdateError UpdateMuditaOS::prepareRoot()
ret = vfs.deltree(previousOSPath.c_str());
if (ret != 0) {
- informError(
- "prepareRoot ff_deltree on %s caused an error %s", previousOSPath.c_str(), vfs.lastErrnoToStr().c_str());
+ informError(updateos::UpdateError::CantDeletePreviousOS,
+ "prepareRoot ff_deltree on %s caused an error %s",
+ previousOSPath.c_str(),
+ vfs.lastErrnoToStr().c_str());
}
- if (vfs.isDir(previousOSPath.c_str())) {
- informError("prepareRoot %s still exists, we can't continue", previousOSPath.c_str());
- return updateos::UpdateError::CantDeletePreviousOS;
+ if (vfs.isDir(purefs::dir::getPreviousOSPath().c_str())) {
+ return informError(updateos::UpdateError::CantDeletePreviousOS,
+ "prepareRoot ff_deltree on %s caused an error %s",
+ previousOSPath.c_str(),
+ vfs.lastErrnoToStr().c_str());
+ }
+
+ if (vfs.isDir(purefs::dir::getPreviousOSPath().c_str())) {
+ return informError(updateos::UpdateError::CantDeletePreviousOS,
+ "prepareRoot %s still exists, we can't continue",
+ purefs::dir::getPreviousOSPath().c_str());
}
// rename the current OS to previous on partition
informDebug("prepareRoot rename: %s->%s", currentOSPath.c_str(), previousOSPath.c_str());
ret = vfs.rename(currentOSPath.c_str(), previousOSPath.c_str());
if (ret != 0) {
- informError("prepareRoot can't rename %s -> %s error %s",
- currentOSPath.c_str(),
- previousOSPath.c_str(),
- vfs.lastErrnoToStr().c_str());
- return updateos::UpdateError::CantRenameCurrentToPrevious;
+ return informError(updateos::UpdateError::CantRenameCurrentToPrevious,
+ "prepareRoot can't rename %s -> %s error %s",
+ purefs::dir::getCurrentOSPath().c_str(),
+ purefs::dir::getPreviousOSPath().c_str(),
+ vfs.lastErrnoToStr().c_str());
}
// rename the temp directory to current (extracted update)
@@ 294,11 311,11 @@ updateos::UpdateError UpdateMuditaOS::prepareRoot()
ret = vfs.rename(updateTempDirectory.c_str(), currentOSPath.c_str());
if (ret != 0) {
- informError("prepareRoot can't rename %s -> %s error %s",
- updateTempDirectory.c_str(),
- currentOSPath.c_str(),
- vfs.lastErrnoToStr().c_str());
- return updateos::UpdateError::CantRenameTempToCurrent;
+ return informError(updateos::UpdateError::CantRenameTempToCurrent,
+ "prepareRoot can't rename %s -> %s error %s",
+ updateTempDirectory.c_str(),
+ purefs::dir::getCurrentOSPath().c_str(),
+ vfs.lastErrnoToStr().c_str());
}
// move the contents of /sys/current/user if it exists to /user
@@ 350,7 367,7 @@ bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)
fileExtracted = h.name;
fileExtractedSize = h.size;
- informUpdate("Unpack %s", fullPath.filename().c_str());
+ informUpdate(status, "Unpack %s", fullPath.filename().c_str());
if (crc32 != nullptr) {
*crc32 = 0;
@@ 362,7 379,8 @@ bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)
int errCode = MTAR_ESUCCESS;
vfs::FILE *fp = vfs.fopen(fullPath.c_str(), "w+");
if (fp == nullptr) {
- informError("unpackFileToTemp %s can't open for writing", fullPath.c_str());
+ informError(
+ updateos::UpdateError::CantWriteToFile, "unpackFileToTemp %s can't open for writing", fullPath.c_str());
return false;
}
@@ 378,14 396,17 @@ bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)
break;
if ((errCode = mtar_read_data(&updateTar, readBuf.get(), sizeToRead)) != MTAR_ESUCCESS) {
- informError("unpackFileToTemp mtar_read_data failed, errCode=%d", errCode);
+ informError(
+ updateos::UpdateError::CantWriteToFile, "unpackFileToTemp mtar_read_data failed, errCode=%d", errCode);
return false;
}
const uint32_t dataWritten = vfs.fwrite(readBuf.get(), 1, sizeToRead, fp);
if (dataWritten != sizeToRead) {
- informError(
- "unpackFileToTemp %s can't write to file error: %s", fullPath.c_str(), vfs.lastErrnoToStr().c_str());
+ informError(updateos::UpdateError::CantWriteToFile,
+ "unpackFileToTemp %s can't write to file error: %s",
+ fullPath.c_str(),
+ vfs.lastErrnoToStr().c_str());
vfs.fclose(fp);
return false;
}
@@ 401,13 422,12 @@ bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)
updateos::UpdateError UpdateMuditaOS::cleanupAfterUpdate()
{
if (vfs.isDir(updateTempDirectory.c_str()) && vfs.deltree(updateTempDirectory.c_str())) {
- informError("ff_deltree failed on %s", updateTempDirectory.c_str());
- return updateos::UpdateError::CantRemoveUniqueTmpDir;
+ return informError(
+ updateos::UpdateError::CantRemoveUniqueTmpDir, "ff_deltree failed on %s", updateTempDirectory.c_str());
}
mtar_close(&updateTar);
if (vfs.remove(updateFile.c_str())) {
- informError("Failed to delete %s", updateFile.c_str());
- return updateos::UpdateError::CantRemoveUpdateFile;
+ return informError(updateos::UpdateError::CantRemoveUpdateFile, "Failed to delete %s", updateFile.c_str());
}
status = updateos::UpdateState::ReadyForReset;
return updateos::UpdateError::NoError;
@@ 429,37 449,50 @@ updateos::UpdateError UpdateMuditaOS::prepareTempDirForUpdate()
const auto updatesOSPath = purefs::dir::getUpdatesOSPath();
if (vfs.isDir(updatesOSPath.c_str()) == false) {
if (vfs.mkdir(updatesOSPath.c_str()) != 0) {
- informError("%s can't create it %s", updatesOSPath.c_str(), vfs.lastErrnoToStr().c_str());
- return updateos::UpdateError::CantCreateUpdatesDir;
+ return informError(updateos::UpdateError::CantCreateUpdatesDir,
+ "%s can't create it %s",
+ updatesOSPath.c_str(),
+ vfs.lastErrnoToStr().c_str());
+ }
+ }
+
+ if (vfs.isDir(purefs::dir::getUpdatesOSPath().c_str()) == false) {
+ if (vfs.mkdir(purefs::dir::getUpdatesOSPath().c_str()) != 0) {
+ return informError(updateos::UpdateError::CantCreateUpdatesDir,
+ "%s can't create it %s",
+ purefs::dir::getUpdatesOSPath().c_str(),
+ vfs.lastErrnoToStr().c_str());
}
else {
- informDebug("prepareTempDirForUpdate %s created", updatesOSPath.c_str());
+ informDebug("prepareTempDirForUpdate %s created", purefs::dir::getUpdatesOSPath().c_str());
}
}
else {
- informDebug("prepareTempDirForUpdate %s exists", updatesOSPath.c_str());
+ informDebug("prepareTempDirForUpdate %s exists", purefs::dir::getUpdatesOSPath().c_str());
}
- const auto tmpPath = purefs::dir::getTemporaryPath();
- if (vfs.isDir(tmpPath.c_str()) == false) {
- informDebug("prepareTempDirForUpdate %s is not a directory", tmpPath.c_str());
- if (vfs.mkdir(tmpPath.c_str()) != 0) {
- informError("%s can't create it %s", tmpPath.c_str(), vfs.lastErrnoToStr().c_str());
- return updateos::UpdateError::CantCreateTempDir;
+ if (vfs.isDir(purefs::dir::getTemporaryPath().c_str()) == false) {
+ informDebug("prepareTempDirForUpdate %s is not a directory", purefs::dir::getTemporaryPath().c_str());
+ if (vfs.mkdir(purefs::dir::getTemporaryPath().c_str()) != 0) {
+ return informError(updateos::UpdateError::CantCreateTempDir,
+ "%s can't create it %s",
+ purefs::dir::getTemporaryPath().c_str(),
+ vfs.lastErrnoToStr().c_str());
}
else {
- informDebug("prepareTempDirForUpdate %s created", tmpPath.c_str());
+ informDebug("prepareTempDirForUpdate %s created", purefs::dir::getTemporaryPath().c_str());
}
}
else {
- informDebug("prepareTempDirForUpdate %s exists", tmpPath.c_str());
+ informDebug("prepareTempDirForUpdate %s exists", purefs::dir::getTemporaryPath().c_str());
}
if (vfs.isDir(updateTempDirectory.c_str())) {
informDebug("prepareTempDirForUpdate %s exists already, try to remove it", updateTempDirectory.c_str());
if (vfs.deltree(updateTempDirectory.c_str()) != 0) {
- informError("prepareTempDirForUpdate can't remove %s", updateTempDirectory.c_str());
- return updateos::UpdateError::CantRemoveUniqueTmpDir;
+ return informError(updateos::UpdateError::CantRemoveUniqueTmpDir,
+ "prepareTempDirForUpdate can't remove %s",
+ updateTempDirectory.c_str());
}
else {
informDebug("prepareTempDirForUpdate %s removed", updateTempDirectory.c_str());
@@ 468,58 501,61 @@ updateos::UpdateError UpdateMuditaOS::prepareTempDirForUpdate()
informDebug("prepareTempDirForUpdate trying to create %s as tempDir", updateTempDirectory.c_str());
if (vfs.mkdir(updateTempDirectory.c_str()) != 0) {
- informError("prepareTempDirForUpdate failed to create: %s error: %s",
+ informError(updateos::UpdateError::CantCreateUniqueTmpDir,
+ "prepareTempDirForUpdate failed to create: %s error: %s",
updateTempDirectory.c_str(),
vfs.lastErrnoToStr().c_str());
- return updateos::UpdateError::CantCreateUniqueTmpDir;
}
return updateos::UpdateError::NoError;
}
-updateos::BootloaderUpdateError UpdateMuditaOS::writeBootloader(fs::path bootloaderFile)
+updateos::UpdateError UpdateMuditaOS::writeBootloader(fs::path bootloaderFile)
{
status = updateos::UpdateState::UpdatingBootloader;
#if defined(TARGET_Linux)
- return updateos::BootloaderUpdateError::NoError;
+ return updateos::UpdateError::NoError;
#else
if (vfs.fileExists(bootloaderFile.c_str()) == false) {
- informError("[Bootloader Update] File %s doesn't exist!\n", bootloaderFile.c_str());
- return updateos::BootloaderUpdateError::NoBootloaderFile;
+ return informError(updateos::UpdateError::NoBootloaderFile,
+ "[Bootloader Update] File %s doesn't exist!\n",
+ bootloaderFile.c_str());
}
auto fileHandler = vfs.fopen(bootloaderFile.c_str(), "r");
if (fileHandler == nullptr) {
- informError("[Bootloader Update] Failed to open file %s\n", bootloaderFile.c_str());
- return updateos::BootloaderUpdateError::CantOpenBootloaderFile;
+ return informError(updateos::UpdateError::CantOpenBootloaderFile,
+ "[Bootloader Update] Failed to open file %s\n",
+ bootloaderFile.c_str());
}
unsigned long fileLen = vfs.filelength(fileHandler);
auto fileBuf = std::make_unique<uint8_t[]>(fileLen);
if (fileBuf == nullptr) {
- informError("[Bootloader Update] Failed to allocate buffer\n");
- return updateos::BootloaderUpdateError::CantAllocateBuffer;
+ return informError(updateos::UpdateError::CantAllocateBuffer,
+ "[Bootloader Update] Failed to allocate buffer\n");
}
auto filesLoaded = vfs.fread(fileBuf.get(), fileLen, 1, fileHandler);
if (filesLoaded == 0) {
- informError("[Bootloader Update] Failed to load file %s\n", bootloaderFile.c_str());
- return updateos::BootloaderUpdateError::CantOpenBootloaderFile;
+ return informError(updateos::UpdateError::CantOpenBootloaderFile,
+ "[Bootloader Update] Failed to load file %s\n",
+ bootloaderFile.c_str());
}
- informUpdate("[Bootloader Update] File size: %lu B, Writing...", fileLen);
+ informUpdate(status, "[Bootloader Update] File size: %lu B, Writing...", fileLen);
bsp::eMMC emmc;
emmc.Init();
emmc.SwitchPartition(bsp::eMMC::Partition::Boot1);
emmc.WriteBlocks(fileBuf.get(), 0, std::ceil(fileLen / FSL_SDMMC_DEFAULT_BLOCK_SIZE));
- informUpdate("[Bootloader Update] DONE!\n");
+ informUpdate(status, "[Bootloader Update] DONE!\n");
emmc.SwitchPartition(bsp::eMMC::Partition::UserArea);
- return updateos::BootloaderUpdateError::NoError;
+ return updateos::UpdateError::NoError;
#endif
}
@@ 552,7 588,7 @@ const json11::Json UpdateMuditaOS::getVersionInfoFromFile(const fs::path &update
updateos::file::version,
updateFile.c_str());
- mtar_close(&tar);
+ // mtar_close(&tar);
return json11::Json();
}
@@ 608,7 644,7 @@ updateos::UpdateError UpdateMuditaOS::updateUserData()
return updateos::UpdateError::NoError;
}
-void UpdateMuditaOS::informError(const char *format, ...)
+updateos::UpdateError UpdateMuditaOS::informError(const updateos::UpdateError errorCode, const char *format, ...)
{
va_list argptr;
std::unique_ptr<char[]> readBuf(new char[purefs::buffer::tar_buf]);
@@ 616,12 652,23 @@ void UpdateMuditaOS::informError(const char *format, ...)
vsnprintf(readBuf.get(), purefs::buffer::tar_buf, format, argptr);
va_end(argptr);
- LOG_ERROR("UPDATE_ERRROR %s", readBuf.get());
+ LOG_ERROR("UPDATE_ERRROR [%d] %s", static_cast<uint8_t>(errorCode), readBuf.get());
auto msgToSend = std::make_shared<sdesktop::UpdateOsMessage>(updateos::UpdateMessageType::UpdateError);
messageText = std::string(readBuf.get());
msgToSend->updateStats = (updateos::UpdateStats)(*this);
sys::Bus::SendUnicast(msgToSend, app::name_desktop, owner);
+
+ parserFSM::Context responseContext;
+ responseContext.setResponseStatus(parserFSM::http::Code::InternalServerError);
+ responseContext.setEndpoint(parserFSM::EndpointType::update);
+ json11::Json responseJson = json11::Json::object{{parserFSM::json::update, parserFSM::json::updateError},
+ {parserFSM::json::status, messageText},
+ {parserFSM::json::errorCode, static_cast<uint8_t>(errorCode)}};
+ responseContext.setResponseBody(responseJson);
+ parserFSM::MessageHandler::putToSendQueue(responseContext.createSimpleResponse());
+
+ return errorCode;
}
void UpdateMuditaOS::informDebug(const char *format, ...)
@@ 635,7 682,7 @@ void UpdateMuditaOS::informDebug(const char *format, ...)
LOG_DEBUG("UPDATE_DEBUG %s", readBuf.get());
}
-void UpdateMuditaOS::informUpdate(const char *format, ...)
+void UpdateMuditaOS::informUpdate(const updateos::UpdateState statusCode, const char *format, ...)
{
va_list argptr;
std::unique_ptr<char[]> readBuf(new char[purefs::buffer::tar_buf]);
@@ 643,10 690,19 @@ void UpdateMuditaOS::informUpdate(const char *format, ...)
vsnprintf(readBuf.get(), purefs::buffer::tar_buf, format, argptr);
va_end(argptr);
- LOG_INFO("UPDATE_INFO %s", readBuf.get());
+ LOG_INFO("UPDATE_INFO [%d] %s", static_cast<uint8_t>(statusCode), readBuf.get());
auto msgToSend = std::make_shared<sdesktop::UpdateOsMessage>(updateos::UpdateMessageType::UpdateInform);
messageText = std::string(readBuf.get());
msgToSend->updateStats = (updateos::UpdateStats)(*this);
sys::Bus::SendUnicast(msgToSend, app::name_desktop, owner);
+
+ parserFSM::Context responseContext;
+ responseContext.setResponseStatus(parserFSM::http::Code::Accepted);
+ responseContext.setEndpoint(parserFSM::EndpointType::update);
+ json11::Json responseJson = json11::Json::object{{parserFSM::json::update, parserFSM::json::updateInfo},
+ {parserFSM::json::status, messageText},
+ {parserFSM::json::statusCode, static_cast<uint8_t>(statusCode)}};
+ responseContext.setResponseBody(responseJson);
+ parserFSM::MessageHandler::putToSendQueue(responseContext.createSimpleResponse());
}
M module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp +7 -11
@@ 14,7 14,6 @@
#include <vector>
class ServiceDesktop;
-
namespace fs = std::filesystem;
namespace updateos
{
@@ 31,7 30,7 @@ namespace updateos
inline constexpr auto update = ".tar";
}
- const inline int prefix_len = 8;
+ inline constexpr auto prefix_len = 8;
enum class UpdateError
{
@@ 52,12 51,9 @@ namespace updateos
CantRenameTempToCurrent,
CantUpdateJSON,
CantSaveJSON,
- CantUpdateCRC32JSON
- };
-
- enum class BootloaderUpdateError
- {
- NoError,
+ CantUpdateCRC32JSON,
+ CantDeltreePreviousOS,
+ CantWriteToFile,
NoBootloaderFile,
CantOpenBootloaderFile,
CantAllocateBuffer,
@@ 128,11 124,11 @@ class UpdateMuditaOS : public updateos::UpdateStats
updateos::UpdateError cleanupAfterUpdate();
updateos::UpdateError updateUserData();
- void informError(const char *format, ...);
+ updateos::UpdateError informError(updateos::UpdateError errorCode, const char *format, ...);
void informDebug(const char *format, ...);
- void informUpdate(const char *format, ...);
+ void informUpdate(const updateos::UpdateState statusCode, const char *format, ...);
- updateos::BootloaderUpdateError writeBootloader(fs::path bootloaderFile);
+ updateos::UpdateError writeBootloader(fs::path bootloaderFile);
void getChecksumInfo(const std::string &infoLine, std::string &filePath, unsigned long *fileCRC32Long);
unsigned long getExtractedFileCRC32(const std::string &filePath);
M module-services/service-desktop/parser/ParserFSM.cpp => module-services/service-desktop/parser/ParserFSM.cpp +15 -7
@@ 3,17 3,25 @@
#include "MessageHandler.hpp"
#include "ParserFSM.hpp"
-#include "ParserUtils.hpp"
-#include <log/log.hpp>
+namespace sys
+{
+ class Service;
+} // namespace sys
+#include <service-desktop/ServiceDesktop.hpp>
+#include <log/log.hpp>
+#include <json/json11.hpp>
#include <memory>
#include <string>
+#include "MessageHandler.hpp" // for MessageHandler
+#include "ParserUtils.hpp" // for eraseFront, calcPayloadLength, extractPayload, getHeader, removeHeader, size_header, endpointChar, parserFSM
+
namespace sys
{
class Service;
-} // namespace sys
+}
using namespace parserFSM;
@@ 52,7 60,7 @@ void StateMachine::parseHeader()
auto messageStart = receivedMsgPtr->find(message::endpointChar);
if (messageStart == std::string::npos) {
- LOG_ERROR("This is not a valid endpoint message! Type=%c\n", receivedMsgPtr->at(0));
+ LOG_ERROR("This is not a valid endpoint message! Type=%c", receivedMsgPtr->at(0));
return;
}
@@ 72,7 80,7 @@ void StateMachine::parseHeader()
return;
}
- LOG_DEBUG("Payload length: %lu\n", payloadLength);
+ LOG_DEBUG("Payload length: %lu", payloadLength);
message::removeHeader(*receivedMsgPtr);
parseNewMessage();
@@ 144,9 152,9 @@ void StateMachine::parsePartialMessage()
void StateMachine::parsePayload()
{
- LOG_DEBUG("Payload: %s\n", payload.c_str());
+ LOG_DEBUG("Payload: %s", payload.c_str());
if (payload.empty()) {
- LOG_ERROR("Empty payload!\n");
+ LOG_ERROR("Empty payload!");
state = State::NoMsg;
return;
}
M module-services/service-desktop/parser/ParserFSM.hpp => module-services/service-desktop/parser/ParserFSM.hpp +5 -5
@@ 10,11 10,6 @@
#include <string>
-namespace sys
-{
- class Service;
-} // namespace sys
-
namespace parserFSM
{
enum class State
@@ 35,6 30,11 @@ namespace parserFSM
return state;
};
+ void setState(const parserFSM::State newState)
+ {
+ state = newState;
+ }
+
private:
std::string *receivedMsgPtr = nullptr;
parserFSM::State state = State::NoMsg;
M module-services/service-desktop/parser/ParserUtils.hpp => module-services/service-desktop/parser/ParserUtils.hpp +46 -26
@@ 2,13 2,11 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-
-#include <log/log.hpp>
-
-#include <bits/exception.h>
-#include <cstddef>
-#include <cstdint>
-#include <string>
+#include <stdint.h> // for uint8_t
+#include <log/log.hpp> // for LOG_ERROR
+#include <bits/exception.h> // for exception
+#include <stddef.h> // for size_t
+#include <string> // for string, allocator, basic_string, stol
#include <vector>
namespace parserFSM
@@ 20,6 18,7 @@ namespace parserFSM
invalid = 0,
deviceInfo,
update,
+ filesystemUpload,
backup,
restore,
factory,
@@ 80,7 79,9 @@ namespace parserFSM
enum class Code
{
OK = 200,
+ Accepted = 202,
BadRequest = 400,
+ NotAcceptable = 406,
InternalServerError = 500
};
@@ 99,27 100,46 @@ namespace parserFSM
namespace json
{
- inline constexpr auto batteryLevel = "batteryLevel";
- inline constexpr auto batteryState = "batteryState";
- inline constexpr auto selectedSim = "selectedSim";
- inline constexpr auto trayState = "trayState";
- inline constexpr auto signalStrength = "signalStrength";
- inline constexpr auto fsTotal = "fsTotal";
- inline constexpr auto fsFreePercent = "fsFreePercent";
- inline constexpr auto fsFree = "fsFree";
- inline constexpr auto gitRevision = "gitRevision";
- inline constexpr auto gitBranch = "gitBranch";
- inline constexpr auto gitTag = "gitTag";
- inline constexpr auto currentRTCTime = "currentRTCTime";
- inline constexpr auto updateReady = "updateReady";
- inline constexpr auto updateFileList = "updateFileList";
- inline constexpr auto backupRequest = "backupRequest";
- inline constexpr auto backupReady = "backupReady";
- inline constexpr auto backupUpload = "backupUpload";
- inline constexpr auto restoreRequest = "restoreRequest";
- inline constexpr auto factoryRequest = "factoryRequest";
+ inline constexpr auto batteryLevel = "batteryLevel";
+ inline constexpr auto batteryState = "batteryState";
+ inline constexpr auto selectedSim = "selectedSim";
+ inline constexpr auto trayState = "trayState";
+ inline constexpr auto signalStrength = "signalStrength";
+ inline constexpr auto fsTotal = "fsTotal";
+ inline constexpr auto fsFreePercent = "fsFreePercent";
+ inline constexpr auto fsFree = "fsFree";
+ inline constexpr auto gitRevision = "gitRevision";
+ inline constexpr auto gitBranch = "gitBranch";
+ inline constexpr auto gitTag = "gitTag";
+ inline constexpr auto currentRTCTime = "currentRTCTime";
+ inline constexpr auto updateReady = "updateReady";
+ inline constexpr auto updateFileList = "updateFileList";
+ inline constexpr auto backupRequest = "backupRequest";
+ inline constexpr auto backupReady = "backupReady";
+ inline constexpr auto backupUpload = "backupUpload";
+ inline constexpr auto restoreRequest = "restoreRequest";
+ inline constexpr auto factoryRequest = "factoryRequest";
inline constexpr auto networkStatus = "networkStatus";
inline constexpr auto accessTechnology = "accessTechnology";
+ inline constexpr auto fileName = "fileName";
+ inline constexpr auto fileSize = "fileSize";
+
+ inline constexpr auto update = "update";
+ inline constexpr auto updateInfo = "updateInfo";
+ inline constexpr auto updateError = "updateError";
+ inline constexpr auto errorCode = "errorCode";
+ inline constexpr auto statusCode = "statusCode";
+
+ namespace filesystem
+ {
+ inline constexpr auto command = "command";
+ namespace commands
+ {
+ inline constexpr auto upload = "upload";
+ inline constexpr auto rm = "rm";
+ inline constexpr auto download = "download";
+ } // namespace commands
+ } // namespace filesystem
namespace messages
{
M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +12 -7
@@ 3,25 3,30 @@
#pragma once
+#include <memory> // for allocator, unique_ptr
+
+#include "WorkerDesktop.hpp"
+#include "endpoints/update/UpdateMuditaOS.hpp"
+#include "Service/Common.hpp" // for ReturnCodes, ServicePowerMode
+#include "Service/Message.hpp" // for MessagePointer, DataMessage (ptr only), ResponseMessage (ptr only)
+#include "Service/Service.hpp" // for Service
#include "Constants.hpp"
#include "WorkerDesktop.hpp"
-
#include <endpoints/update/UpdateMuditaOS.hpp>
-
#include <Service/Common.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <memory>
-class UpdateMuditaOS;
-class WorkerDesktop;
-
namespace sdesktop
{
inline constexpr auto service_stack = 8192;
- inline constexpr auto cdc_queue_len = 10;
- inline constexpr auto cdc_queue_object_size = 10;
+ inline constexpr auto cdc_queue_len = 32;
+ inline constexpr auto cdc_queue_object_size = 1024;
+ inline constexpr auto file_transfer_timeout = 5000;
+ inline constexpr auto RECEIVE_QUEUE_BUFFER_NAME = "receiveQueueBuffer";
+ inline constexpr auto SEND_QUEUE_BUFFER_NAME = "sendQueueBuffer";
}; // namespace sdesktop
class ServiceDesktop : public sys::Service
M module-services/service-desktop/service-desktop/WorkerDesktop.hpp => module-services/service-desktop/service-desktop/WorkerDesktop.hpp +39 -26
@@ 3,39 3,52 @@
#pragma once
-#include <Service/Message.hpp>
-#include <Service/Service.hpp>
-#include <Service/Worker.hpp>
-#include <bsp/usb/usb.hpp>
-#include <parser/ParserFSM.hpp>
+#include <string.h>
+#include <stdio.h>
+#include <filesystem>
+#include "Service/Message.hpp"
+#include "Service/Service.hpp"
+#include "Service/Worker.hpp"
+#include "Service/Timer.hpp"
+#include "parser/ParserFSM.hpp"
+#include "bsp/usb/usb.hpp"
-extern "C"
+class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
{
-#include <FreeRTOS.h>
-#include <task.h>
-}
-
-#include <cstdint>
-#include <list>
-#include <string>
-
-namespace sys
-{
- class Service;
-} // namespace sys
-
-class WorkerDesktop : public sys::Worker
-{
- private:
public:
- const std::string RECEIVE_QUEUE_BUFFER_NAME = "receiveQueueBuffer";
- const std::string SEND_QUEUE_BUFFER_NAME = "sendQueueBuffer";
+ enum TransferFailAction
+ {
+ doNothing,
+ removeDesitnationFile
+ };
+ WorkerDesktop(sys::Service *ownerServicePtr);
- WorkerDesktop(sys::Service *ownerServicePtr)
- : sys::Worker(ownerServicePtr), ownerService(ownerServicePtr), parser(ownerServicePtr){};
virtual bool init(std::list<sys::WorkerQueueInfo> queues) override;
virtual bool deinit() override;
bool handleMessage(uint32_t queueID) override final;
+
sys::Service *ownerService = nullptr;
parserFSM::StateMachine parser;
+
+ xQueueHandle getReceiveQueue()
+ {
+ return receiveQueue;
+ }
+ sys::ReturnCodes startDownload(const std::filesystem::path &destinationPath, const uint32_t fileSize);
+ void stopTransfer(const TransferFailAction action);
+
+ void timerHandler(void);
+
+ void rawDataReceived(void *dataPtr, uint32_t dataLen) override;
+ bool getRawMode() const noexcept override;
+
+ private:
+ void uploadFileFailedResponse();
+ xQueueHandle receiveQueue;
+ FILE *fileDes = nullptr;
+ uint32_t writeFileSizeExpected = 0;
+ uint32_t writeFileDataWritten = 0;
+ std::filesystem::path filePath;
+ volatile bool rawModeEnabled = false;
+ std::unique_ptr<sys::Timer> transferTimer;
};
M module-sys/Service/Timer.hpp => module-sys/Service/Timer.hpp +1 -1
@@ 5,7 5,7 @@
#include "FreeRTOS.h"
#include "portmacro.h" // for TickType_t
-#include <timer.hpp> // for Timer
+#include <module-os/RTOSWrapper/include/timer.hpp> // for Timer
#include <functional> // for function
#include <string> // for string
namespace sys