2014-12-22 12:35:05 +01:00
|
|
|
|
#include "c_stdio.h"
|
|
|
|
|
#include "platform.h"
|
|
|
|
|
#include "spiffs.h"
|
2016-06-05 23:10:58 +02:00
|
|
|
|
|
2014-12-22 12:35:05 +01:00
|
|
|
|
spiffs fs;
|
|
|
|
|
|
2016-06-05 23:10:58 +02:00
|
|
|
|
#define LOG_PAGE_SIZE 256
|
|
|
|
|
#define LOG_BLOCK_SIZE (INTERNAL_FLASH_SECTOR_SIZE * 2)
|
|
|
|
|
#define LOG_BLOCK_SIZE_SMALL_FS (INTERNAL_FLASH_SECTOR_SIZE)
|
|
|
|
|
#define MIN_BLOCKS_FS 4
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
|
|
|
|
static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
|
|
|
|
|
static u8_t spiffs_fds[32*4];
|
2015-07-31 08:29:29 +02:00
|
|
|
|
#if SPIFFS_CACHE
|
|
|
|
|
static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*2];
|
|
|
|
|
#endif
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
|
static s32_t my_spiffs_read(u32_t addr, u32_t size, u8_t *dst) {
|
2014-12-22 12:35:05 +01:00
|
|
|
|
platform_flash_read(dst, addr, size);
|
|
|
|
|
return SPIFFS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
|
static s32_t my_spiffs_write(u32_t addr, u32_t size, u8_t *src) {
|
2014-12-22 12:35:05 +01:00
|
|
|
|
platform_flash_write(src, addr, size);
|
|
|
|
|
return SPIFFS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
|
static s32_t my_spiffs_erase(u32_t addr, u32_t size) {
|
2014-12-22 12:35:05 +01:00
|
|
|
|
u32_t sect_first = platform_flash_get_sector_of_address(addr);
|
|
|
|
|
u32_t sect_last = sect_first;
|
|
|
|
|
while( sect_first <= sect_last )
|
|
|
|
|
if( platform_flash_erase_sector( sect_first ++ ) == PLATFORM_ERR )
|
|
|
|
|
return SPIFFS_ERR_INTERNAL;
|
|
|
|
|
return SPIFFS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void myspiffs_check_callback(spiffs_check_type type, spiffs_check_report report, u32_t arg1, u32_t arg2){
|
|
|
|
|
// if(SPIFFS_CHECK_PROGRESS == report) return;
|
|
|
|
|
// NODE_ERR("type: %d, report: %d, arg1: %d, arg2: %d\n", type, report, arg1, arg2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************
|
|
|
|
|
The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time.
|
|
|
|
|
Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or
|
|
|
|
|
the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively.
|
|
|
|
|
The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage.
|
|
|
|
|
|
|
|
|
|
********************/
|
|
|
|
|
|
2016-06-05 23:10:58 +02:00
|
|
|
|
static bool myspiffs_set_location(spiffs_config *cfg, int align, int offset, int block_size) {
|
2015-10-09 04:54:51 +02:00
|
|
|
|
#ifdef SPIFFS_FIXED_LOCATION
|
2016-06-05 23:10:58 +02:00
|
|
|
|
cfg->phys_addr = (SPIFFS_FIXED_LOCATION + block_size - 1) & ~(block_size-1);
|
|
|
|
|
#else
|
|
|
|
|
cfg->phys_addr = ( u32_t )platform_flash_get_first_free_block_address( NULL ) + offset;
|
|
|
|
|
cfg->phys_addr = (cfg->phys_addr + align - 1) & ~(align - 1);
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPIFFS_SIZE_1M_BOUNDARY
|
2016-07-22 23:18:47 +02:00
|
|
|
|
cfg->phys_size = ((0x100000 - (SYS_PARAM_SEC_NUM * INTERNAL_FLASH_SECTOR_SIZE) - ( ( u32_t )cfg->phys_addr )) & ~(block_size - 1)) & 0xfffff;
|
2016-06-05 23:10:58 +02:00
|
|
|
|
#else
|
|
|
|
|
cfg->phys_size = (INTERNAL_FLASH_SIZE - ( ( u32_t )cfg->phys_addr )) & ~(block_size - 1);
|
|
|
|
|
#endif
|
|
|
|
|
if ((int) cfg->phys_size < 0) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
cfg->log_block_size = block_size;
|
|
|
|
|
|
|
|
|
|
return (cfg->phys_size / block_size) >= MIN_BLOCKS_FS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns TRUE if FS was found
|
|
|
|
|
* align must be a power of two
|
|
|
|
|
*/
|
|
|
|
|
static bool myspiffs_set_cfg(spiffs_config *cfg, int align, int offset, bool force_create) {
|
|
|
|
|
cfg->phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; // according to datasheet
|
|
|
|
|
cfg->log_page_size = LOG_PAGE_SIZE; // as we said
|
|
|
|
|
|
|
|
|
|
cfg->hal_read_f = my_spiffs_read;
|
|
|
|
|
cfg->hal_write_f = my_spiffs_write;
|
|
|
|
|
cfg->hal_erase_f = my_spiffs_erase;
|
|
|
|
|
|
|
|
|
|
if (!myspiffs_set_location(cfg, align, offset, LOG_BLOCK_SIZE)) {
|
|
|
|
|
if (!myspiffs_set_location(cfg, align, offset, LOG_BLOCK_SIZE_SMALL_FS)) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NODE_DBG("fs.start:%x,max:%x\n",cfg->phys_addr,cfg->phys_size);
|
|
|
|
|
|
|
|
|
|
#ifdef SPIFFS_USE_MAGIC_LENGTH
|
|
|
|
|
if (force_create) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int size = SPIFFS_probe_fs(cfg);
|
|
|
|
|
|
|
|
|
|
if (size > 0 && size < cfg->phys_size) {
|
|
|
|
|
NODE_DBG("Overriding size:%x\n",size);
|
|
|
|
|
cfg->phys_size = size;
|
|
|
|
|
}
|
|
|
|
|
if (size > 0) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
2015-10-09 04:54:51 +02:00
|
|
|
|
#else
|
2016-06-05 23:10:58 +02:00
|
|
|
|
return TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool myspiffs_find_cfg(spiffs_config *cfg, bool force_create) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!force_create) {
|
|
|
|
|
#ifdef SPIFFS_FIXED_LOCATION
|
|
|
|
|
if (myspiffs_set_cfg(cfg, 0, 0, FALSE)) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (INTERNAL_FLASH_SIZE >= 700000) {
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
|
if (myspiffs_set_cfg(cfg, 0x10000, 0x10000 * i, FALSE)) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
|
if (myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, LOG_BLOCK_SIZE * i, FALSE)) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No existing file system -- set up for a format
|
|
|
|
|
if (INTERNAL_FLASH_SIZE >= 700000) {
|
|
|
|
|
myspiffs_set_cfg(cfg, 0x10000, 0x10000, TRUE);
|
|
|
|
|
#ifndef SPIFFS_MAX_FILESYSTEM_SIZE
|
|
|
|
|
if (cfg->phys_size < 400000) {
|
|
|
|
|
// Don't waste so much in alignment
|
|
|
|
|
myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, LOG_BLOCK_SIZE * 4, TRUE);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, 0, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SPIFFS_MAX_FILESYSTEM_SIZE
|
|
|
|
|
if (cfg->phys_size > SPIFFS_MAX_FILESYSTEM_SIZE) {
|
|
|
|
|
cfg->phys_size = (SPIFFS_MAX_FILESYSTEM_SIZE) & ~(cfg->log_block_size - 1);
|
|
|
|
|
}
|
2015-10-09 04:54:51 +02:00
|
|
|
|
#endif
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
2016-06-05 23:10:58 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool myspiffs_mount_internal(bool force_mount) {
|
|
|
|
|
spiffs_config cfg;
|
|
|
|
|
if (!myspiffs_find_cfg(&cfg, force_mount) && !force_mount) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fs.err_code = 0;
|
|
|
|
|
|
2014-12-22 12:35:05 +01:00
|
|
|
|
int res = SPIFFS_mount(&fs,
|
|
|
|
|
&cfg,
|
|
|
|
|
spiffs_work_buf,
|
|
|
|
|
spiffs_fds,
|
|
|
|
|
sizeof(spiffs_fds),
|
2015-07-31 08:29:29 +02:00
|
|
|
|
#if SPIFFS_CACHE
|
2014-12-22 12:35:05 +01:00
|
|
|
|
spiffs_cache,
|
|
|
|
|
sizeof(spiffs_cache),
|
2015-07-31 08:29:29 +02:00
|
|
|
|
#else
|
|
|
|
|
0, 0,
|
|
|
|
|
#endif
|
2014-12-22 12:35:05 +01:00
|
|
|
|
// myspiffs_check_callback);
|
|
|
|
|
0);
|
2016-06-05 23:10:58 +02:00
|
|
|
|
NODE_DBG("mount res: %d, %d\n", res, fs.err_code);
|
|
|
|
|
return res == SPIFFS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool myspiffs_mount() {
|
|
|
|
|
return myspiffs_mount_internal(FALSE);
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-02 18:51:02 +02:00
|
|
|
|
void myspiffs_unmount() {
|
|
|
|
|
SPIFFS_unmount(&fs);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-22 12:35:05 +01:00
|
|
|
|
// FS formatting function
|
|
|
|
|
// Returns 1 if OK, 0 for error
|
2015-01-05 03:09:51 +01:00
|
|
|
|
int myspiffs_format( void )
|
2014-12-22 12:35:05 +01:00
|
|
|
|
{
|
|
|
|
|
SPIFFS_unmount(&fs);
|
2016-06-05 23:10:58 +02:00
|
|
|
|
myspiffs_mount_internal(TRUE);
|
|
|
|
|
SPIFFS_unmount(&fs);
|
|
|
|
|
|
|
|
|
|
NODE_DBG("Formatting: size 0x%x, addr 0x%x\n", fs.cfg.phys_size, fs.cfg.phys_addr);
|
|
|
|
|
|
|
|
|
|
if (SPIFFS_format(&fs) < 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return myspiffs_mount();
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
|
#if 0
|
|
|
|
|
void test_spiffs() {
|
|
|
|
|
char buf[12];
|
|
|
|
|
|
|
|
|
|
// Surely, I've mounted spiffs before entering here
|
|
|
|
|
|
|
|
|
|
spiffs_file fd = SPIFFS_open(&fs, "my_file", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
|
|
|
|
|
if (SPIFFS_write(&fs, fd, (u8_t *)"Hello world", 12) < 0) NODE_DBG("errno %i\n", SPIFFS_errno(&fs));
|
|
|
|
|
SPIFFS_close(&fs, fd);
|
|
|
|
|
|
|
|
|
|
fd = SPIFFS_open(&fs, "my_file", SPIFFS_RDWR, 0);
|
|
|
|
|
if (SPIFFS_read(&fs, fd, (u8_t *)buf, 12) < 0) NODE_DBG("errno %i\n", SPIFFS_errno(&fs));
|
|
|
|
|
SPIFFS_close(&fs, fd);
|
|
|
|
|
|
|
|
|
|
NODE_DBG("--> %s <--\n", buf);
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
#endif
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// vfs API
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
#include <c_stdlib.h>
|
|
|
|
|
#include "vfs_int.h"
|
|
|
|
|
|
|
|
|
|
#define MY_LDRV_ID "FLASH"
|
|
|
|
|
|
|
|
|
|
// default current drive
|
|
|
|
|
static int is_current_drive = TRUE;
|
|
|
|
|
|
|
|
|
|
// forward declarations
|
|
|
|
|
static sint32_t myspiffs_vfs_close( const struct vfs_file *fd );
|
|
|
|
|
static sint32_t myspiffs_vfs_read( const struct vfs_file *fd, void *ptr, size_t len );
|
|
|
|
|
static sint32_t myspiffs_vfs_write( const struct vfs_file *fd, const void *ptr, size_t len );
|
|
|
|
|
static sint32_t myspiffs_vfs_lseek( const struct vfs_file *fd, sint32_t off, int whence );
|
|
|
|
|
static sint32_t myspiffs_vfs_eof( const struct vfs_file *fd );
|
|
|
|
|
static sint32_t myspiffs_vfs_tell( const struct vfs_file *fd );
|
|
|
|
|
static sint32_t myspiffs_vfs_flush( const struct vfs_file *fd );
|
2016-10-03 03:32:48 +02:00
|
|
|
|
static uint32_t myspiffs_vfs_size( const struct vfs_file *fd );
|
2016-09-05 20:17:13 +02:00
|
|
|
|
static sint32_t myspiffs_vfs_ferrno( const struct vfs_file *fd );
|
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_closedir( const struct vfs_dir *dd );
|
|
|
|
|
static vfs_item *myspiffs_vfs_readdir( const struct vfs_dir *dd );
|
|
|
|
|
|
|
|
|
|
static void myspiffs_vfs_iclose( const struct vfs_item *di );
|
|
|
|
|
static uint32_t myspiffs_vfs_isize( const struct vfs_item *di );
|
|
|
|
|
//static const struct tm *myspiffs_vfs_time( const struct vfs_item *di );
|
|
|
|
|
static const char *myspiffs_vfs_name( const struct vfs_item *di );
|
|
|
|
|
|
|
|
|
|
static vfs_vol *myspiffs_vfs_mount( const char *name, int num );
|
|
|
|
|
static vfs_file *myspiffs_vfs_open( const char *name, const char *mode );
|
|
|
|
|
static vfs_dir *myspiffs_vfs_opendir( const char *name );
|
|
|
|
|
static vfs_item *myspiffs_vfs_stat( const char *name );
|
|
|
|
|
static sint32_t myspiffs_vfs_remove( const char *name );
|
|
|
|
|
static sint32_t myspiffs_vfs_rename( const char *oldname, const char *newname );
|
|
|
|
|
static sint32_t myspiffs_vfs_fsinfo( uint32_t *total, uint32_t *used );
|
|
|
|
|
static sint32_t myspiffs_vfs_fscfg( uint32_t *phys_addr, uint32_t *phys_size );
|
|
|
|
|
static sint32_t myspiffs_vfs_format( void );
|
|
|
|
|
static sint32_t myspiffs_vfs_errno( void );
|
|
|
|
|
static void myspiffs_vfs_clearerr( void );
|
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_umount( const struct vfs_vol *vol );
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// function tables
|
|
|
|
|
//
|
|
|
|
|
static vfs_fs_fns myspiffs_fs_fns = {
|
|
|
|
|
.mount = myspiffs_vfs_mount,
|
|
|
|
|
.open = myspiffs_vfs_open,
|
|
|
|
|
.opendir = myspiffs_vfs_opendir,
|
|
|
|
|
.stat = myspiffs_vfs_stat,
|
|
|
|
|
.remove = myspiffs_vfs_remove,
|
|
|
|
|
.rename = myspiffs_vfs_rename,
|
|
|
|
|
.mkdir = NULL,
|
|
|
|
|
.fsinfo = myspiffs_vfs_fsinfo,
|
|
|
|
|
.fscfg = myspiffs_vfs_fscfg,
|
|
|
|
|
.format = myspiffs_vfs_format,
|
|
|
|
|
.chdrive = NULL,
|
|
|
|
|
.chdir = NULL,
|
|
|
|
|
.ferrno = myspiffs_vfs_errno,
|
|
|
|
|
.clearerr = myspiffs_vfs_clearerr
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static vfs_file_fns myspiffs_file_fns = {
|
|
|
|
|
.close = myspiffs_vfs_close,
|
|
|
|
|
.read = myspiffs_vfs_read,
|
|
|
|
|
.write = myspiffs_vfs_write,
|
|
|
|
|
.lseek = myspiffs_vfs_lseek,
|
|
|
|
|
.eof = myspiffs_vfs_eof,
|
|
|
|
|
.tell = myspiffs_vfs_tell,
|
|
|
|
|
.flush = myspiffs_vfs_flush,
|
2016-10-03 03:32:48 +02:00
|
|
|
|
.size = myspiffs_vfs_size,
|
2016-09-05 20:17:13 +02:00
|
|
|
|
.ferrno = myspiffs_vfs_ferrno
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static vfs_item_fns myspiffs_item_fns = {
|
|
|
|
|
.close = myspiffs_vfs_iclose,
|
|
|
|
|
.size = myspiffs_vfs_isize,
|
|
|
|
|
.time = NULL,
|
|
|
|
|
.name = myspiffs_vfs_name,
|
|
|
|
|
.is_dir = NULL,
|
|
|
|
|
.is_rdonly = NULL,
|
|
|
|
|
.is_hidden = NULL,
|
|
|
|
|
.is_sys = NULL,
|
|
|
|
|
.is_arch = NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static vfs_dir_fns myspiffs_dd_fns = {
|
|
|
|
|
.close = myspiffs_vfs_closedir,
|
|
|
|
|
.readdir = myspiffs_vfs_readdir
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// specific struct extensions
|
|
|
|
|
//
|
|
|
|
|
struct myvfs_file {
|
|
|
|
|
struct vfs_file vfs_file;
|
|
|
|
|
spiffs_file fh;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct myvfs_dir {
|
|
|
|
|
struct vfs_dir vfs_dir;
|
|
|
|
|
spiffs_DIR d;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct myvfs_stat {
|
|
|
|
|
struct vfs_item vfs_item;
|
|
|
|
|
spiffs_stat s;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// stat functions
|
|
|
|
|
//
|
|
|
|
|
#define GET_STAT_S(descr) \
|
|
|
|
|
const struct myvfs_stat *mystat = (const struct myvfs_stat *)descr; \
|
|
|
|
|
spiffs_stat *s = (spiffs_stat *)&(mystat->s);
|
|
|
|
|
|
|
|
|
|
static void myspiffs_vfs_iclose( const struct vfs_item *di ) {
|
|
|
|
|
// free descriptor memory
|
|
|
|
|
c_free( (void *)di );
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
|
static uint32_t myspiffs_vfs_isize( const struct vfs_item *di ) {
|
|
|
|
|
GET_STAT_S(di);
|
|
|
|
|
|
|
|
|
|
return s->size;
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static const char *myspiffs_vfs_name( const struct vfs_item *di ) {
|
|
|
|
|
GET_STAT_S(di);
|
|
|
|
|
|
|
|
|
|
return s->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// volume functions
|
|
|
|
|
//
|
|
|
|
|
static sint32_t myspiffs_vfs_umount( const struct vfs_vol *vol ) {
|
|
|
|
|
// not implemented
|
|
|
|
|
|
|
|
|
|
return VFS_RES_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// dir functions
|
|
|
|
|
//
|
|
|
|
|
#define GET_DIR_D(descr) \
|
|
|
|
|
const struct myvfs_dir *mydd = (const struct myvfs_dir *)descr; \
|
|
|
|
|
spiffs_DIR *d = (spiffs_DIR *)&(mydd->d);
|
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_closedir( const struct vfs_dir *dd ) {
|
|
|
|
|
GET_DIR_D(dd);
|
|
|
|
|
|
|
|
|
|
sint32_t res = SPIFFS_closedir( d );
|
|
|
|
|
|
|
|
|
|
// free descriptor memory
|
|
|
|
|
c_free( (void *)dd );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static vfs_item *myspiffs_vfs_readdir( const struct vfs_dir *dd ) {
|
|
|
|
|
GET_DIR_D(dd);
|
|
|
|
|
struct myvfs_stat *stat;
|
|
|
|
|
struct spiffs_dirent dirent;
|
|
|
|
|
|
|
|
|
|
if (stat = c_malloc( sizeof( struct myvfs_stat ) )) {
|
|
|
|
|
if (SPIFFS_readdir( d, &dirent )) {
|
|
|
|
|
stat->vfs_item.fs_type = VFS_FS_FATFS;
|
|
|
|
|
stat->vfs_item.fns = &myspiffs_item_fns;
|
|
|
|
|
// copy entries to vfs' directory item
|
|
|
|
|
stat->s.size = dirent.size;
|
|
|
|
|
c_strncpy( stat->s.name, dirent.name, SPIFFS_OBJ_NAME_LEN );
|
|
|
|
|
return (vfs_item *)stat;
|
|
|
|
|
} else {
|
|
|
|
|
c_free( stat );
|
|
|
|
|
}
|
2015-01-07 08:57:17 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// file functions
|
|
|
|
|
//
|
|
|
|
|
#define GET_FILE_FH(descr) \
|
|
|
|
|
const struct myvfs_file *myfd = (const struct myvfs_file *)descr; \
|
|
|
|
|
spiffs_file fh = myfd->fh;
|
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_close( const struct vfs_file *fd ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
|
|
|
|
|
sint32_t res = SPIFFS_close( &fs, fh );
|
|
|
|
|
|
|
|
|
|
// free descriptor memory
|
|
|
|
|
c_free( (void *)fd );
|
|
|
|
|
|
2015-01-07 08:57:17 +01:00
|
|
|
|
return res;
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_read( const struct vfs_file *fd, void *ptr, size_t len ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
|
|
|
|
|
return SPIFFS_read( &fs, fh, ptr, len );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_write( const struct vfs_file *fd, const void *ptr, size_t len ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
|
|
|
|
|
return SPIFFS_write( &fs, fh, (void *)ptr, len );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_lseek( const struct vfs_file *fd, sint32_t off, int whence ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
int spiffs_whence;
|
|
|
|
|
|
|
|
|
|
switch (whence) {
|
|
|
|
|
default:
|
|
|
|
|
case VFS_SEEK_SET:
|
|
|
|
|
spiffs_whence = SPIFFS_SEEK_SET;
|
|
|
|
|
break;
|
|
|
|
|
case VFS_SEEK_CUR:
|
|
|
|
|
spiffs_whence = SPIFFS_SEEK_CUR;
|
|
|
|
|
break;
|
|
|
|
|
case VFS_SEEK_END:
|
|
|
|
|
spiffs_whence = SPIFFS_SEEK_END;
|
|
|
|
|
break;
|
2015-01-07 08:57:17 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
return SPIFFS_lseek( &fs, fh, off, spiffs_whence );
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_eof( const struct vfs_file *fd ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
|
|
|
|
|
return SPIFFS_eof( &fs, fh );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_tell( const struct vfs_file *fd ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
|
|
|
|
|
return SPIFFS_tell( &fs, fh );
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_flush( const struct vfs_file *fd ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
|
|
|
|
|
return SPIFFS_fflush( &fs, fh ) >= 0 ? VFS_RES_OK : VFS_RES_ERR;
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
2016-10-03 03:32:48 +02:00
|
|
|
|
static uint32_t myspiffs_vfs_size( const struct vfs_file *fd ) {
|
|
|
|
|
GET_FILE_FH(fd);
|
|
|
|
|
|
|
|
|
|
int32_t curpos = SPIFFS_tell( &fs, fh );
|
|
|
|
|
int32_t size = SPIFFS_lseek( &fs, fh, 0, SPIFFS_SEEK_END );
|
|
|
|
|
(void) SPIFFS_lseek( &fs, fh, curpos, SPIFFS_SEEK_SET );
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
|
static sint32_t myspiffs_vfs_ferrno( const struct vfs_file *fd ) {
|
|
|
|
|
return SPIFFS_errno( &fs );
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int fs_mode2flag(const char *mode){
|
|
|
|
|
if(c_strlen(mode)==1){
|
|
|
|
|
if(c_strcmp(mode,"w")==0)
|
|
|
|
|
return SPIFFS_WRONLY|SPIFFS_CREAT|SPIFFS_TRUNC;
|
|
|
|
|
else if(c_strcmp(mode, "r")==0)
|
|
|
|
|
return SPIFFS_RDONLY;
|
|
|
|
|
else if(c_strcmp(mode, "a")==0)
|
|
|
|
|
return SPIFFS_WRONLY|SPIFFS_CREAT|SPIFFS_APPEND;
|
|
|
|
|
else
|
|
|
|
|
return SPIFFS_RDONLY;
|
|
|
|
|
} else if (c_strlen(mode)==2){
|
|
|
|
|
if(c_strcmp(mode,"r+")==0)
|
|
|
|
|
return SPIFFS_RDWR;
|
|
|
|
|
else if(c_strcmp(mode, "w+")==0)
|
|
|
|
|
return SPIFFS_RDWR|SPIFFS_CREAT|SPIFFS_TRUNC;
|
|
|
|
|
else if(c_strcmp(mode, "a+")==0)
|
|
|
|
|
return SPIFFS_RDWR|SPIFFS_CREAT|SPIFFS_APPEND;
|
|
|
|
|
else
|
|
|
|
|
return SPIFFS_RDONLY;
|
|
|
|
|
} else {
|
|
|
|
|
return SPIFFS_RDONLY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// filesystem functions
|
|
|
|
|
//
|
|
|
|
|
static vfs_file *myspiffs_vfs_open( const char *name, const char *mode ) {
|
|
|
|
|
struct myvfs_file *fd;
|
|
|
|
|
int flags = fs_mode2flag( mode );
|
|
|
|
|
|
|
|
|
|
if (fd = (struct myvfs_file *)c_malloc( sizeof( struct myvfs_file ) )) {
|
|
|
|
|
if (0 < (fd->fh = SPIFFS_open( &fs, name, flags, 0 ))) {
|
|
|
|
|
fd->vfs_file.fs_type = VFS_FS_SPIFFS;
|
|
|
|
|
fd->vfs_file.fns = &myspiffs_file_fns;
|
|
|
|
|
return (vfs_file *)fd;
|
2015-01-08 09:03:21 +01:00
|
|
|
|
} else {
|
2016-09-05 20:17:13 +02:00
|
|
|
|
c_free( fd );
|
2015-01-07 08:57:17 +01:00
|
|
|
|
}
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
return NULL;
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static vfs_dir *myspiffs_vfs_opendir( const char *name ){
|
|
|
|
|
struct myvfs_dir *dd;
|
|
|
|
|
|
|
|
|
|
if (dd = (struct myvfs_dir *)c_malloc( sizeof( struct myvfs_dir ) )) {
|
|
|
|
|
if (SPIFFS_opendir( &fs, name, &(dd->d) )) {
|
|
|
|
|
dd->vfs_dir.fs_type = VFS_FS_SPIFFS;
|
|
|
|
|
dd->vfs_dir.fns = &myspiffs_dd_fns;
|
|
|
|
|
return (vfs_dir *)dd;
|
|
|
|
|
} else {
|
|
|
|
|
c_free( dd );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static vfs_item *myspiffs_vfs_stat( const char *name ) {
|
|
|
|
|
struct myvfs_stat *s;
|
|
|
|
|
|
|
|
|
|
if (s = (struct myvfs_stat *)c_malloc( sizeof( struct myvfs_stat ) )) {
|
|
|
|
|
if (0 <= SPIFFS_stat( &fs, name, &(s->s) )) {
|
|
|
|
|
s->vfs_item.fs_type = VFS_FS_SPIFFS;
|
|
|
|
|
s->vfs_item.fns = &myspiffs_item_fns;
|
|
|
|
|
return (vfs_item *)s;
|
|
|
|
|
} else {
|
|
|
|
|
c_free( s );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_remove( const char *name ) {
|
|
|
|
|
return SPIFFS_remove( &fs, name );
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_rename( const char *oldname, const char *newname ) {
|
|
|
|
|
return SPIFFS_rename( &fs, oldname, newname );
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_fsinfo( uint32_t *total, uint32_t *used ) {
|
|
|
|
|
return SPIFFS_info( &fs, total, used );
|
2015-02-11 14:20:54 +01:00
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
|
|
|
|
|
|
static sint32_t myspiffs_vfs_fscfg( uint32_t *phys_addr, uint32_t *phys_size ) {
|
|
|
|
|
*phys_addr = fs.cfg.phys_addr;
|
|
|
|
|
*phys_size = fs.cfg.phys_size;
|
|
|
|
|
return VFS_RES_OK;
|
2015-02-13 12:23:30 +01:00
|
|
|
|
}
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
|
static vfs_vol *myspiffs_vfs_mount( const char *name, int num ) {
|
|
|
|
|
// volume descriptor not supported, just return TRUE / FALSE
|
|
|
|
|
return myspiffs_mount() ? (vfs_vol *)1 : NULL;
|
|
|
|
|
}
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
|
static sint32_t myspiffs_vfs_format( void ) {
|
|
|
|
|
return myspiffs_format();
|
|
|
|
|
}
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
|
static sint32_t myspiffs_vfs_errno( void ) {
|
|
|
|
|
return SPIFFS_errno( &fs );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void myspiffs_vfs_clearerr( void ) {
|
|
|
|
|
SPIFFS_clearerr( &fs );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// VFS interface functions
|
|
|
|
|
//
|
|
|
|
|
vfs_fs_fns *myspiffs_realm( const char *inname, char **outname, int set_current_drive ) {
|
|
|
|
|
if (inname[0] == '/') {
|
|
|
|
|
size_t idstr_len = c_strlen( MY_LDRV_ID );
|
|
|
|
|
// logical drive is specified, check if it's our id
|
|
|
|
|
if (0 == c_strncmp( &(inname[1]), MY_LDRV_ID, idstr_len )) {
|
|
|
|
|
*outname = (char *)&(inname[1 + idstr_len]);
|
|
|
|
|
if (*outname[0] == '/') {
|
|
|
|
|
// skip leading /
|
|
|
|
|
(*outname)++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (set_current_drive) is_current_drive = TRUE;
|
|
|
|
|
return &myspiffs_fs_fns;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// no logical drive in patchspec, are we current drive?
|
|
|
|
|
if (is_current_drive) {
|
|
|
|
|
*outname = (char *)inname;
|
|
|
|
|
return &myspiffs_fs_fns;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (set_current_drive) is_current_drive = FALSE;
|
|
|
|
|
return NULL;
|
2014-12-22 12:35:05 +01:00
|
|
|
|
}
|