diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 6551c20c..2cfd5ccd 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -1,5 +1,6 @@ #include #include "FSService.h" +#include "components/ble/BleController.h" using namespace Pinetime::Controllers; @@ -13,8 +14,8 @@ int FSServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gat } FSService::FSService(Pinetime::Controllers::FS& fs) - : fs {fs}, - characteristicDefinition {{.uuid = &fsVersionUuid.u, + : fs {fs}, + characteristicDefinition {{.uuid = &fsVersionUuid.u, .access_cb = FSServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, @@ -24,7 +25,7 @@ FSService::FSService(Pinetime::Controllers::FS& fs) .access_cb = FSServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, - .val_handle = nullptr, + .val_handle = &transferCharacteristicHandle, }, {0}}, serviceDefinition { @@ -51,5 +52,71 @@ int FSService::OnFSServiceRequested(uint16_t connectionHandle, uint16_t attribut int res = os_mbuf_append(context->om, &fsVersion, sizeof(fsVersion)); return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } + if (attributeHandle == transferCharacteristicHandle) { + return FSCommandHandler(connectionHandle, context->om); + } + return 0; +} + +int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { + auto command = static_cast(om->om_data[0]); + NRF_LOG_INFO("[FS_S] -> FSCommandHandler"); + + switch (command) { + case commands::LISTDIR: { + NRF_LOG_INFO("[FS_S] -> ListDir"); + ListDirHeader *header = (ListDirHeader *)&om->om_data[0]; + uint16_t plen = header->pathlen; + char path[plen+1] = {0}; + memcpy(path, header->pathstr, plen); + NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); + lfs_dir_t dir; + struct lfs_info info; + + ListDirResponse resp; + resp.command = 0x51; // LISTDIR_ENTRY; + resp.status = 1; // TODO actually use res above! + resp.totalentries = 0; + resp.entry = 0; + int res = fs.DirOpen(path, &dir); + while (fs.DirRead(&dir, &info)) { + resp.totalentries++; + } + NRF_LOG_INFO("[FS_S] -> %d ", resp.totalentries); + fs.DirClose(&dir); + fs.DirOpen(path, &dir); + while (fs.DirRead(&dir, &info)) { + switch(info.type){ + case LFS_TYPE_REG: + { + resp.flags = 0; + resp.file_size = info.size; + break; + } + case LFS_TYPE_DIR: + { + resp.flags = 1; + resp.file_size = 0; + break; + } + } + resp.modification_time = 0; // TODO Does LFS actually support TS? + strcpy(resp.path,info.name); + resp.path_length = strlen(info.name); + NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); + auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)); + ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); + resp.entry++; + } + resp.entry++; + resp.file_size = 0; + resp.path_length = 0; + resp.flags = 0; + //Todo this better + auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)-70+resp.path_length); + ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); + NRF_LOG_INFO("[FS_S] -> done "); + } + } return 0; } diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index 85b484a3..eb4b34d7 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -4,6 +4,7 @@ #include #undef max #undef min + #include "components/fs/FS.h" namespace Pinetime { @@ -42,8 +43,26 @@ namespace Pinetime { struct ble_gatt_chr_def characteristicDefinition[3]; struct ble_gatt_svc_def serviceDefinition[2]; uint16_t versionCharacteristicHandle; + uint16_t transferCharacteristicHandle; + typedef struct __attribute__((packed)) { + uint8_t command; + uint8_t padding; + uint16_t pathlen; + char pathstr[70]; + } ListDirHeader; + typedef struct __attribute__((packed)) { + uint8_t command; + uint8_t status; + uint16_t path_length; + uint32_t entry; + uint32_t totalentries; + uint32_t flags; + uint32_t modification_time; + uint32_t file_size; + char path[70]; + } ListDirResponse; - enum class commands { + enum class commands : uint8_t { INVALID = 0x00, READ = 0x10, READ_DATA = 0x11, @@ -58,8 +77,10 @@ namespace Pinetime { LISTDIR = 0x50, LISTDIR_ENTRY = 0x51, MOVE = 0x60, - MOVE_STATUS = 0x61, - } + MOVE_STATUS = 0x61 + }; + + int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); }; } } diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 1cad4f02..f287c28e 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -5,29 +5,28 @@ using namespace Pinetime::Controllers; -FS::FS(Pinetime::Drivers::SpiNorFlash& driver) : - flashDriver{ driver }, - lfsConfig{ - .context = this, - .read = SectorRead, - .prog = SectorProg, - .erase = SectorErase, - .sync = SectorSync, +FS::FS(Pinetime::Drivers::SpiNorFlash& driver) + : flashDriver {driver}, + lfsConfig { + .context = this, + .read = SectorRead, + .prog = SectorProg, + .erase = SectorErase, + .sync = SectorSync, - .read_size = 16, - .prog_size = 8, - .block_size = blockSize, - .block_count = size / blockSize, - .block_cycles = 1000u, + .read_size = 16, + .prog_size = 8, + .block_size = blockSize, + .block_count = size / blockSize, + .block_cycles = 1000u, - .cache_size = 16, - .lookahead_size = 16, - - .name_max = 50, - .attr_max = 50, - } -{ } + .cache_size = 16, + .lookahead_size = 16, + .name_max = 50, + .attr_max = 50, + } { +} void FS::Init() { @@ -48,7 +47,6 @@ void FS::Init() { VerifyResource(); LVGLFileSystemInit(); #endif - } void FS::VerifyResource() { @@ -56,7 +54,7 @@ void FS::VerifyResource() { resourcesValid = true; } -int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) { +int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) { return lfs_file_open(&lfs, file_p, fileName, flags); } @@ -80,6 +78,17 @@ int FS::FileDelete(const char* fileName) { return lfs_remove(&lfs, fileName); } +int FS::DirOpen(const char* path, lfs_dir_t* lfs_dir) { + return lfs_dir_open(&lfs, lfs_dir, path); +} + +int FS::DirClose(lfs_dir_t* lfs_dir) { + return lfs_dir_close(&lfs, lfs_dir); +} + +int FS::DirRead(lfs_dir_t* dir, lfs_info* info) { + return lfs_dir_read(&lfs, dir, info); +} int FS::DirCreate(const char* path) { return lfs_mkdir(&lfs, path); @@ -148,8 +157,7 @@ namespace { if (file->type == 0) { return LV_FS_RES_FS_ERR; - } - else { + } else { return LV_FS_RES_OK; } } @@ -193,5 +201,4 @@ void FS::LVGLFileSystemInit() { fs_drv.user_data = this; lv_fs_drv_register(&fs_drv); - } \ No newline at end of file diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 75ba16c8..28d28d3c 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -21,6 +21,9 @@ namespace Pinetime { int FileDelete(const char* fileName); + int DirOpen(const char* path, lfs_dir_t* lfs_dir); + int DirClose(lfs_dir_t* lfs_dir); + int DirRead(lfs_dir_t* dir, lfs_info* info); int DirCreate(const char* path); int DirDelete(const char* path);