eive-obsw/bsp_q7s/memory/SdCardManager.h

217 lines
7.9 KiB
C
Raw Normal View History

2021-07-07 20:50:11 +02:00
#ifndef BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
#define BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
2021-08-05 15:43:19 +02:00
#include <fsfw/osal/linux/CommandExecutor.h>
2021-07-07 20:50:11 +02:00
#include "definitions.h"
#include "returnvalues/classIds.h"
2021-07-19 12:44:43 +02:00
#include "events/subsystemIdRanges.h"
2021-07-07 20:50:11 +02:00
2021-07-19 12:44:43 +02:00
#include "fsfw/events/Event.h"
2021-07-07 20:50:11 +02:00
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
2021-08-05 10:14:17 +02:00
#include <poll.h>
2021-07-07 20:50:11 +02:00
#include <cstdint>
2021-07-08 11:23:08 +02:00
#include <utility>
2021-07-12 11:37:10 +02:00
#include <string>
#include <optional>
2021-08-05 10:14:17 +02:00
#include <array>
2021-07-07 20:50:11 +02:00
class MutexIF;
/**
* @brief Manages handling of SD cards like switching them on or off or getting the current
* state
*/
class SdCardManager {
friend class SdCardAccess;
public:
2021-08-05 10:14:17 +02:00
enum class Operations {
SWITCHING_ON,
SWITCHING_OFF,
MOUNTING,
2021-08-05 16:02:35 +02:00
UNMOUNTING,
2021-08-05 10:14:17 +02:00
IDLE
};
enum class OpStatus {
IDLE,
TIMEOUT,
ONGOING,
2021-08-05 16:02:35 +02:00
SUCCESS,
2021-08-05 10:14:17 +02:00
FAIL
};
2021-08-06 01:25:36 +02:00
using SdStatePair = std::pair<sd::SdState, sd::SdState>;
2021-07-12 15:19:06 +02:00
2021-07-07 20:50:11 +02:00
static constexpr uint8_t INTERFACE_ID = CLASS_ID::SD_CARD_MANAGER;
2021-08-05 10:14:17 +02:00
static constexpr ReturnValue_t OP_ONGOING =
2021-07-12 13:26:02 +02:00
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 0);
2021-08-05 10:14:17 +02:00
static constexpr ReturnValue_t ALREADY_ON =
2021-07-12 13:26:02 +02:00
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1);
2021-08-05 10:14:17 +02:00
static constexpr ReturnValue_t ALREADY_MOUNTED =
2021-07-08 11:23:08 +02:00
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2);
2021-08-05 10:14:17 +02:00
static constexpr ReturnValue_t ALREADY_OFF =
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 3);
2021-07-12 13:26:02 +02:00
static constexpr ReturnValue_t STATUS_FILE_NEXISTS =
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 10);
2021-07-08 11:23:08 +02:00
static constexpr ReturnValue_t STATUS_FILE_FORMAT_INVALID =
2021-07-12 13:26:02 +02:00
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 11);
static constexpr ReturnValue_t MOUNT_ERROR =
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 12);
2021-07-12 11:37:10 +02:00
static constexpr ReturnValue_t UNMOUNT_ERROR =
2021-07-12 13:26:02 +02:00
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 13);
2021-07-08 11:23:08 +02:00
static constexpr ReturnValue_t SYSTEM_CALL_ERROR =
2021-07-12 13:26:02 +02:00
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 14);
2021-08-05 10:14:17 +02:00
static constexpr ReturnValue_t POPEN_CALL_ERROR =
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 15);
2021-07-12 11:37:10 +02:00
2021-07-19 12:44:43 +02:00
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM;
static constexpr Event SANITIZATION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
2021-07-12 11:37:10 +02:00
// C++17 does not support constexpr std::string yet
static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1";
static constexpr char SD_1_DEV_NAME[] = "/dev/mmcblk1p1";
static constexpr char SD_0_MOUNT_POINT[] = "/mnt/sd0";
static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1";
2021-07-12 11:47:23 +02:00
static constexpr char SD_STATE_FILE[] = "/tmp/sd_status.txt";
2021-07-07 20:50:11 +02:00
virtual ~SdCardManager();
static void create();
/**
* Returns the single instance of the SD card manager.
*/
static SdCardManager* instance();
2021-07-12 16:32:14 +02:00
/**
* Set the preferred SD card which will determine which SD card will be used as the primary
* SD card in hot redundant and cold redundant mode. This function will not switch the
* SD cards which are currently on and mounted, this needs to be implemented by
* an upper layer by using #switchOffSdCard , #switchOnSdCard and #updateSdCardStateFile
* @param sdCard
* @return
*/
ReturnValue_t setPreferredSdCard(sd::SdCard sdCard);
2021-07-07 20:50:11 +02:00
2021-07-12 16:32:14 +02:00
/**
* Get the currently configured preferred SD card
* @param sdCard
* @return
*/
ReturnValue_t getPreferredSdCard(sd::SdCard& sdCard) const;
2021-07-07 20:50:11 +02:00
2021-07-08 12:07:39 +02:00
/**
2021-07-12 11:47:23 +02:00
* Switch on the specified SD card.
2021-07-08 12:07:39 +02:00
* @param sdCard
2021-07-12 11:37:10 +02:00
* @param doMountSdCard Mount the SD card after switching it on, which is necessary
* to use it
2021-07-12 15:19:06 +02:00
* @param statusPair If the status pair is already available, it can be passed here
2021-07-08 12:07:39 +02:00
* @return - RETURN_OK on success, ALREADY_ON if it is already on,
* SYSTEM_CALL_ERROR on system error
*/
2021-07-12 15:19:06 +02:00
ReturnValue_t switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard = true,
2021-08-06 01:25:36 +02:00
SdStatePair* statusPair = nullptr);
2021-07-07 20:50:11 +02:00
2021-07-08 12:07:39 +02:00
/**
2021-07-12 11:47:23 +02:00
* Switch off the specified SD card.
2021-07-08 12:07:39 +02:00
* @param sdCard
2021-07-12 11:37:10 +02:00
* @param doUnmountSdCard Unmount the SD card before switching the card off, which makes
* the operation safer
2021-07-12 15:19:06 +02:00
* @param statusPair If the status pair is already available, it can be passed here
2021-07-08 12:07:39 +02:00
* @return - RETURN_OK on success, ALREADY_ON if it is already on,
* SYSTEM_CALL_ERROR on system error
*/
2021-07-12 15:19:06 +02:00
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
2021-08-06 01:25:36 +02:00
SdStatePair* statusPair = nullptr);
2021-07-07 20:50:11 +02:00
2021-07-08 11:23:08 +02:00
/**
2021-07-12 11:47:23 +02:00
* Update the state file or creates one if it does not exist. You need to call this
* function before calling #sdCardActive
2021-08-05 16:02:35 +02:00
* @return
* - RETURN_OK if the state file was updated successfully
* - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending
* - RETURN_FAILED: blocking command failed
2021-07-08 11:23:08 +02:00
*/
ReturnValue_t updateSdCardStateFile();
/**
* Get the state of the SD cards. If the state file does not exist, this function will
* take care of updating it. If it does not, the function will use the state file to get
* the status of the SD cards and set the field of the provided boolean pair.
* @param active Pair of booleans, where the first entry is the state of the first SD card
* and the second one the state of the second SD card
* @return - RETURN_OK if the state was read successfully
* - STATUS_FILE_FORMAT_INVALID if there was an issue with the state file. The user
* should call #updateSdCardStateFile again in that case
* - STATUS_FILE_NEXISTS if the status file does not exist
*/
2021-08-06 01:25:36 +02:00
ReturnValue_t getSdCardActiveStatus(SdStatePair& active);
2021-07-12 11:37:10 +02:00
2021-07-12 11:47:23 +02:00
/**
* Mount the specified SD card. This is necessary to use it.
* @param sdCard
* @return
*/
2021-07-12 11:37:10 +02:00
ReturnValue_t mountSdCard(sd::SdCard sdCard);
2021-07-12 11:47:23 +02:00
/**
* Unmount the specified SD card. This is recommended before switching it off. The SD card
* can't be used after it has been unmounted.
* @param sdCard
* @return
*/
2021-07-12 11:37:10 +02:00
ReturnValue_t unmountSdCard(sd::SdCard sdCard);
2021-07-07 20:50:11 +02:00
2021-07-12 17:23:32 +02:00
/**
* In case that there is a discrepancy between the preferred SD card and the currently
* mounted one, this function will sanitize the state by attempting to mount the
* currently preferred SD card. If the caller already has state information, it can be
2021-08-06 01:25:36 +02:00
* passed into the function. For now, this operation will be enforced in blocking mode.
2021-07-12 17:23:32 +02:00
* @param statusPair Current SD card status capture with #getSdCardActiveStatus
* @param prefSdCard Preferred SD card captured with #getPreferredSdCard
2021-07-12 17:23:32 +02:00
* @throws std::bad_alloc if one of the two arguments was a nullptr and an allocation failed
* @return
*/
2021-08-06 01:25:36 +02:00
ReturnValue_t sanitizeState(SdStatePair* statusPair = nullptr,
sd::SdCard prefSdCard = sd::SdCard::NONE);
2021-07-12 17:23:32 +02:00
/**
* If sd::SdCard::NONE is passed as an argument, this funtion will get the currently
* preferred SD card from the scratch buffer.
* @param prefSdCardPtr
* @return
*/
std::string getCurrentMountPrefix(sd::SdCard prefSdCardPtr = sd::SdCard::NONE);
2021-08-05 10:14:17 +02:00
OpStatus checkCurrentOp(Operations& currentOp);
/**
* If there are issues with the state machine, it can be reset with this function
*/
void resetState();
void setBlocking(bool blocking);
2021-08-08 00:11:21 +02:00
void setPrintCommandOutput(bool print);
2021-07-07 20:50:11 +02:00
private:
2021-08-05 15:43:19 +02:00
CommandExecutor cmdExecutor;
2021-08-05 10:14:17 +02:00
Operations currentOp = Operations::IDLE;
bool blocking = false;
2021-08-08 00:11:21 +02:00
bool printCmdOutput = true;
2021-08-05 10:14:17 +02:00
2021-07-07 20:50:11 +02:00
SdCardManager();
2021-07-08 11:23:08 +02:00
ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on);
2021-07-07 20:50:11 +02:00
2021-08-06 01:25:36 +02:00
void processSdStatusLine(SdStatePair& active, std::string& line, uint8_t& idx,
2021-07-12 15:19:06 +02:00
sd::SdCard& currentSd);
2021-07-12 11:37:10 +02:00
std::string currentPrefix;
2021-07-07 20:50:11 +02:00
static SdCardManager* factoryInstance;
};
#endif /* BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_ */