From e89c739e6ff06c756b6ea246b8b4f13b5dfcff95 Mon Sep 17 00:00:00 2001 From: Ramesh Thomas Date: Fri, 29 Jul 2016 02:24:37 -0700 Subject: [PATCH] fs: Adds the glue layer for the Fat FS module Adds the glue layer to interface the Fat FS module with Zephyr file system API. Origin: Original Jira: ZEP-228 ZEP-483 Change-Id: I878fdad8ecaf46992d6163e24a9b0b633f49154f Signed-off-by: Ramesh Thomas --- fs/Makefile | 1 + fs/fat_fs.c | 235 ++++++++++++++++++++++++++++++++++++++++++++ include/fs/fat_fs.h | 41 ++++++++ 3 files changed, 277 insertions(+) create mode 100644 fs/fat_fs.c create mode 100644 include/fs/fat_fs.h diff --git a/fs/Makefile b/fs/Makefile index 4e618c7c037..154755759d9 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_FS_FAT_RAM_DISK) += fat_ram_diskio.o +obj-$(CONFIG_FILE_SYSTEM_FAT) += fat_fs.o diff --git a/fs/fat_fs.c b/fs/fat_fs.c new file mode 100644 index 00000000000..af335eb1a43 --- /dev/null +++ b/fs/fat_fs.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * + * Licensed 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static FATFS fat_fs; /* FatFs work area */ + +static int translate_error(int error) +{ + switch (error) { + case FR_OK: + return 0; + case FR_NO_FILE: + case FR_NO_PATH: + case FR_INVALID_NAME: + return -ENOENT; + case FR_DENIED: + return -EACCES; + case FR_EXIST: + return -EEXIST; + case FR_INVALID_OBJECT: + return -EBADF; + case FR_WRITE_PROTECTED: + return -EROFS; + case FR_INVALID_DRIVE: + case FR_NOT_ENABLED: + case FR_NO_FILESYSTEM: + return -ENODEV; + case FR_NOT_ENOUGH_CORE: + return -ENOMEM; + case FR_TOO_MANY_OPEN_FILES: + return -EMFILE; + case FR_INVALID_PARAMETER: + return -EINVAL; + case FR_LOCKED: + case FR_TIMEOUT: + case FR_MKFS_ABORTED: + case FR_DISK_ERR: + case FR_INT_ERR: + case FR_NOT_READY: + return -EIO; + } + + return -EIO; +} + +int fs_open(ZFILE *zfp, const char *file_name) +{ + FRESULT res; + uint8_t fs_mode; + + fs_mode = FA_READ | FA_WRITE | FA_OPEN_ALWAYS; + + res = f_open(&zfp->fp, file_name, fs_mode); + + return translate_error(res); +} + +int fs_close(ZFILE *zfp) +{ + FRESULT res; + + res = f_close(&zfp->fp); + + return translate_error(res); +} + +int fs_unlink(const char *path) +{ + FRESULT res; + + res = f_unlink(path); + + return translate_error(res); +} + +ssize_t fs_read(ZFILE *zfp, void *ptr, size_t size) +{ + FRESULT res; + unsigned int br; + + res = f_read(&zfp->fp, ptr, size, &br); + if (res != FR_OK) { + return translate_error(res); + } + + return br; +} + +ssize_t fs_write(ZFILE *zfp, const void *ptr, size_t size) +{ + FRESULT res; + unsigned int bw; + + res = f_write(&zfp->fp, ptr, size, &bw); + if (res != FR_OK) { + return translate_error(res); + } + + return bw; +} + +int fs_seek(ZFILE *zfp, off_t offset, int whence) +{ + FRESULT res = FR_OK; + off_t pos; + + switch (whence) { + case SEEK_SET: + pos = offset; + break; + case SEEK_CUR: + pos = f_tell(&zfp->fp) + offset; + break; + case SEEK_END: + pos = f_size(&zfp->fp) + offset; + break; + default: + return -EINVAL; + } + + if ((pos < 0) || (pos > f_size(&zfp->fp))) { + return -EINVAL; + } + + res = f_lseek(&zfp->fp, pos); + + return translate_error(res); +} + +int fs_mkdir(const char *path) +{ + FRESULT res; + + res = f_mkdir(path); + + return translate_error(res); +} + +int fs_opendir(ZDIR *zdp, const char *path) +{ + FRESULT res; + + res = f_opendir(&zdp->dp, path); + + return translate_error(res); +} + +int fs_readdir(ZDIR *zdp, struct zfs_dirent *entry) +{ + FRESULT res; + FILINFO fno; + + res = f_readdir(&zdp->dp, &fno); + if (res == FR_OK) { + entry->type = ((fno.fattrib & AM_DIR) ? + DIR_ENTRY_DIR : DIR_ENTRY_FILE); + strcpy(entry->name, fno.fname); + entry->size = fno.fsize; + } + + return translate_error(res); +} + +int fs_closedir(ZDIR *zdp) +{ + FRESULT res; + + res = f_closedir(&zdp->dp); + + return translate_error(res); +} + +int fs_stat(const char *path, struct zfs_dirent *entry) +{ + FRESULT res; + FILINFO fno; + + res = f_stat(path, &fno); + if (res == FR_OK) { + entry->type = ((fno.fattrib & AM_DIR) ? + DIR_ENTRY_DIR : DIR_ENTRY_FILE); + strcpy(entry->name, fno.fname); + entry->size = fno.fsize; + } + + return translate_error(res); +} + +static int fs_init(struct device *dev) +{ + FRESULT res; + + ARG_UNUSED(dev); + + res = f_mount(&fat_fs, "", 1); + + /* If no file system found then create one */ + if (res == FR_NO_FILESYSTEM) { + uint8_t work[_MAX_SS]; + + res = f_mkfs("", (FM_FAT | FM_SFD), _MAX_SS, + work, sizeof(work)); + + if (res == FR_OK) { + res = f_mount(&fat_fs, "", 1); + } + } + + __ASSERT((res == FR_OK), "FS init failed (%d)", translate_error(res)); + + return translate_error(res); +} + +SYS_INIT(fs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/include/fs/fat_fs.h b/include/fs/fat_fs.h new file mode 100644 index 00000000000..f69930c35c8 --- /dev/null +++ b/include/fs/fat_fs.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * + * Licensed 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. + */ + +#ifndef _FAT_FS_H_ +#define _FAT_FS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ZFILE_DEFINE(FIL fp); +ZDIR_DEFINE(DIR dp); + +#define MAX_FILE_NAME 12 /* Uses 8.3 SFN */ + +static inline off_t fs_tell(struct _zfile_object *zfp) +{ + return f_tell(&zfp->fp); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _FAT_FS_H_ */