89d6bbbcd6
error: Path relative to repository other than nuttx must begin with the root directory Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
576 lines
16 KiB
C
576 lines
16 KiB
C
/****************************************************************************
|
|
* apps/graphics/lvgl/lv_fs_interface.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <sys/statfs.h>
|
|
#include "lv_fs_interface.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define LV_FS_LETTER '/'
|
|
|
|
/****************************************************************************
|
|
* Private Type Declarations
|
|
****************************************************************************/
|
|
|
|
/* Create a type to store the required data about your file. */
|
|
|
|
typedef int file_t;
|
|
|
|
/* Similarly to `file_t` create a type for directory reading too */
|
|
|
|
typedef DIR *dir_t;
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_open(lv_fs_drv_t *drv, void *file_p,
|
|
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_write(lv_fs_drv_t *drv, void *file_p,
|
|
const void *buf, uint32_t btw, uint32_t *bw);
|
|
static lv_fs_res_t fs_seek(lv_fs_drv_t *drv, void *file_p,
|
|
uint32_t pos);
|
|
static lv_fs_res_t fs_size(lv_fs_drv_t *drv, void *file_p,
|
|
uint32_t *size_p);
|
|
static lv_fs_res_t fs_tell(lv_fs_drv_t *drv, void *file_p,
|
|
uint32_t *pos_p);
|
|
static lv_fs_res_t fs_remove(lv_fs_drv_t *drv, const char *path);
|
|
static lv_fs_res_t fs_trunc(lv_fs_drv_t *drv, void *file_p);
|
|
static lv_fs_res_t fs_rename(lv_fs_drv_t *drv, const char *oldname,
|
|
const char *newname);
|
|
static lv_fs_res_t fs_free(lv_fs_drv_t *drv, uint32_t *total_p,
|
|
uint32_t *free_p);
|
|
static lv_fs_res_t fs_dir_open(lv_fs_drv_t *drv, void *dir_p,
|
|
const char *path);
|
|
static lv_fs_res_t fs_dir_read(lv_fs_drv_t *drv, void *dir_p, char *fn);
|
|
static lv_fs_res_t fs_dir_close(lv_fs_drv_t *drv, void *dir_p);
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: fs_open
|
|
*
|
|
* Description:
|
|
* Open a file.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
* path - path to the file beginning with the driver letter.
|
|
* (e.g. /folder/file.txt)
|
|
* mode - read: FS_MODE_RD, write: FS_MODE_WR,
|
|
* both: FS_MODE_RD | FS_MODE_WR
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_open(lv_fs_drv_t *drv, void *file_p,
|
|
const char *path, lv_fs_mode_t mode)
|
|
{
|
|
uint32_t flags = 0;
|
|
if (mode == LV_FS_MODE_WR)
|
|
{
|
|
flags = O_WRONLY | O_CREAT;
|
|
}
|
|
else if (mode == LV_FS_MODE_RD)
|
|
{
|
|
flags = O_RDONLY;
|
|
}
|
|
else if (mode == (LV_FS_MODE_WR | LV_FS_MODE_RD))
|
|
{
|
|
flags = O_RDWR | O_CREAT;
|
|
}
|
|
else
|
|
{
|
|
return LV_FS_RES_UNKNOWN;
|
|
}
|
|
|
|
file_t f = open(--path, flags);
|
|
if (f < 0)
|
|
{
|
|
return LV_FS_RES_FS_ERR;
|
|
}
|
|
|
|
/* 'file_p' is pointer to a file descriptor and
|
|
* we need to store our file descriptor here
|
|
*/
|
|
|
|
file_t *fp = file_p; /* Just avoid the confusing casings */
|
|
*fp = f;
|
|
|
|
return LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_close
|
|
*
|
|
* Description:
|
|
* Close an opened file.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
*
|
|
* Returned Value:
|
|
* 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)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
file_t *fp = file_p;
|
|
|
|
return close(*fp) < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_read
|
|
*
|
|
* Description:
|
|
* Read data from an opened file.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
* buf - pointer to a memory block where to store the read data.
|
|
* btr - number of Bytes To Read.
|
|
* br - the real number of read bytes (Byte Read).
|
|
*
|
|
* Returned Value:
|
|
* 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)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
file_t *fp = file_p;
|
|
|
|
*br = read(*fp, buf, btr);
|
|
|
|
return (int32_t)*br < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_write
|
|
*
|
|
* Description:
|
|
* Write into a file.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
* buf - pointer to a buffer with the bytes to write.
|
|
* btw - Bytes To Write.
|
|
* bw - the number of real written bytes (Bytes Written).
|
|
* NULL if unused.
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_write(lv_fs_drv_t *drv, void *file_p,
|
|
const void *buf, uint32_t btw, uint32_t *bw)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
file_t *fp = file_p;
|
|
|
|
*bw = write(*fp, buf, btw);
|
|
|
|
return (int32_t)*bw < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_seek
|
|
*
|
|
* Description:
|
|
* Set the read write pointer. Also expand the file size if necessary.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
* pos - the new position of read write pointer.
|
|
*
|
|
* Returned Value:
|
|
* 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)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
file_t *fp = file_p;
|
|
|
|
off_t offset = lseek(*fp, pos, SEEK_SET);
|
|
|
|
return offset < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_size
|
|
*
|
|
* Description:
|
|
* Give the size of a file bytes.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
* size - pointer to a variable to store the size.
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_size(lv_fs_drv_t *drv, void *file_p,
|
|
uint32_t *size_p)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
file_t *fp = file_p;
|
|
|
|
off_t cur = lseek(*fp, 0, SEEK_CUR);
|
|
|
|
*size_p = lseek(*fp, 0L, SEEK_END);
|
|
|
|
/* Restore file pointer */
|
|
|
|
lseek(*fp, cur, SEEK_SET);
|
|
|
|
return (int32_t)*size_p < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_tell
|
|
*
|
|
* Description:
|
|
* Give the position of the read write pointer.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
* pos_p - pointer to to store the result.
|
|
*
|
|
* Returned Value:
|
|
* 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)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
file_t *fp = file_p;
|
|
|
|
*pos_p = lseek(*fp, 0, SEEK_CUR);
|
|
|
|
return (int32_t)*pos_p < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_remove
|
|
*
|
|
* Description:
|
|
* Delete a file.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* path - path of the file to delete.
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_remove(lv_fs_drv_t *drv, const char *path)
|
|
{
|
|
return remove(--path) < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_trunc
|
|
*
|
|
* Description:
|
|
* Truncate the file size to the current position of
|
|
* the read write pointer.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* file_p - pointer to a file_t variable.
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_trunc(lv_fs_drv_t *drv, void *file_p)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
file_t *fp = file_p;
|
|
|
|
off_t p = lseek(*fp, 0, SEEK_CUR);
|
|
|
|
return ftruncate(*fp, p) < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_rename
|
|
*
|
|
* Description:
|
|
* Rename a file.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* oldname - path to the file.
|
|
* newname - path with the new name
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_rename(lv_fs_drv_t *drv, const char *oldname,
|
|
const char *newname)
|
|
{
|
|
return rename(--oldname, --newname) < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_free
|
|
*
|
|
* Description:
|
|
* Get the free and total size of a driver in kB.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* total_p - pointer to store the total size [kB].
|
|
* free_p - pointer to store the free size [kB]
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_free(lv_fs_drv_t *drv, uint32_t *total_p,
|
|
uint32_t *free_p)
|
|
{
|
|
struct statfs sfs;
|
|
|
|
if (statfs(CONFIG_LV_FILESYSTEM_MOUNTPOINT, &sfs) < 0)
|
|
{
|
|
return LV_FS_RES_FS_ERR;
|
|
}
|
|
else
|
|
{
|
|
*total_p = sfs.f_blocks * sfs.f_bsize / 1024;
|
|
*free_p = sfs.f_bfree * sfs.f_bsize / 1024;
|
|
return LV_FS_RES_OK;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_dir_open
|
|
*
|
|
* Description:
|
|
* Initialize a 'fs_read_dir_t' variable for directory reading.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* dir_p - pointer to a 'fs_read_dir_t' variable.
|
|
* path - path to a directory.
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_dir_open(lv_fs_drv_t *drv, void *dir_p,
|
|
const char *path)
|
|
{
|
|
dir_t d;
|
|
|
|
/* Make the path relative to the current directory
|
|
* (the projects root folder)
|
|
*/
|
|
|
|
if ((d = opendir(--path)) == NULL)
|
|
{
|
|
return LV_FS_RES_FS_ERR;
|
|
}
|
|
else
|
|
{
|
|
/* 'dir_p' is pointer to a file descriptor and
|
|
* we need to store our file descriptor here
|
|
*/
|
|
|
|
/* Just avoid the confusing casings */
|
|
|
|
dir_t *dp = dir_p;
|
|
*dp = d;
|
|
}
|
|
|
|
return LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_dir_read
|
|
*
|
|
* Description:
|
|
* Read the next filename form a directory.
|
|
* The name of the directories will begin with '/'.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* dir_p - pointer to an initialized 'fs_read_dir_t' variable.
|
|
* fn - pointer to a buffer to store the filename.
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_dir_read(lv_fs_drv_t *drv, void *dir_p, char *fn)
|
|
{
|
|
/* Just avoid the confusing casings */
|
|
|
|
dir_t *dp = dir_p;
|
|
|
|
do
|
|
{
|
|
struct dirent *entry = readdir(*dp);
|
|
|
|
if (entry)
|
|
{
|
|
if (entry->d_type == DT_DIR)
|
|
{
|
|
sprintf(fn, "/%s", entry->d_name);
|
|
}
|
|
else
|
|
{
|
|
strcpy(fn, entry->d_name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy(fn, "");
|
|
}
|
|
}
|
|
while (strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0);
|
|
|
|
return LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: fs_dir_read
|
|
*
|
|
* Description:
|
|
* Close the directory reading.
|
|
*
|
|
* Input Parameters:
|
|
* drv - pointer to a driver where this function belongs.
|
|
* dir_p - pointer to an initialized 'fs_read_dir_t' variable.
|
|
*
|
|
* Returned Value:
|
|
* LV_FS_RES_OK or any error from lv_fs_res_t enum.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static lv_fs_res_t fs_dir_close(lv_fs_drv_t *drv, void *dir_p)
|
|
{
|
|
dir_t *dp = dir_p;
|
|
|
|
return closedir(*dp) < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: lv_fs_interface_init
|
|
*
|
|
* Description:
|
|
* Register a driver for the File system interface.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void lv_fs_interface_init(void)
|
|
{
|
|
/* Add a simple drive to open images */
|
|
|
|
lv_fs_drv_t fs_drv; /* A driver descriptor */
|
|
|
|
lv_fs_drv_init(&fs_drv);
|
|
|
|
/* Set up fields... */
|
|
|
|
fs_drv.file_size = sizeof(file_t);
|
|
fs_drv.letter = LV_FS_LETTER;
|
|
fs_drv.open_cb = fs_open;
|
|
fs_drv.close_cb = fs_close;
|
|
fs_drv.read_cb = fs_read;
|
|
fs_drv.write_cb = fs_write;
|
|
fs_drv.seek_cb = fs_seek;
|
|
fs_drv.tell_cb = fs_tell;
|
|
fs_drv.free_space_cb = fs_free;
|
|
fs_drv.size_cb = fs_size;
|
|
fs_drv.remove_cb = fs_remove;
|
|
fs_drv.rename_cb = fs_rename;
|
|
fs_drv.trunc_cb = fs_trunc;
|
|
|
|
fs_drv.rddir_size = sizeof(dir_t);
|
|
fs_drv.dir_close_cb = fs_dir_close;
|
|
fs_drv.dir_open_cb = fs_dir_open;
|
|
fs_drv.dir_read_cb = fs_dir_read;
|
|
|
|
lv_fs_drv_register(&fs_drv);
|
|
}
|