| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 | /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date           Author       Notes * 2018-02-11     Bernard      Ignore O_CREAT flag in open. */#include <rtthread.h>#include <rtdevice.h>#include <dfs.h>#include <dfs_fs.h>#include <dfs_file.h>#include "devfs.h"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 RT_EOK;}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 RT_EOK;    return result;}int dfs_device_fs_read(struct dfs_fd *file, void *buf, 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, 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->type == 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 RT_EOK;    }    /* 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 RT_EOK;    }    return -EIO;}int dfs_device_fs_open(struct dfs_fd *file){    rt_err_t result;    rt_device_t device;    /* open root directory */    if ((file->path[0] == '/') && (file->path[1] == '\0') &&        (file->flags & 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;        /* lock scheduler */        rt_enter_critical();        /* traverse device object */        information = rt_object_get_information(RT_Object_Class_Device);        RT_ASSERT(information != RT_NULL);        for (node = information->object_list.next; node != &(information->object_list); node = node->next)        {            count ++;        }        rt_exit_critical();        root_dirent = (struct device_dirent *)rt_malloc(sizeof(struct device_dirent) +                      count * sizeof(rt_device_t));        if (root_dirent != RT_NULL)        {            /* lock scheduler */            rt_enter_critical();            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)            {                /* avoid memory write through */                if (count == root_dirent->device_count)                {                    rt_kprintf("warning: There are newly added devices that are not displayed!");                    break;                }                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 RT_EOK;    }    device = rt_device_find(&file->path[1]);    if (device == RT_NULL)        return -ENODEV;#ifdef RT_USING_POSIX_DEVIO    if (device->fops)    {        /* use device fops */        file->fops = device->fops;        file->data = (void *)device;        /* use fops */        if (file->fops->open)        {            result = file->fops->open(file);            if (result == RT_EOK || result == -RT_ENOSYS)            {                file->type = FT_DEVICE;                return 0;            }        }    }    else#endif /* RT_USING_POSIX_DEVIO */    {        result = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);        if (result == RT_EOK || result == -RT_ENOSYS)        {            file->data = device;            file->type = FT_DEVICE;            return RT_EOK;        }    }    file->data = RT_NULL;    /* open device failed. */    return -EIO;}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 = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |                      S_IWUSR | S_IWGRP | S_IWOTH;        st->st_mode &= ~S_IFREG;        st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;        st->st_size  = 0;        st->st_mtime = 0;        return RT_EOK;    }    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 = S_IRUSR | S_IRGRP | S_IROTH |                          S_IWUSR | S_IWGRP | S_IWOTH;            if (dev_id->type == RT_Device_Class_Char)                st->st_mode |= S_IFCHR;            else if (dev_id->type == RT_Device_Class_Block)                st->st_mode |= S_IFBLK;            else if (dev_id->type == RT_Device_Class_Pipe)                st->st_mode |= S_IFIFO;            else                st->st_mode |= S_IFREG;            st->st_size  = 0;            st->st_mtime = 0;            return RT_EOK;        }    }    return -ENOENT;}int dfs_device_fs_getdents(struct dfs_fd *file, struct dirent *dirp, 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));    if (count == 0)        return -EINVAL;    for (index = 0; index < count && 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 = 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 int dfs_device_fs_poll(struct dfs_fd *fd, struct rt_pollreq *req){    int mask = 0;    return mask;}static const struct dfs_file_ops _device_fops ={    dfs_device_fs_open,    dfs_device_fs_close,    dfs_device_fs_ioctl,    dfs_device_fs_read,    dfs_device_fs_write,    RT_NULL,                    /* flush */    RT_NULL,                    /* lseek */    dfs_device_fs_getdents,    dfs_device_fs_poll,};static const struct dfs_filesystem_ops _device_fs ={    "devfs",    DFS_FS_FLAG_DEFAULT,    &_device_fops,    dfs_device_fs_mount,    RT_NULL, /*unmount*/    RT_NULL, /*mkfs*/    RT_NULL, /*statfs*/    RT_NULL, /*unlink*/    dfs_device_fs_stat,    RT_NULL, /*rename*/};int devfs_init(void){    /* register device file system */    dfs_register(&_device_fs);    return 0;}
 |