sd-filesystem-api.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. #include "fatfs.h"
  2. #include "filesystem-api.h"
  3. #include "sd-filesystem.h"
  4. /******************* Global vars for api *******************/
  5. static SdFsInfo* fs_info;
  6. /******************* Core Functions *******************/
  7. bool _fs_init(SdFsInfo* _fs_info) {
  8. bool result = true;
  9. _fs_info->mutex = osMutexNew(NULL);
  10. if(_fs_info->mutex == NULL) result = false;
  11. for(uint8_t i = 0; i < SD_FS_MAX_FILES; i++) {
  12. _fs_info->files[i].thread_id = NULL;
  13. }
  14. _fs_info->path = "0:/";
  15. _fs_info->status = SD_NO_CARD;
  16. // store pointer for api fns
  17. fs_info = _fs_info;
  18. return result;
  19. }
  20. bool _fs_lock(SdFsInfo* fs_info) {
  21. api_hal_power_insomnia_enter();
  22. return (osMutexAcquire(fs_info->mutex, osWaitForever) == osOK);
  23. }
  24. bool _fs_unlock(SdFsInfo* fs_info) {
  25. api_hal_power_insomnia_exit();
  26. return (osMutexRelease(fs_info->mutex) == osOK);
  27. }
  28. SDError _get_filedata(SdFsInfo* fs_info, File* file, FileData** filedata, FiledataFilter filter) {
  29. SDError error = SD_OK;
  30. _fs_lock(fs_info);
  31. if(fs_info->status == SD_OK) {
  32. if(file != NULL && file->file_id < SD_FS_MAX_FILES) {
  33. if(fs_info->files[file->file_id].thread_id == osThreadGetId()) {
  34. if(filter == FDF_ANY) {
  35. // any type
  36. *filedata = &fs_info->files[file->file_id];
  37. } else if(filter == FDF_FILE) {
  38. // file type
  39. if(!fs_info->files[file->file_id].is_dir) {
  40. *filedata = &fs_info->files[file->file_id];
  41. } else {
  42. error = SD_NOT_A_FILE;
  43. }
  44. } else if(filter == FDF_DIR) {
  45. // dir type
  46. if(fs_info->files[file->file_id].is_dir) {
  47. *filedata = &fs_info->files[file->file_id];
  48. } else {
  49. error = SD_NOT_A_DIR;
  50. }
  51. }
  52. } else {
  53. error = SD_OTHER_APP;
  54. }
  55. } else {
  56. error = SD_INVALID_PARAMETER;
  57. }
  58. } else {
  59. error = SD_NO_CARD;
  60. }
  61. _fs_unlock(fs_info);
  62. return error;
  63. }
  64. SDError _get_file(SdFsInfo* fs_info, File* file, FileData** filedata) {
  65. return _get_filedata(fs_info, file, filedata, FDF_FILE);
  66. }
  67. SDError _get_dir(SdFsInfo* fs_info, File* file, FileData** filedata) {
  68. return _get_filedata(fs_info, file, filedata, FDF_DIR);
  69. }
  70. SDError _get_any(SdFsInfo* fs_info, File* file, FileData** filedata) {
  71. return _get_filedata(fs_info, file, filedata, FDF_ANY);
  72. }
  73. SDError _fs_status(SdFsInfo* fs_info) {
  74. SDError result;
  75. _fs_lock(fs_info);
  76. result = fs_info->status;
  77. _fs_unlock(fs_info);
  78. return result;
  79. }
  80. void _fs_on_client_app_exit(SdFsInfo* fs_info) {
  81. _fs_lock(fs_info);
  82. for(uint8_t i = 0; i < SD_FS_MAX_FILES; i++) {
  83. if(fs_info->files[i].thread_id == osThreadGetId()) {
  84. if(fs_info->files[i].is_dir) {
  85. // TODO close dir
  86. } else {
  87. // TODO close file
  88. }
  89. }
  90. }
  91. _fs_unlock(fs_info);
  92. }
  93. FS_Error _fs_parse_error(SDError error) {
  94. FS_Error result;
  95. switch(error) {
  96. case SD_OK:
  97. result = FSE_OK;
  98. break;
  99. case SD_INT_ERR:
  100. result = FSE_INTERNAL;
  101. break;
  102. case SD_NO_FILE:
  103. result = FSE_NOT_EXIST;
  104. break;
  105. case SD_NO_PATH:
  106. result = FSE_NOT_EXIST;
  107. break;
  108. case SD_INVALID_NAME:
  109. result = FSE_INVALID_NAME;
  110. break;
  111. case SD_DENIED:
  112. result = FSE_DENIED;
  113. break;
  114. case SD_EXIST:
  115. result = FSE_EXIST;
  116. break;
  117. case SD_INVALID_OBJECT:
  118. result = FSE_INTERNAL;
  119. break;
  120. case SD_WRITE_PROTECTED:
  121. result = FSE_INTERNAL;
  122. break;
  123. case SD_INVALID_DRIVE:
  124. result = FSE_INTERNAL;
  125. break;
  126. case SD_NOT_ENABLED:
  127. result = FSE_INTERNAL;
  128. break;
  129. case SD_NO_FILESYSTEM:
  130. result = FSE_NOT_READY;
  131. break;
  132. case SD_MKFS_ABORTED:
  133. result = FSE_INTERNAL;
  134. break;
  135. case SD_TIMEOUT:
  136. result = FSE_INTERNAL;
  137. break;
  138. case SD_LOCKED:
  139. result = FSE_INTERNAL;
  140. break;
  141. case SD_NOT_ENOUGH_CORE:
  142. result = FSE_INTERNAL;
  143. break;
  144. case SD_TOO_MANY_OPEN_FILES:
  145. result = FSE_INTERNAL;
  146. break;
  147. case SD_INVALID_PARAMETER:
  148. result = FSE_INVALID_PARAMETER;
  149. break;
  150. case SD_NO_CARD:
  151. result = FSE_NOT_READY;
  152. break;
  153. case SD_NOT_A_FILE:
  154. result = FSE_INVALID_PARAMETER;
  155. break;
  156. case SD_NOT_A_DIR:
  157. result = FSE_INVALID_PARAMETER;
  158. break;
  159. case SD_OTHER_APP:
  160. result = FSE_INTERNAL;
  161. break;
  162. default:
  163. result = FSE_INTERNAL;
  164. break;
  165. }
  166. return result;
  167. }
  168. /******************* File Functions *******************/
  169. // Open/Create a file
  170. bool fs_file_open(File* file, const char* path, FS_AccessMode access_mode, FS_OpenMode open_mode) {
  171. SDFile* sd_file = NULL;
  172. _fs_lock(fs_info);
  173. for(uint8_t index = 0; index < SD_FS_MAX_FILES; index++) {
  174. FileData* filedata = &fs_info->files[index];
  175. if(filedata->thread_id == NULL) {
  176. file->file_id = index;
  177. memset(&(filedata->data), 0, sizeof(SDFileDirStorage));
  178. filedata->thread_id = osThreadGetId();
  179. filedata->is_dir = false;
  180. sd_file = &(filedata->data.file);
  181. break;
  182. }
  183. }
  184. _fs_unlock(fs_info);
  185. if(sd_file == NULL) {
  186. file->internal_error_id = SD_TOO_MANY_OPEN_FILES;
  187. } else {
  188. uint8_t _mode = 0;
  189. if(access_mode & FSAM_READ) _mode |= FA_READ;
  190. if(access_mode & FSAM_WRITE) _mode |= FA_WRITE;
  191. if(open_mode & FSOM_OPEN_EXISTING) _mode |= FA_OPEN_EXISTING;
  192. if(open_mode & FSOM_OPEN_ALWAYS) _mode |= FA_OPEN_ALWAYS;
  193. if(open_mode & FSOM_OPEN_APPEND) _mode |= FA_OPEN_APPEND;
  194. if(open_mode & FSOM_CREATE_NEW) _mode |= FA_CREATE_NEW;
  195. if(open_mode & FSOM_CREATE_ALWAYS) _mode |= FA_CREATE_ALWAYS;
  196. file->internal_error_id = f_open(sd_file, path, _mode);
  197. }
  198. // TODO on exit
  199. //furiac_onexit(_fs_on_client_app_exit, fs_info);
  200. file->error_id = _fs_parse_error(file->internal_error_id);
  201. return (file->internal_error_id == SD_OK);
  202. }
  203. // Close an opened file
  204. bool fs_file_close(File* file) {
  205. FileData* filedata = NULL;
  206. file->internal_error_id = _get_file(fs_info, file, &filedata);
  207. if(file->internal_error_id == SD_OK) {
  208. file->internal_error_id = f_close(&filedata->data.file);
  209. _fs_lock(fs_info);
  210. filedata->thread_id = NULL;
  211. _fs_unlock(fs_info);
  212. }
  213. file->error_id = _fs_parse_error(file->internal_error_id);
  214. return (file->internal_error_id == SD_OK);
  215. }
  216. // Read data from the file
  217. uint16_t fs_file_read(File* file, void* buff, uint16_t const bytes_to_read) {
  218. FileData* filedata = NULL;
  219. uint16_t bytes_readed = 0;
  220. file->internal_error_id = _get_file(fs_info, file, &filedata);
  221. if(file->internal_error_id == SD_OK) {
  222. file->internal_error_id = f_read(&filedata->data.file, buff, bytes_to_read, &bytes_readed);
  223. }
  224. file->error_id = _fs_parse_error(file->internal_error_id);
  225. return bytes_readed;
  226. }
  227. // Write data to the file
  228. uint16_t fs_file_write(File* file, const void* buff, uint16_t const bytes_to_write) {
  229. FileData* filedata = NULL;
  230. uint16_t bytes_written = 0;
  231. file->internal_error_id = _get_file(fs_info, file, &filedata);
  232. if(file->internal_error_id == SD_OK) {
  233. file->internal_error_id =
  234. f_write(&filedata->data.file, buff, bytes_to_write, &bytes_written);
  235. }
  236. file->error_id = _fs_parse_error(file->internal_error_id);
  237. return bytes_written;
  238. }
  239. // Move read/write pointer, expand size
  240. bool fs_file_seek(File* file, const uint32_t offset, const bool from_start) {
  241. FileData* filedata = NULL;
  242. file->internal_error_id = _get_file(fs_info, file, &filedata);
  243. if(file->internal_error_id == SD_OK) {
  244. if(from_start) {
  245. file->internal_error_id = f_lseek(&filedata->data.file, offset);
  246. } else {
  247. uint64_t position = f_tell(&filedata->data.file);
  248. position += offset;
  249. file->internal_error_id = f_lseek(&filedata->data.file, position);
  250. }
  251. }
  252. file->error_id = _fs_parse_error(file->internal_error_id);
  253. return (file->internal_error_id == SD_OK);
  254. }
  255. // Tell pointer position
  256. uint64_t fs_file_tell(File* file) {
  257. FileData* filedata = NULL;
  258. uint64_t position = 0;
  259. file->internal_error_id = _get_file(fs_info, file, &filedata);
  260. if(file->internal_error_id == SD_OK) {
  261. position = f_tell(&filedata->data.file);
  262. }
  263. file->error_id = _fs_parse_error(file->internal_error_id);
  264. return position;
  265. }
  266. // Truncate file size to current pointer value
  267. bool fs_file_truncate(File* file) {
  268. FileData* filedata = NULL;
  269. file->internal_error_id = _get_file(fs_info, file, &filedata);
  270. if(file->internal_error_id == SD_OK) {
  271. file->internal_error_id = f_truncate(&filedata->data.file);
  272. }
  273. file->error_id = _fs_parse_error(file->internal_error_id);
  274. return (file->internal_error_id == SD_OK);
  275. }
  276. // Flush cached data
  277. bool fs_file_sync(File* file) {
  278. FileData* filedata = NULL;
  279. file->internal_error_id = _get_file(fs_info, file, &filedata);
  280. if(file->internal_error_id == SD_OK) {
  281. file->internal_error_id = f_sync(&filedata->data.file);
  282. }
  283. file->error_id = _fs_parse_error(file->internal_error_id);
  284. return (file->internal_error_id == SD_OK);
  285. }
  286. // Get size
  287. uint64_t fs_file_size(File* file) {
  288. FileData* filedata = NULL;
  289. uint64_t size = 0;
  290. file->internal_error_id = _get_file(fs_info, file, &filedata);
  291. if(file->internal_error_id == SD_OK) {
  292. size = f_size(&filedata->data.file);
  293. }
  294. file->error_id = _fs_parse_error(file->internal_error_id);
  295. return size;
  296. }
  297. // Test EOF
  298. bool fs_file_eof(File* file) {
  299. FileData* filedata = NULL;
  300. bool eof = true;
  301. file->internal_error_id = _get_file(fs_info, file, &filedata);
  302. if(file->internal_error_id == SD_OK) {
  303. eof = f_eof(&filedata->data.file);
  304. }
  305. file->error_id = _fs_parse_error(file->internal_error_id);
  306. return eof;
  307. }
  308. /******************* Dir Functions *******************/
  309. // Open directory
  310. bool fs_dir_open(File* file, const char* path) {
  311. SDDir* sd_dir = NULL;
  312. _fs_lock(fs_info);
  313. for(uint8_t index = 0; index < SD_FS_MAX_FILES; index++) {
  314. FileData* filedata = &fs_info->files[index];
  315. if(filedata->thread_id == NULL) {
  316. file->file_id = index;
  317. memset(&(filedata->data), 0, sizeof(SDFileDirStorage));
  318. filedata->thread_id = osThreadGetId();
  319. filedata->is_dir = true;
  320. sd_dir = &(filedata->data.dir);
  321. break;
  322. }
  323. }
  324. _fs_unlock(fs_info);
  325. if(sd_dir == NULL) {
  326. file->internal_error_id = SD_TOO_MANY_OPEN_FILES;
  327. } else {
  328. file->internal_error_id = f_opendir(sd_dir, path);
  329. }
  330. // TODO on exit
  331. //furiac_onexit(_fs_on_client_app_exit, fs_info);
  332. file->error_id = _fs_parse_error(file->internal_error_id);
  333. return (file->internal_error_id == SD_OK);
  334. }
  335. // Close directory
  336. bool fs_dir_close(File* file) {
  337. FileData* filedata = NULL;
  338. file->internal_error_id = _get_dir(fs_info, file, &filedata);
  339. if(file->internal_error_id == SD_OK) {
  340. file->internal_error_id = f_closedir(&filedata->data.dir);
  341. _fs_lock(fs_info);
  342. filedata->thread_id = NULL;
  343. _fs_unlock(fs_info);
  344. }
  345. file->error_id = _fs_parse_error(file->internal_error_id);
  346. return (file->internal_error_id == SD_OK);
  347. }
  348. // Read next file info and name from directory
  349. bool fs_dir_read(File* file, FileInfo* fileinfo, char* name, const uint16_t name_length) {
  350. FileData* filedata = NULL;
  351. file->internal_error_id = _get_dir(fs_info, file, &filedata);
  352. if(file->internal_error_id == SD_OK) {
  353. SDFileInfo _fileinfo;
  354. file->internal_error_id = f_readdir(&filedata->data.dir, &_fileinfo);
  355. if(fileinfo != NULL) {
  356. fileinfo->date.value = _fileinfo.fdate;
  357. fileinfo->time.value = _fileinfo.ftime;
  358. fileinfo->size = _fileinfo.fsize;
  359. fileinfo->flags = 0;
  360. if(_fileinfo.fattrib & AM_RDO) fileinfo->flags |= FSF_READ_ONLY;
  361. if(_fileinfo.fattrib & AM_HID) fileinfo->flags |= FSF_HIDDEN;
  362. if(_fileinfo.fattrib & AM_SYS) fileinfo->flags |= FSF_SYSTEM;
  363. if(_fileinfo.fattrib & AM_DIR) fileinfo->flags |= FSF_DIRECTORY;
  364. if(_fileinfo.fattrib & AM_ARC) fileinfo->flags |= FSF_ARCHIVE;
  365. }
  366. if(name != NULL && name_length > 0) {
  367. strlcpy(name, _fileinfo.fname, name_length);
  368. }
  369. }
  370. file->error_id = _fs_parse_error(file->internal_error_id);
  371. return (file->internal_error_id == SD_OK);
  372. }
  373. bool fs_dir_rewind(File* file) {
  374. FileData* filedata = NULL;
  375. file->internal_error_id = _get_dir(fs_info, file, &filedata);
  376. if(file->internal_error_id == SD_OK) {
  377. file->internal_error_id = f_readdir(&filedata->data.dir, NULL);
  378. }
  379. file->error_id = _fs_parse_error(file->internal_error_id);
  380. return (file->internal_error_id == SD_OK);
  381. }
  382. /******************* Common FS Functions *******************/
  383. // Get info about file/dir
  384. FS_Error
  385. fs_common_info(const char* path, FileInfo* fileinfo, char* name, const uint16_t name_length) {
  386. SDFileInfo _fileinfo;
  387. SDError fresult = _fs_status(fs_info);
  388. if(fresult == SD_OK) {
  389. fresult = f_stat(path, &_fileinfo);
  390. if((FRESULT)fresult == FR_OK) {
  391. if(fileinfo != NULL) {
  392. fileinfo->date.value = _fileinfo.fdate;
  393. fileinfo->time.value = _fileinfo.ftime;
  394. fileinfo->size = _fileinfo.fsize;
  395. fileinfo->flags = 0;
  396. if(_fileinfo.fattrib & AM_RDO) fileinfo->flags |= FSF_READ_ONLY;
  397. if(_fileinfo.fattrib & AM_HID) fileinfo->flags |= FSF_HIDDEN;
  398. if(_fileinfo.fattrib & AM_SYS) fileinfo->flags |= FSF_SYSTEM;
  399. if(_fileinfo.fattrib & AM_DIR) fileinfo->flags |= FSF_DIRECTORY;
  400. if(_fileinfo.fattrib & AM_ARC) fileinfo->flags |= FSF_ARCHIVE;
  401. }
  402. if(name != NULL && name_length > 0) {
  403. strlcpy(name, _fileinfo.fname, name_length);
  404. }
  405. }
  406. }
  407. return _fs_parse_error(fresult);
  408. }
  409. // Delete file/dir
  410. // File/dir must not have read-only attribute.
  411. // File/dir must be empty.
  412. // File/dir must not be opened, or the FAT volume can be collapsed. FF_FS_LOCK fix that.
  413. FS_Error fs_common_remove(const char* path) {
  414. SDError fresult = _fs_status(fs_info);
  415. if(fresult == SD_OK) {
  416. fresult = f_unlink(path);
  417. }
  418. return _fs_parse_error(fresult);
  419. }
  420. // Rename file/dir
  421. // File/dir must not be opened, or the FAT volume can be collapsed. FF_FS_LOCK fix that.
  422. FS_Error fs_common_rename(const char* old_path, const char* new_path) {
  423. SDError fresult = _fs_status(fs_info);
  424. if(fresult == SD_OK) {
  425. fresult = f_rename(old_path, new_path);
  426. }
  427. return _fs_parse_error(fresult);
  428. }
  429. // Set attributes of file/dir
  430. // For example:
  431. // set "read only" flag and remove "hidden" flag
  432. // fs_common_set_attr("file.txt", FSF_READ_ONLY, FSF_READ_ONLY | FSF_HIDDEN);
  433. FS_Error fs_common_set_attr(const char* path, uint8_t attr, uint8_t mask) {
  434. SDError fresult = _fs_status(fs_info);
  435. if(fresult == SD_OK) {
  436. uint8_t _mask = 0;
  437. uint8_t _attr = 0;
  438. if(mask & FSF_READ_ONLY) _mask |= AM_RDO;
  439. if(mask & FSF_HIDDEN) _mask |= AM_HID;
  440. if(mask & FSF_SYSTEM) _mask |= AM_SYS;
  441. if(mask & FSF_DIRECTORY) _mask |= AM_DIR;
  442. if(mask & FSF_ARCHIVE) _mask |= AM_ARC;
  443. if(attr & FSF_READ_ONLY) _attr |= AM_RDO;
  444. if(attr & FSF_HIDDEN) _attr |= AM_HID;
  445. if(attr & FSF_SYSTEM) _attr |= AM_SYS;
  446. if(attr & FSF_DIRECTORY) _attr |= AM_DIR;
  447. if(attr & FSF_ARCHIVE) _attr |= AM_ARC;
  448. fresult = f_chmod(path, attr, mask);
  449. }
  450. return _fs_parse_error(fresult);
  451. }
  452. // Set time of file/dir
  453. FS_Error fs_common_set_time(const char* path, FileDateUnion date, FileTimeUnion time) {
  454. SDError fresult = _fs_status(fs_info);
  455. if(fresult == SD_OK) {
  456. SDFileInfo _fileinfo;
  457. _fileinfo.fdate = date.value;
  458. _fileinfo.ftime = time.value;
  459. fresult = f_utime(path, &_fileinfo);
  460. }
  461. return _fs_parse_error(fresult);
  462. }
  463. // Create new directory
  464. FS_Error fs_common_mkdir(const char* path) {
  465. SDError fresult = _fs_status(fs_info);
  466. if(fresult == SD_OK) {
  467. fresult = f_mkdir(path);
  468. }
  469. return _fs_parse_error(fresult);
  470. }
  471. // Get common info about FS
  472. FS_Error fs_get_fs_info(uint64_t* total_space, uint64_t* free_space) {
  473. SDError fresult = _fs_status(fs_info);
  474. if(fresult == SD_OK) {
  475. DWORD free_clusters;
  476. FATFS* fs;
  477. fresult = f_getfree("0:/", &free_clusters, &fs);
  478. if((FRESULT)fresult == FR_OK) {
  479. uint32_t total_sectors = (fs->n_fatent - 2) * fs->csize;
  480. uint32_t free_sectors = free_clusters * fs->csize;
  481. uint16_t sector_size = _MAX_SS;
  482. #if _MAX_SS != _MIN_SS
  483. sector_size = fs->ssize;
  484. #endif
  485. if(total_space != NULL) {
  486. *total_space = (uint64_t)total_sectors * (uint64_t)sector_size;
  487. }
  488. if(free_space != NULL) {
  489. *free_space = (uint64_t)free_sectors * (uint64_t)sector_size;
  490. }
  491. }
  492. }
  493. return _fs_parse_error(fresult);
  494. }
  495. /******************* Error Reporting Functions *******************/
  496. // Get common error description
  497. const char* fs_error_get_desc(FS_Error error_id) {
  498. const char* result;
  499. switch(error_id) {
  500. case(FSE_OK):
  501. result = "OK";
  502. break;
  503. case(FSE_NOT_READY):
  504. result = "filesystem not ready";
  505. break;
  506. case(FSE_EXIST):
  507. result = "file/dir already exist";
  508. break;
  509. case(FSE_NOT_EXIST):
  510. result = "file/dir not exist";
  511. break;
  512. case(FSE_INVALID_PARAMETER):
  513. result = "invalid parameter";
  514. break;
  515. case(FSE_DENIED):
  516. result = "access denied";
  517. break;
  518. case(FSE_INVALID_NAME):
  519. result = "invalid name/path";
  520. break;
  521. case(FSE_INTERNAL):
  522. result = "internal error";
  523. break;
  524. case(FSE_NOT_IMPLEMENTED):
  525. result = "function not implemented";
  526. break;
  527. default:
  528. result = "unknown error";
  529. break;
  530. }
  531. return result;
  532. }
  533. // Get internal error description
  534. const char* fs_error_get_internal_desc(uint32_t internal_error_id) {
  535. const char* result;
  536. switch(internal_error_id) {
  537. case(SD_OK):
  538. result = "OK";
  539. break;
  540. case(SD_DISK_ERR):
  541. result = "disk error";
  542. break;
  543. case(SD_INT_ERR):
  544. result = "internal error";
  545. break;
  546. case(SD_NO_FILE):
  547. result = "no file";
  548. break;
  549. case(SD_NO_PATH):
  550. result = "no path";
  551. break;
  552. case(SD_INVALID_NAME):
  553. result = "invalid name";
  554. break;
  555. case(SD_DENIED):
  556. result = "access denied";
  557. break;
  558. case(SD_EXIST):
  559. result = "file/dir exist";
  560. break;
  561. case(SD_INVALID_OBJECT):
  562. result = "invalid object";
  563. break;
  564. case(SD_WRITE_PROTECTED):
  565. result = "write protected";
  566. break;
  567. case(SD_INVALID_DRIVE):
  568. result = "invalid drive";
  569. break;
  570. case(SD_NOT_ENABLED):
  571. result = "not enabled";
  572. break;
  573. case(SD_NO_FILESYSTEM):
  574. result = "no filesystem";
  575. break;
  576. case(SD_MKFS_ABORTED):
  577. result = "aborted";
  578. break;
  579. case(SD_TIMEOUT):
  580. result = "timeout";
  581. break;
  582. case(SD_LOCKED):
  583. result = "file locked";
  584. break;
  585. case(SD_NOT_ENOUGH_CORE):
  586. result = "not enough memory";
  587. break;
  588. case(SD_TOO_MANY_OPEN_FILES):
  589. result = "too many open files";
  590. break;
  591. case(SD_INVALID_PARAMETER):
  592. result = "invalid parameter";
  593. break;
  594. case(SD_NO_CARD):
  595. result = "no SD Card";
  596. break;
  597. case(SD_NOT_A_FILE):
  598. result = "not a file";
  599. break;
  600. case(SD_NOT_A_DIR):
  601. result = "not a directory";
  602. break;
  603. case(SD_OTHER_APP):
  604. result = "opened by other app";
  605. break;
  606. case(SD_LOW_LEVEL_ERR):
  607. result = "low level error";
  608. break;
  609. default:
  610. result = "unknown error";
  611. break;
  612. }
  613. return result;
  614. }