xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/devfs/devfs.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2018-02-11     Bernard      Ignore O_CREAT flag in open.
9*10465441SEvalZero  */
10*10465441SEvalZero 
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include <rtdevice.h>
13*10465441SEvalZero 
14*10465441SEvalZero #include <dfs.h>
15*10465441SEvalZero #include <dfs_fs.h>
16*10465441SEvalZero #include <dfs_file.h>
17*10465441SEvalZero 
18*10465441SEvalZero #include "devfs.h"
19*10465441SEvalZero 
20*10465441SEvalZero struct device_dirent
21*10465441SEvalZero {
22*10465441SEvalZero     rt_device_t *devices;
23*10465441SEvalZero     rt_uint16_t read_index;
24*10465441SEvalZero     rt_uint16_t device_count;
25*10465441SEvalZero };
26*10465441SEvalZero 
dfs_device_fs_mount(struct dfs_filesystem * fs,unsigned long rwflag,const void * data)27*10465441SEvalZero int dfs_device_fs_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
28*10465441SEvalZero {
29*10465441SEvalZero     return RT_EOK;
30*10465441SEvalZero }
31*10465441SEvalZero 
dfs_device_fs_ioctl(struct dfs_fd * file,int cmd,void * args)32*10465441SEvalZero int dfs_device_fs_ioctl(struct dfs_fd *file, int cmd, void *args)
33*10465441SEvalZero {
34*10465441SEvalZero     rt_err_t result;
35*10465441SEvalZero     rt_device_t dev_id;
36*10465441SEvalZero 
37*10465441SEvalZero     RT_ASSERT(file != RT_NULL);
38*10465441SEvalZero 
39*10465441SEvalZero     /* get device handler */
40*10465441SEvalZero     dev_id = (rt_device_t)file->data;
41*10465441SEvalZero     RT_ASSERT(dev_id != RT_NULL);
42*10465441SEvalZero 
43*10465441SEvalZero     /* close device handler */
44*10465441SEvalZero     result = rt_device_control(dev_id, cmd, args);
45*10465441SEvalZero     if (result == RT_EOK)
46*10465441SEvalZero         return RT_EOK;
47*10465441SEvalZero 
48*10465441SEvalZero     return result;
49*10465441SEvalZero }
50*10465441SEvalZero 
dfs_device_fs_read(struct dfs_fd * file,void * buf,size_t count)51*10465441SEvalZero int dfs_device_fs_read(struct dfs_fd *file, void *buf, size_t count)
52*10465441SEvalZero {
53*10465441SEvalZero     int result;
54*10465441SEvalZero     rt_device_t dev_id;
55*10465441SEvalZero 
56*10465441SEvalZero     RT_ASSERT(file != RT_NULL);
57*10465441SEvalZero 
58*10465441SEvalZero     /* get device handler */
59*10465441SEvalZero     dev_id = (rt_device_t)file->data;
60*10465441SEvalZero     RT_ASSERT(dev_id != RT_NULL);
61*10465441SEvalZero 
62*10465441SEvalZero     /* read device data */
63*10465441SEvalZero     result = rt_device_read(dev_id, file->pos, buf, count);
64*10465441SEvalZero     file->pos += result;
65*10465441SEvalZero 
66*10465441SEvalZero     return result;
67*10465441SEvalZero }
68*10465441SEvalZero 
dfs_device_fs_write(struct dfs_fd * file,const void * buf,size_t count)69*10465441SEvalZero int dfs_device_fs_write(struct dfs_fd *file, const void *buf, size_t count)
70*10465441SEvalZero {
71*10465441SEvalZero     int result;
72*10465441SEvalZero     rt_device_t dev_id;
73*10465441SEvalZero 
74*10465441SEvalZero     RT_ASSERT(file != RT_NULL);
75*10465441SEvalZero 
76*10465441SEvalZero     /* get device handler */
77*10465441SEvalZero     dev_id = (rt_device_t)file->data;
78*10465441SEvalZero     RT_ASSERT(dev_id != RT_NULL);
79*10465441SEvalZero 
80*10465441SEvalZero     /* read device data */
81*10465441SEvalZero     result = rt_device_write(dev_id, file->pos, buf, count);
82*10465441SEvalZero     file->pos += result;
83*10465441SEvalZero 
84*10465441SEvalZero     return result;
85*10465441SEvalZero }
86*10465441SEvalZero 
dfs_device_fs_close(struct dfs_fd * file)87*10465441SEvalZero int dfs_device_fs_close(struct dfs_fd *file)
88*10465441SEvalZero {
89*10465441SEvalZero     rt_err_t result;
90*10465441SEvalZero     rt_device_t dev_id;
91*10465441SEvalZero 
92*10465441SEvalZero     RT_ASSERT(file != RT_NULL);
93*10465441SEvalZero 
94*10465441SEvalZero     if (file->type == FT_DIRECTORY)
95*10465441SEvalZero     {
96*10465441SEvalZero         struct device_dirent *root_dirent;
97*10465441SEvalZero 
98*10465441SEvalZero         root_dirent = (struct device_dirent *)file->data;
99*10465441SEvalZero         RT_ASSERT(root_dirent != RT_NULL);
100*10465441SEvalZero 
101*10465441SEvalZero         /* release dirent */
102*10465441SEvalZero         rt_free(root_dirent);
103*10465441SEvalZero         return RT_EOK;
104*10465441SEvalZero     }
105*10465441SEvalZero 
106*10465441SEvalZero     /* get device handler */
107*10465441SEvalZero     dev_id = (rt_device_t)file->data;
108*10465441SEvalZero     RT_ASSERT(dev_id != RT_NULL);
109*10465441SEvalZero 
110*10465441SEvalZero     /* close device handler */
111*10465441SEvalZero     result = rt_device_close(dev_id);
112*10465441SEvalZero     if (result == RT_EOK)
113*10465441SEvalZero     {
114*10465441SEvalZero         file->data = RT_NULL;
115*10465441SEvalZero 
116*10465441SEvalZero         return RT_EOK;
117*10465441SEvalZero     }
118*10465441SEvalZero 
119*10465441SEvalZero     return -EIO;
120*10465441SEvalZero }
121*10465441SEvalZero 
dfs_device_fs_open(struct dfs_fd * file)122*10465441SEvalZero int dfs_device_fs_open(struct dfs_fd *file)
123*10465441SEvalZero {
124*10465441SEvalZero     rt_err_t result;
125*10465441SEvalZero     rt_device_t device;
126*10465441SEvalZero 
127*10465441SEvalZero     /* open root directory */
128*10465441SEvalZero     if ((file->path[0] == '/') && (file->path[1] == '\0') &&
129*10465441SEvalZero         (file->flags & O_DIRECTORY))
130*10465441SEvalZero     {
131*10465441SEvalZero         struct rt_object *object;
132*10465441SEvalZero         struct rt_list_node *node;
133*10465441SEvalZero         struct rt_object_information *information;
134*10465441SEvalZero         struct device_dirent *root_dirent;
135*10465441SEvalZero         rt_uint32_t count = 0;
136*10465441SEvalZero 
137*10465441SEvalZero         /* lock scheduler */
138*10465441SEvalZero         rt_enter_critical();
139*10465441SEvalZero 
140*10465441SEvalZero         /* traverse device object */
141*10465441SEvalZero         information = rt_object_get_information(RT_Object_Class_Device);
142*10465441SEvalZero         RT_ASSERT(information != RT_NULL);
143*10465441SEvalZero         for (node = information->object_list.next; node != &(information->object_list); node = node->next)
144*10465441SEvalZero         {
145*10465441SEvalZero             count ++;
146*10465441SEvalZero         }
147*10465441SEvalZero 
148*10465441SEvalZero         root_dirent = (struct device_dirent *)rt_malloc(sizeof(struct device_dirent) +
149*10465441SEvalZero             count * sizeof(rt_device_t));
150*10465441SEvalZero         if (root_dirent != RT_NULL)
151*10465441SEvalZero         {
152*10465441SEvalZero             root_dirent->devices = (rt_device_t *)(root_dirent + 1);
153*10465441SEvalZero             root_dirent->read_index = 0;
154*10465441SEvalZero             root_dirent->device_count = count;
155*10465441SEvalZero             count = 0;
156*10465441SEvalZero             /* get all device node */
157*10465441SEvalZero             for (node = information->object_list.next; node != &(information->object_list); node = node->next)
158*10465441SEvalZero             {
159*10465441SEvalZero                 object = rt_list_entry(node, struct rt_object, list);
160*10465441SEvalZero                 root_dirent->devices[count] = (rt_device_t)object;
161*10465441SEvalZero                 count ++;
162*10465441SEvalZero             }
163*10465441SEvalZero         }
164*10465441SEvalZero         rt_exit_critical();
165*10465441SEvalZero 
166*10465441SEvalZero         /* set data */
167*10465441SEvalZero         file->data = root_dirent;
168*10465441SEvalZero 
169*10465441SEvalZero         return RT_EOK;
170*10465441SEvalZero     }
171*10465441SEvalZero 
172*10465441SEvalZero     device = rt_device_find(&file->path[1]);
173*10465441SEvalZero     if (device == RT_NULL)
174*10465441SEvalZero         return -ENODEV;
175*10465441SEvalZero 
176*10465441SEvalZero #ifdef RT_USING_POSIX
177*10465441SEvalZero     if (device->fops)
178*10465441SEvalZero     {
179*10465441SEvalZero         /* use device fops */
180*10465441SEvalZero         file->fops = device->fops;
181*10465441SEvalZero         file->data = (void*)device;
182*10465441SEvalZero 
183*10465441SEvalZero         /* use fops */
184*10465441SEvalZero         if (file->fops->open)
185*10465441SEvalZero         {
186*10465441SEvalZero             result = file->fops->open(file);
187*10465441SEvalZero             if (result == RT_EOK || result == -RT_ENOSYS)
188*10465441SEvalZero             {
189*10465441SEvalZero                 return 0;
190*10465441SEvalZero             }
191*10465441SEvalZero         }
192*10465441SEvalZero     }
193*10465441SEvalZero     else
194*10465441SEvalZero #endif
195*10465441SEvalZero     {
196*10465441SEvalZero         result = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
197*10465441SEvalZero         if (result == RT_EOK || result == -RT_ENOSYS)
198*10465441SEvalZero         {
199*10465441SEvalZero             file->data = device;
200*10465441SEvalZero             return RT_EOK;
201*10465441SEvalZero         }
202*10465441SEvalZero     }
203*10465441SEvalZero 
204*10465441SEvalZero     file->data = RT_NULL;
205*10465441SEvalZero     /* open device failed. */
206*10465441SEvalZero     return -EIO;
207*10465441SEvalZero }
208*10465441SEvalZero 
dfs_device_fs_stat(struct dfs_filesystem * fs,const char * path,struct stat * st)209*10465441SEvalZero int dfs_device_fs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
210*10465441SEvalZero {
211*10465441SEvalZero     /* stat root directory */
212*10465441SEvalZero     if ((path[0] == '/') && (path[1] == '\0'))
213*10465441SEvalZero     {
214*10465441SEvalZero         st->st_dev = 0;
215*10465441SEvalZero 
216*10465441SEvalZero         st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
217*10465441SEvalZero             S_IWUSR | S_IWGRP | S_IWOTH;
218*10465441SEvalZero         st->st_mode &= ~S_IFREG;
219*10465441SEvalZero         st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
220*10465441SEvalZero 
221*10465441SEvalZero         st->st_size  = 0;
222*10465441SEvalZero         st->st_mtime = 0;
223*10465441SEvalZero 
224*10465441SEvalZero         return RT_EOK;
225*10465441SEvalZero     }
226*10465441SEvalZero     else
227*10465441SEvalZero     {
228*10465441SEvalZero         rt_device_t dev_id;
229*10465441SEvalZero 
230*10465441SEvalZero         dev_id = rt_device_find(&path[1]);
231*10465441SEvalZero         if (dev_id != RT_NULL)
232*10465441SEvalZero         {
233*10465441SEvalZero             st->st_dev = 0;
234*10465441SEvalZero 
235*10465441SEvalZero             st->st_mode = S_IRUSR | S_IRGRP | S_IROTH |
236*10465441SEvalZero                 S_IWUSR | S_IWGRP | S_IWOTH;
237*10465441SEvalZero 
238*10465441SEvalZero             if (dev_id->type == RT_Device_Class_Char)
239*10465441SEvalZero                 st->st_mode |= S_IFCHR;
240*10465441SEvalZero             else if (dev_id->type == RT_Device_Class_Block)
241*10465441SEvalZero                 st->st_mode |= S_IFBLK;
242*10465441SEvalZero             else if (dev_id->type == RT_Device_Class_Pipe)
243*10465441SEvalZero                 st->st_mode |= S_IFIFO;
244*10465441SEvalZero             else
245*10465441SEvalZero                 st->st_mode |= S_IFREG;
246*10465441SEvalZero 
247*10465441SEvalZero             st->st_size  = 0;
248*10465441SEvalZero             st->st_mtime = 0;
249*10465441SEvalZero 
250*10465441SEvalZero             return RT_EOK;
251*10465441SEvalZero         }
252*10465441SEvalZero     }
253*10465441SEvalZero 
254*10465441SEvalZero     return -ENOENT;
255*10465441SEvalZero }
256*10465441SEvalZero 
dfs_device_fs_getdents(struct dfs_fd * file,struct dirent * dirp,uint32_t count)257*10465441SEvalZero int dfs_device_fs_getdents(struct dfs_fd *file, struct dirent *dirp, uint32_t count)
258*10465441SEvalZero {
259*10465441SEvalZero     rt_uint32_t index;
260*10465441SEvalZero     rt_object_t object;
261*10465441SEvalZero     struct dirent *d;
262*10465441SEvalZero     struct device_dirent *root_dirent;
263*10465441SEvalZero 
264*10465441SEvalZero     root_dirent = (struct device_dirent *)file->data;
265*10465441SEvalZero     RT_ASSERT(root_dirent != RT_NULL);
266*10465441SEvalZero 
267*10465441SEvalZero     /* make integer count */
268*10465441SEvalZero     count = (count / sizeof(struct dirent));
269*10465441SEvalZero     if (count == 0)
270*10465441SEvalZero         return -EINVAL;
271*10465441SEvalZero 
272*10465441SEvalZero     for (index = 0; index < count && index + root_dirent->read_index < root_dirent->device_count;
273*10465441SEvalZero         index ++)
274*10465441SEvalZero     {
275*10465441SEvalZero         object = (rt_object_t)root_dirent->devices[root_dirent->read_index + index];
276*10465441SEvalZero 
277*10465441SEvalZero         d = dirp + index;
278*10465441SEvalZero         d->d_type = DT_REG;
279*10465441SEvalZero         d->d_namlen = RT_NAME_MAX;
280*10465441SEvalZero         d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
281*10465441SEvalZero         rt_strncpy(d->d_name, object->name, RT_NAME_MAX);
282*10465441SEvalZero     }
283*10465441SEvalZero 
284*10465441SEvalZero     root_dirent->read_index += index;
285*10465441SEvalZero 
286*10465441SEvalZero     return index * sizeof(struct dirent);
287*10465441SEvalZero }
288*10465441SEvalZero 
dfs_device_fs_poll(struct dfs_fd * fd,struct rt_pollreq * req)289*10465441SEvalZero static int dfs_device_fs_poll(struct dfs_fd *fd, struct rt_pollreq *req)
290*10465441SEvalZero {
291*10465441SEvalZero     int mask = 0;
292*10465441SEvalZero 
293*10465441SEvalZero     return mask;
294*10465441SEvalZero }
295*10465441SEvalZero 
296*10465441SEvalZero static const struct dfs_file_ops _device_fops =
297*10465441SEvalZero {
298*10465441SEvalZero     dfs_device_fs_open,
299*10465441SEvalZero     dfs_device_fs_close,
300*10465441SEvalZero     dfs_device_fs_ioctl,
301*10465441SEvalZero     dfs_device_fs_read,
302*10465441SEvalZero     dfs_device_fs_write,
303*10465441SEvalZero     RT_NULL,                    /* flush */
304*10465441SEvalZero     RT_NULL,                    /* lseek */
305*10465441SEvalZero     dfs_device_fs_getdents,
306*10465441SEvalZero     dfs_device_fs_poll,
307*10465441SEvalZero };
308*10465441SEvalZero 
309*10465441SEvalZero static const struct dfs_filesystem_ops _device_fs =
310*10465441SEvalZero {
311*10465441SEvalZero     "devfs",
312*10465441SEvalZero     DFS_FS_FLAG_DEFAULT,
313*10465441SEvalZero     &_device_fops,
314*10465441SEvalZero 
315*10465441SEvalZero     dfs_device_fs_mount,
316*10465441SEvalZero     RT_NULL,
317*10465441SEvalZero     RT_NULL,
318*10465441SEvalZero     RT_NULL,
319*10465441SEvalZero 
320*10465441SEvalZero     RT_NULL,
321*10465441SEvalZero     dfs_device_fs_stat,
322*10465441SEvalZero     RT_NULL,
323*10465441SEvalZero };
324*10465441SEvalZero 
devfs_init(void)325*10465441SEvalZero int devfs_init(void)
326*10465441SEvalZero {
327*10465441SEvalZero     /* register rom file system */
328*10465441SEvalZero     dfs_register(&_device_fs);
329*10465441SEvalZero 
330*10465441SEvalZero     return 0;
331*10465441SEvalZero }
332