procfs/: Extenstive architectural changes and enhancements by Ken Pettit

This commit is contained in:
Gregory Nutt 2013-12-12 09:21:55 -06:00
parent 33a3bb0e37
commit e4471dc8e0
24 changed files with 3352 additions and 692 deletions

View File

@ -6200,3 +6200,7 @@
* libc/misc/lib_match.c: Pattern matching logic extended to handle * libc/misc/lib_match.c: Pattern matching logic extended to handle
matches to sets of characters and ranges of character values. From matches to sets of characters and ranges of character values. From
Ken Pettit (2013-12-12). Ken Pettit (2013-12-12).
* fs/procfs, drivers/mtd, fs/smartfs, includes/nuttx/fs, .. to many
files to list: Extensive changes by Ken Pettit to extend procfs/
functionality. Includes some incomplete changes related to
SmartFS (2013-12-12).

View File

@ -26,6 +26,16 @@ config MTD_PARTITION
managing the sub-region of flash beginning at 'offset' (in blocks) managing the sub-region of flash beginning at 'offset' (in blocks)
and of size 'nblocks' on the device specified by 'mtd'. and of size 'nblocks' on the device specified by 'mtd'.
config MTD_PARTITION_NAMES
bool "Support MTD partition naming"
depends on FS_PROCFS
depends on MTD_PARTITION
default n
---help---
MTD partitions can be assigned a name for reporting via the procfs
file system interface. This adds an API which must be called to
specify the partition name.
config MTD_BYTE_WRITE config MTD_BYTE_WRITE
bool "Byte write" bool "Byte write"
default n default n

View File

@ -86,6 +86,12 @@ CSRCS += smart.c
endif endif
endif endif
ifeq ($(CONFIG_FS_PROCFS),y)
ifneq ($(CONFIG_FS_PROCFS_EXCLUDE_MTD),y)
CSRCS += mtd_procfs.c
endif
endif
# Include MTD driver support # Include MTD driver support
DEPPATH += --dep-path mtd DEPPATH += --dep-path mtd

View File

@ -429,6 +429,12 @@ FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_dev_s *dev)
priv->dev = dev; priv->dev = dev;
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "at24xx");
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);

View File

@ -709,6 +709,12 @@ FAR struct mtd_dev_s *at25_initialize(FAR struct spi_dev_s *dev)
} }
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "at25");
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);

View File

@ -886,6 +886,12 @@ FAR struct mtd_dev_s *at45db_initialize(FAR struct spi_dev_s *spi)
at45db_unlock(priv); at45db_unlock(priv);
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "at45db");
#endif
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);
return (FAR struct mtd_dev_s *)priv; return (FAR struct mtd_dev_s *)priv;

View File

@ -1032,6 +1032,12 @@ FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev)
} }
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "m25px");
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);

View File

