From 74315bee5ef6fb1ba0e0112321a58b4e4d32342c Mon Sep 17 00:00:00 2001 From: WillianChan Date: Wed, 1 Jun 2022 18:12:20 +0800 Subject: [PATCH] =?UTF-8?q?[=E6=B7=BB=E5=8A=A0]PPS=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WillianChan --- bsp/qemu-vexpress-a9/applications/mnt.c | 11 + bsp/qemu-vexpress-a9/applications/romfs.c | 3 +- components/dfs/Kconfig | 3 + components/dfs/filesystems/pps/SConscript | 9 + components/dfs/filesystems/pps/dfs_pps.c | 434 ++++++++++++++++++++++ components/dfs/filesystems/pps/dfs_pps.h | 46 +++ 6 files changed, 505 insertions(+), 1 deletion(-) create mode 100644 components/dfs/filesystems/pps/SConscript create mode 100644 components/dfs/filesystems/pps/dfs_pps.c create mode 100644 components/dfs/filesystems/pps/dfs_pps.h diff --git a/bsp/qemu-vexpress-a9/applications/mnt.c b/bsp/qemu-vexpress-a9/applications/mnt.c index 0fc9b62860..c5ad626cac 100644 --- a/bsp/qemu-vexpress-a9/applications/mnt.c +++ b/bsp/qemu-vexpress-a9/applications/mnt.c @@ -19,6 +19,17 @@ int mnt_init(void) return -1; } + rt_thread_mdelay(200); + if (dfs_mount(RT_NULL, "/pps", "pps", 0, dfs_pps_init(rt_malloc(1024), 1024)) != 0) + { + rt_kprintf("Dir /mnt mount failed!\n"); + return -1; + } + else + { + rt_kprintf("PPS service initializated!\n"); + } + rt_kprintf("file system initialization done!\n"); return 0; } diff --git a/bsp/qemu-vexpress-a9/applications/romfs.c b/bsp/qemu-vexpress-a9/applications/romfs.c index c28ba8ea7f..8c475f9e2c 100644 --- a/bsp/qemu-vexpress-a9/applications/romfs.c +++ b/bsp/qemu-vexpress-a9/applications/romfs.c @@ -8,7 +8,8 @@ static const struct romfs_dirent _romfs_root[] = { {ROMFS_DIRENT_DIR, "etc", RT_NULL, 0}, - {ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0} + {ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0}, + {ROMFS_DIRENT_DIR, "pps", RT_NULL, 0}, }; const struct romfs_dirent romfs_root = { diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index 657c8a25c4..c0c4feb8ac 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -169,6 +169,9 @@ if RT_USING_DFS default "192.168.1.5:/" endif + config RT_USING_DFS_PPS + bool "Enable PPS service" + default n endif endmenu diff --git a/components/dfs/filesystems/pps/SConscript b/components/dfs/filesystems/pps/SConscript new file mode 100644 index 0000000000..293e62306c --- /dev/null +++ b/components/dfs/filesystems/pps/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('pps', src, depend = ['RT_USING_DFS', 'RT_USING_MEMHEAP', 'RT_USING_DFS_PPS'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/dfs/filesystems/pps/dfs_pps.c b/components/dfs/filesystems/pps/dfs_pps.c new file mode 100644 index 0000000000..76a559fa62 --- /dev/null +++ b/components/dfs/filesystems/pps/dfs_pps.c @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: GPL-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-31 WillianChan The first version + */ + +#include +#include +#include +#include + +#include "dfs_pps.h" + +int dfs_pps_mount(struct dfs_filesystem *fs, + unsigned long rwflag, + const void *data) +{ + struct dfs_pps *pps; + + if (data == NULL) + return -EIO; + + pps = (struct dfs_pps *)data; + fs->data = pps; + + return RT_EOK; +} + +int dfs_pps_unmount(struct dfs_filesystem *fs) +{ + fs->data = NULL; + + return RT_EOK; +} + +int dfs_pps_statfs(struct dfs_filesystem *fs, struct statfs *buf) +{ + struct dfs_pps *pps; + + pps = (struct dfs_pps *)fs->data; + RT_ASSERT(pps != NULL); + RT_ASSERT(buf != NULL); + + buf->f_bsize = 512; + buf->f_blocks = pps->memheap.pool_size / 512; + buf->f_bfree = pps->memheap.available_size / 512; + + return RT_EOK; +} + +int ddfs_pps_ioctl(struct dfs_fd *file, int cmd, void *args) +{ + return -EIO; +} + +struct pps_dirent *dfs_pps_lookup(struct dfs_pps *pps, + const char *path, + rt_size_t *size) +{ + const char *subpath; + struct pps_dirent *dirent; + + subpath = path; + while (*subpath == '/' && *subpath) + subpath ++; + if (! *subpath) /* is root directory */ + { + *size = 0; + + return &(pps->root); + } + + for (dirent = rt_list_entry(pps->root.list.next, struct pps_dirent, list); + dirent != &(pps->root); + dirent = rt_list_entry(dirent->list.next, struct pps_dirent, list)) + { + if (rt_strcmp(dirent->name, subpath) == 0) + { + *size = dirent->size; + + return dirent; + } + } + + /* not found */ + return NULL; +} + +int dfs_pps_read(struct dfs_fd *file, void *buf, size_t count) +{ + rt_size_t length; + struct pps_dirent *dirent; + + dirent = (struct pps_dirent *)file->fnode->data; + RT_ASSERT(dirent != NULL); + + if (count < file->fnode->size - file->pos) + length = count; + else + length = file->fnode->size - file->pos; + + if (length > 0) + memcpy(buf, &(dirent->data[file->pos]), length); + + /* update file current position */ + file->pos += length; + + return length; +} + +int dfs_pps_write(struct dfs_fd *fd, const void *buf, size_t count) +{ + struct pps_dirent *dirent; + struct dfs_pps *pps; + rt_uint8_t *ptr; + char dirent_name[PPS_NAME_MAX]; + rt_int32_t dirent_name_len; + + dirent = (struct pps_dirent *)fd->fnode->data; + RT_ASSERT(dirent != NULL); + + pps = dirent->fs; + RT_ASSERT(pps != NULL); + + if (count + fd->pos > fd->fnode->size) + { + dirent_name_len = rt_snprintf(dirent_name, sizeof(dirent_name), "@%s\n", dirent->name); + ptr = rt_memheap_realloc(&(pps->memheap), dirent->data, fd->pos + count + dirent_name_len); + if (ptr == NULL) + { + rt_set_errno(-ENOMEM); + + return 0; + } + + /* update dirent and file size */ + dirent->data = ptr; + dirent->size = fd->pos + count + dirent_name_len; + fd->fnode->size = dirent->size; + } + + if (count > 0) + { + memcpy(dirent->data, dirent_name, dirent_name_len); + memcpy(dirent->data + fd->pos + dirent_name_len, buf, count); + } + + return count; +} + +int dfs_pps_lseek(struct dfs_fd *file, off_t offset) +{ + if (offset <= (off_t)file->fnode->size) + { + file->pos = offset; + + return file->pos; + } + + return -EIO; +} + +int dfs_pps_close(struct dfs_fd *file) +{ + RT_ASSERT(file->fnode->ref_count > 0); + if (file->fnode->ref_count > 1) + { + return 0; + } + + file->fnode->data = NULL; + + return RT_EOK; +} + +int dfs_pps_open(struct dfs_fd *file) +{ + rt_size_t size; + struct dfs_pps *pps; + struct pps_dirent *dirent; + struct dfs_filesystem *fs; + + RT_ASSERT(file->fnode->ref_count > 0); + if (file->fnode->ref_count > 1) + { + if (file->fnode->type == FT_DIRECTORY + && !(file->flags & O_DIRECTORY)) + { + return -ENOENT; + } + file->pos = 0; + return 0; + } + + fs = file->fnode->fs; + + pps = (struct dfs_pps *)fs->data; + RT_ASSERT(pps != NULL); + + if (file->flags & O_DIRECTORY) + { + if (file->flags & O_CREAT) + { + return -ENOSPC; + } + + /* open directory */ + dirent = dfs_pps_lookup(pps, file->fnode->path, &size); + if (dirent == NULL) + return -ENOENT; + if (dirent == &(pps->root)) /* it's root directory */ + { + if (!(file->flags & O_DIRECTORY)) + { + return -ENOENT; + } + } + file->fnode->type = FT_DIRECTORY; + } + else + { + dirent = dfs_pps_lookup(pps, file->fnode->path, &size); + if (dirent == &(pps->root)) /* it's root directory */ + { + return -ENOENT; + } + + if (dirent == NULL) + { + if (file->flags & O_CREAT || file->flags & O_WRONLY) + { + char *name_ptr; + + /* create a file entry */ + dirent = (struct pps_dirent *) + rt_memheap_alloc(&(pps->memheap), + sizeof(struct pps_dirent)); + if (dirent == NULL) + { + return -ENOMEM; + } + + /* remove '/' separator */ + name_ptr = file->fnode->path; + while (*name_ptr == '/' && *name_ptr) + { + name_ptr++; + } + strncpy(dirent->name, name_ptr, PPS_NAME_MAX); + + rt_list_init(&(dirent->list)); + dirent->data = NULL; + dirent->size = 0; + dirent->fs = pps; + file->fnode->type = FT_DIRECTORY; + + /* add to the root directory */ + rt_list_insert_after(&(pps->root.list), &(dirent->list)); + } + else + return -ENOENT; + } + + /* Creates a new file. + * If the file is existing, it is truncated and overwritten. + */ + if (file->flags & O_TRUNC) + { + dirent->size = 0; + if (dirent->data != NULL) + { + rt_memheap_free(dirent->data); + dirent->data = NULL; + } + } + } + + file->fnode->data = dirent; + file->fnode->size = dirent->size; + if (file->flags & O_APPEND) + { + file->pos = file->fnode->size; + } + else + { + file->pos = 0; + } + + return 0; +} + +int dfs_pps_stat(struct dfs_filesystem *fs, + const char *path, + struct stat *st) +{ + rt_size_t size; + struct pps_dirent *dirent; + struct dfs_pps *ramfs; + + ramfs = (struct dfs_pps *)fs->data; + dirent = dfs_pps_lookup(ramfs, path, &size); + + if (dirent == NULL) + return -ENOENT; + + st->st_dev = 0; + st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH | + S_IWUSR | S_IWGRP | S_IWOTH; + + st->st_size = dirent->size; + st->st_mtime = 0; + + return RT_EOK; +} + +int dfs_pps_getdents(struct dfs_fd *file, + struct dirent *dirp, + uint32_t count) +{ + rt_size_t index, end; + struct dirent *d; + struct pps_dirent *dirent; + struct dfs_pps *pps; + + dirent = (struct pps_dirent *)file->fnode->data; + + pps = dirent->fs; + RT_ASSERT(pps != RT_NULL); + + if (dirent != &(pps->root)) + return -EINVAL; + + /* make integer count */ + count = (count / sizeof(struct dirent)); + if (count == 0) + return -EINVAL; + + end = file->pos + count; + index = 0; + count = 0; + for (dirent = rt_list_entry(dirent->list.next, struct pps_dirent, list); + dirent != &(pps->root) && index < end; + dirent = rt_list_entry(dirent->list.next, struct pps_dirent, list)) + { + if (index >= (rt_size_t)file->pos) + { + d = dirp + count; + d->d_type = DT_REG; + d->d_namlen = RT_NAME_MAX; + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, dirent->name, PPS_NAME_MAX); + + count += 1; + file->pos += 1; + } + index += 1; + } + + return count * sizeof(struct dirent); +} + +static const struct dfs_file_ops _pps_fops = +{ + dfs_pps_open, + dfs_pps_close, + ddfs_pps_ioctl, + dfs_pps_read, + dfs_pps_write, + NULL, /* flush */ + dfs_pps_lseek, + dfs_pps_getdents, +}; + +static const struct dfs_filesystem_ops _pps = +{ + "pps", + DFS_FS_FLAG_DEFAULT, + &_pps_fops, + + dfs_pps_mount, + dfs_pps_unmount, + NULL, /* mkfs */ + dfs_pps_statfs, + + NULL, /* unlink */ + dfs_pps_stat, + NULL, /* rename */ +}; + +int dfs_pps_register(void) +{ + /* register pps file system */ + dfs_register(&_pps); + + return 0; +} +INIT_COMPONENT_EXPORT(dfs_pps_register); + +struct dfs_pps *dfs_pps_init(rt_uint8_t *pool, rt_size_t size) +{ + struct dfs_pps *pps; + rt_uint8_t *data_ptr; + rt_err_t result; + + size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); + pps = (struct dfs_pps *)pool; + + data_ptr = (rt_uint8_t *)(pps + 1); + size = size - sizeof(struct dfs_pps); + size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); + + result = rt_memheap_init(&pps->memheap, "pps", data_ptr, size); + if (result != RT_EOK) + return NULL; + /* detach this memheap object from the system */ + rt_object_detach((rt_object_t) & (pps->memheap)); + + /* initialize pps object */ + pps->magic = PPS_MAGIC; + pps->memheap.parent.type = RT_Object_Class_MemHeap | RT_Object_Class_Static; + + /* initialize root directory */ + memset(&(pps->root), 0x00, sizeof(pps->root)); + rt_list_init(&(pps->root.list)); + pps->root.size = 0; + strcpy(pps->root.name, "."); + pps->root.fs = pps; + + return pps; +} diff --git a/components/dfs/filesystems/pps/dfs_pps.h b/components/dfs/filesystems/pps/dfs_pps.h new file mode 100644 index 0000000000..a6b5c232ed --- /dev/null +++ b/components/dfs/filesystems/pps/dfs_pps.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: GPL-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-31 WillianChan The first version + */ + +#ifndef __DFS_PPS_H__ +#define __DFS_PPS_H__ + +#include +#include + +#define PPS_NAME_MAX 32 +#define PPS_MAGIC 0x70707373 + +struct pps_dirent +{ + rt_list_t list; + struct dfs_pps *fs; /* file system ref */ + + char name[PPS_NAME_MAX]; /* dirent name */ + rt_uint8_t *data; + + rt_size_t size; /* file size */ +}; + +/** + * DFS ramfs object + */ +struct dfs_pps +{ + rt_uint32_t magic; + + struct rt_memheap memheap; + struct pps_dirent root; +}; + +int dfs_pps_register(void); +struct dfs_pps *dfs_pps_init(rt_uint8_t *pool, rt_size_t size); + +#endif /* __DFS_PPS_H__ */ + -- Gitee