summaryrefslogtreecommitdiffstats
path: root/fs/devfs.c
blob: 3716aaeb2d3844198a99ecc99b3e18fdad27f446 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <common.h>
#include <driver.h>
#include <init.h>
#include <malloc.h>
#include <fs.h>
#include <command.h>
#include <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->driver))
		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;

	if (!dev->driver)
		return -ENXIO;

	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);