From 171748f83c8df92358f4cd1b9ff37c520ff52e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Tue, 12 Jul 2016 07:58:42 +0200 Subject: [PATCH] drivers/nvram: Add vfs compatible functions --- drivers/Makefile.dep | 1 + drivers/include/nvram.h | 8 +++ drivers/nvram/Makefile | 3 + drivers/nvram/nvram-vfs.c | 136 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 drivers/nvram/Makefile create mode 100644 drivers/nvram/nvram-vfs.c diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 558ff0e35a6d..67b72ba398fd 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -150,6 +150,7 @@ ifneq (,$(filter nrfmin,$(USEMODULE))) endif ifneq (,$(filter nvram_spi,$(USEMODULE))) + USEMODULE += nvram USEMODULE += xtimer endif diff --git a/drivers/include/nvram.h b/drivers/include/nvram.h index 6bc79feff6d0..4eab01be30c4 100644 --- a/drivers/include/nvram.h +++ b/drivers/include/nvram.h @@ -30,6 +30,10 @@ #include #include +#if MODULE_VFS +#include "vfs.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -79,6 +83,10 @@ typedef struct nvram { void *extra; } nvram_t; +#if MODULE_VFS +extern const vfs_file_ops_t nvram_vfs_ops; +#endif + #ifdef __cplusplus } #endif diff --git a/drivers/nvram/Makefile b/drivers/nvram/Makefile new file mode 100644 index 000000000000..48055ad6339b --- /dev/null +++ b/drivers/nvram/Makefile @@ -0,0 +1,3 @@ +MODULE = nvram + +include $(RIOTBASE)/Makefile.base diff --git a/drivers/nvram/nvram-vfs.c b/drivers/nvram/nvram-vfs.c new file mode 100644 index 000000000000..9118ae60d527 --- /dev/null +++ b/drivers/nvram/nvram-vfs.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2016 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +#if MODULE_VFS + +#include +#include +#include + +#include "nvram.h" +#include "vfs.h" + +/** + * @ingroup nvram + * @{ + * + * @file + * + * @brief NVRAM generic VFS operations + * + * This allows the nvram driver to register as a node on DevFS + * + * See boards/mulle or tests/unittests/tests-devfs for examples on how to use. + * + * Tested with nvram_spi on Mulle + * + * @author Joakim NohlgÄrd + */ + +static int nvram_vfs_fstat(vfs_file_t *filp, struct stat *buf); +static off_t nvram_vfs_lseek(vfs_file_t *filp, off_t off, int whence); +static ssize_t nvram_vfs_read(vfs_file_t *filp, void *dest, size_t nbytes); +static ssize_t nvram_vfs_write(vfs_file_t *filp, const void *src, size_t nbytes); + +const vfs_file_ops_t nvram_vfs_ops = { + .fstat = nvram_vfs_fstat, + .lseek = nvram_vfs_lseek, + .read = nvram_vfs_read, + .write = nvram_vfs_write, +}; + +static int nvram_vfs_fstat(vfs_file_t *filp, struct stat *buf) +{ + if (buf == NULL) { + return -EFAULT; + } + nvram_t *dev = filp->private_data.ptr; + if (dev == NULL) { + return -EFAULT; + } + buf->st_nlink = 1; + buf->st_size = dev->size; + return 0; +} + +static off_t nvram_vfs_lseek(vfs_file_t *filp, off_t off, int whence) +{ + nvram_t *dev = filp->private_data.ptr; + if (dev == NULL) { + return -EFAULT; + } + switch (whence) { + case SEEK_SET: + break; + case SEEK_CUR: + off += filp->pos; + break; + case SEEK_END: + off += dev->size; + break; + default: + return -EINVAL; + } + if (off < 0) { + /* the resulting file offset would be negative */ + return -EINVAL; + } + /* POSIX allows seeking past the end of the file */ + filp->pos = off; + return off; +} + +static ssize_t nvram_vfs_read(vfs_file_t *filp, void *dest, size_t nbytes) +{ + nvram_t *dev = filp->private_data.ptr; + if (dev == NULL) { + return -EFAULT; + } + uint32_t src = filp->pos; + if (src >= dev->size) { + return 0; + } + if (src + nbytes > dev->size) { + nbytes = dev->size - src; + } + int res = dev->read(dev, dest, src, nbytes); + if (res < 0) { + return res; + } + /* Advance file position */ + filp->pos += res; + return res; +} + +static ssize_t nvram_vfs_write(vfs_file_t *filp, const void *src, size_t nbytes) +{ + nvram_t *dev = filp->private_data.ptr; + if (dev == NULL) { + return -EFAULT; + } + uint32_t dest = filp->pos; + if (dest >= dev->size) { + return 0; + } + if (dest + nbytes > dev->size) { + nbytes = dev->size - dest; + } + int res = dev->write(dev, src, dest, nbytes); + if (res < 0) { + return res; + } + /* Advance file position */ + filp->pos += res; + return res; +} + +/** @} */ + +#else +typedef int dont_be_pedantic; +#endif /* MODULE_VFS */