/* * 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 #include #include #include #include #include #include #include #include #include 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 &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) { 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."; } }