|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include "graphics/map/TileService.h" |
| 4 | +#include "lvgl.h" |
| 5 | +#include <set> |
| 6 | +#include <stdint.h> |
| 7 | +#include <string> |
| 8 | + |
| 9 | +/** |
| 10 | + * Statistics of the remote SD card; numeric values match the |
| 11 | + * meshtastic.SdCardInfo interdevice protobuf enums. |
| 12 | + */ |
| 13 | +struct RemoteSdInfo { |
| 14 | + bool present = false; |
| 15 | + uint8_t cardType = 0; // 0 none, 1 MMC, 2 SD, 3 SDHC, 4 SDXC, 5 unknown |
| 16 | + uint8_t fatType = 0; // 0 unknown, 1 FAT16, 2 FAT32, 3 exFAT |
| 17 | + uint64_t cardSize = 0; |
| 18 | + uint64_t usedBytes = 0; |
| 19 | + uint64_t freeBytes = 0; |
| 20 | +}; |
| 21 | + |
| 22 | +/** |
| 23 | + * Backend transport for RemoteSDService: chunked file access on a filesystem |
| 24 | + * that lives on another MCU (e.g. the SD card behind the SenseCAP Indicator |
| 25 | + * RP2040). Implemented and registered by the firmware before the view loads |
| 26 | + * the map. |
| 27 | + */ |
| 28 | +class IRemoteFS |
| 29 | +{ |
| 30 | + public: |
| 31 | + /** |
| 32 | + * Read up to len bytes at offset. Returns false on transport error or |
| 33 | + * missing file. *bytesRead receives the chunk size actually read, |
| 34 | + * *fileSize the total size of the file. |
| 35 | + */ |
| 36 | + virtual bool readChunk(const char *path, uint32_t offset, uint8_t *buf, uint32_t len, uint32_t *bytesRead, |
| 37 | + uint32_t *fileSize) = 0; |
| 38 | + /** |
| 39 | + * Sequential chunked write; create=true starts a new file (offset 0), |
| 40 | + * create=false appends the chunk at offset == current file size. |
| 41 | + */ |
| 42 | + virtual bool writeChunk(const char *path, uint32_t offset, const uint8_t *buf, uint32_t len, bool create) = 0; |
| 43 | + /** |
| 44 | + * List all entries of a directory; subdirectories carry a trailing |
| 45 | + * slash. Returns false on transport error or when path is not a |
| 46 | + * directory. |
| 47 | + */ |
| 48 | + virtual bool listDir(const char *path, std::set<std::string> &entries) = 0; |
| 49 | + /** |
| 50 | + * Card statistics, answered from a cache on the co-processor so the |
| 51 | + * call stays fast. usedBytes/freeBytes may still read zero while the |
| 52 | + * background FAT scan runs; a later call returns real values. |
| 53 | + * Returns false on transport error. |
| 54 | + */ |
| 55 | + virtual bool sdInfo(RemoteSdInfo &info) = 0; |
| 56 | + virtual ~IRemoteFS() {} |
| 57 | +}; |
| 58 | + |
| 59 | +/** |
| 60 | + * Map tile service for a remote SD card, accessed chunk-wise through an |
| 61 | + * IRemoteFS backend. Registers an LVGL filesystem driver so the image |
| 62 | + * decoder reads tiles like from a local drive. |
| 63 | + */ |
| 64 | +class RemoteSDService : public ITileService |
| 65 | +{ |
| 66 | + public: |
| 67 | + static void setBackend(IRemoteFS *fs); |
| 68 | + static IRemoteFS *backend(void); |
| 69 | + |
| 70 | + RemoteSDService(); |
| 71 | + virtual ~RemoteSDService(); |
| 72 | + |
| 73 | + bool load(const char *name, void *img) override; |
| 74 | + bool save(const char *name, void *img, size_t len) override; |
| 75 | + |
| 76 | + protected: |
| 77 | + static void *fs_open(lv_fs_drv_t *drv, const char *path, lv_fs_mode_t mode); |
| 78 | + static lv_fs_res_t fs_close(lv_fs_drv_t *drv, void *file_p); |
| 79 | + static lv_fs_res_t fs_read(lv_fs_drv_t *drv, void *file_p, void *buf, uint32_t btr, uint32_t *br); |
| 80 | + static lv_fs_res_t fs_write(lv_fs_drv_t *drv, void *file_p, const void *buf, uint32_t btw, uint32_t *bw); |
| 81 | + static lv_fs_res_t fs_seek(lv_fs_drv_t *drv, void *file_p, uint32_t pos, lv_fs_whence_t whence); |
| 82 | + static lv_fs_res_t fs_tell(lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p); |
| 83 | + |
| 84 | + private: |
| 85 | + static IRemoteFS *remoteFS; |
| 86 | + |
| 87 | + enum { CHUNK_SIZE = 4096 }; // matches FileTransfer.filedata max_size |
| 88 | + |
| 89 | + typedef struct RemoteFile { |
| 90 | + char path[256]; // full FAT LFN paths round-trip |
| 91 | + uint32_t pos; |
| 92 | + uint32_t size; |
| 93 | + // single chunk read-ahead cache |
| 94 | + uint32_t chunkOffset; |
| 95 | + uint32_t chunkLen; |
| 96 | + uint8_t chunk[CHUNK_SIZE]; |
| 97 | + } RemoteFile; |
| 98 | +}; |
0 commit comments