@ -45,10 +45,17 @@
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <debug.h> #include <debug.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <nuttx/mtd/mtd.h> #include <nuttx/mtd/mtd.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/fs/ioctl.h> #include <nuttx/fs/ioctl.h>
#ifdef CONFIG_FS_PROCFS
#include <nuttx/fs/procfs.h>
#endif
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@ -81,31 +88,95 @@ struct mtd_partition_s
* sub-region */ * sub-region */
off_t blocksize; /* The size of one read/write block */ off_t blocksize; /* The size of one read/write block */
uint16_t blkpererase; /* Number of R/W blocks in one erase block */ uint16_t blkpererase; /* Number of R/W blocks in one erase block */
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
struct mtd_partition_s *pnext; /* Pointer to next partition struct */
#endif
#ifdef CONFIG_MTD_PARTITION_NAMES
FAR const char *name; /* Name of the partition */
#endif
}; };
/* This structure describes one open "file" */
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
struct part_procfs_file_s
{
struct procfs_file_s base; /* Base open file structure */
struct mtd_partition_s *nextpart;
};
#endif
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
/* MTD driver methods */ /* MTD driver methods */
static int part_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks); static int part_erase(FAR struct mtd_dev_s *dev, off_t startblock,
static ssize_t part_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, size_t nblocks);
FAR uint8_t *buf); static ssize_t part_bread(FAR struct mtd_dev_s *dev, off_t startblock,
static ssize_t part_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks, size_t nblocks, FAR uint8_t *buf);
FAR const uint8_t *buf); static ssize_t part_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, size_t nblocks, FAR const uint8_t *buf);
FAR uint8_t *buffer); static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR uint8_t *buffer);
#ifdef CONFIG_MTD_BYTE_WRITE #ifdef CONFIG_MTD_BYTE_WRITE
static ssize_t part_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, static ssize_t part_write(FAR struct mtd_dev_s *dev, off_t offset,
FAR const uint8_t *buffer); size_t nbytes, FAR const uint8_t *buffer);
#endif
static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd,
unsigned long arg);
/* File system methods */
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
static int part_procfs_open(FAR struct file *filep,
FAR const char *relpath, int oflags, mode_t mode);
static int part_procfs_close(FAR struct file *filep);
static ssize_t part_procfs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static int part_procfs_dup(FAR const struct file *oldp,
FAR struct file *newp);
#if 0 /* Not implemented */
static int part_procfs_opendir(const char *relpath,
FAR struct fs_dirent_s *dir);
static int part_procfs_closedir(FAR struct fs_dirent_s *dir);
static int part_procfs_readdir(FAR struct fs_dirent_s *dir);
static int part_procfs_rewinddir(FAR struct fs_dirent_s *dir);
#endif
static int part_procfs_stat(FAR const char *relpath,
FAR struct stat *buf);
#endif #endif
static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
struct mtd_partition_s *g_pfirstpartition = NULL;
const struct procfs_operations part_procfsoperations =
{
part_procfs_open, /* open */
part_procfs_close, /* close */
part_procfs_read, /* read */
NULL, /* write */
part_procfs_dup, /* dup */
NULL, /* opendir */
NULL, /* closedir */
NULL, /* readdir */
NULL, /* rewinddir */
part_procfs_stat /* stat */
};
#endif
/**************************************************************************** /****************************************************************************
* Name: part_blockcheck * Name: part_blockcheck
* *
@ -397,6 +468,269 @@ static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
return ret; return ret;
} }
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
/****************************************************************************
* Name: part_procfs_open
****************************************************************************/
static int part_procfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
FAR struct part_procfs_file_s *attr;
fvdbg("Open '%s'\n", relpath);
/* PROCFS is read-only. Any attempt to open with any kind of write
* access is not permitted.
*
* REVISIT: Write-able proc files could be quite useful.
*/
if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
{
fdbg("ERROR: Only O_RDONLY supported\n");
return -EACCES;
}
/* Allocate a container to hold the task and attribute selection */
attr = (FAR struct part_procfs_file_s *)kzalloc(sizeof(struct part_procfs_file_s));
if (!attr)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* Initialize the file attributes */
attr->nextpart = g_pfirstpartition;
/* Save the index as the open-specific state in filep->f_priv */
filep->f_priv = (FAR void *)attr;
return OK;
}
/****************************************************************************
* Name: part_procfs_close
****************************************************************************/
static int part_procfs_close(FAR struct file *filep)
{
FAR struct part_procfs_file_s *attr;
/* Recover our private data from the struct file instance */
attr = (FAR struct part_procfs_file_s *)filep->f_priv;
DEBUGASSERT(attr);
/* Release the file attributes structure */
kfree(attr);
filep->f_priv = NULL;
return OK;
}
/****************************************************************************
* Name: part_procfs_read
****************************************************************************/
static ssize_t part_procfs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct part_procfs_file_s *attr;
ssize_t ret, total = 0, blkpererase;
FAR struct mtd_geometry_s geo;
#ifdef CONFIG_MTD_PARTITION_NAMES
char partname[11];
FAR const char *ptr;
uint8_t x;
#endif
fvdbg("buffer=%p buflen=%d\n", buffer, (int)buflen);
/* Recover our private data from the struct file instance */
attr = (FAR struct part_procfs_file_s *)filep->f_priv;
DEBUGASSERT(attr);
/* Provide the requested data */
if (attr->nextpart == g_pfirstpartition)
{
#ifdef CONFIG_MTD_PARTITION_NAMES
total = snprintf(buffer, buflen, "Name Start Size");
#else
total = snprintf(buffer, buflen, " Start Size");
#endif
#ifndef CONFIG_FS_PROCFS_EXCLUDE_MTD
total += snprintf(&buffer[total], buflen - total, " MTD\n");
#else
total += snprintf(&buffer[total], buflen - total, "\n");
#endif
}
while (attr->nextpart)
{
/* Get the geometry of the FLASH device */
ret = attr->nextpart->parent->ioctl(attr->nextpart->parent, MTDIOC_GEOMETRY,
(unsigned long)((uintptr_t)&geo));
if (ret < 0)
{
fdbg("ERROR: mtd->ioctl failed: %d\n", ret);
return 0;
}
/* Get the number of blocks per erase. There must be an even number of
* blocks in one erase blocks.
*/
blkpererase = geo.erasesize / geo.blocksize;
/* Copy data from the next known partition */
#ifdef CONFIG_MTD_PARTITION_NAMES
if (attr->nextpart->name == NULL)
{
strcpy(partname, "(noname) ");
}
else
{
ptr = attr->nextpart->name;
for (x = 0; x < sizeof(partname) - 1; x++)
{
/* Test for end of partition name */
if (*ptr == ',' || *ptr == '\0')
{
/* Perform space fill for alignment */
partname[x] = ' ';
}
else
{
/* Copy next byte of partition name */
partname[x] = *ptr++;
}
}
partname[x] = '\0';
}
/* Terminate the partition name and add to output buffer */
ret = snprintf(&buffer[total], buflen - total, "%s%7d %7d",
partname, attr->nextpart->firstblock / blkpererase,
attr->nextpart->neraseblocks);
#else
ret = snprintf(&buffer[total], buflen - total, "%7d %7d",
attr->nextpart->firstblock / blkpererase,
attr->nextpart->neraseblocks);
#endif
#ifndef CONFIG_FS_PROCFS_EXCLUDE_MTD
if (ret + total < buflen)
{
ret += snprintf(&buffer[total + ret], buflen - (total + ret),
" %s\n", attr->nextpart->parent->name);
}
#else
if (ret + total < buflen)
{
ret += snprintf(&buffer[total + ret], buflen - (total + ret), "\n");
}
#endif
if (ret + total < buflen)
{
/* It fit in the buffer totally. Advance total and move to
* next partition.
*/
total += ret;
attr->nextpart = attr->nextpart->pnext;
}
else
{
/* This one didn't fit completely. Truncate the partial
* entry and break the loop.
*/
buffer[total] = '\0';
break;
}
}
/* Update the file offset */
if (total > 0)
{
filep->f_pos += total;
}
return total;
}
/****************************************************************************
* Name: part_procfs_dup
*
* Description:
* Duplicate open file data in the new file structure.
*
****************************************************************************/
static int part_procfs_dup(FAR const struct file *oldp, FAR struct file *newp)
{
FAR struct part_procfs_file_s *oldattr;
FAR struct part_procfs_file_s *newattr;
fvdbg("Dup %p->%p\n", oldp, newp);
/* Recover our private data from the old struct file instance */
oldattr = (FAR struct part_procfs_file_s *)oldp->f_priv;
DEBUGASSERT(oldattr);
/* Allocate a new container to hold the task and attribute selection */
newattr = (FAR struct part_procfs_file_s *)kzalloc(sizeof(struct part_procfs_file_s));
if (!newattr)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* The copy the file attribtes from the old attributes to the new */
memcpy(newattr, oldattr, sizeof(struct part_procfs_file_s));
/* Save the new attributes in the new file structure */
newp->f_priv = (FAR void *)newattr;
return OK;
}
/****************************************************************************
* Name: part_procfs_stat
*
* Description: Return information about a file or directory
*
****************************************************************************/
static int part_procfs_stat(const char *relpath, struct stat *buf)
{
/* File/directory size, access block size */
buf->st_mode = S_IFREG|S_IROTH|S_IRGRP|S_IRUSR;
buf->st_size = 0;
buf->st_blksize = 0;
buf->st_blocks = 0;
return OK;
}
#endif
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@ -500,8 +834,59 @@ FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd, off_t firstblock,
part->blocksize = geo.blocksize; part->blocksize = geo.blocksize;
part->blkpererase = blkpererase; part->blkpererase = blkpererase;
#ifdef CONFIG_MTD_PARTITION_NAMES
part->name = NULL;
#endif
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
/* Add this parition to the list of known partitions */
if (g_pfirstpartition == NULL)
{
g_pfirstpartition = part;
}
else
{
struct mtd_partition_s *plast;
/* Add the partition to the end of the list */
part->pnext = NULL;
plast = g_pfirstpartition;
while (plast->pnext != NULL)
{
/* Get pointer to next partition */
plast = plast->pnext;
}
plast->pnext = part;
}
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
return &part->child; return &part->child;
} }
/****************************************************************************
* Name: mtd_setpartitionname
*
* Description:
* Sets the name of the specified partition.
*
****************************************************************************/
#ifdef CONFIG_MTD_PARTITION_NAMES
int mtd_setpartitionname(FAR struct mtd_dev_s *mtd, FAR const char *name)
{
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)mtd;
DEBUGASSERT(mtd);
DEBUGASSERT(name);
/* Allocate space for the name */
priv->name = name;
return OK;
}
#endif

