summaryrefslogtreecommitdiffstats
path: root/fs/devfs.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:01:39 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:01:39 +0200
commit877e92f7f12a8b3653fef509c08837febda4f27c (patch)
tree2c92b385c39450485bd6e3b88834f97daa3dc911 /fs/devfs.c
parentf0c67c6581e1e2f89fb6296797885af475dd878a (diff)
downloadbarebox-877e92f7f12a8b3653fef509c08837febda4f27c.tar.gz
barebox-877e92f7f12a8b3653fef509c08837febda4f27c.tar.xz
svn_rev_284
add devfs
Diffstat (limited to 'fs/devfs.c')
-rw-r--r--fs/devfs.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/fs/devfs.c b/fs/devfs.c
new file mode 100644
index 0000000000..6cf8920cb8
--- /dev/null
+++ b/fs/devfs.c
@@ -0,0 +1,122 @@
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <fs.h>
+#include <command.h>
+#include <errno.h>
+#include <asm-generic/errno.h>
+#include <linux/stat.h>
+
+static int devfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
+{
+ struct device_d *dev = f->inode;
+ return dev->driver->read(dev, buf, size, f->pos, f->flags);
+}
+
+static int devfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t size)
+{
+ struct device_d *dev = f->inode;
+ return dev->driver->write(dev, buf, size, f->pos, f->flags);
+}
+
+static int devfs_open(struct device_d *_dev, FILE *file, const char *filename)
+{
+ struct device_d *dev = get_device_by_id(filename + 1);
+
+ if (!dev)
+ return -ENOENT;
+
+ file->size = dev->size;
+ file->inode = dev;
+ return 0;
+}
+
+static int devfs_close(struct device_d *dev, FILE *f)
+{
+ return 0;
+}
+
+struct dir* devfs_opendir(struct device_d *dev, const char *pathname)
+{
+ struct dir *dir;
+
+ dir = malloc(sizeof(struct dir));
+ if (!dir)
+ return NULL;
+
+ dir->priv = get_first_device();
+
+ return dir;
+}
+
+struct dirent* devfs_readdir(struct device_d *_dev, struct dir *dir)
+{
+ struct device_d *dev = dir->priv;
+
+ while (dev && !strlen(dev->id))
+ dev = dev->next;
+
+ if (dev) {
+ strcpy(dir->d.name, dev->id);
+ dir->priv = dev->next;
+ return &dir->d;
+ }
+ return NULL;
+}
+
+int devfs_closedir(struct device_d *dev, struct dir *dir)
+{
+ free(dir);
+ return 0;
+}
+
+int devfs_stat(struct device_d *_dev, const char *filename, struct stat *s)
+{
+ struct device_d *dev;
+
+ dev = get_device_by_id(filename + 1);
+ if (!dev)
+ return -ENOENT;
+
+ s->st_mode = S_IFCHR;
+ s->st_size = dev->size;
+ if (dev->driver->write)
+ s->st_mode |= S_IWUSR;
+ if (dev->driver->read)
+ s->st_mode |= S_IRUSR;
+
+ return 0;
+}
+
+int devfs_probe(struct device_d *dev)
+{
+ return 0;
+}
+
+static struct fs_driver_d devfs_driver = {
+ .type = FS_TYPE_DEVFS,
+ .read = devfs_read,
+ .write = devfs_write,
+ .open = devfs_open,
+ .close = devfs_close,
+ .opendir = devfs_opendir,
+ .readdir = devfs_readdir,
+ .closedir = devfs_closedir,
+ .stat = devfs_stat,
+ .flags = FS_DRIVER_NO_DEV,
+ .drv = {
+ .type = DEVICE_TYPE_FS,
+ .probe = devfs_probe,
+ .name = "devfs",
+ .type_data = &devfs_driver,
+ }
+};
+
+int devfs_init(void)
+{
+ return register_driver(&devfs_driver.drv);
+}
+
+device_initcall(devfs_init);
+