blob: 37268e29ccb88c9d41550d8e5f421e7880d9efc9 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001#include <stdio.h>
2#include <kernel/mutex.h>
3#include <malloc.h>
4#include <dev/driver.h>
5#include <dev/class/block.h>
6#include <err.h>
7
8#include "ff.h"
9#include "diskio.h"
10
11static struct {
12 FATFS work;
13 struct device *dev;
14} mount_table[_VOLUMES];
15
16status_t ffs_mount(size_t index, struct device *dev)
17{
18 FRESULT res;
19
20 if (index >= countof(mount_table))
21 return ERR_INVALID_ARGS;
22
23 if (dev && mount_table[index].dev)
24 return ERR_ALREADY_MOUNTED;
25
26 if (dev) {
27 mount_table[index].dev = dev;
28
29 res = f_mount(index, &mount_table[index].work);
30 if (res != FR_OK)
31 return ERR_INVALID_ARGS;
32 } else {
33 mount_table[index].dev = NULL;
34
35 res = f_mount(index, NULL);
36 if (res != FR_OK)
37 return ERR_NOT_FOUND;
38 }
39
40 return NO_ERROR;
41}
42
43#if _USE_LFN == 3
44void *ff_memalloc(UINT size)
45{
46 return malloc(size);
47}
48
49void ff_memfree(void *mblock)
50{
51 free(mblock);
52}
53#endif
54
55#if _FS_REENTRANT
56int ff_cre_syncobj(BYTE vol, _SYNC_t *sobj)
57{
58 *sobj = malloc(sizeof(mutex_t));
59 if (!*sobj)
60 return false;
61
62 mutex_init(*sobj);
63 return true;
64}
65
66int ff_del_syncobj(_SYNC_t sobj)
67{
68 mutex_destroy(sobj);
69 free(sobj);
70 return true;
71}
72
73int ff_req_grant(_SYNC_t sobj)
74{
75 mutex_acquire(sobj);
76 return true;
77}
78
79void ff_rel_grant(_SYNC_t sobj)
80{
81 mutex_release(sobj);
82}
83#endif
84
85DSTATUS disk_initialize(BYTE pdrv)
86{
87 return RES_OK;
88}
89
90DSTATUS disk_status(BYTE pdrv)
91{
92 return RES_OK;
93}
94
95DRESULT disk_read(BYTE pdrv, BYTE* buf, DWORD sector, BYTE count)
96{
97 ssize_t ret;
98
99 struct device *dev = mount_table[pdrv].dev;
100 if (!dev)
101 return RES_NOTRDY;
102
103 ret = class_block_read(dev, sector, buf, count);
104 if (ret < 0)
105 return RES_ERROR;
106
107 return RES_OK;
108}
109
110#if _READONLY == 0
111DRESULT disk_write(BYTE pdrv, const BYTE* buf, DWORD sector, BYTE count)
112{
113 ssize_t ret;
114
115 struct device *dev = mount_table[pdrv].dev;
116 if (!dev)
117 return RES_NOTRDY;
118
119 ret = class_block_write(dev, sector, buf, count);
120 if (ret < 0)
121 return RES_ERROR;
122
123 return RES_OK;
124}
125#endif
126
127DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buf)
128{
129 ssize_t ret;
130
131 struct device *dev = mount_table[pdrv].dev;
132 if (!dev)
133 return RES_NOTRDY;
134
135 switch (cmd) {
136 case GET_SECTOR_SIZE: {
137 WORD *val = buf;
138
139 ret = class_block_get_size(dev);
140 if (ret < 0)
141 return RES_ERROR;
142
143 *val = ret;
144 }
145 break;
146
147 case GET_BLOCK_SIZE: {
148 DWORD *val = buf;
149
150 ret = class_block_get_size(dev);
151 if (ret < 0)
152 return RES_ERROR;
153
154 *val = ret;
155 }
156 break;
157
158 case GET_SECTOR_COUNT: {
159 DWORD *val = buf;
160
161 ret = class_block_get_count(dev);
162 if (ret < 0)
163 return RES_ERROR;
164
165 *val = ret;
166 }
167 break;
168 }
169
170 return RES_OK;
171}
172
173DWORD get_fattime(void)
174{
175 return
176 ((2013 - 1980) << 25) | // year
177 (1 << 21) | // month
178 (1 << 16) | // day
179 (0 << 11) | // hour
180 (0 << 5) | // minute
181 (0 << 0) // even second
182 ;
183}
184
185FILE *fopen(const char *filename, const char *mode)
186{
187 FRESULT res;
188 BYTE flags = 0;
189 FIL *fil;
190 int i;
191
192 fil = malloc(sizeof(FIL));
193 if (!fil)
194 return NULL;
195
196 for (i=0; mode[i] != 0; i++) {
197 switch (mode[i]) {
198 case 'w':
199 flags |= FA_WRITE | FA_CREATE_ALWAYS;
200 break;
201
202 case 'r':
203 flags |= FA_READ;
204 break;
205
206 case '+':
207 flags |= FA_READ | FA_WRITE;
208 break;
209 }
210 }
211
212 res = f_open(fil, filename, flags);
213 if (res != FR_OK) {
214 free(fil);
215 return NULL;
216 }
217
218 return (FILE *) fil;
219}
220
221int fclose(FILE *stream)
222{
223 FRESULT res;
224 FIL *fil = (FIL *) stream;
225
226 res = f_close(fil);
227 if (res != FR_OK)
228 return -1;
229
230 free(fil);
231 return 0;
232}
233
234size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
235{
236 FRESULT res;
237 FIL *fil = (FIL *) stream;
238 UINT bread;
239
240 res = f_read(fil, ptr, size * count, &bread);
241 if (res != FR_OK)
242 return 0;
243
244 return bread;
245}
246
247size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
248{
249 FRESULT res;
250 FIL *fil = (FIL *) stream;
251 UINT bwrite;
252
253 res = f_write(fil, ptr, size * count, &bwrite);
254 if (res != FR_OK)
255 return 0;
256
257 return bwrite;
258}
259
260int fflush(FILE *stream)
261{
262 FRESULT res;
263 FIL *fil;
264
265 if (!stream)
266 return 0;
267
268 fil = (FIL *) stream;
269
270 res = f_sync(fil);
271 if (res != FR_OK)
272 return -1;
273
274 return 0;
275}
276
277int feof(FILE *stream)
278{
279 FIL *fil = (FIL *) stream;
280
281 return f_eof(fil);
282}
283
284int fseek(FILE *stream, long offset, int whence)
285{
286 FRESULT res;
287 FIL *fil = (FIL *) stream;
288 long o;
289
290 switch (whence) {
291 case SEEK_SET:
292 o = offset;
293 break;
294
295 case SEEK_CUR:
296 o = offset + f_tell(fil);
297 break;
298
299 case SEEK_END:
300 o = f_size(fil) + offset;
301 if (o < 0)
302 o = 0;
303 break;
304
305 default:
306 return -1;
307 }
308
309 res = f_lseek(fil, o);
310 if (res != FR_OK)
311 return -1;
312
313 return 0;
314}
315
316long ftell(FILE *stream)
317{
318 FIL *fil = (FIL *) stream;
319
320 return f_tell(fil);
321}
322