352
drivers/mtd/mtd_procfs.c Normal file
View File

@ -0,0 +1,352 @@
/****************************************************************************
* drivers/mtd/mtd_procfs.c
*
* Copyright (C) 2013 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
//#include <sys/statfs.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/procfs.h>
#include <nuttx/mtd/mtd.h>
#if !defined(CONFIG_FS_PROCFS_EXCLUDE_MTD) && defined(CONFIG_FS_PROCFS)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure describes one open "file" */
struct mtd_file_s
{
struct procfs_file_s base; /* Base open file structure */
FAR struct mtd_dev_s *pnextmtd; /* Pointer to next registered MTD */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* File system methods */
static int mtd_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int mtd_close(FAR struct file *filep);
static ssize_t mtd_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static int mtd_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int mtd_stat(FAR const char *relpath, FAR struct stat *buf);
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/* See fs_mount.c -- this structure is explicitly externed there.
* We use the old-fashioned kind of initializers so that this will compile
* with any compiler.
*/
const struct procfs_operations mtd_procfsoperations =
{
mtd_open, /* open */
mtd_close, /* close */
mtd_read, /* read */
NULL, /* write */
mtd_dup, /* dup */
NULL, /* opendir */
NULL, /* closedir */
NULL, /* readdir */
NULL, /* rewinddir */
mtd_stat /* stat */
};
/* MTD registration variables */
static struct mtd_dev_s *g_pfirstmtd = NULL;
static uint8_t g_nextmtdno = 0;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mtd_open
****************************************************************************/
static int mtd_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
FAR struct mtd_file_s *attr;
fvdbg("Open '%s'\n", relpath);
/* PROCFS is read-only. Any attempt to open with any kind of write
* access is not permitted.
*
* REVISIT: Write-able proc files could be quite useful.
*/
if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
{
fdbg("ERROR: Only O_RDONLY supported\n");
return -EACCES;
}
/* Allocate a context structure */
attr = (FAR struct mtd_file_s *)kzalloc(sizeof(struct mtd_file_s));
if (!attr)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
attr->pnextmtd = g_pfirstmtd;
/* Save the context as the open-specific state in filep->f_priv */
filep->f_priv = (FAR void *)attr;
return OK;
}
/****************************************************************************
* Name: mtd_close
****************************************************************************/
static int mtd_close(FAR struct file *filep)
{
FAR struct mtd_file_s *attr;
/* Recover our private data from the struct file instance */
attr = (FAR struct mtd_file_s *)filep->f_priv;
DEBUGASSERT(attr);
/* Release the file attributes structure */
kfree(attr);
filep->f_priv = NULL;
return OK;
}
/****************************************************************************
* Name: mtd_read
****************************************************************************/
static ssize_t mtd_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct mtd_file_s *priv;
ssize_t total = 0, ret;
fvdbg("buffer=%p buflen=%d\n", buffer, (int)buflen);
/* Recover our private data from the struct file instance */
priv = (FAR struct mtd_file_s *)filep->f_priv;
DEBUGASSERT(priv);
/* Provide the requested data */
if (priv->pnextmtd == g_pfirstmtd)
{
total = snprintf(buffer, buflen, "Num Device\n");
}
while (priv->pnextmtd)
{
ret = snprintf(&buffer[total], buflen - total, "%-5d%s\n",
priv->pnextmtd->mtdno, priv->pnextmtd->name);
if (ret + total < buflen)
{
total += ret;
priv->pnextmtd = priv->pnextmtd->pnext;
}
else
{
buffer[total] = '\0';
break;
}
}
/* Update the file offset */
if (total > 0)
{
filep->f_pos += total;
}
return total;
}
/****************************************************************************
* Name: mtd_dup
*
* Description:
* Duplicate open file data in the new file structure.
*
****************************************************************************/
static int mtd_dup(FAR const struct file *oldp, FAR struct file *newp)
{
FAR struct mtd_file_s *oldattr;
FAR struct mtd_file_s *newattr;
fvdbg("Dup %p->%p\n", oldp, newp);
/* Recover our private data from the old struct file instance */
oldattr = (FAR struct mtd_file_s *)oldp->f_priv;
DEBUGASSERT(oldattr);
/* Allocate a new container to hold the task and attribute selection */
newattr = (FAR struct mtd_file_s *)kzalloc(sizeof(struct mtd_file_s));
if (!newattr)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* The copy the file attribtes from the old attributes to the new */
memcpy(newattr, oldattr, sizeof(struct mtd_file_s));
/* Save the new attributes in the new file structure */
newp->f_priv = (FAR void *)newattr;
return OK;
}
/****************************************************************************
* Name: mtd_stat
*
* Description: Return information about a file or directory
*
****************************************************************************/
static int mtd_stat(const char *relpath, struct stat *buf)
{
/* File/directory size, access block size */
buf->st_mode = S_IFREG|S_IROTH|S_IRGRP|S_IRUSR;
buf->st_size = 0;
buf->st_blksize = 0;
buf->st_blocks = 0;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mtd_register
*
* Description:
* Registers MTD device with the procfs file system. This assigns a unique
* MTD number and associates the given device name, then add adds it to
* the list of registered devices.
*
* In an embedded system, this all is really unnecessary, but is provided
* in the procfs system simply for information purposes (if desired).
*
****************************************************************************/
int mtd_register(FAR struct mtd_dev_s *mtd, FAR const char *name)
{
FAR struct mtd_dev_s *plast;
/* Assign the MTD number and device name */
mtd->mtdno = g_nextmtdno++;
mtd->name = name;
mtd->pnext = NULL;
/* Add to the list of registered devices */
if (g_pfirstmtd == NULL)
{
g_pfirstmtd = mtd;
}
else
{
/* Insert at end of list */
plast = g_pfirstmtd;
while (plast->pnext)
{
/* Skip to next entry as long as there is one */
plast = plast->pnext;
}
/* Now insert at this location */
plast->pnext = mtd;
}
}
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */

View File

@ -474,5 +474,12 @@ FAR struct mtd_dev_s *rammtd_initialize(FAR uint8_t *start, size_t size)
priv->start = start; priv->start = start;
priv->nblocks = nblocks; priv->nblocks = nblocks;
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "rammtd");
#endif
return &priv->mtd; return &priv->mtd;
} }

