diff --git a/components/dfs/SConscript b/components/dfs/SConscript index 6ca534ef52..0eb0902636 100644 --- a/components/dfs/SConscript +++ b/components/dfs/SConscript @@ -22,6 +22,12 @@ filesystems/romfs/dfs_romfs.c filesystems/romfs/romfs.c """) +# DFS-DeviceFS options +devfs = Split(""" +filesystems/devfs/devfs.c +filesystems/devfs/console.c +""") + # DFS-YAFFS2 options yaffs2_main = Split(""" filesystems/yaffs2/direct/yaffscfg.c @@ -79,6 +85,10 @@ if 'RT_USING_DFS_ROMFS' in dir(rtconfig) and rtconfig.RT_USING_DFS_ROMFS: src_local = src_local + romfs path = path + [RTT_ROOT + '/components/dfs/filesystems/romfs'] +if 'RT_USING_DFS_DEVFS' in dir(rtconfig) and rtconfig.RT_USING_DFS_DEVFS: + src_local = src_local + devfs + path = path + [RTT_ROOT + '/components/dfs/filesystems/devfs'] + # group definitions group = {} group['name'] = 'Filesystem' diff --git a/components/dfs/filesystems/devfs/console.c b/components/dfs/filesystems/devfs/console.c new file mode 100644 index 0000000000..c8774613d2 --- /dev/null +++ b/components/dfs/filesystems/devfs/console.c @@ -0,0 +1,85 @@ +/* + * RT-Thread Console Device File + * + */ +#include + +struct console_device +{ + struct rt_device parent; + + rt_device_t device; /* the actual device */ +}; +struct console_device _console; + +/* common device interface */ +static rt_err_t console_init(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_err_t console_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t console_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t console_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + struct console_device* device; + + device = (struct console_device*)dev; + RT_ASSERT(device != RT_NULL); + + return rt_device_read(device->device, pos, buffer, size); +} + +static rt_size_t console_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + struct console_device* device; + + device = (struct console_device*)dev; + RT_ASSERT(device != RT_NULL); + + return rt_device_write(device->device, pos, buffer, size); +} + +static rt_err_t console_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + return rt_device_control(_console.device, cmd, args); +} + +void rt_console_init(const char* device_name) +{ + rt_device_t device; + /* register to device framework */ + + device = rt_device_find(device_name); + if (device != RT_NULL) + { + struct console_device* console; + /* get console device */ + console = &_console; + rt_memset(console, 0, sizeof(_console)); + + /* device initialization */ + console->parent.type = RT_Device_Class_Char; + /* set device interface */ + console->parent.init = console_init; + console->parent.open = console_open; + console->parent.close = console_close; + console->parent.read = console_read; + console->parent.write = console_write; + console->parent.control = RT_NULL; + console->parent.private = RT_NULL; + + console->device = device; + + rt_device_register(&console->parent, "console", RT_DEVICE_FLAG_RDWR); + } +} + diff --git a/components/dfs/filesystems/devfs/devfs.c b/components/dfs/filesystems/devfs/devfs.c new file mode 100644 index 0000000000..af44bbb230 --- /dev/null +++ b/components/dfs/filesystems/devfs/devfs.c @@ -0,0 +1,276 @@ +#include +#include +#include + +#include "devfs.h" + +/* introduce from kservice.c */ +#define rt_list_entry(node, type, member) \ + ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member))) + +struct device_dirent +{ + rt_device_t *devices; + rt_uint16_t read_index; + rt_uint16_t device_count; +}; + +int dfs_device_fs_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* data) +{ + return DFS_STATUS_OK; +} + +int dfs_device_fs_ioctl(struct dfs_fd* file, int cmd, void* args) +{ + rt_err_t result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* close device handler */ + result = rt_device_control(dev_id, cmd, args); + if (result == RT_EOK) + return DFS_STATUS_OK; + + return -DFS_STATUS_EIO; +} + +int dfs_device_fs_read(struct dfs_fd* file, void *buf, rt_size_t count) +{ + int result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* read device data */ + result = rt_device_read(dev_id, file->pos, buf, count); + file->pos += result; + + return result; +} + +int dfs_device_fs_write(struct dfs_fd* file, const void *buf, rt_size_t count) +{ + int result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* read device data */ + result = rt_device_write(dev_id, file->pos, buf, count); + file->pos += result; + + return result; +} + +int dfs_device_fs_close(struct dfs_fd* file) +{ + rt_err_t result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + if (file->flags & FT_DIRECTORY) + { + struct device_dirent *root_dirent; + + root_dirent = (struct device_dirent*)file->data; + RT_ASSERT(root_dirent != RT_NULL); + + /* release dirent */ + rt_free(root_dirent); + return DFS_STATUS_OK; + } + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* close device handler */ + result = rt_device_close(dev_id); + if (result == RT_EOK) + { + file->data = RT_NULL; + return DFS_STATUS_OK; + } + + return -DFS_STATUS_EIO; +} + +int dfs_device_fs_open(struct dfs_fd* file) +{ + rt_device_t device; + + if (file->flags & DFS_O_CREAT) return -DFS_STATUS_EINVAL; + + /* open root directory */ + if ((file->path[0] == '/') && (file->path[1] == '\0') && + (file->flags & DFS_O_DIRECTORY)) + { + struct rt_object* object; + struct rt_list_node* node; + struct rt_object_information *information; + struct device_dirent* root_dirent; + rt_uint32_t count = 0; + + extern struct rt_object_information rt_object_container[]; + + /* lock scheduler */ + rt_enter_critical(); + + /* traverse device object */ + information = &rt_object_container[RT_Object_Class_Device]; + for (node = information->object_list.next; node != &(information->object_list); node = node->next) + { + count ++; + } + + root_dirent = (struct device_dirent*) rt_malloc (sizeof(struct device_dirent) + + count * sizeof(rt_device_t)); + if (root_dirent != RT_NULL) + { + root_dirent->devices = (rt_device_t *)(root_dirent + 1); + root_dirent->read_index = 0; + root_dirent->device_count = count; + count = 0; + /* get all device node */ + for (node = information->object_list.next; node != &(information->object_list); node = node->next) + { + object = rt_list_entry(node, struct rt_object, list); + root_dirent->devices[count] = (rt_device_t)object; + count ++; + } + } + rt_exit_critical(); + + /* set data */ + file->data = root_dirent; + return DFS_STATUS_OK; + } + + device = rt_device_find(&file->path[1]); + if (device == RT_NULL) + return -DFS_STATUS_ENODEV; + + file->data = device; + return DFS_STATUS_OK; +} + +int dfs_device_fs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st) +{ + /* stat root directory */ + if ((path[0] == '/') && (path[1] == '\0')) + { + st->st_dev = 0; + + st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + st->st_mode &= ~DFS_S_IFREG; + st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; + + st->st_size = 0; + st->st_mtime = 0; + st->st_blksize = 512; + return DFS_STATUS_OK; + } + else + { + rt_device_t dev_id; + + dev_id = rt_device_find(&path[1]); + if (dev_id != RT_NULL) + { + st->st_dev = 0; + + st->st_mode = DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + + if (dev_id->type == RT_Device_Class_Char) + st->st_mode |= DFS_S_IFCHR; + else if (dev_id->type == RT_Device_Class_Block) + st->st_mode |= DFS_S_IFBLK; + else + st->st_mode |= DFS_S_IFREG; + + st->st_size = 0; + st->st_mtime = 0; + st->st_blksize = 512; + return DFS_STATUS_OK; + } + } + + return -DFS_STATUS_ENOENT; +} + +int dfs_device_fs_getdents(struct dfs_fd* file, struct dirent* dirp, rt_uint32_t count) +{ + rt_uint32_t index; + rt_object_t object; + struct dirent* d; + struct device_dirent *root_dirent; + + root_dirent = (struct device_dirent*)file->data; + RT_ASSERT(root_dirent != RT_NULL); + + /* make integer count */ + count = (count / sizeof(struct dirent)) * sizeof(struct dirent); + if ( count == 0 ) return -DFS_STATUS_EINVAL; + + for (index = 0; index < count/sizeof(struct dirent) && index + root_dirent->read_index < root_dirent->device_count; + index ++) + { + object = (rt_object_t)root_dirent->devices[root_dirent->read_index + index]; + + d = dirp + index; + d->d_type = DFS_DT_REG; + d->d_namlen = RT_NAME_MAX; + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, object->name, RT_NAME_MAX); + } + + root_dirent->read_index += index; + + return index * sizeof(struct dirent); +} + +static const struct dfs_filesystem_operation _device_fs = +{ + "devfs", + dfs_device_fs_mount, + RT_NULL, + RT_NULL, + RT_NULL, + + dfs_device_fs_open, + dfs_device_fs_close, + dfs_device_fs_ioctl, + dfs_device_fs_read, + dfs_device_fs_write, + RT_NULL, + RT_NULL, + dfs_device_fs_getdents, + RT_NULL, + dfs_device_fs_stat, + RT_NULL, +}; + +int devfs_init(void) +{ + /* register rom file system */ + dfs_register(&_device_fs); + + return 0; +} + diff --git a/components/dfs/filesystems/devfs/devfs.h b/components/dfs/filesystems/devfs/devfs.h new file mode 100644 index 0000000000..90583e979f --- /dev/null +++ b/components/dfs/filesystems/devfs/devfs.h @@ -0,0 +1,8 @@ +#ifndef __DEVICE_FS_H__ +#define __DEVICE_FS_H__ + +#include + +int devfs_init(void); + +#endif