dfs_elm.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2008-02-22 QiuYi The first version.
  9. * 2011-10-08 Bernard fixed the block size in statfs.
  10. * 2011-11-23 Bernard fixed the rename issue.
  11. * 2012-07-26 aozima implement ff_memalloc and ff_memfree.
  12. * 2012-12-19 Bernard fixed the O_APPEND and lseek issue.
  13. * 2013-03-01 aozima fixed the stat(st_mtime) issue.
  14. * 2014-01-26 Bernard Check the sector size before mount.
  15. * 2017-02-13 Hichard Update Fatfs version to 0.12b, support exFAT.
  16. * 2017-04-11 Bernard fix the st_blksize issue.
  17. * 2017-05-26 Urey fix f_mount error when mount more fats
  18. */
  19. #include <rtthread.h>
  20. #include "ffconf.h"
  21. #include "ff.h"
  22. #include <string.h>
  23. #include <sys/time.h>
  24. /* ELM FatFs provide a DIR struct */
  25. #define HAVE_DIR_STRUCTURE
  26. #include <dfs_fs.h>
  27. #include <dfs_file.h>
  28. static rt_device_t disk[FF_VOLUMES] = {0};
  29. static int elm_result_to_dfs(FRESULT result)
  30. {
  31. int status = RT_EOK;
  32. switch (result)
  33. {
  34. case FR_OK:
  35. break;
  36. case FR_NO_FILE:
  37. case FR_NO_PATH:
  38. case FR_NO_FILESYSTEM:
  39. status = -ENOENT;
  40. break;
  41. case FR_INVALID_NAME:
  42. status = -EINVAL;
  43. break;
  44. case FR_EXIST:
  45. case FR_INVALID_OBJECT:
  46. status = -EEXIST;
  47. break;
  48. case FR_DISK_ERR:
  49. case FR_NOT_READY:
  50. case FR_INT_ERR:
  51. status = -EIO;
  52. break;
  53. case FR_WRITE_PROTECTED:
  54. case FR_DENIED:
  55. status = -EROFS;
  56. break;
  57. case FR_MKFS_ABORTED:
  58. status = -EINVAL;
  59. break;
  60. default:
  61. status = -1;
  62. break;
  63. }
  64. return status;
  65. }
  66. /* results:
  67. * -1, no space to install fatfs driver
  68. * >= 0, there is an space to install fatfs driver
  69. */
  70. static int get_disk(rt_device_t id)
  71. {
  72. int index;
  73. for (index = 0; index < FF_VOLUMES; index ++)
  74. {
  75. if (disk[index] == id)
  76. return index;
  77. }
  78. return -1;
  79. }
  80. int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
  81. {
  82. FATFS *fat;
  83. FRESULT result;
  84. int index;
  85. struct rt_device_blk_geometry geometry;
  86. char logic_nbr[3] = {'0',':', 0};
  87. /* get an empty position */
  88. index = get_disk(RT_NULL);
  89. if (index == -1)
  90. return -ENOENT;
  91. logic_nbr[0] = '0' + index;
  92. /* save device */
  93. disk[index] = fs->dev_id;
  94. /* check sector size */
  95. if (rt_device_control(fs->dev_id, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry) == RT_EOK)
  96. {
  97. if (geometry.bytes_per_sector > FF_MAX_SS)
  98. {
  99. rt_kprintf("The sector size of device is greater than the sector size of FAT.\n");
  100. return -EINVAL;
  101. }
  102. }
  103. fat = (FATFS *)rt_malloc(sizeof(FATFS));
  104. if (fat == RT_NULL)
  105. {
  106. disk[index] = RT_NULL;
  107. return -ENOMEM;
  108. }
  109. /* mount fatfs, always 0 logic driver */
  110. result = f_mount(fat, (const TCHAR *)logic_nbr, 1);
  111. if (result == FR_OK)
  112. {
  113. char drive[8];
  114. DIR *dir;
  115. rt_snprintf(drive, sizeof(drive), "%d:/", index);
  116. dir = (DIR *)rt_malloc(sizeof(DIR));
  117. if (dir == RT_NULL)
  118. {
  119. f_mount(RT_NULL, (const TCHAR *)logic_nbr, 1);
  120. disk[index] = RT_NULL;
  121. rt_free(fat);
  122. return -ENOMEM;
  123. }
  124. /* open the root directory to test whether the fatfs is valid */
  125. result = f_opendir(dir, drive);
  126. if (result != FR_OK)
  127. goto __err;
  128. /* mount succeed! */
  129. fs->data = fat;
  130. rt_free(dir);
  131. return 0;
  132. }
  133. __err:
  134. f_mount(RT_NULL, (const TCHAR *)logic_nbr, 1);
  135. disk[index] = RT_NULL;
  136. rt_free(fat);
  137. return elm_result_to_dfs(result);
  138. }
  139. int dfs_elm_unmount(struct dfs_filesystem *fs)
  140. {
  141. FATFS *fat;
  142. FRESULT result;
  143. int index;
  144. char logic_nbr[3] = {'0',':', 0};
  145. fat = (FATFS *)fs->data;
  146. RT_ASSERT(fat != RT_NULL);
  147. /* find the device index and then umount it */
  148. index = get_disk(fs->dev_id);
  149. if (index == -1) /* not found */
  150. return -ENOENT;
  151. logic_nbr[0] = '0' + index;
  152. result = f_mount(RT_NULL, logic_nbr, (BYTE)0);
  153. if (result != FR_OK)
  154. return elm_result_to_dfs(result);
  155. fs->data = RT_NULL;
  156. disk[index] = RT_NULL;
  157. rt_free(fat);
  158. return RT_EOK;
  159. }
  160. int dfs_elm_mkfs(rt_device_t dev_id)
  161. {
  162. #define FSM_STATUS_INIT 0
  163. #define FSM_STATUS_USE_TEMP_DRIVER 1
  164. FATFS *fat = RT_NULL;
  165. BYTE *work;
  166. int flag;
  167. FRESULT result;
  168. int index;
  169. char logic_nbr[3] = {'0',':', 0};
  170. MKFS_PARM opt;
  171. work = rt_malloc(FF_MAX_SS);
  172. if(RT_NULL == work) {
  173. return -ENOMEM;
  174. }
  175. if (dev_id == RT_NULL)
  176. {
  177. rt_free(work); /* release memory */
  178. return -EINVAL;
  179. }
  180. /* if the device is already mounted, then just do mkfs to the drv,
  181. * while if it is not mounted yet, then find an empty drive to do mkfs
  182. */
  183. flag = FSM_STATUS_INIT;
  184. index = get_disk(dev_id);
  185. if (index == -1)
  186. {
  187. /* not found the device id */
  188. index = get_disk(RT_NULL);
  189. if (index == -1)
  190. {
  191. /* no space to store an temp driver */
  192. rt_kprintf("sorry, there is no space to do mkfs! \n");
  193. rt_free(work); /* release memory */
  194. return -ENOSPC;
  195. }
  196. else
  197. {
  198. fat = (FATFS *)rt_malloc(sizeof(FATFS));
  199. if (fat == RT_NULL)
  200. {
  201. rt_free(work); /* release memory */
  202. return -ENOMEM;
  203. }
  204. flag = FSM_STATUS_USE_TEMP_DRIVER;
  205. disk[index] = dev_id;
  206. /* try to open device */
  207. rt_device_open(dev_id, RT_DEVICE_OFLAG_RDWR);
  208. /* just fill the FatFs[vol] in ff.c, or mkfs will failded!
  209. * consider this condition: you just umount the elm fat,
  210. * then the space in FatFs[index] is released, and now do mkfs
  211. * on the disk, you will get a failure. so we need f_mount here,
  212. * just fill the FatFS[index] in elm fatfs to make mkfs work.
  213. */
  214. logic_nbr[0] = '0' + index;
  215. f_mount(fat, logic_nbr, (BYTE)index);
  216. }
  217. }
  218. else
  219. {
  220. logic_nbr[0] = '0' + index;
  221. }
  222. /* [IN] Logical drive number */
  223. /* [IN] Format options */
  224. /* [-] Working buffer */
  225. /* [IN] Size of working buffer */
  226. memset(&opt, 0, sizeof(opt));
  227. opt.fmt = FM_ANY|FM_SFD;
  228. result = f_mkfs(logic_nbr, &opt, work, FF_MAX_SS);
  229. rt_free(work); work = RT_NULL;
  230. /* check flag status, we need clear the temp driver stored in disk[] */
  231. if (flag == FSM_STATUS_USE_TEMP_DRIVER)
  232. {
  233. rt_free(fat);
  234. f_mount(RT_NULL, logic_nbr, (BYTE)index);
  235. disk[index] = RT_NULL;
  236. /* close device */
  237. rt_device_close(dev_id);
  238. }
  239. if (result != FR_OK)
  240. {
  241. rt_kprintf("format error, result=%d\n", result);
  242. return elm_result_to_dfs(result);
  243. }
  244. return RT_EOK;
  245. }
  246. int dfs_elm_statfs(struct dfs_filesystem *fs, struct statfs *buf)
  247. {
  248. FATFS *f;
  249. FRESULT res;
  250. char driver[4];
  251. DWORD fre_clust, fre_sect, tot_sect;
  252. RT_ASSERT(fs != RT_NULL);
  253. RT_ASSERT(buf != RT_NULL);
  254. f = (FATFS *)fs->data;
  255. rt_snprintf(driver, sizeof(driver), "%d:", f->pdrv);
  256. res = f_getfree(driver, &fre_clust, &f);
  257. if (res)
  258. return elm_result_to_dfs(res);
  259. /* Get total sectors and free sectors */
  260. tot_sect = (f->n_fatent - 2) * f->csize;
  261. fre_sect = fre_clust * f->csize;
  262. buf->f_bfree = fre_sect;
  263. buf->f_blocks = tot_sect;
  264. #if FF_MAX_SS != 512
  265. buf->f_bsize = f->ssize;
  266. #else
  267. buf->f_bsize = 512;
  268. #endif
  269. return 0;
  270. }
  271. int dfs_elm_open(struct dfs_fd *file)
  272. {
  273. FIL *fd;
  274. BYTE mode;
  275. FRESULT result;
  276. char *drivers_fn;
  277. #if (FF_VOLUMES > 1)
  278. int vol;
  279. struct dfs_filesystem *fs = (struct dfs_filesystem *)file->data;
  280. extern int elm_get_vol(FATFS * fat);
  281. if (fs == NULL)
  282. return -ENOENT;
  283. /* add path for ELM FatFS driver support */
  284. vol = elm_get_vol((FATFS *)fs->data);
  285. if (vol < 0)
  286. return -ENOENT;
  287. drivers_fn = (char *)rt_malloc(256);
  288. if (drivers_fn == RT_NULL)
  289. return -ENOMEM;
  290. rt_snprintf(drivers_fn, 256, "%d:%s", vol, file->path);
  291. #else
  292. drivers_fn = file->path;
  293. #endif
  294. if (file->flags & O_DIRECTORY)
  295. {
  296. DIR *dir;
  297. if (file->flags & O_CREAT)
  298. {
  299. result = f_mkdir(drivers_fn);
  300. if (result != FR_OK)
  301. {
  302. #if FF_VOLUMES > 1
  303. rt_free(drivers_fn);
  304. #endif
  305. return elm_result_to_dfs(result);
  306. }
  307. }
  308. /* open directory */
  309. dir = (DIR *)rt_malloc(sizeof(DIR));
  310. if (dir == RT_NULL)
  311. {
  312. #if FF_VOLUMES > 1
  313. rt_free(drivers_fn);
  314. #endif
  315. return -ENOMEM;
  316. }
  317. result = f_opendir(dir, drivers_fn);
  318. #if FF_VOLUMES > 1
  319. rt_free(drivers_fn);
  320. #endif
  321. if (result != FR_OK)
  322. {
  323. rt_free(dir);
  324. return elm_result_to_dfs(result);
  325. }
  326. file->data = dir;
  327. return RT_EOK;
  328. }
  329. else
  330. {
  331. mode = FA_READ;
  332. if (file->flags & O_WRONLY)
  333. mode |= FA_WRITE;
  334. if ((file->flags & O_ACCMODE) & O_RDWR)
  335. mode |= FA_WRITE;
  336. /* Opens the file, if it is existing. If not, a new file is created. */
  337. if (file->flags & O_CREAT)
  338. mode |= FA_OPEN_ALWAYS;
  339. /* Creates a new file. If the file is existing, it is truncated and overwritten. */
  340. if (file->flags & O_TRUNC)
  341. mode |= FA_CREATE_ALWAYS;
  342. /* Creates a new file. The function fails if the file is already existing. */
  343. if (file->flags & O_EXCL)
  344. mode |= FA_CREATE_NEW;
  345. /* allocate a fd */
  346. fd = (FIL *)rt_malloc(sizeof(FIL));
  347. if (fd == RT_NULL)
  348. {
  349. #if FF_VOLUMES > 1
  350. rt_free(drivers_fn);
  351. #endif
  352. return -ENOMEM;
  353. }
  354. result = f_open(fd, drivers_fn, mode);
  355. #if FF_VOLUMES > 1
  356. rt_free(drivers_fn);
  357. #endif
  358. if (result == FR_OK)
  359. {
  360. file->pos = fd->fptr;
  361. file->size = f_size(fd);
  362. file->data = fd;
  363. if (file->flags & O_APPEND)
  364. {
  365. /* seek to the end of file */
  366. f_lseek(fd, f_size(fd));
  367. file->pos = fd->fptr;
  368. }
  369. }
  370. else
  371. {
  372. /* open failed, return */
  373. rt_free(fd);
  374. return elm_result_to_dfs(result);
  375. }
  376. }
  377. return RT_EOK;
  378. }
  379. int dfs_elm_close(struct dfs_fd *file)
  380. {
  381. FRESULT result;
  382. result = FR_OK;
  383. if (file->type == FT_DIRECTORY)
  384. {
  385. DIR *dir;
  386. dir = (DIR *)(file->data);
  387. RT_ASSERT(dir != RT_NULL);
  388. /* release memory */
  389. rt_free(dir);
  390. }
  391. else if (file->type == FT_REGULAR)
  392. {
  393. FIL *fd;
  394. fd = (FIL *)(file->data);
  395. RT_ASSERT(fd != RT_NULL);
  396. result = f_close(fd);
  397. if (result == FR_OK)
  398. {
  399. /* release memory */
  400. rt_free(fd);
  401. }
  402. }
  403. return elm_result_to_dfs(result);
  404. }
  405. int dfs_elm_ioctl(struct dfs_fd *file, int cmd, void *args)
  406. {
  407. switch (cmd)
  408. {
  409. case RT_FIOFTRUNCATE:
  410. {
  411. FIL *fd;
  412. FSIZE_t fptr, length;
  413. FRESULT result = FR_OK;
  414. fd = (FIL *)(file->data);
  415. RT_ASSERT(fd != RT_NULL);
  416. /* save file read/write point */
  417. fptr = fd->fptr;
  418. length = *(off_t*)args;
  419. if (length <= fd->obj.objsize)
  420. {
  421. fd->fptr = length;
  422. result = f_truncate(fd);
  423. }
  424. else
  425. {
  426. result = f_lseek(fd, length);
  427. }
  428. /* restore file read/write point */
  429. fd->fptr = fptr;
  430. return elm_result_to_dfs(result);
  431. }
  432. }
  433. return -ENOSYS;
  434. }
  435. int dfs_elm_read(struct dfs_fd *file, void *buf, size_t len)
  436. {
  437. FIL *fd;
  438. FRESULT result;
  439. UINT byte_read;
  440. if (file->type == FT_DIRECTORY)
  441. {
  442. return -EISDIR;
  443. }
  444. fd = (FIL *)(file->data);
  445. RT_ASSERT(fd != RT_NULL);
  446. result = f_read(fd, buf, len, &byte_read);
  447. /* update position */
  448. file->pos = fd->fptr;
  449. if (result == FR_OK)
  450. return byte_read;
  451. return elm_result_to_dfs(result);
  452. }
  453. int dfs_elm_write(struct dfs_fd *file, const void *buf, size_t len)
  454. {
  455. FIL *fd;
  456. FRESULT result;
  457. UINT byte_write;
  458. if (file->type == FT_DIRECTORY)
  459. {
  460. return -EISDIR;
  461. }
  462. fd = (FIL *)(file->data);
  463. RT_ASSERT(fd != RT_NULL);
  464. result = f_write(fd, buf, len, &byte_write);
  465. /* update position and file size */
  466. file->pos = fd->fptr;
  467. file->size = f_size(fd);
  468. if (result == FR_OK)
  469. return byte_write;
  470. return elm_result_to_dfs(result);
  471. }
  472. int dfs_elm_flush(struct dfs_fd *file)
  473. {
  474. FIL *fd;
  475. FRESULT result;
  476. fd = (FIL *)(file->data);
  477. RT_ASSERT(fd != RT_NULL);
  478. result = f_sync(fd);
  479. return elm_result_to_dfs(result);
  480. }
  481. int dfs_elm_lseek(struct dfs_fd *file, rt_off_t offset)
  482. {
  483. FRESULT result = FR_OK;
  484. if (file->type == FT_REGULAR)
  485. {
  486. FIL *fd;
  487. /* regular file type */
  488. fd = (FIL *)(file->data);
  489. RT_ASSERT(fd != RT_NULL);
  490. result = f_lseek(fd, offset);
  491. if (result == FR_OK)
  492. {
  493. /* return current position */
  494. file->pos = fd->fptr;
  495. return fd->fptr;
  496. }
  497. }
  498. else if (file->type == FT_DIRECTORY)
  499. {
  500. /* which is a directory */
  501. DIR *dir;
  502. dir = (DIR *)(file->data);
  503. RT_ASSERT(dir != RT_NULL);
  504. result = f_seekdir(dir, offset / sizeof(struct dirent));
  505. if (result == FR_OK)
  506. {
  507. /* update file position */
  508. file->pos = offset;
  509. return file->pos;
  510. }
  511. }
  512. return elm_result_to_dfs(result);
  513. }
  514. int dfs_elm_getdents(struct dfs_fd *file, struct dirent *dirp, uint32_t count)
  515. {
  516. DIR *dir;
  517. FILINFO fno;
  518. FRESULT result;
  519. rt_uint32_t index;
  520. struct dirent *d;
  521. dir = (DIR *)(file->data);
  522. RT_ASSERT(dir != RT_NULL);
  523. /* make integer count */
  524. count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
  525. if (count == 0)
  526. return -EINVAL;
  527. index = 0;
  528. while (1)
  529. {
  530. char *fn;
  531. d = dirp + index;
  532. result = f_readdir(dir, &fno);
  533. if (result != FR_OK || fno.fname[0] == 0)
  534. break;
  535. #if FF_USE_LFN
  536. fn = *fno.fname ? fno.fname : fno.altname;
  537. #else
  538. fn = fno.fname;
  539. #endif
  540. d->d_type = DT_UNKNOWN;
  541. if (fno.fattrib & AM_DIR)
  542. d->d_type = DT_DIR;
  543. else
  544. d->d_type = DT_REG;
  545. d->d_namlen = (rt_uint8_t)rt_strlen(fn);
  546. d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  547. rt_strncpy(d->d_name, fn, DFS_PATH_MAX);
  548. index ++;
  549. if (index * sizeof(struct dirent) >= count)
  550. break;
  551. }
  552. if (index == 0)
  553. return elm_result_to_dfs(result);
  554. file->pos += index * sizeof(struct dirent);
  555. return index * sizeof(struct dirent);
  556. }
  557. int dfs_elm_unlink(struct dfs_filesystem *fs, const char *path)
  558. {
  559. FRESULT result;
  560. #if FF_VOLUMES > 1
  561. int vol;
  562. char *drivers_fn;
  563. extern int elm_get_vol(FATFS * fat);
  564. /* add path for ELM FatFS driver support */
  565. vol = elm_get_vol((FATFS *)fs->data);
  566. if (vol < 0)
  567. return -ENOENT;
  568. drivers_fn = (char *)rt_malloc(256);
  569. if (drivers_fn == RT_NULL)
  570. return -ENOMEM;
  571. rt_snprintf(drivers_fn, 256, "%d:%s", vol, path);
  572. #else
  573. const char *drivers_fn;
  574. drivers_fn = path;
  575. #endif
  576. result = f_unlink(drivers_fn);
  577. #if FF_VOLUMES > 1
  578. rt_free(drivers_fn);
  579. #endif
  580. return elm_result_to_dfs(result);
  581. }
  582. int dfs_elm_rename(struct dfs_filesystem *fs, const char *oldpath, const char *newpath)
  583. {
  584. FRESULT result;
  585. #if FF_VOLUMES > 1
  586. char *drivers_oldfn;
  587. const char *drivers_newfn;
  588. int vol;
  589. extern int elm_get_vol(FATFS * fat);
  590. /* add path for ELM FatFS driver support */
  591. vol = elm_get_vol((FATFS *)fs->data);
  592. if (vol < 0)
  593. return -ENOENT;
  594. drivers_oldfn = (char *)rt_malloc(256);
  595. if (drivers_oldfn == RT_NULL)
  596. return -ENOMEM;
  597. drivers_newfn = newpath;
  598. rt_snprintf(drivers_oldfn, 256, "%d:%s", vol, oldpath);
  599. #else
  600. const char *drivers_oldfn, *drivers_newfn;
  601. drivers_oldfn = oldpath;
  602. drivers_newfn = newpath;
  603. #endif
  604. result = f_rename(drivers_oldfn, drivers_newfn);
  605. #if FF_VOLUMES > 1
  606. rt_free(drivers_oldfn);
  607. #endif
  608. return elm_result_to_dfs(result);
  609. }
  610. int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
  611. {
  612. FILINFO file_info;
  613. FRESULT result;
  614. #if FF_VOLUMES > 1
  615. int vol;
  616. char *drivers_fn;
  617. extern int elm_get_vol(FATFS * fat);
  618. /* add path for ELM FatFS driver support */
  619. vol = elm_get_vol((FATFS *)fs->data);
  620. if (vol < 0)
  621. return -ENOENT;
  622. drivers_fn = (char *)rt_malloc(256);
  623. if (drivers_fn == RT_NULL)
  624. return -ENOMEM;
  625. rt_snprintf(drivers_fn, 256, "%d:%s", vol, path);
  626. #else
  627. const char *drivers_fn;
  628. drivers_fn = path;
  629. #endif
  630. result = f_stat(drivers_fn, &file_info);
  631. #if FF_VOLUMES > 1
  632. rt_free(drivers_fn);
  633. #endif
  634. if (result == FR_OK)
  635. {
  636. /* convert to dfs stat structure */
  637. st->st_dev = 0;
  638. st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
  639. S_IWUSR | S_IWGRP | S_IWOTH;
  640. if (file_info.fattrib & AM_DIR)
  641. {
  642. st->st_mode &= ~S_IFREG;
  643. st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
  644. }
  645. if (file_info.fattrib & AM_RDO)
  646. st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
  647. st->st_size = file_info.fsize;
  648. /* get st_mtime. */
  649. {
  650. struct tm tm_file;
  651. int year, mon, day, hour, min, sec;
  652. WORD tmp;
  653. tmp = file_info.fdate;
  654. day = tmp & 0x1F; /* bit[4:0] Day(1..31) */
  655. tmp >>= 5;
  656. mon = tmp & 0x0F; /* bit[8:5] Month(1..12) */
  657. tmp >>= 4;
  658. year = (tmp & 0x7F) + 1980; /* bit[15:9] Year origin from 1980(0..127) */
  659. tmp = file_info.ftime;
  660. sec = (tmp & 0x1F) * 2; /* bit[4:0] Second/2(0..29) */
  661. tmp >>= 5;
  662. min = tmp & 0x3F; /* bit[10:5] Minute(0..59) */
  663. tmp >>= 6;
  664. hour = tmp & 0x1F; /* bit[15:11] Hour(0..23) */
  665. memset(&tm_file, 0, sizeof(tm_file));
  666. tm_file.tm_year = year - 1900; /* Years since 1900 */
  667. tm_file.tm_mon = mon - 1; /* Months *since* january: 0-11 */
  668. tm_file.tm_mday = day; /* Day of the month: 1-31 */
  669. tm_file.tm_hour = hour; /* Hours since midnight: 0-23 */
  670. tm_file.tm_min = min; /* Minutes: 0-59 */
  671. tm_file.tm_sec = sec; /* Seconds: 0-59 */
  672. st->st_mtime = timegm(&tm_file);
  673. } /* get st_mtime. */
  674. }
  675. return elm_result_to_dfs(result);
  676. }
  677. static const struct dfs_file_ops dfs_elm_fops =
  678. {
  679. dfs_elm_open,
  680. dfs_elm_close,
  681. dfs_elm_ioctl,
  682. dfs_elm_read,
  683. dfs_elm_write,
  684. dfs_elm_flush,
  685. dfs_elm_lseek,
  686. dfs_elm_getdents,
  687. RT_NULL, /* poll interface */
  688. };
  689. static const struct dfs_filesystem_ops dfs_elm =
  690. {
  691. "elm",
  692. DFS_FS_FLAG_DEFAULT,
  693. &dfs_elm_fops,
  694. dfs_elm_mount,
  695. dfs_elm_unmount,
  696. dfs_elm_mkfs,
  697. dfs_elm_statfs,
  698. dfs_elm_unlink,
  699. dfs_elm_stat,
  700. dfs_elm_rename,
  701. };
  702. int elm_init(void)
  703. {
  704. /* register fatfs file system */
  705. dfs_register(&dfs_elm);
  706. return 0;
  707. }
  708. INIT_COMPONENT_EXPORT(elm_init);
  709. /*
  710. * RT-Thread Device Interface for ELM FatFs
  711. */
  712. #include "diskio.h"
  713. /* Initialize a Drive */
  714. DSTATUS disk_initialize(BYTE drv)
  715. {
  716. return 0;
  717. }
  718. /* Return Disk Status */
  719. DSTATUS disk_status(BYTE drv)
  720. {
  721. return 0;
  722. }
  723. /* Read Sector(s) */
  724. DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, UINT count)
  725. {
  726. rt_size_t result;
  727. rt_device_t device = disk[drv];
  728. result = rt_device_read(device, sector, buff, count);
  729. if (result == count)
  730. {
  731. return RES_OK;
  732. }
  733. return RES_ERROR;
  734. }
  735. /* Write Sector(s) */
  736. DRESULT disk_write(BYTE drv, const BYTE *buff, DWORD sector, UINT count)
  737. {
  738. rt_size_t result;
  739. rt_device_t device = disk[drv];
  740. result = rt_device_write(device, sector, buff, count);
  741. if (result == count)
  742. {
  743. return RES_OK;
  744. }
  745. return RES_ERROR;
  746. }
  747. /* Miscellaneous Functions */
  748. DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void *buff)
  749. {
  750. rt_device_t device = disk[drv];
  751. if (device == RT_NULL)
  752. return RES_ERROR;
  753. if (ctrl == GET_SECTOR_COUNT)
  754. {
  755. struct rt_device_blk_geometry geometry;
  756. rt_memset(&geometry, 0, sizeof(geometry));
  757. rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  758. *(DWORD *)buff = geometry.sector_count;
  759. if (geometry.sector_count == 0)
  760. return RES_ERROR;
  761. }
  762. else if (ctrl == GET_SECTOR_SIZE)
  763. {
  764. struct rt_device_blk_geometry geometry;
  765. rt_memset(&geometry, 0, sizeof(geometry));
  766. rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  767. *(WORD *)buff = (WORD)(geometry.bytes_per_sector);
  768. }
  769. else if (ctrl == GET_BLOCK_SIZE) /* Get erase block size in unit of sectors (DWORD) */
  770. {
  771. struct rt_device_blk_geometry geometry;
  772. rt_memset(&geometry, 0, sizeof(geometry));
  773. rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  774. *(DWORD *)buff = geometry.block_size / geometry.bytes_per_sector;
  775. }
  776. else if (ctrl == CTRL_SYNC)
  777. {
  778. rt_device_control(device, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL);
  779. }
  780. else if (ctrl == CTRL_TRIM)
  781. {
  782. rt_device_control(device, RT_DEVICE_CTRL_BLK_ERASE, buff);
  783. }
  784. return RES_OK;
  785. }
  786. DWORD get_fattime(void)
  787. {
  788. DWORD fat_time = 0;
  789. #ifdef RT_LIBC_USING_TIME
  790. time_t now;
  791. struct tm *p_tm;
  792. struct tm tm_now;
  793. /* get current time */
  794. now = time(RT_NULL);
  795. /* lock scheduler. */
  796. rt_enter_critical();
  797. /* converts calendar time time into local time. */
  798. p_tm = gmtime(&now);
  799. /* copy the statically located variable */
  800. memcpy(&tm_now, p_tm, sizeof(struct tm));
  801. /* unlock scheduler. */
  802. rt_exit_critical();
  803. fat_time = (DWORD)(tm_now.tm_year - 80) << 25 |
  804. (DWORD)(tm_now.tm_mon + 1) << 21 |
  805. (DWORD)tm_now.tm_mday << 16 |
  806. (DWORD)tm_now.tm_hour << 11 |
  807. (DWORD)tm_now.tm_min << 5 |
  808. (DWORD)tm_now.tm_sec / 2 ;
  809. #endif /* RT_USING_LIBC */
  810. return fat_time;
  811. }
  812. #if FF_FS_REENTRANT
  813. int ff_cre_syncobj(BYTE drv, FF_SYNC_t *m)
  814. {
  815. char name[8];
  816. rt_mutex_t mutex;
  817. rt_snprintf(name, sizeof(name), "fat%d", drv);
  818. mutex = rt_mutex_create(name, RT_IPC_FLAG_FIFO);
  819. if (mutex != RT_NULL)
  820. {
  821. *m = mutex;
  822. return RT_TRUE;
  823. }
  824. return RT_FALSE;
  825. }
  826. int ff_del_syncobj(FF_SYNC_t m)
  827. {
  828. if (m != RT_NULL)
  829. rt_mutex_delete(m);
  830. return RT_TRUE;
  831. }
  832. int ff_req_grant(FF_SYNC_t m)
  833. {
  834. if (rt_mutex_take(m, FF_FS_TIMEOUT) == RT_EOK)
  835. return RT_TRUE;
  836. return RT_FALSE;
  837. }
  838. void ff_rel_grant(FF_SYNC_t m)
  839. {
  840. rt_mutex_release(m);
  841. }
  842. #endif
  843. /* Memory functions */
  844. #if FF_USE_LFN == 3
  845. /* Allocate memory block */
  846. void *ff_memalloc(UINT size)
  847. {
  848. return rt_malloc(size);
  849. }
  850. /* Free memory block */
  851. void ff_memfree(void *mem)
  852. {
  853. rt_free(mem);
  854. }
  855. #endif /* FF_USE_LFN == 3 */