View File

@ -689,6 +689,12 @@ FAR struct mtd_dev_s *ramtron_initialize(FAR struct spi_dev_s *dev)
} }
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "ramtron");
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);

View File

@ -1256,6 +1256,12 @@ FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev)
} }
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "sst25");
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);

View File

@ -993,6 +993,12 @@ FAR struct mtd_dev_s *sst25xx_initialize(FAR struct spi_dev_s *dev)
} }
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "sst25xx");
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);

View File

@ -844,6 +844,12 @@ FAR struct mtd_dev_s *sst39vf_initialize(void)
return NULL; return NULL;
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "sst39vf");
#endif
/* Return the state structure as the MTD device */ /* Return the state structure as the MTD device */
return (FAR struct mtd_dev_s *)&g_sst39vf; return (FAR struct mtd_dev_s *)&g_sst39vf;

View File

@ -1174,6 +1174,12 @@ FAR struct mtd_dev_s *w25_initialize(FAR struct spi_dev_s *spi)
} }
} }
/* Register the MTD with the procfs system if enabled */
#ifdef CONFIG_MTD_REGISTRATION
mtd_register(&priv->mtd, "w25");
#endif
/* Return the implementation-specific state structure as the MTD device */ /* Return the implementation-specific state structure as the MTD device */
fvdbg("Return %p\n", priv); fvdbg("Return %p\n", priv);

View File

@ -6,9 +6,45 @@
config FS_PROCFS config FS_PROCFS
bool "PROCFS File System" bool "PROCFS File System"
default n default n
select FS_WRITABLE select FS_READABLE
---help--- ---help---
The PROCFS file system is provides access to task status through the The PROCFS file system provides access to task status and other driver
NuttX file system. The PROCFS may, for example, be mount at /proc. status through the NuttX file system. The PROCFS may, for example, be
Then information about all of the currently active tasks and threads mount at /proc. Then information about all of the currently active
will be available in proc/. tasks and threads will be available in /proc.
if FS_PROCFS
menu "Exclude individual procfs entries"
config FS_PROCFS_EXCLUDE_MOUNTS
bool "Exclude mounts"
depends on !DISABLE_MOUNTPOINT
default n
config FS_PROCFS_EXCLUDE_MTD
bool "Exclude mtd"
depends on MTD
default n
config FS_PROCFS_EXCLUDE_PROCESS
bool "Exclude process information"
default n
---help---
Causes the process information to be excluded from the procfs system.
This will reduce code space, but then giving access to process info
was kinda the whole point of procfs, but hey, whatever.
config FS_PROCFS_EXCLUDE_PARTITIONS
bool "Exclude partitions"
depends on MTD_PARTITION
default n
config FS_PROCFS_EXCLUDE_SMARTFS
bool "Exclude fs/smartfs"
depends on FS_SMARTFS
default n
endmenu
endif

