/* * Author: Pawel Jablonski * E-mail: pj@xirx.net * WWW: xirx.net * GIT: git.xirx.net * * License: You can use this code however you like * but leave information about the original author. * Code is free for non-commercial and commercial use. */ #include "fatfs/ff_gen_drv.h" #include "type.h" #include "flash.h" #include "fs.h" //! File system block type list enum FSReadBlockType { FS_READ_BLOCK_UNKNOWN = 0, //!< Unknown type FS_READ_BLOCK_FILE, //!< File type FS_READ_BLOCK_DIR, //!< Directory type }; static void fsMakePath(char *path, const char *dirName, const char *fileName); static DSTATUS fsFatInit(BYTE pdrv); static DSTATUS fsFatGetStatus(BYTE pdrv); static DRESULT fsFatRead(BYTE pdrv, BYTE *buf, DWORD sector, UINT count); //! File system handlers to functions static Diskio_drvTypeDef fatDriver = { fsFatInit, fsFatGetStatus, fsFatRead }; static char fatDiskPath[4]; //!< Path to the FAT file system static FATFS fatFS; //!< Descriptor of the FAT file system static FRESULT fatMountStatus = FR_NOT_READY; //!< Mount status of the physical drive static FRESULT fatOpenStatus = FR_NOT_READY; //!< Open status of the file static FIL fatFile; //!< Descriptor of the file static int readBlockType = FS_READ_BLOCK_UNKNOWN; //!< Type of reading block static unsigned char dirBuffer[FS_DIR_ENTRY_SIZE * FS_DIR_MAX_QUANTITY]; //!< Directory entrys buffer //! Init file system and set up the FAT void fsInit(void) { if(!FATFS_LinkDriver(&fatDriver, fatDiskPath)) { fatMountStatus = f_mount(&fatFS, fatDiskPath, 1); } } /** * Open a file from the file system * * @param dirName Name of the directory. "app" or "file". * @param fileName Name of the file to open * @param size Struct where size of the file will be written * * @return Status of the open operation */ bool fsOpen(const char *dirName, const struct FSName *fileName, struct FSSize *size) { size->low = 0; size->high = 0; readBlockType = FS_READ_BLOCK_FILE; if(!fatMountStatus) { char path[FS_PATH_MAX_LENGTH + 1]; fsMakePath(path, dirName, (const char *)(fileName->data)); fatOpenStatus = f_open(&fatFile, path, FA_READ); if(!fatOpenStatus) { DWORD fileSize = f_size(&fatFile); size->low = (fileSize % 256); size->high = ((fileSize / 256) & 0xff); return(TRUE); } } return(FALSE); } /** * Create a list of files in the directory from the file system * * @param dirName Name of the directory. "app" or "file". * @param size Struct where size of the buffer with description of the files will be written * * @return Status of the list operation */ bool fsList(const char *dirName, struct FSSize *size) { size->low = 0; size->high = 0; readBlockType = FS_READ_BLOCK_DIR; if(!fatMountStatus) { char path[FS_PATH_MAX_LENGTH + 1]; DIR dir; FILINFO info; fsMakePath(path, dirName, NULL); if(!f_opendir(&dir, path)) { int dirSize = 0; while(1) { if(f_readdir(&dir, &info) != FR_OK) { break; } if(info.fname[0] == 0) { break; } for(int i = 0; i < FS_NAME_MAX_LENGTH; i++) { dirBuffer[dirSize + i] = info.fname[i]; } dirBuffer[dirSize + FS_NAME_MAX_LENGTH] = 0; dirBuffer[dirSize + FS_DIR_ENTRY_SIZE - 2] = (info.fsize % 256); dirBuffer[dirSize + FS_DIR_ENTRY_SIZE - 1] = ((info.fsize / 256) & 0xff); dirSize += FS_DIR_ENTRY_SIZE; if(dirSize >= (FS_DIR_ENTRY_SIZE * FS_DIR_MAX_QUANTITY)) { break; } } size->low = ((dirSize) % 256); size->high = (((dirSize) / 256) & 0xff); return(TRUE); } } return(FALSE); } /** * Read data from buffer to block based on offset * * @param block Struct where the data from the buffer will be written * @param number Number of the block selected to read */ void fsReadBlock(struct FSBlock *block, int number) { if((!fatMountStatus) && (!fatOpenStatus)) { if(readBlockType == FS_READ_BLOCK_FILE) { if(!f_lseek(&fatFile, (number * FS_BLOCK_SIZE))) { UINT read; f_read(&fatFile, block->data, 256, &read); } } else if(readBlockType == FS_READ_BLOCK_DIR) { for(int i = 0; i < FS_BLOCK_SIZE; i++) { block->data[i] = 0; } if(((number * FS_BLOCK_SIZE) / FS_DIR_ENTRY_SIZE) < (FS_DIR_MAX_QUANTITY)) { int offset = (number * FS_BLOCK_SIZE); for(int i = 0; i < FS_BLOCK_SIZE; i++) { block->data[i] = dirBuffer[offset + i]; } } } } } /** * Generate a full path to file * * @param path Buffer to write * @param dirName * @param fileName */ static void fsMakePath(char *path, const char *dirName, const char *fileName) { path[0] = '/'; int i = 1; for(int j = 0; dirName[j]; j++, i++) { path[i] = dirName[j]; } if(fileName) { path[i] = '/'; i++; for(int j = 0; fileName[j]; j++, i++) { path[i] = fileName[j]; } } path[i] = 0; } /** * Get status of init * * @param pdrv Physical drive number * * @return Status of init */ static DSTATUS fsFatInit(BYTE pdrv) { return(0); } /** * Get status of the physical drive * * @param pdrv Physical drive number * * @return Status of the physical drive */ static DSTATUS fsFatGetStatus(BYTE pdrv) { return(0); } /** * Read sector of the physical drive * * @param pdrv Physical drive number * @param buf Buffer to write * @param sector Sector number to read * @param count Count of sectors to read * * @return Status of the reading process */ static DRESULT fsFatRead(BYTE pdrv, BYTE *buf, DWORD sector, UINT count) { for(uint32_t i = 0; i < count; i++) { if(!flashRead((sector + i), (buf + (FLASH_SECTOR_SIZE * i)))) { return(RES_ERROR); } } return(RES_OK); }