hunting/hal/src/SdCardHal.cpp
2024-06-15 08:36:44 +08:00

191 lines
6.7 KiB
C++

/*
* Copyright (c) 2023 Fancy Code.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SdCardHal.h"
#include "ILog.h"
#include "LinuxApi.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>
const char *SD_CARD_DEVICE = SD_CARD_DEV;
const char *SD_MOUNT_PATH = SD_CARD_MOUNT_PATH;
SdCardHal::SdCardHal() : mStatus(SdCardHalStatus::END), mThreadRuning(false), mDeviceFd(-1)
{
}
void SdCardHal::SetSdCardMonitor(std::shared_ptr<VSdCardHalMonitor> &monitor)
{
LogInfo("SetSdCardMonitor.\n");
mMonitor = monitor;
monitor->ReportEvent(mStatus);
}
SdCardHalStatus SdCardHal::GetSdCardStatus(void)
{
return mStatus;
}
StatusCode SdCardHal::GetCapacity(unsigned long long &totalSizeMB, unsigned long long &freeSizeMB,
unsigned long long &usedSizeMB)
{
using SD_SIZE = unsigned long long;
constexpr SD_SIZE ONE_MB = 1024ULL * 1024;
if (SdCardHalStatus::MOUNTED != mStatus) {
LogWarning("SdCardHalStatus::MOUNTED != mStatus\n");
return CreateStatusCode(STATUS_CODE_NOT_OK);
}
struct statfs sd_fs;
if (statfs(SD_MOUNT_PATH, &sd_fs) != 0) {
LogError("statfs failed!\n");
return CreateStatusCode(STATUS_CODE_NOT_OK);
}
totalSizeMB = ((SD_SIZE)sd_fs.f_blocks * (SD_SIZE)sd_fs.f_bsize) / ONE_MB;
freeSizeMB = ((SD_SIZE)sd_fs.f_bavail * (SD_SIZE)sd_fs.f_bsize) / ONE_MB;
usedSizeMB = (((SD_SIZE)sd_fs.f_blocks - (SD_SIZE)sd_fs.f_bfree) * (SD_SIZE)sd_fs.f_bsize) / ONE_MB;
LogInfo("Total size: %llu MB\n", totalSizeMB);
LogInfo("Free size: %llu MB\n", freeSizeMB);
LogInfo("Used size: %llu MB\n", usedSizeMB);
return CreateStatusCode(STATUS_CODE_OK);
}
void SdCardHal::Init(void)
{
auto detectThread = [](std::shared_ptr<SdCardHal> sdCardHal) {
LogInfo("sdCardHal DevDetectingThread started.\n");
sdCardHal->DevDetectingThread();
};
mDevDetectingThread = std::thread(detectThread, shared_from_this());
}
void SdCardHal::UnInit(void)
{
mThreadRuning = false;
if (mDevDetectingThread.joinable()) {
mDevDetectingThread.join();
}
}
void SdCardHal::DevDetectingThread(void)
{
constexpr int SLEEP_TIME_MS = 100;
constexpr int DEVICE_EXIST = 0;
// SdCardHalStatus status = SdCardHalStatus::END;
// const char *SD_CARD_DEVICE = "/SD_CARD_DEVICE/mmcblk1p1";
mThreadRuning = true;
while (mThreadRuning) {
if (fx_access(SD_CARD_DEVICE, F_OK) != DEVICE_EXIST) {
if (SdCardHalStatus::PULL_OUT_DEVICE_NOT_EXIST != mStatus) {
mStatus = SdCardHalStatus::PULL_OUT_DEVICE_NOT_EXIST;
ReportDetecedChangedResult(mStatus);
}
if (mDeviceFd > 0) {
close(mDeviceFd);
mDeviceFd = -1;
}
goto CONTINUE;
}
if (mDeviceFd < 0) {
mDeviceFd = fx_open(SD_CARD_DEVICE, O_RDONLY);
if (mDeviceFd < 0) {
// LogInfo("sdCardHal: %s open failed.\n", SD_CARD_DEVICE);
if (SdCardHalStatus::PULL_OUT_OPEN_FAILED != mStatus) {
mStatus = SdCardHalStatus::PULL_OUT_OPEN_FAILED;
ReportDetecedChangedResult(mStatus);
}
goto CONTINUE;
}
}
struct stat sdStat;
if (fx_fstat(mDeviceFd, &sdStat) < 0) {
// LogInfo("sdCardHal: %s fstat failed.\n", SD_CARD_DEVICE);
if (SdCardHalStatus::ERROR != mStatus) {
mStatus = SdCardHalStatus::ERROR;
ReportDetecedChangedResult(mStatus);
}
close(mDeviceFd);
mDeviceFd = -1;
goto CONTINUE;
}
if (!S_ISBLK(sdStat.st_mode)) {
// LogInfo("sdCardHal: %s is not block device.\n", SD_CARD_DEVICE);
if (SdCardHalStatus::PULL_OUT_NOT_BLOCK_DEVICE != mStatus) {
mStatus = SdCardHalStatus::PULL_OUT_NOT_BLOCK_DEVICE;
ReportDetecedChangedResult(mStatus);
}
close(mDeviceFd);
mDeviceFd = -1;
}
else {
// LogInfo("sdCardHal: %s is inserted.\n", SD_CARD_DEVICE);
if (SdCardHalStatus::INSERTED != mStatus && SdCardHalStatus::MOUNTED != mStatus &&
SdCardHalStatus::UNMOUNTED != mStatus) {
mStatus = SdCardHalStatus::INSERTED;
ReportDetecedChangedResult(mStatus);
}
}
CONTINUE:
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_MS));
}
if (mDeviceFd > 0) {
close(mDeviceFd);
mDeviceFd = -1;
}
}
void SdCardHal::ReportDetecedChangedResult(const SdCardHalStatus &status)
{
LogInfo("SdCardHalStatus changed: %s.\n", PrintfStatusString(status));
SdCardHalStatus mountedStatus = SdCardHalStatus::END;
if (SdCardHalStatus::INSERTED == status) {
LogInfo("mount sd to %s.\n", SD_CARD_MOUNT_PATH);
constexpr int BUF_LENGTH = 128;
char cmd[BUF_LENGTH] = {0};
snprintf(cmd, BUF_LENGTH, "mount %s %s", SD_CARD_DEV, SD_CARD_MOUNT_PATH);
fx_system(cmd);
mountedStatus = SdCardHalStatus::MOUNTED;
mStatus = SdCardHalStatus::MOUNTED;
}
auto monitor = mMonitor.lock();
if (mMonitor.expired()) {
LogWarning("SdCardHal: monitor is expired.\n");
return;
}
if (SdCardHalStatus::END != mountedStatus) {
monitor->ReportEvent(mountedStatus);
return;
}
monitor->ReportEvent(status);
}
const char *SdCardHal::PrintfStatusString(const SdCardHalStatus &status)
{
switch (status) {
case SdCardHalStatus::MOUNTED:
return "MOUNTE\n";
case SdCardHalStatus::UNMOUNTED:
return "UNMOUNTED.";
case SdCardHalStatus::INSERTED:
return "INSERTED.";
case SdCardHalStatus::PULL_OUT_DEVICE_NOT_EXIST:
return "PULL_OUT_DEVICE_NOT_EXIST.";
case SdCardHalStatus::PULL_OUT_OPEN_FAILED:
return "PULL_OUT_OPEN_FAILED.";
case SdCardHalStatus::PULL_OUT_NOT_BLOCK_DEVICE:
return "PULL_OUT_NOT_BLOCK_DEVICE.";
case SdCardHalStatus::END:
return "END.";
default:
return "UNDEFINE.";
}
}