Files
lvgl/src/libs/fsdrv/lv_fs_memfs.c
2024-01-18 10:57:16 +01:00

216 lines
6.4 KiB
C

/**
* @file lv_fs_memfs.c
*
* File System Interface driver for memory-mapped files
*
* This driver allows using a memory area as a file that can be read by normal file operations. It can
* be used, e.g., to store font files in slow flash memory, and load them into RAM on demand.
*
* You can enable it in lv_conf.h:
*
* #define LV_USE_FS_MEMFS 1
*
* The actual implementation uses the built-in cache mechanism of the file system interface.
*
* Since this is not an actual file system, file write and directories are not supported.
*
* The default drive letter is 'M', but this can be changed in lv_conf.h:
*
* #define LV_FS_MEMFS_LETTER 'M'
*
* To use it seamlessly with the file system interface a new extended path object has been introduced:
*
* lv_fs_path_ex_t mempath;
*
* This structure can be initialized with the helper function:
*
* lv_fs_make_path_ex(&mempath, (const uint8_t *) & my_mem_buffer, sizeof(my_mem_buffer));
*
* Then the "file" can be opened with:
*
* lv_fs_file_t file;
* lv_fs_res_t res = lv_fs_open(&file, (const char *) & mempath, LV_FS_MODE_RD);
*
* The path object can be used at any place where a file path is required, e.g.:
*
* lv_font_t* my_font = lv_binfont_create((const char *) & mempath);
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FS_MEMFS
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
/**********************
* STATIC VARIABLES
**********************/
static lv_fs_drv_t fs_drv; /*A driver descriptor*/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Register a driver for the File system interface
*/
void lv_fs_memfs_init(void)
{
/*---------------------------------------------------
* Register the file system interface in LVGL
*--------------------------------------------------*/
/*Add a simple drive to open images*/
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_FS_MEMFS_LETTER;
fs_drv.cache_size = LV_FS_CACHE_FROM_BUFFER;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
fs_drv.write_cb = NULL;
fs_drv.seek_cb = fs_seek;
fs_drv.tell_cb = fs_tell;
fs_drv.dir_close_cb = NULL;
fs_drv.dir_open_cb = NULL;
fs_drv.dir_read_cb = NULL;
lv_fs_drv_register(&fs_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Open a file
* @param drv pointer to a driver where this function belongs
* @param path pointer to an extended path object containing the memory buffer address and size
* @param mode read: FS_MODE_RD (currently only reading from the buffer is supported)
* @return pointer to FIL struct or NULL in case of fail
*/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
{
LV_UNUSED(drv);
LV_UNUSED(mode);
return (void *)path;
}
/**
* Close an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. (opened with fs_open)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
{
LV_UNUSED(drv);
LV_UNUSED(file_p);
return LV_FS_RES_OK;
}
/**
* Read data from an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable.
* @param buf pointer to a memory block where to store the read data
* @param btr number of Bytes To Read
* @param br the real number of read bytes (Byte Read)
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
LV_UNUSED(drv);
LV_UNUSED(file_p);
LV_UNUSED(buf);
LV_UNUSED(btr);
*br = 0;
return LV_FS_RES_OK;
}
/**
* Set the read pointer.
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. (opened with fs_open )
* @param pos the new position of read pointer
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
{
/* NOTE: this function is only called to determine the end of the buffer when LV_FS_SEEK_END was given to lv_fs_seek() */
LV_UNUSED(drv);
lv_fs_file_t * fp = (lv_fs_file_t *)file_p;
switch(whence) {
case LV_FS_SEEK_SET: {
fp->cache->file_position = pos;
break;
}
case LV_FS_SEEK_CUR: {
fp->cache->file_position += pos;
break;
}
case LV_FS_SEEK_END: {
fp->cache->file_position = fp->cache->end - pos;
break;
}
}
if(fp->cache->file_position < fp->cache->start)
fp->cache->file_position = fp->cache->start;
else if(fp->cache->file_position > fp->cache->end)
fp->cache->file_position = fp->cache->end;
return LV_FS_RES_OK;
}
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable.
* @param pos_p pointer to to store the result
* @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum
*/
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
LV_UNUSED(drv);
*pos_p = ((lv_fs_file_t *)file_p)->cache->file_position;
return LV_FS_RES_OK;
}
#else /*LV_USE_FS_MEMFS == 0*/
#if defined(LV_FS_MEMFS_LETTER) && LV_FS_MEMFS_LETTER != '\0'
#warning "LV_USE_FS_MEMFS is not enabled but LV_FS_MEMFS_LETTER is set"
#endif
#endif /*LV_USE_FS_MEMFS*/