Start of read command
This commit is contained in:
parent
1b4b422ab6
commit
8f6a390c36
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
using namespace Pinetime::Controllers;
|
using namespace Pinetime::Controllers;
|
||||||
|
|
||||||
constexpr ble_uuid128_t FSService::fsServiceUuid;
|
constexpr ble_uuid16_t FSService::fsServiceUuid;
|
||||||
constexpr ble_uuid128_t FSService::fsVersionUuid;
|
constexpr ble_uuid128_t FSService::fsVersionUuid;
|
||||||
constexpr ble_uuid128_t FSService::fsTransferUuid;
|
constexpr ble_uuid128_t FSService::fsTransferUuid;
|
||||||
|
|
||||||
|
@ -63,9 +63,90 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||||
NRF_LOG_INFO("[FS_S] -> FSCommandHandler");
|
NRF_LOG_INFO("[FS_S] -> FSCommandHandler");
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
|
case commands::READ: {
|
||||||
|
NRF_LOG_INFO("[FS_S] -> Read");
|
||||||
|
if (state != FSState::IDLE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
state = FSState::READ;
|
||||||
|
auto* header = (ReadHeader*) om->om_data;
|
||||||
|
uint16_t plen = header->pathlen;
|
||||||
|
if (plen > maxpathlen - 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(filepath, header->pathstr, plen);
|
||||||
|
filepath[plen + 1] = 0; // Copy and null teminate string
|
||||||
|
ReadResponse resp;
|
||||||
|
resp.command = commands::READ_DATA;
|
||||||
|
resp.chunkoff = header->chunkoff;
|
||||||
|
resp.status = 0x01;
|
||||||
|
struct lfs_info info = {};
|
||||||
|
int res = fs.Stat(filepath, &info);
|
||||||
|
if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) {
|
||||||
|
resp.status = 0x03;
|
||||||
|
resp.chunklen = 0;
|
||||||
|
resp.totallen = 0;
|
||||||
|
} else {
|
||||||
|
lfs_file f;
|
||||||
|
resp.chunklen = std::min(header->chunksize, info.size);
|
||||||
|
resp.totallen = info.size;
|
||||||
|
fs.FileOpen(&f, filepath, LFS_O_RDONLY);
|
||||||
|
fs.FileSeek(&f, header->chunkoff);
|
||||||
|
resp.chunklen = fs.FileRead(&f, resp.chunk, resp.chunklen);
|
||||||
|
fs.FileClose(&f);
|
||||||
|
}
|
||||||
|
auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse));
|
||||||
|
ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om);
|
||||||
|
if (header->chunksize >= resp.totallen) { // probably removeable...but then usafe
|
||||||
|
state = FSState::IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case commands::READ_PACING: {
|
||||||
|
NRF_LOG_INFO("[FS_S] -> ReadPacing");
|
||||||
|
if (state != FSState::READ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto* header = (ReadPacing*) om->om_data;
|
||||||
|
ReadResponse resp = {};
|
||||||
|
|
||||||
|
resp.command = commands::READ_DATA;
|
||||||
|
resp.chunkoff = header->chunkoff;
|
||||||
|
resp.status = 0x01;
|
||||||
|
struct lfs_info info = {};
|
||||||
|
int res = fs.Stat(filepath, &info);
|
||||||
|
if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) {
|
||||||
|
resp.status = 0x03;
|
||||||
|
resp.chunklen = 0;
|
||||||
|
resp.totallen = 0;
|
||||||
|
} else {
|
||||||
|
lfs_file f;
|
||||||
|
resp.chunklen = std::min(header->chunksize, info.size);
|
||||||
|
resp.totallen = info.size;
|
||||||
|
fs.FileOpen(&f, filepath, LFS_O_RDONLY);
|
||||||
|
fs.FileSeek(&f, header->chunkoff);
|
||||||
|
resp.chunklen = fs.FileRead(&f, resp.chunk, resp.chunklen);
|
||||||
|
fs.FileClose(&f);
|
||||||
|
}
|
||||||
|
auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse));
|
||||||
|
ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om);
|
||||||
|
if (resp.chunklen >= header->chunksize) { // is this right?
|
||||||
|
state = FSState::IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case commands::WRITE: {
|
||||||
|
if (state != FSState::IDLE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case commands::WRITE_PACING: {
|
||||||
|
if (state != FSState::WRITE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case commands::DELETE: {
|
case commands::DELETE: {
|
||||||
NRF_LOG_INFO("[FS_S] -> Delete");
|
NRF_LOG_INFO("[FS_S] -> Delete");
|
||||||
auto* header = (DelHeader*)om->om_data;
|
auto* header = (DelHeader*) om->om_data;
|
||||||
uint16_t plen = header->pathlen;
|
uint16_t plen = header->pathlen;
|
||||||
char path[plen + 1] = {0};
|
char path[plen + 1] = {0};
|
||||||
struct lfs_info info = {};
|
struct lfs_info info = {};
|
||||||
|
@ -116,7 +197,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||||
}
|
}
|
||||||
case commands::LISTDIR: {
|
case commands::LISTDIR: {
|
||||||
NRF_LOG_INFO("[FS_S] -> ListDir");
|
NRF_LOG_INFO("[FS_S] -> ListDir");
|
||||||
ListDirHeader* header = (ListDirHeader*)om->om_data;
|
ListDirHeader* header = (ListDirHeader*) om->om_data;
|
||||||
uint16_t plen = header->pathlen;
|
uint16_t plen = header->pathlen;
|
||||||
char path[plen + 1] = {0};
|
char path[plen + 1] = {0};
|
||||||
memcpy(path, header->pathstr, plen);
|
memcpy(path, header->pathstr, plen);
|
||||||
|
@ -140,7 +221,11 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||||
|
|
||||||
fs.DirRewind(&dir);
|
fs.DirRewind(&dir);
|
||||||
|
|
||||||
while (fs.DirRead(&dir, &info)) {
|
while (true) {
|
||||||
|
int res = fs.DirRead(&dir, &info);
|
||||||
|
if(res <= 0){
|
||||||
|
break;
|
||||||
|
}
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
case LFS_TYPE_REG: {
|
case LFS_TYPE_REG: {
|
||||||
resp.flags = 0;
|
resp.flags = 0;
|
||||||
|
@ -157,9 +242,9 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||||
strcpy(resp.path, info.name);
|
strcpy(resp.path, info.name);
|
||||||
resp.path_length = strlen(info.name);
|
resp.path_length = strlen(info.name);
|
||||||
NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name);
|
NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name);
|
||||||
auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse));
|
auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)+resp.path_length);
|
||||||
ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om);
|
ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om);
|
||||||
vTaskDelay(1); // Allow stuff to actually go out over the BLE conn
|
vTaskDelay(5); // Allow stuff to actually go out over the BLE conn
|
||||||
resp.entry++;
|
resp.entry++;
|
||||||
}
|
}
|
||||||
fs.DirClose(&dir);
|
fs.DirClose(&dir);
|
||||||
|
@ -167,7 +252,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||||
resp.path_length = 0;
|
resp.path_length = 0;
|
||||||
resp.flags = 0;
|
resp.flags = 0;
|
||||||
// TODO Handle Size of response better.
|
// TODO Handle Size of response better.
|
||||||
auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse) - 70 + resp.path_length);
|
auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)+resp.path_length);
|
||||||
ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om);
|
ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om);
|
||||||
NRF_LOG_INFO("[FS_S] -> done ");
|
NRF_LOG_INFO("[FS_S] -> done ");
|
||||||
break;
|
break;
|
||||||
|
@ -175,3 +260,25 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
// Loads resp with file data given a valid filepath header and resp
|
||||||
|
void FSService::prepareReadDataResp(ReadHeader* header, ReadResponse* resp) {
|
||||||
|
uint16_t plen = header->pathlen;
|
||||||
|
resp->command = commands::READ_DATA;
|
||||||
|
resp->chunkoff = header->chunkoff;
|
||||||
|
resp->status = 0x01;
|
||||||
|
struct lfs_info info = {};
|
||||||
|
int res = fs.Stat(filepath, &info);
|
||||||
|
if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) {
|
||||||
|
resp->status = 0x03;
|
||||||
|
resp->chunklen = 0;
|
||||||
|
resp->totallen = 0;
|
||||||
|
} else {
|
||||||
|
lfs_file f;
|
||||||
|
resp->chunklen = std::min(header->chunksize, info.size);
|
||||||
|
resp->totallen = info.size;
|
||||||
|
fs.FileOpen(&f, filepath, LFS_O_RDONLY);
|
||||||
|
fs.FileSeek(&f, header->chunkoff);
|
||||||
|
resp->chunklen = fs.FileRead(&f, resp->chunk, resp->chunklen);
|
||||||
|
fs.FileClose(&f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ namespace Pinetime {
|
||||||
static constexpr uint16_t fsVersionId {0x0100};
|
static constexpr uint16_t fsVersionId {0x0100};
|
||||||
static constexpr uint16_t fsTransferId {0x0200};
|
static constexpr uint16_t fsTransferId {0x0200};
|
||||||
uint16_t fsVersion = {0x0004};
|
uint16_t fsVersion = {0x0004};
|
||||||
|
static constexpr uint8_t maxpathlen = 100;
|
||||||
static constexpr ble_uuid128_t fsServiceUuid {
|
static constexpr ble_uuid16_t fsServiceUuid {
|
||||||
.u {.type = BLE_UUID_TYPE_128},
|
.u {.type = BLE_UUID_TYPE_16},
|
||||||
.value = {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}};
|
.value = {0xFEBB}};// {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}};
|
||||||
|
|
||||||
static constexpr ble_uuid128_t fsVersionUuid {
|
static constexpr ble_uuid128_t fsVersionUuid {
|
||||||
.u {.type = BLE_UUID_TYPE_128},
|
.u {.type = BLE_UUID_TYPE_128},
|
||||||
|
@ -45,8 +45,6 @@ namespace Pinetime {
|
||||||
uint16_t versionCharacteristicHandle;
|
uint16_t versionCharacteristicHandle;
|
||||||
uint16_t transferCharacteristicHandle;
|
uint16_t transferCharacteristicHandle;
|
||||||
|
|
||||||
int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om);
|
|
||||||
|
|
||||||
enum class commands : uint8_t {
|
enum class commands : uint8_t {
|
||||||
INVALID = 0x00,
|
INVALID = 0x00,
|
||||||
READ = 0x10,
|
READ = 0x10,
|
||||||
|
@ -64,12 +62,44 @@ namespace Pinetime {
|
||||||
MOVE = 0x60,
|
MOVE = 0x60,
|
||||||
MOVE_STATUS = 0x61
|
MOVE_STATUS = 0x61
|
||||||
};
|
};
|
||||||
|
enum class FSState : uint8_t {
|
||||||
|
IDLE = 0x00,
|
||||||
|
READ = 0x01,
|
||||||
|
WRITE = 0x02,
|
||||||
|
};
|
||||||
|
FSState state;
|
||||||
|
char filepath[maxpathlen]; // TODO ..ugh fixed filepath len
|
||||||
|
using ReadHeader = struct __attribute__((packed)) {
|
||||||
|
commands command;
|
||||||
|
uint8_t padding;
|
||||||
|
uint16_t pathlen;
|
||||||
|
uint32_t chunkoff;
|
||||||
|
uint32_t chunksize;
|
||||||
|
char pathstr[];
|
||||||
|
};
|
||||||
|
|
||||||
|
using ReadResponse = struct __attribute__((packed)) {
|
||||||
|
commands command;
|
||||||
|
uint8_t status;
|
||||||
|
uint16_t padding;
|
||||||
|
uint32_t chunkoff;
|
||||||
|
uint32_t totallen;
|
||||||
|
uint32_t chunklen;
|
||||||
|
uint8_t chunk[];
|
||||||
|
};
|
||||||
|
using ReadPacing = struct __attribute__((packed)) {
|
||||||
|
commands command;
|
||||||
|
uint8_t status;
|
||||||
|
uint16_t padding;
|
||||||
|
uint32_t chunkoff;
|
||||||
|
uint32_t chunksize;
|
||||||
|
};
|
||||||
|
|
||||||
using ListDirHeader = struct __attribute__((packed)) {
|
using ListDirHeader = struct __attribute__((packed)) {
|
||||||
commands command;
|
commands command;
|
||||||
uint8_t padding;
|
uint8_t padding;
|
||||||
uint16_t pathlen;
|
uint16_t pathlen;
|
||||||
char pathstr[70];
|
char pathstr[];
|
||||||
};
|
};
|
||||||
|
|
||||||
using ListDirResponse = struct __attribute__((packed)) {
|
using ListDirResponse = struct __attribute__((packed)) {
|
||||||
|
@ -81,7 +111,7 @@ namespace Pinetime {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t modification_time;
|
uint32_t modification_time;
|
||||||
uint32_t file_size;
|
uint32_t file_size;
|
||||||
char path[70];
|
char path[];
|
||||||
};
|
};
|
||||||
|
|
||||||
using MKDirHeader = struct __attribute__((packed)) {
|
using MKDirHeader = struct __attribute__((packed)) {
|
||||||
|
@ -90,7 +120,7 @@ namespace Pinetime {
|
||||||
uint16_t pathlen;
|
uint16_t pathlen;
|
||||||
uint32_t padding2;
|
uint32_t padding2;
|
||||||
uint64_t time;
|
uint64_t time;
|
||||||
char pathstr[70];
|
char pathstr[];
|
||||||
};
|
};
|
||||||
|
|
||||||
using MKDirResponse = struct __attribute__((packed)) {
|
using MKDirResponse = struct __attribute__((packed)) {
|
||||||
|
@ -100,19 +130,21 @@ namespace Pinetime {
|
||||||
uint16_t padding2;
|
uint16_t padding2;
|
||||||
uint64_t modification_time;
|
uint64_t modification_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
using DelHeader = struct __attribute__((packed)) {
|
using DelHeader = struct __attribute__((packed)) {
|
||||||
commands command;
|
commands command;
|
||||||
uint8_t padding;
|
uint8_t padding;
|
||||||
uint16_t pathlen;
|
uint16_t pathlen;
|
||||||
char pathstr[70];
|
char pathstr[];
|
||||||
};
|
};
|
||||||
|
|
||||||
using DelResponse = struct __attribute__((packed)) {
|
using DelResponse = struct __attribute__((packed)) {
|
||||||
commands command;
|
commands command;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om);
|
||||||
|
void prepareReadDataResp(ReadHeader *header, ReadResponse *resp);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user