View File

@ -37,7 +37,7 @@ ifeq ($(CONFIG_FS_PROCFS),y)
# Files required for procfs file system support # Files required for procfs file system support
ASRCS += ASRCS +=
CSRCS += fs_procfs.c CSRCS += fs_procfs.c fs_procfsproc.c
# Include procfs build support # Include procfs build support

File diff suppressed because it is too large Load Diff

1003
fs/procfs/fs_procfsproc.c Normal file

File diff suppressed because it is too large Load Diff

460
fs/procfs/fs_skeleton.c Normal file
View File

@ -0,0 +1,460 @@
/****************************************************************************
* fs/procfs/fs_skeleton.c
*
* Copyright (C) 2013 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/statfs.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/procfs.h>
#include <nuttx/fs/dirent.h>
#include <arch/irq.h>
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* This enumeration identifies all of the thread attributes that can be
* accessed via the procfs file system.
*/
/* This structure describes one open "file" */
struct skel_file_s
{
struct procfs_file_s base; /* Base open file structure */
/* Add context specific data types for managing an open file here */
};
/* Level 1 is the directory of attributes */
struct skel_level1_s
{
struct procfs_dir_priv_s base; /* Base directory private data */
/* Add context specific data types here for managing the directory
* open / read / stat, etc.
*/
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* File system methods */
static int skel_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int skel_close(FAR struct file *filep);
static ssize_t skel_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static int skel_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int skel_opendir(const char *relpath, FAR struct fs_dirent_s *dir);
static int skel_closedir(FAR struct fs_dirent_s *dir);
static int skel_readdir(FAR struct fs_dirent_s *dir);
static int skel_rewinddir(FAR struct fs_dirent_s *dir);
static int skel_stat(FAR const char *relpath, FAR struct stat *buf);
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/* See include/nutts/fs/procfs.h
* We use the old-fashioned kind of initializers so that this will compile
* with any compiler.
*/
const struct procfs_operations skel_procfsoperations =
{
skel_open, /* open */
skel_close, /* close */
skel_read, /* read */
/* TODO: Decide if this driver supports write */
NULL, /* write */
skel_dup, /* dup */
skel_opendir, /* opendir */
skel_closedir, /* closedir */
skel_readdir, /* readdir */
skel_rewinddir, /* rewinddir */
skel_stat /* stat */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: skel_open
****************************************************************************/
static int skel_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
FAR struct skel_file_s *priv;
fvdbg("Open '%s'\n", relpath);
/* PROCFS is read-only. Any attempt to open with any kind of write
* access is not permitted.
*
* REVISIT: Write-able proc files could be quite useful.
*/
if (((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) &&
(skel_procfsoperations.write == NULL))
{
fdbg("ERROR: Only O_RDONLY supported\n");
return -EACCES;
}
/* Allocate a container to hold the task and attribute selection */
priv = (FAR struct skel_file_s *)kzalloc(sizeof(struct skel_file_s));
if (!priv)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* TODO: Initialize the context specific data here */
/* Save the index as the open-specific state in filep->f_priv */
filep->f_priv = (FAR void *)priv;
return OK;
}
/****************************************************************************
* Name: skel_close
****************************************************************************/
static int skel_close(FAR struct file *filep)
{
FAR struct skel_file_s *priv;
/* Recover our private data from the struct file instance */
priv = (FAR struct skel_file_s *)filep->f_priv;
DEBUGASSERT(priv);
/* Release the file attributes structure */
kfree(priv);
filep->f_priv = NULL;
return OK;
}
/****************************************************************************
* Name: skel_read
****************************************************************************/
static ssize_t skel_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct skel_file_s *priv;
ssize_t ret;
fvdbg("buffer=%p buflen=%d\n", buffer, (int)buflen);
/* Recover our private data from the struct file instance */
priv = (FAR struct skel_file_s *)filep->f_priv;
DEBUGASSERT(priv);
/* TODO: Provide the requested data */
ret = 0;
/* Update the file offset */
if (ret > 0)
{
filep->f_pos += ret;
}
return ret;
}
/****************************************************************************
* Name: skel_dup
*
* Description:
* Duplicate open file data in the new file structure.
*
****************************************************************************/
static int skel_dup(FAR const struct file *oldp, FAR struct file *newp)
{
FAR struct skel_file_s *oldpriv;
FAR struct skel_file_s *newpriv;
fvdbg("Dup %p->%p\n", oldp, newp);
/* Recover our private data from the old struct file instance */
oldpriv = (FAR struct skel_file_s *)oldp->f_priv;
DEBUGASSERT(oldpriv);
/* Allocate a new container to hold the task and attribute selection */
newpriv = (FAR struct skel_file_s *)kzalloc(sizeof(struct skel_file_s));
if (!newpriv)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* The copy the file attribtes from the old attributes to the new */
memcpy(newpriv, oldpriv, sizeof(struct skel_file_s));
/* Save the new attributes in the new file structure */
newp->f_priv = (FAR void *)newpriv;
return OK;
}
/****************************************************************************
* Name: skel_opendir
*
* Description:
* Open a directory for read access
*
****************************************************************************/
static int skel_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
{
FAR struct skel_level1_s *level1;
fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL");
DEBUGASSERT(relpath && dir && !dir->u.procfs);
/* The path refers to the 1st level sbdirectory. Allocate the level1
* dirent structure.
*/
level1 = (FAR struct skel_level1_s *)
kzalloc(sizeof(struct skel_level1_s));
if (!level1)
{
fdbg("ERROR: Failed to allocate the level1 directory structure\n");
return -ENOMEM;
}
/* TODO: Initialze context specific data */
/* Initialze base structure components */
level1->base.level = 1;
level1->base.nentries = 0;
level1->base.index = 0;
dir->u.procfs = (FAR void *) level1;
return OK;
}
/****************************************************************************
* Name: skel_closedir
*
* Description: Close the directory listing
*
****************************************************************************/
static int skel_closedir(FAR struct fs_dirent_s *dir)
{
FAR struct skel_level1_s *priv;
DEBUGASSERT(dir && dir->u.procfs);
priv = dir->u.procfs;
if (priv)
{
kfree(priv);
}
dir->u.procfs = NULL;
return OK;
}
/****************************************************************************
* Name: skel_readdir
*
* Description: Read the next directory entry
*
****************************************************************************/
static int skel_readdir(struct fs_dirent_s *dir)
{
FAR struct skel_level1_s *level1;
char filename[16];
int ret, index;
DEBUGASSERT(dir && dir->u.procfs);
level1 = dir->u.procfs;
/* TODO: Perform device specific readdir function here. This may
* or may not involve validating the nentries variable
* in the base depending on the implementation.
*/
/* Have we reached the end of the directory */
index = level1->base.index;
if (index >= level1->base.nentries)
{
/* We signal the end of the directory by returning the special
* error -ENOENT
*/
fvdbg("Entry %d: End of directory\n", index);
ret = -ENOENT;
}
/* We are tranversing a subdirectory of task attributes */
else
{
DEBUGASSERT(level1->base.level == 1);
/* TODO: Add device specific entries */
strcpy(filename, "dummy");
/* TODO: Specify the type of entry */
dir->fd_dir.d_type = DTYPE_FILE;
strncpy(dir->fd_dir.d_name, filename, NAME_MAX+1);
/* Set up the next directory entry offset. NOTE that we could use the
* standard f_pos instead of our own private index.
*/
ret = OK;
}
return ret;
}
/****************************************************************************
* Name: skel_rewindir
*
* Description: Reset directory read to the first entry
*
****************************************************************************/
static int skel_rewinddir(struct fs_dirent_s *dir)
{
FAR struct skel_level1_s *priv;
DEBUGASSERT(dir && dir->u.procfs);
priv = dir->u.procfs;
priv->base.index = 0;
return OK;
}
/****************************************************************************
* Name: skel_stat
*
* Description: Return information about a file or directory
*
****************************************************************************/
static int skel_stat(const char *relpath, struct stat *buf)
{
int ret = -ENOENT;
/* TODO: Decide if the relpath is valid and if it is a file
* or a directory and set it's permissions.
*/
buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR;
ret = OK;
/* File/directory size, access block size */
buf->st_size = 0;
buf->st_blksize = 0;
buf->st_blocks = 0;
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */

View File

@ -38,7 +38,7 @@ ifeq ($(CONFIG_FS_SMARTFS),y)
# Files required for SmartFS file system support # Files required for SmartFS file system support
ASRCS += ASRCS +=
CSRCS += smartfs_smart.c smartfs_utils.c CSRCS += smartfs_smart.c smartfs_utils.c smartfs_procfs.c
# Files required for mksmartfs utility function # Files required for mksmartfs utility function

460
fs/smartfs/smartfs_procfs.c Normal file
View File

@ -0,0 +1,460 @@
/****************************************************************************
* fs/smartfs/smartfs_procfs.c
*
* Copyright (C) 2013 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/statfs.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/procfs.h>
#include <nuttx/fs/dirent.h>
#include <arch/irq.h>
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_EXCLUDE_SMARTFS)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* This enumeration identifies all of the thread attributes that can be
* accessed via the procfs file system.
*/
/* This structure describes one open "file" */
struct smartfs_file_s
{
struct procfs_file_s base; /* Base open file structure */
/* Add context specific data types for managing an open file here */
};
/* Level 1 is the directory of attributes */
struct smartfs_level1_s
{
struct procfs_dir_priv_s base; /* Base directory private data */
/* Add context specific data types here for managing the directory
* open / read / stat, etc.
*/
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* File system methods */
static int smartfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int smartfs_close(FAR struct file *filep);
static ssize_t smartfs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static int smartfs_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int smartfs_opendir(const char *relpath, FAR struct fs_dirent_s *dir);
static int smartfs_closedir(FAR struct fs_dirent_s *dir);
static int smartfs_readdir(FAR struct fs_dirent_s *dir);
static int smartfs_rewinddir(FAR struct fs_dirent_s *dir);
static int smartfs_stat(FAR const char *relpath, FAR struct stat *buf);
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/* See include/nutts/fs/procfs.h
* We use the old-fashioned kind of initializers so that this will compile
* with any compiler.
*/
const struct procfs_operations smartfs_procfsoperations =
{
smartfs_open, /* open */
smartfs_close, /* close */
smartfs_read, /* read */
/* TODO: Decide if this deiver supports write */
NULL, /* write */
smartfs_dup, /* dup */
smartfs_opendir, /* opendir */
smartfs_closedir, /* closedir */
smartfs_readdir, /* readdir */
smartfs_rewinddir, /* rewinddir */
smartfs_stat /* stat */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: smartfs_open
****************************************************************************/
static int smartfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
FAR struct smartfs_file_s *priv;
fvdbg("Open '%s'\n", relpath);
/* PROCFS is read-only. Any attempt to open with any kind of write
* access is not permitted.
*
* REVISIT: Write-able proc files could be quite useful.
*/
if (((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) &&
(smartfs_procfsoperations.write == NULL))
{
fdbg("ERROR: Only O_RDONLY supported\n");
return -EACCES;
}
/* Allocate a container to hold the task and attribute selection */
priv = (FAR struct smartfs_file_s *)kzalloc(sizeof(struct smartfs_file_s));
if (!priv)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* TODO: Initialize the context specific data here */
/* Save the index as the open-specific state in filep->f_priv */
filep->f_priv = (FAR void *)priv;
return OK;
}
/****************************************************************************
* Name: smartfs_close
****************************************************************************/
static int smartfs_close(FAR struct file *filep)
{
FAR struct smartfs_file_s *priv;
/* Recover our private data from the struct file instance */
priv = (FAR struct smartfs_file_s *)filep->f_priv;
DEBUGASSERT(priv);
/* Release the file attributes structure */
kfree(priv);
filep->f_priv = NULL;
return OK;
}
/****************************************************************************
* Name: smartfs_read
****************************************************************************/
static ssize_t smartfs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct smartfs_file_s *priv;
ssize_t ret;
fvdbg("buffer=%p buflen=%d\n", buffer, (int)buflen);
/* Recover our private data from the struct file instance */
priv = (FAR struct smartfs_file_s *)filep->f_priv;
DEBUGASSERT(priv);
/* TODO: Provide the requested data */
ret = 0;
/* Update the file offset */
if (ret > 0)
{
filep->f_pos += ret;
}
return ret;
}
/****************************************************************************
* Name: smartfs_dup
*
* Description:
* Duplicate open file data in the new file structure.
*
****************************************************************************/
static int smartfs_dup(FAR const struct file *oldp, FAR struct file *newp)
{
FAR struct smartfs_file_s *oldpriv;
FAR struct smartfs_file_s *newpriv;
fvdbg("Dup %p->%p\n", oldp, newp);
/* Recover our private data from the old struct file instance */
oldpriv = (FAR struct smartfs_file_s *)oldp->f_priv;
DEBUGASSERT(oldpriv);
/* Allocate a new container to hold the task and attribute selection */
newpriv = (FAR struct smartfs_file_s *)kzalloc(sizeof(struct smartfs_file_s));
if (!newpriv)
{
fdbg("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* The copy the file attribtes from the old attributes to the new */
memcpy(newpriv, oldpriv, sizeof(struct smartfs_file_s));
/* Save the new attributes in the new file structure */
newp->f_priv = (FAR void *)newpriv;
return OK;
}
/****************************************************************************
* Name: smartfs_opendir
*
* Description:
* Open a directory for read access
*
****************************************************************************/
static int smartfs_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
{
FAR struct smartfs_level1_s *level1;
fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL");
DEBUGASSERT(relpath && dir && !dir->u.procfs);
/* The path refers to the 1st level sbdirectory. Allocate the level1
* dirent structure.
*/
level1 = (FAR struct smartfs_level1_s *)
kzalloc(sizeof(struct smartfs_level1_s));
if (!level1)
{
fdbg("ERROR: Failed to allocate the level1 directory structure\n");
return -ENOMEM;
}
/* TODO: Initialze context specific data */
/* Initialze base structure components */
level1->base.level = 1;
level1->base.nentries = 0;
level1->base.index = 0;
dir->u.procfs = (FAR void *) level1;
return OK;
}
/****************************************************************************
* Name: smartfs_closedir
*
* Description: Close the directory listing
*
****************************************************************************/
static int smartfs_closedir(FAR struct fs_dirent_s *dir)
{
FAR struct smartfs_level1_s *priv;
DEBUGASSERT(dir && dir->u.procfs);
priv = dir->u.procfs;
if (priv)
{
kfree(priv);
}
dir->u.procfs = NULL;
return OK;
}
/****************************************************************************
* Name: smartfs_readdir
*
* Description: Read the next directory entry
*
****************************************************************************/
static int smartfs_readdir(struct fs_dirent_s *dir)
{
FAR struct smartfs_level1_s *level1;
char filename[16];
int ret, index;
DEBUGASSERT(dir && dir->u.procfs);
level1 = dir->u.procfs;
/* TODO: Perform device specific readdir function here. This may
* or may not involve validating the nentries variable
* in the base depending on the implementation.
*/
/* Have we reached the end of the directory */
index = level1->base.index;
if (index >= level1->base.nentries)
{
/* We signal the end of the directory by returning the special
* error -ENOENT
*/
fvdbg("Entry %d: End of directory\n", index);
ret = -ENOENT;
}
/* We are tranversing a subdirectory of task attributes */
else
{
DEBUGASSERT(level1->base.level == 1);
/* TODO: Add device specific entries */
strcpy(filename, "dummy");
/* TODO: Specify the type of entry */
dir->fd_dir.d_type = DTYPE_FILE;
strncpy(dir->fd_dir.d_name, filename, NAME_MAX+1);
/* Set up the next directory entry offset. NOTE that we could use the
* standard f_pos instead of our own private index.
*/
ret = OK;
}
return ret;
}
/****************************************************************************
* Name: smartfs_rewindir
*
* Description: Reset directory read to the first entry
*
****************************************************************************/
static int smartfs_rewinddir(struct fs_dirent_s *dir)
{
FAR struct smartfs_level1_s *priv;
DEBUGASSERT(dir && dir->u.procfs);
priv = dir->u.procfs;
priv->base.index = 0;
return OK;
}
/****************************************************************************
* Name: smartfs_stat
*
* Description: Return information about a file or directory
*
****************************************************************************/
static int smartfs_stat(const char *relpath, struct stat *buf)
{
int ret = -ENOENT;
/* TODO: Decide if the relpath is valid and if it is a file
* or a directory and set it's permissions.
*/
buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR;
ret = OK;
/* File/directory size, access block size */
buf->st_size = 0;
buf->st_blksize = 0;
buf->st_blocks = 0;
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
#endif /* CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_SMARTFS */

144
include/nuttx/fs/procfs.h Normal file
View File

@ -0,0 +1,144 @@
/****************************************************************************
* include/nuttx/fs/procfs.h
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_FS_PROCFS_H
#define __INCLUDE_NUTTX_FS_PROCFS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/* Data entry declaration prototypes ****************************************/
/* Procfs operations are a subset of the mountpt_operations */
struct procfs_operations
{
/* The mountpoint open method differs from the driver open method
* because it receives (1) the inode that contains the mountpoint
* private data, (2) the relative path into the mountpoint, and (3)
* information to manage privileges.
*/
int (*open)(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
/* The following methods must be identical in signature and position because
* the struct file_operations and struct mountp_operations are treated like
* unions.
*/
int (*close)(FAR struct file *filep);
ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen);
ssize_t (*write)(FAR struct file *filep, FAR const char *buffer, size_t buflen);
/* The two structures need not be common after this point. The following
* are extended methods needed to deal with the unique needs of mounted
* file systems.
*
* Additional open-file-specific mountpoint operations:
*/
int (*dup)(FAR const struct file *oldp, FAR struct file *newp);
/* Directory operations */
int (*opendir)(FAR const char *relpath, FAR struct fs_dirent_s *dir);
int (*closedir)(FAR struct fs_dirent_s *dir);
int (*readdir)(FAR struct fs_dirent_s *dir);
int (*rewinddir)(FAR struct fs_dirent_s *dir);
/* Operations on paths */
int (*stat)(FAR const char *relpath, FAR struct stat *buf);
};
/* Procfs handler prototypes ************************************************/
/* This is a procfs entry that each handler should provide to supply
* specific operations for file and directory handling.
*/
struct procfs_entry_s
{
FAR const char *pathpattern;
const struct procfs_operations *ops;
};
/* Specifies the common elements for an open file in the procfs
* file system. This structure should be sub-classed by handlers
* to add their own specific data elements to the context.
*/
struct procfs_file_s
{
const struct procfs_entry_s *pProcfsEntry;
};
/* The generic proc/ pseudo directory structure */
struct procfs_dir_priv_s
{
uint8_t level; /* Directory level. Currently 0 or 1 */
uint16_t index; /* Index to the next directory entry */
uint16_t nentries; /* Number of directory entries */
struct procfs_entry_s *pProcfsEntry; /* Pointer to procfs handler entry */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
#else
#define EXTERN extern
#endif
/* Nothing here yet */
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_NUTTX_FS_PROCFS_H */

View File

@ -67,6 +67,10 @@
# define CONFIG_MTD_SUBSECTOR_ERASE 1 # define CONFIG_MTD_SUBSECTOR_ERASE 1
#endif #endif
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MTD)
#define CONFIG_MTD_REGISTRATION 1
#endif
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
@ -142,6 +146,20 @@ struct mtd_dev_s
*/ */
int (*ioctl)(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg); int (*ioctl)(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
#ifdef CONFIG_MTD_REGISTRATION
/* An assigned MTD number for procfs reporting */
uint8_t mtdno;
/* Pointer to the next registered MTD device */
FAR struct mtd_dev_s *pnext;
/* Name of this MTD device */
FAR const char *name;
#endif
}; };
/**************************************************************************** /****************************************************************************
@ -185,6 +203,17 @@ extern "C"
FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd, FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd,
off_t firstblock, off_t nblocks); off_t firstblock, off_t nblocks);
/****************************************************************************
* Name: mtd_setpartitionname
*
* Description:
* Sets the name of the specified partition.
*
****************************************************************************/
#ifdef CONFIG_MTD_PARTITION_NAMES
int mtd_setpartitionname(FAR struct mtd_dev_s *mtd, FAR const char *name);
#endif
/**************************************************************************** /****************************************************************************
* Name: ftl_initialize * Name: ftl_initialize
* *
@ -352,6 +381,23 @@ FAR struct mtd_dev_s *w25_initialize(FAR struct spi_dev_s *dev);
FAR struct mtd_dev_s *up_flashinitialize(void); FAR struct mtd_dev_s *up_flashinitialize(void);
/****************************************************************************
* Name: mtd_register
*
* Description:
* Registers MTD device with the procfs file system. This assigns a unique
* MTD number and associates the given device name, then add adds it to
* the list of registered devices.
*
* In an embedded system, this all is really unnecessary, but is provided
* in the procfs system simply for information purposes (if desired).
*
****************************************************************************/
#ifdef CONFIG_MTD_REGISTRATION
int mtd_register(FAR struct mtd_dev_s *mtd, FAR const char *name);
#endif
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }