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