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